db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF subversion and git services (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DERBY-6414) Incorrect handling when using an UPDATE to SET an identity column to DEFAULT
Date Thu, 18 Sep 2014 03:53:34 GMT

    [ https://issues.apache.org/jira/browse/DERBY-6414?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14138457#comment-14138457

ASF subversion and git services commented on DERBY-6414:

Commit 1625884 from [~mamtas] in branch 'code/trunk'
[ https://svn.apache.org/r1625884 ]

CERBY-6414(Incorrect handling when using an UPDATE to SET an identity column to DEFAULT)

I have created DERBY-6742 for JDBC part of this feature so we can generate auto generated
resultset for an update statement updating generated columns. This implementation is supported
through Statement.RETURN_GENERATED_KEYS flag.

Junit tests for this feature are in GeneratedColumnsTest.java. Upgrade tests are in Changes10_12.java.
Upgrade test shows that a soft upgrade from pre-10.11 will not support update of generated
columns using DEFAULT but 10.11 to trunk soft upgrade will allow it. This is because starting
10.11, we have started using sequence generator to create unique ids. If we want to support
updating of idetity columns for pre-10.11 releases, we will need to maintain the code for
old way of generating unique ids. In order to avoid that, this feature is available to only
10.11 db during soft upgrade.

For UPDATE of identity column to work in the MERGE sql, we need to make changes to MERGE code(DERBY-6743).
MERGE already has required code for insert putting DEFAULT in generated columns. Implementation
needs to be added for update putting DEFAULT in generated columns in case of MERGE. In the
mean time, I have renamed existing junit test test_015_bug_6414 to atest_015_bug_6414 in MergeStatementTest.java
so we do not run into failures.

Some detail about the part of the implementation that was tricky for DERBY-6414.
The existing code was originally written to handle inserting values in identity columns using
DEFAULT. In case of insert, InsertResultSet uses ColumnDescriptors in resultDescription to
find the type of the generated columns. This data structure holds the column descriptors of
all the columns in the table. All the columns are in this data structure because even though
INSERT statement may not explicitly assign a value to each and every column in the table,
all the columns end up getting some value in them through an INSERT statement. The code in
InsertResultSet.initializeAIcache method relies on availability of all the columns type information.
But in case of Update, resultDescription does not include all the columns in the table. It
only has the columns being touched by the Update statement(the rest of the columns in the
table will retain their original values), and for each of those touched columns, it has a
duplicate entry in resultDescription in order to have before and after values for the changed
column values. This difference in array content of resultDescription requires us to have separate
implementation of initializeAIcache method for insert and update.

> Incorrect handling when using an UPDATE to SET an identity column to DEFAULT
> ----------------------------------------------------------------------------
>                 Key: DERBY-6414
>                 URL: https://issues.apache.org/jira/browse/DERBY-6414
>             Project: Derby
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions:,
>            Reporter: Rick Hillegas
>            Assignee: Mamta A. Satoor
>              Labels: backport_reject_10_10
>         Attachments: DERBY6414_patch1_diff.txt, DERBY6414_patch1_notReadyForCommit_diff.txt,
DERBY6414_patch1_stat.txt, DERBY6414_patch2_diff.txt, DERBY6414_patch2_stat.txt
> Derby violates the SQL Standard when an UPDATE statement SETs an identity column to the
value DEFAULT. Derby does the right thing for INSERTs, however.
> For INSERTs, the 2011 Standard defines the meaning of DEFAULT in part 2, section 15.10
(Effect of inserting tables into base tables), general rule 2. For INSERTs, the DEFAULT value
is the next value of the sequence generator which defines the identity column.
> For UPDATEs, the 2011 Standard defines the meaning of DEFAULT in part 2, section 15.13
(Effect of replacing rows in base tables), general rule 5. For UPDATEs, the DEFAULT value
is also the next value of the sequence generator which defines the identity column.
> Note also that the 2011 Standard says that a GENERATED ALWAYS identity column can be
SET to DEFAULT. Furthermore, that is the only explicit value accepted. See the 2011 Standard,
part 2, section 14.15 (set clause list), syntax rule 5:
> {
> "If <set clause> SC specifies an <object column> that references a column
of which some underlying column is either a generated column or an identity column whose descriptor
indicates that values are always generated, then the <update source> specified in SC
shall consist of a <default specification>."
> }
> What Derby actually does for UPDATEs is the following:
> 1) If the column was declared GENERATED ALWAYS, then Derby raises a compile-time error
saying that the value of an identity column can't be overridden.
> 2) If the column was declared GENERATED BY DEFAULT, then Derby raises an execution time-error
when trying to stuff a null into the column.
> Correcting this bug would result in backwardly incompatible behavior. However, I think
that the incompatibility is minor: it would mean the successful run of statements which previously
raised errors.
> I tripped across this problem while implementing the UPDATE action of the MERGE statement
(DERBY-3155). If we decide to fix this bug, we will want to make sure that the UPDATE actions
of MERGE statements also correctly handle DEFAULT values for identity columns.
> The following script shows this problem:
> connect 'jdbc:derby:memory:db;create=true';
> create table t1( a int generated always as identity, b int );
> create table t2( a int generated by default as identity, b int );
> insert into t1( a, b ) values ( default, 100 );
> insert into t2( a, b ) values ( default, 100 );
> update t1 set a = default;
> update t2 set a = default;
> select * from t1;
> select * from t2;

This message was sent by Atlassian JIRA

View raw message