db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bryan Pendleton (JIRA)" <j...@apache.org>
Subject [jira] Commented: (DERBY-1644) NPE when inserting values to a table that has a column declared as generated by default as identity
Date Sat, 18 Nov 2006 20:35:38 GMT
    [ http://issues.apache.org/jira/browse/DERBY-1644?page=comments#action_12451063 ] 
Bryan Pendleton commented on DERBY-1644:

Thanks Army! I think that your observation is crucial, and here's why:

The problem arises due to this code in InsertNode.bind():

                if (! inOrder || resultSet.resultColumns.size() < numTableColumns)
                        // one thing we do know is that all of the resultsets underneath
                        // us have their resultColumn names filled in with the names of
                        // the target table columns.  That makes generating the mapping
                        // "easier" -- we simply generate the names of the target table columns
                        // that are included.  For the missing columns, we generate default
                        // value expressions.

                        resultSet = resultSet.enhanceRCLForInsert(numTableColumns, colMap,
                                       targetTableDescriptor, targetVTI);

                if (resultSet instanceof UnionNode)
                        // If we are inserting a number of rows in VALUES clause, we need
                        // examine each row for 'autoincrement'.
                else resultColumnList.checkAutoincrement(resultSet.getResultColumns());

When the VALUES clause encounters multiple rows, it generates a UNION node tree to 
combine the rows to be inserted. The code above notices the top-level UNION node
and calls the special checkAutoincrementUnion() method which knows how to
recursively traverse the Union tree and call checkAutoIncrement() on the underlying
RowResultSetNode instances at the leaf level of the tree.

HOWEVER, when the number of columns in the rows in the VALUES clause is a subset of
the number of columns in the table we're inserting into, the top node of the tree
is not a UnionNode, but is rather a ProjectRestrictNode. This means that we skip past
the UnionNode test and just call checkAutoincrement(), which processes the PRN but doesn't
go down to the RowResultSetNode(s) at the leaf level.

This leaves the ResultColumn instance at the leaf level with a NULL column descriptor,
which causes the NPE during the code generation phase.

And, there is a second, related problem. The enhanceRCLForInsert() call is also only made
at the top level of the tree. However, this call is a necessary pre-condition for calling
checkAutoincrement() because enhanceRCLForInsert() ensures that the proper ResultColumnList
values are in place prior to the checkAutoincrement() reconciliation of the column lists.

I believe that the way to solve this is to merge the above code from InsertNode.bind
together with the current recursive processing in ResultColumnList.checkAutoincrementUnion()
to produce a new recursive routine, which I have called enhanceAndCheckForAutoincrement(),
which will recursively traverse the ResultSet tree, calling *both* enhanceRCLForInsert()
and checkAutoincrement() on the various nodes in the tree.

That way, even if the RowResultSetNode instances are buried within UnionNode trees, they
will still be correctly set up for autoincrement processing during bind processing.

I'll attach a complete patch to this Jira issue once I finish writing a bunch of tests
and tidying up the code changes.

> NPE when inserting values to a table that has a column declared as generated by default
as identity
> ---------------------------------------------------------------------------------------------------
>                 Key: DERBY-1644
>                 URL: http://issues.apache.org/jira/browse/DERBY-1644
>             Project: Derby
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions:
>         Environment: Sun JDK 1.4.2
>            Reporter: Yip Ng
>         Assigned To: Bryan Pendleton
>            Priority: Minor
> The following scenario triggers a NullPointerException in statement compilation:
> ij> create table t1 (c1 int, c2 int generated by default as identity);
> 0 rows inserted/updated/deleted
> ij> insert into t1 (c2) values default, 10;
> ERROR XJ001: Java exception: ': java.lang.NullPointerException'.
> Stacktrace from derby.log:
> Database Class Loader started - derby.database.classpath=''
> 2006-08-04 06:31:17.235 GMT Thread[main,5,main] (XID = 235), (SESSIONID = 0), (DATABASE
= wombat), (DRDAID = null), Cleanup action starting
> 2006-08-04 06:31:17.235 GMT Thread[main,5,main] (XID = 235), (SESSIONID = 0), (DATABASE
= wombat), (DRDAID = null), Failed Statement is: insert into t1 (c2) values default, 10
> java.lang.NullPointerException
> 	at org.apache.derby.impl.sql.compile.ResultColumnList.generateCore(ResultColumnList.java:1033)
> 	at org.apache.derby.impl.sql.compile.ResultColumnList.generate(ResultColumnList.java:893)
> 	at org.apache.derby.impl.sql.compile.RowResultSetNode.generate(RowResultSetNode.java:690)
> 	at org.apache.derby.impl.sql.compile.UnionNode.generate(UnionNode.java:589)
> 	at org.apache.derby.impl.sql.compile.ProjectRestrictNode.generateMinion(ProjectRestrictNode.java:1424)
> 	at org.apache.derby.impl.sql.compile.ProjectRestrictNode.generate(ProjectRestrictNode.java:1286)
> 	at org.apache.derby.impl.sql.compile.NormalizeResultSetNode.generate(NormalizeResultSetNode.java:122)
> 	at org.apache.derby.impl.sql.compile.InsertNode.generate(InsertNode.java:764)
> 	at org.apache.derby.impl.sql.compile.StatementNode.generate(StatementNode.java:232)
> 	at org.apache.derby.impl.sql.GenericStatement.prepMinion(GenericStatement.java:477)
> 	at org.apache.derby.impl.sql.GenericStatement.prepare(GenericStatement.java:118)
> 	at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(GenericLanguageConnectionContext.java:713)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:567)
> 	at org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:516)
> 	at org.apache.derby.impl.tools.ij.ij.executeImmediate(ij.java:313)
> 	at org.apache.derby.impl.tools.ij.utilMain.doCatch(utilMain.java:478)
> 	at org.apache.derby.impl.tools.ij.utilMain.runScriptGuts(utilMain.java:347)
> 	at org.apache.derby.impl.tools.ij.utilMain.go(utilMain.java:248)
> 	at org.apache.derby.impl.tools.ij.Main.go(Main.java:203)
> 	at org.apache.derby.impl.tools.ij.Main.mainCore(Main.java:169)
> 	at org.apache.derby.impl.tools.ij.Main14.main(Main14.java:55)
> 	at org.apache.derby.tools.ij.main(ij.java:69)
> sysinfo:
> ------------------ Java Information ------------------
> Java Version:    1.4.2_12
> Java Vendor:     Sun Microsystems Inc.
> Java home:       C:\jdk142\jre
> Java classpath:  classes;.
> OS name:         Windows XP
> OS architecture: x86
> OS version:      5.1
> Java user name:  yip
> Java user home:  C:\Documents and Settings\Administrator
> Java user dir:   C:\derby\trunk
> java.specification.name: Java Platform API Specification
> java.specification.version: 1.4
> --------- Derby Information --------
> JRE - JDBC: J2SE 1.4.2 - JDBC 3.0
> [C:\derby\trunk\classes] alpha - (1)
> ------------------------------------------------------
> ----------------- Locale Information -----------------
> Current Locale :  [English/United States [en_US]]
> Found support for locale: [de_DE]
>          version: alpha - (1)
> Found support for locale: [es]
>          version: alpha - (1)
> Found support for locale: [fr]
>          version: alpha - (1)
> Found support for locale: [it]
>          version: alpha - (1)
> Found support for locale: [ja_JP]
>          version: alpha - (1)
> Found support for locale: [ko_KR]
>          version: alpha - (1)
> Found support for locale: [pt_BR]
>          version: alpha - (1)
> Found support for locale: [zh_CN]
>          version: alpha - (1)
> Found support for locale: [zh_TW]
>          version: alpha - (1)
> ------------------------------------------------------

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


View raw message