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)