Issue Details (XML | Word | Printable)

Key: NUCRDBMS-747
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Unassigned
Reporter: Julian Schillinger
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
DataNucleus Store RDBMS

Null Pointer exception when running executeWithArray together with addGroup

Created: 07/Jan/14 12:32 PM   Updated: 11/Jan/14 07:43 PM   Resolved: 10/Jan/14 09:02 AM
Component/s: Queries
Affects Version/s: None
Fix Version/s: 3.2.11

File Attachments: 1. Java Source File BulkFetchHelper_usethis.java (13 kB)
2. Zip Archive DNFetchGroupsTestCase.zip (25 kB)

Environment: Ubuntu 13.10 64bit, OpenJDK 7

Datastore: MySQL
Severity: Production


 Description  « Hide
*** Overview:
When defining a custom/named fetch group in JDO files and running query.executeWithArray a Null Pointer Exception is thrown. Testcase attached.


*** Stacktrace
...19:20:30,428 DEBUG [DataNucleus.Datastore.Native] - SELECT 'org.datanucleus.test.Parent' AS NUCLEUS_TYPE,`A0`.`KEY`,`A0`.`VERSION` FROM `PARENT` `A0` WHERE `A0`.`KEY` = <'161'>
19:20:30,428 DEBUG [DataNucleus.Datastore.Native] - SELECT 'org.datanucleus.test.Parent' AS NUCLEUS_TYPE,`A0`.`KEY`,`A0`.`VERSION` FROM `PARENT` `A0` WHERE `A0`.`KEY` = <'161'>
19:20:30,429 DEBUG [DataNucleus.Datastore.Retrieve] - Execution Time = 1 ms
19:20:30,429 DEBUG [DataNucleus.Datastore.Retrieve] - Execution Time = 1 ms
19:20:30,431 DEBUG [DataNucleus.Datastore.Retrieve] - >> JDOQL Bulk-Fetch of org.datanucleus.test.Parent.children
19:20:30,431 DEBUG [DataNucleus.Datastore.Retrieve] - >> JDOQL Bulk-Fetch of org.datanucleus.test.Parent.children
19:20:30,432 ERROR [DataNucleus.General] - >> Error reading objects
java.lang.NullPointerException
at java.util.HashMap.putAll(HashMap.java:597)
at org.datanucleus.store.rdbms.query.BulkFetchHelper.applyParametersToStatement(BulkFetchHelper.java:223)
at org.datanucleus.store.rdbms.query.JDOQLQuery.performExecute(JDOQLQuery.java:722)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1786)
at org.datanucleus.store.query.Query.executeWithArray(Query.java:1672)
at org.datanucleus.api.jdo.JDOQuery.executeWithArray(JDOQuery.java:312)
at org.datanucleus.test.Main.main(Main.java:89)
19:20:30,433 INFO [DataNucleus.General] - >> Stop


*** Relevant code piece

// set up fetch group
pm1.getFetchPlan().addGroup("fetchgrp1"); // adding this line causes null pointer further down

// getting parent object
NucleusLogger.GENERAL.info("Getting parent object with key "
+ keyToLookFor);
Query query = pm1.newQuery(Parent.class);
query.setFilter("key == my_key");
query.declareParameters("String my_key");
Object[] params = { keyToLookFor };
query.compile();
List<Parent> parents = (List<Parent>) query
.executeWithArray(params); // this line throws the exception
Parent parent = parents.get(0);


*** Libs
datanucleus-api-jdo-3.2.7.jar
datanucleus-core-3.2.11.jar
datanucleus-api-rest-3.2.1.jar
datanucleus-rdbms-3.2.10.jar
datanucleus-cache-3.1.3.jar




Julian Schillinger made changes - 07/Jan/14 12:33 PM
Field Original Value New Value
Attachment DNFetchGroupsTestCase.zip [ 12040 ]
Julian Schillinger added a comment - 07/Jan/14 02:22 PM
Think this is related to the 'new' bulk fetching of nested objects if they are in the fetch group in combination with the use of explicit parameters (ie the declareParameter() call) in the JDOQL query.

Julian Schillinger added a comment - 08/Jan/14 07:28 AM
This occurs when calling q.execute, q.executeWithArray and q.executeWithMap.

It appears that SQLStatementHelper.applyParametersToStatement (line 164) checks whether parameter paramNameByPosition (which is fed from datastoreCompilation.getParameterNameByPosition()) is null, but BulkFetchHelper.applyParametersToStatement does not do so (line 214).

