Heath Thomann created OPENJPA-2557:
--------------------------------------

             Summary: FinderCache contains incorrectly cached query with a NULL 
for a Primary Key.
                 Key: OPENJPA-2557
                 URL: https://issues.apache.org/jira/browse/OPENJPA-2557
             Project: OpenJPA
          Issue Type: Bug
          Components: query
    Affects Versions: 2.2.2, 2.1.2, 2.2.1.1, 2.3.1, 2.4.0
            Reporter: Heath Thomann
            Priority: Critical


Take the following SQL from a finder:

SELECT t1.code, t1.EXTDISCR, t0.field1, t0.field2 FROM TB1 t0 LEFT OUTER JOIN 
AbstractExtValue t1 ON t0.EXT_USR = t1.code WHERE (t1.EXTDISCR IS NULL OR 
t1.EXTDISCR IN (?)) AND t0.field1 = ? AND t0.field2 IS NULL

Notice the 't0.field2 IS NULL' part.  Field2 is part of a compound PK of table 
'TB1', where the compound PK consists of two fields (field1 and field2).  This 
will become more apparent when looking at the attached test.  Because the PK 
field 'IS NULL', this finder query should NOT be added to the FinderQuery cache 
(i.e. we can't cache something which is "hard coded" to 'IS NULL'....in the 
case where field2 is non-null, the query will never account for that).  
However, this query is in fact incorrectly added to the cache.  To understand 
why this is incorrectly added we must look at two things.  First, if we look at 
the attached test, we can see that the test uses inheritance and a 
discriminator value.  In the above SQL the 't1.EXTDISCR' is the discriminator 
value.  As you can see we are selecting field1 and field2, where field2 IS 
NULL.  Second, we have to look at the OpenJPA code where we determine if the 
finder query can be cached.  That is, look here in FinderQueryImpl:

    static FinderQueryImpl newFinder(ClassMapping mapping,
        SelectExecutor select) {
        SelectImpl impl = extractImplementation(select);
        if (impl == null)
            return null;
        SQLBuffer buffer = impl.getSQL();
        Column[] pkCols = mapping.getPrimaryKeyColumns();
        boolean canCache = pkCols.length == buffer.getParameters().size();

As you can see, the last line determines if the query can be cached (i.e. 
'canCache').  In this case, OpenJPA compares the pkCols (PK columns) to the 
parameters.  In most cases, these two should be equal for a finder query.  
However, at least in the case where a discriminator is used, the finder will 
have one extra more parameter in the finder query.  In those cases, the 
'canCache' will be false and the query not cached.  However, take the case 
where one of the compound PKs contains 'IS NULL' (see above SQL at the start of 
this text).  In this case, 'pkCols.length' will be two, AND the params will be 
two.  So by the 'canCache' test, it will be true.  However, in this case we 
should not cache the above query (i.e. in so doing field2 will always be 
"NULL").  
To resolve this issue, I feel that we need to make sure the the columns in the 
'buffer'  exactly match that of pkCols.  See the attached test/patch for 
proposed fix.

Thanks,

Heath Thomann



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to