db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mamta A. Satoor (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DERBY-6786) NullPointerException in INSERT INTO statement with multiple subselects
Date Wed, 28 Jan 2015 08:48:34 GMT

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

Mamta A. Satoor commented on DERBY-6786:

I have done more debugging and found that the code in JoinNode:buildRCL() is what is causing
for us to run into NPE. 

The code here checks if we already have built a ResultColumnList. If yes, then we leave the
routine with no other work.
		/* NOTE - we only need to build this list if it does not already 
		 * exist.  This can happen in the degenerate case of an insert
		 * select with a join expression in a derived table within the select.
		if (getResultColumns() != null)

If the ResultColumnList for JoinNode is not built yet, we go through the LeftResultSet's result
column list and make a copy of it, build virtual nodes on top of them and then we do the same
with RightResultSet's result column list and then we append thecopy of the right resultcolumns
to the copy of the left result columns and use it as JoinNode's result column list. 

In case of our INSERT case, as described earlier in this jira, we go through two cycles of
binds. Once for the SELECT inside the INSERT statement and then for the bind of INSERT statement
itself(which causes the SELECT to rebind itself). In the first iteration of bind of the SELECT,
the JoinNode.buildRCL will find the resultcolumn list to be null and hence we build a result
column list using left resultset and right resultset. The second time when we come again for
the bind of the SELECT, we find that the result column list already exist and hence we just
return from this method. But I believe what is happening is that the resultset list built
in the first cycle ends up having virtual nodes created on top of it and that causes it to
loose its column id. I removed the if condition from JoinNode.buildRCL and we do not run into
NPE with the test cases provided here. I am going to enable the junit test case zztestDerby6786InsertIntoSelectCase3
and see if it runs successfully. I will also run the test case added for DERBY-6788. If they
both pass, I will run our junit suite and derbyall suite to see how things go.

This if condition has been there from Derby 10.1 days(and that is why we see the failures
in 10.1 codeline as well). But my guess is that the reason we have the if condition in JoinNode.buildRCL
is to avoid recreating the result column list. But it looks like, it should be ok to remove
the if statement and let the result column list to be built again during the second round
of the bind of SELECT in case of INSERT statement. 

> NullPointerException in INSERT INTO statement with multiple subselects
> ----------------------------------------------------------------------
>                 Key: DERBY-6786
>                 URL: https://issues.apache.org/jira/browse/DERBY-6786
>             Project: Derby
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions:,,,,,
>         Environment: not relevant, but tested under Windows 7 32bit, Windows Server 2008
64bit, Java 6 and Java 7.
>            Reporter: Johannes Stadler
>              Labels: NullPointerException
>         Attachments: acaaeec04ex014axaa2ex076bx000000c72a081.java, repro.sql
> Hello,
> I'm getting this wrapped NullPointerException when I try to execute an INSERT INTO SQL
> java.sql.SQLException: The exception 'java.lang.NullPointerException' was thrown while
evaluating an expression.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:101)
> 	at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:148)
> 	at org.apache.derby.impl.jdbc.Util.seeNextException(Util.java:349)
> 	at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:431)
> 	at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(TransactionResourceImpl.java:353)
> 	at org.apache.derby.impl.jdbc.EmbedConnection.handleException(EmbedConnection.java:2400)
> 	at org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:85)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1437)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:711)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.executeLargeUpdate(EmbedStatement.java:190)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:179)
> 	at de.foconis.dakobp.unittests.div.TestMain.testNullpointer(TestMain.java:49)
> 	at de.foconis.dakobp.unittests.div.TestMain.main(TestMain.java:28)
> Caused by: java.sql.SQLException: The exception 'java.lang.NullPointerException' was
thrown while evaluating an expression.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:42)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:125)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:71)
> 	... 12 more
> Caused by: java.sql.SQLException: Java exception: ': java.lang.NullPointerException'.
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:42)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:125)
> 	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:71)
> 	at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:148)
> 	at org.apache.derby.impl.jdbc.Util.javaException(Util.java:370)
> 	at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:436)
> 	... 10 more
> Caused by: java.lang.NullPointerException
> 	at org.apache.derby.exe.acf81e0010x014axa9c2x46e6x000000c6dc781.e2(Unknown Source)
> 	at org.apache.derby.impl.services.reflect.DirectCall.invoke(ReflectGeneratedClass.java:105)
> 	at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:275)
> 	at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:263)
> 	at org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
> 	at org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:519)
> 	at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:461)
> 	at org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:340)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1344)
> 	... 5 more
> Most likely this bug has already been reported as DERBY-5041, which has already been
closed (although I don't use a GROUP BY clause).
> The original statement is quite complex and partially generated, but the error can be
reproduced easily, using a statement as simple as this:
> insert into t
>  select erg.* from (
>   select d1.s from (select k,s from k1) as d1
>    right join (select k,s from k2) as d2 on d1.k = d2.k
>   ) as erg
>  where s > 10
> I will attach the file "repro.sql", containing all SQL statements required to reproduce
it (including the CREATE TABLEs).
> These are my investigation results:
> Conditions
> -------------
> 1. the outermost statement must NOT be a SELECT (e. g. INSERT)
> 2. there has to be a outer join in the subselect, where at least one dataset has no join
> 3. an outer SELECT must have a restriction (WHERE clause) and access a column from the
table, that did not have a join partner
> Error state
> -------------
> The NullPointer occurs inside a generated class. So i enabled the Debug Option "DumpClassFile",
to get the generated class file (the decompiled java class file will also be appended).
> The method "e2", stated in the StackTrace, performs the restrction "where s > 10".
Therefore it calls getColumnFromRow() with its resultSetNumber.
> This is where the error occurs: there is no "current row" available. Precisely, the "row"
property of the activation class at the specified index (which is the resultSetNumber=3 in
this example) is not set.
> It gets a bit complicated now, I will try to explain it, starting with the generated
resultset hierarchy.
> This tree of resultset implementations is generated to perform the query:
> Implementation				resultSetNumber
> -------------------				---------------------
> InsertResultSet			-> none
>  ProjectRestrictResultSet		-> 5
>   ProjectRestrictResultSet	-> 4
>    HashLeftOuterJoinResultSet	-> 0
>     TableScanResultSet		-> 1
>     HashTableResultSet		-> 3
>      TableScanResultSet		-> 2
> The HashTableResultSet, which got the resultSetNumber 3 doesn't set a current row, because
there is no join partner (still everything correct). But the ProjectRestrictResultSet on position
4 uses the restriction method ("e2"), which accesses a column on resultSetNumber 3 -> error.
> As far as I can tell, a restriction must never relate to the source of an outer join
ResultSet. The numeration error does not occur, if the outermost statement is a SELECT and
the numeration is generated top-down.
> Unfortunately I couldn't find an easy solution for this problem. In my case, this is
a critical bug, because changing the query as workaround is difficult, since parts of it are
generated. Please note, that this error is not dependent on any environment settings or platform
and occured with all of the abolve mentioned versions. I didn't test the versions from 10.6
to 10.7, but probably those are also affected.
> If you require any further information, please let me know. I'm able to perform a build,
so I wouldn't need a full version, a patch would be sufficient.

This message was sent by Atlassian JIRA

View raw message