Andy Jefferson added a comment - 08/Jan/14 12:08 PM
Suggest you work with the raiser of NUCRDBMS-748 and develop a fix

Julian Schillinger added a comment - 08/Jan/14 05:51 PM
Hi Andy,

Am willing to help. I would just catch the null pointer and basically not add the parameter in BulkFetchHelper.applyParametersToStatement. Unfortunately I do not fully comprehend the intention behind this function and why it is invoked. Can you shed some more light on this?

Thanks,
Julian

Julian Schillinger added a comment - 10/Jan/14 04:23 AM - edited
Hi Andy,

Below code change in BulkFetchHelper makes my test pass (updated file attached). As mentioned I am not totally confident that this fix does not break something else. Please consider it or give me a pointer in case I missed something.

public void applyParametersToStatement(PreparedStatement ps, RDBMSQueryCompilation datastoreCompilation, SQLStatement sqlStmt, Map parameters)
    {
    
     // fixes to resolve NUCRDBMS-747
     Map<Integer,String> parameterNameByPos = datastoreCompilation.getParameterNameByPosition();
     if (parameterNameByPos==null) {
     parameterNameByPos=new HashMap<Integer,String>();
     datastoreCompilation.setParameterNameByPosition(parameterNameByPos);
     }
    
     // previous code where datastoreCompilation.getParameterNameByPosition() is replaced by parameterNameByPos
        Map<Integer, String> stmtParamNameByPosition = null;
        List<SQLStatementParameter> stmtParams = null;
        if (datastoreCompilation.getStatementParameters() != null)
        {
            stmtParams = new ArrayList<SQLStatementParameter>();
            stmtParams.addAll(datastoreCompilation.getStatementParameters());
            stmtParamNameByPosition = new HashMap<Integer, String>();
            stmtParamNameByPosition.putAll(parameterNameByPos);
            int numUnions = sqlStmt.getNumberOfUnions();
            int numParams = stmtParamNameByPosition.size();
            for (int i=0;i<numUnions;i++)
            {
                stmtParams.addAll(datastoreCompilation.getStatementParameters());
                Iterator<Map.Entry<Integer, String>> paramEntryIter = parameterNameByPos.entrySet().iterator();
                while (paramEntryIter.hasNext())
                {
                    Map.Entry<Integer, String> paramEntry = paramEntryIter.next();
                    stmtParamNameByPosition.put(numParams*(i+1) + paramEntry.getKey(), paramEntry.getValue());
                }
            }

            SQLStatementHelper.applyParametersToStatement(ps, query.getExecutionContext(), stmtParams, stmtParamNameByPosition, parameters);
        }
    }


Julian Schillinger made changes - 10/Jan/14 04:25 AM
Attachment BulkFetchHelper.java [ 12041 ]
Julian Schillinger made changes - 10/Jan/14 04:25 AM
Attachment datanucleus-rdbms-3.2.11-FIXED.jar [ 12042 ]
Julian Schillinger made changes - 10/Jan/14 04:41 AM
Attachment BulkFetchHelper_usethis.java [ 12043 ]
Julian Schillinger made changes - 10/Jan/14 04:42 AM
Attachment datanucleus-rdbms-3.2.11-FIXED_usethis.jar [ 12044 ]
Andy Jefferson made changes - 10/Jan/14 08:48 AM
Attachment datanucleus-rdbms-3.2.11-FIXED_usethis.jar [ 12044 ]
Andy Jefferson made changes - 10/Jan/14 08:48 AM
Attachment datanucleus-rdbms-3.2.11-FIXED.jar [ 12042 ]
Andy Jefferson made changes - 10/Jan/14 08:48 AM
Attachment BulkFetchHelper.java [ 12041 ]
Andy Jefferson added a comment - 10/Jan/14 09:02 AM
Thx for your code proposal. GitHub master has a slightly different variant, but with the same effect.

PS, please make any code contributions in "diff" format or as a Git pull request. Thx

Andy Jefferson made changes - 10/Jan/14 09:02 AM
Status Open [ 1 ] Resolved [ 5 ]
Resolution Fixed [ 1 ]
Andy Jefferson made changes - 10/Jan/14 09:02 AM
Fix Version/s 3.2.11 [ 12075 ]
Component/s Queries [ 10142 ]
Andy Jefferson made changes - 11/Jan/14 07:43 PM
Status Resolved [ 5 ] Closed [ 6 ]