[ http://issues.apache.org/jira/browse/DERBY-1329?page=all ]
A B updated DERBY-1329:
-----------------------
Attachment: d1329.patch
Attaching a patch to address this issue. In a word, the problem is that the
ColumnReference in a CurrentOfNode can, in certain situations, end up with a
tableNumber that is never set, and hence it defaults to -1. The fix I've made
ensures that the ColumnReference's tableNumber will always be set when
necessary--i.e. when we've found the ResultColumn that matches the received
ColumnReference. I think this is the correct fix for two reasons:
1) In FromList.bindColumnReferences(), there is the following comment:
/* TableNumbers are set in the CR in the underlying
* FromTable. This ensures that they get the table
* number from the underlying table, not the join node.
* This is important for beging able to push predicates
* down through join nodes.
*/
The place where "TableNumbers are set" is in the getMatchingColumn() call,
which means that the underlying FromTable (which includes CurrentOfNode) is
responsible for setting the table number.
2) Inspection of all other FromTables that implement getMatchingColumn() shows
that they all set the ColumnReference's table number if the corresponding
ResultColumn is found. The one exception is JoinNode, but the
getMatchingColumn() method in JoinNode in turn calls the method of the same
name on the join's left and right nodes, so we know that, eventually, the
ColumnReference's tableNumber will get set by one of the other FromTable's
getMatchingColumn() calls. So the only FromTable that does not set the
tableNumber is CurrentOfNode, and that's the reason for the failure described
in this issue.
The change seems fairly minor but if anyone has a chance to double-check it,
that'd be great. I also added a test case (using the repro posted in the above
comments) to lang/update.sql.
I ran derbyall on Linux Red Hat (RHEL4) using ibm142 and saw no new failures.
Thanks,
Army
> ASSERT failure/IndexOutOfBoundsException with correlated subquery for UPDATE
> ... SET ... WHERE CURRENT OF ... statement.
> ------------------------------------------------------------------------------------------------------------------------
>
> Key: DERBY-1329
> URL: http://issues.apache.org/jira/browse/DERBY-1329
> Project: Derby
> Type: Bug
> Components: SQL
> Versions: 10.0.2.0, 10.0.2.1, 10.1.1.0, 10.2.0.0, 10.1.2.0, 10.1.1.1,
> 10.1.1.2, 10.1.2.1, 10.1.2.2, 10.1.2.3, 10.1.2.4
> Reporter: A B
> Assignee: A B
> Priority: Minor
> Fix For: 10.2.0.0, 10.1.3.0
> Attachments: d1329.java, d1329.patch
>
> If in a statement of the form "UPDATE ... SET ... WHERE CURRENT OF ..." the
> SET clause includes a correlated subquery that has a predicate referencing
> the table that is being updated, Derby will fail with an ASSERT failure in
> sane mode and an IndexOutOfBounds exception in insane mode.
> For example, if we have a cursor CUR1 for the results of a SELECT query on
> BASICTABLE1, and then we try to execute the following update statement:
> update BASICTABLE1 set C3 = (SELECT CC3 FROM
> BASICTABLE2 WHERE BASICTABLE1.ID=BASICTABLE2.IID)
> where current of CUR1
> the result in SANE mode will be:
> org.apache.derby.shared.common.sanity.AssertFailure: ASSERT FAILED
> tableNumber is expected to be non-negative.
> and in INSANE mode will be:
> java.lang.IndexOutOfBoundsException: bitIndex < 0: -1
> The failure occurs during preprocessing of the subquery node when Derby is
> trying to "categorize" a predicate to see if it is pushable. The exact code
> is in ColumnReference.categorize():
> public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
> {
> if (SanityManager.DEBUG)
> SanityManager.ASSERT(tableNumber >= 0,
> "tableNumber is expected to be non-negative");
> referencedTabs.set(tableNumber);
> return ( ! replacesAggregate ) &&
> ( (source.getExpression() instanceof ColumnReference) ||
> (source.getExpression() instanceof VirtualColumnNode) ||
> (source.getExpression() instanceof ConstantNode));
> }
> We get to this code for a ColumnReference who's tableNumber is -1, which
> means that, in sane mode, the assert will fire; in insane mode, we'll call
> "referencedTabs.set()" passing in a -1, which leads to the
> IndexOutOfBoundsException.
> This failure occurs in embedded and with both clients, and occurs in 10.0,
> 10.1, and the 10.2 trunk.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira