[ https://issues.apache.org/jira/browse/CAY-1905?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13938527#comment-13938527
]
Mikaël Cluseau edited comment on CAY-1905 at 3/17/14 11:06 PM:
---------------------------------------------------------------
The code that handles the prefetches:
{code:java}
for (String prefetch : allPrefetches) {
LOG.info("Adding prefetch: " + prefetch);
PrefetchTreeNode prefetchTreeNode = query
.addPrefetch(prefetch);
if (canUseJoinPrefetch(entity, prefetch)) {
prefetchTreeNode.setSemantics(JOINT_PREFETCH_SEMANTICS);
}
}
{code}
canUseJoinPrefetch returns false if is finds a toMany or a not mandatory relationship for
the given path.
The resulting log, where everything is N-to-1:
{code}
INFO - Adding prefetch: address1
INFO - Adding prefetch: address1.way
INFO - Adding prefetch: address1.city
INFO - Adding prefetch: person
INFO - --- transaction started.
INFO - SELECT t0.* FROM app.file t0 JOIN app.person t1 ON (t0.person_2_id = t1.id) WHERE t1.name_2
ILIKE ? [bind: 1->name_2:'%xx%']
INFO - === returned 4 rows. - took 6 ms.
INFO - +++ transaction committed.
INFO - --- transaction started.
INFO - SELECT t0.*, t1.*, t2.* FROM app.file t0 LEFT JOIN app.address t1 ON (t0.address_1_id
= t1.id) LEFT JOIN app.person t2 ON (t0.person_id = t2.id) WHERE (t0.id IN (?, [...], ?))
[bind: 1->id:123, [...], 56->id:456] - prepared in 7 ms.
INFO - === returned 56 rows. - took 29 ms.
INFO - SELECT DISTINCT t0.* FROM global.way t0 JOIN app.address t1 ON (t0.way_code = t1.way_code)
JOIN app.file t2 ON (t1.id = t2.address_1_id) WHERE t2.id IN (?, [...], ?) [bind: 1->id:123,
[...], 56->id:456]
INFO - === returned 38 rows. - took 16 ms.
INFO - SELECT DISTINCT t0.* FROM global.city t0 JOIN app.address t1 ON (t0.city_code = t1.city_code)
JOIN app.file t2 ON (t1.id = t2.address_1_id) WHERE t2.id IN (?, [...], ?) [bind: 1->id:123,
[...], 56->id:456]
INFO - === returned 1 row. - took 4 ms.
INFO - +++ transaction committed.
{code}
The stack trace:
{code}
org.apache.cayenne.access.ResultScanParentAttachmentStrategy.indexParents(ResultScanParentAttachmentStrategy.java:113)
org.apache.cayenne.access.ResultScanParentAttachmentStrategy.linkToParent(ResultScanParentAttachmentStrategy.java:72)
org.apache.cayenne.access.HierarchicalObjectResolverNode.objectsFromDataRows(HierarchicalObjectResolverNode.java:70)
org.apache.cayenne.access.HierarchicalObjectResolver$DisjointProcessor.startDisjointPrefetch(HierarchicalObjectResolver.java:121)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:206)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
org.apache.cayenne.access.HierarchicalObjectResolver.resolveObjectTree(HierarchicalObjectResolver.java:96)
org.apache.cayenne.access.HierarchicalObjectResolver.synchronizedRootResultNodeFromDataRows(HierarchicalObjectResolver.java:78)
org.apache.cayenne.access.DataDomainQueryAction$ObjectConversionStrategy.toResultsTree(DataDomainQueryAction.java:605)
org.apache.cayenne.access.DataDomainQueryAction$SingleObjectConversionStrategy.convert(DataDomainQueryAction.java:643)
org.apache.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:468)
org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:129)
org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:610)
org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:847)
org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:602)
org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
org.apache.cayenne.access.DataContext.onQuery(DataContext.java:968)
org.apache.cayenne.access.DataContext.performQuery(DataContext.java:957)
{code}
was (Author: mcluseau):
The code that handles the prefetches:
{code:java}
for (String prefetch : allPrefetches) {
LOG.info("Adding prefetch: " + prefetch);
PrefetchTreeNode prefetchTreeNode = query
.addPrefetch(prefetch);
if (canUseJoinPrefetch(entity, prefetch)) {
prefetchTreeNode.setSemantics(JOINT_PREFETCH_SEMANTICS);
}
}
{code}
canUseJoinPrefetch returns false if is finds a toMany or a not mandatory relationship for
the given path.
The resulting log:
{code}
INFO - Adding prefetch: address1
INFO - Adding prefetch: address1.way
INFO - Adding prefetch: address1.city
INFO - Adding prefetch: person
INFO - --- transaction started.
INFO - SELECT t0.* FROM app.file t0 JOIN app.person t1 ON (t0.person_2_id = t1.id) WHERE t1.name_2
ILIKE ? [bind: 1->name_2:'%xx%']
INFO - === returned 4 rows. - took 6 ms.
INFO - +++ transaction committed.
INFO - --- transaction started.
INFO - SELECT t0.*, t1.*, t2.* FROM app.file t0 LEFT JOIN app.address t1 ON (t0.address_1_id
= t1.id) LEFT JOIN app.person t2 ON (t0.person_id = t2.id) WHERE (t0.id IN (?, [...], ?))
[bind: 1->id:123, [...], 56->id:456] - prepared in 7 ms.
INFO - === returned 56 rows. - took 29 ms.
INFO - SELECT DISTINCT t0.* FROM global.way t0 JOIN app.address t1 ON (t0.way_code = t1.way_code)
JOIN app.file t2 ON (t1.id = t2.address_1_id) WHERE t2.id IN (?, [...], ?) [bind: 1->id:123,
[...], 56->id:456]
INFO - === returned 38 rows. - took 16 ms.
INFO - SELECT DISTINCT t0.* FROM global.city t0 JOIN app.address t1 ON (t0.city_code = t1.city_code)
JOIN app.file t2 ON (t1.id = t2.address_1_id) WHERE t2.id IN (?, [...], ?) [bind: 1->id:123,
[...], 56->id:456]
INFO - === returned 1 row. - took 4 ms.
INFO - +++ transaction committed.
{code}
The stack trace:
{code}
org.apache.cayenne.access.ResultScanParentAttachmentStrategy.indexParents(ResultScanParentAttachmentStrategy.java:113)
org.apache.cayenne.access.ResultScanParentAttachmentStrategy.linkToParent(ResultScanParentAttachmentStrategy.java:72)
org.apache.cayenne.access.HierarchicalObjectResolverNode.objectsFromDataRows(HierarchicalObjectResolverNode.java:70)
org.apache.cayenne.access.HierarchicalObjectResolver$DisjointProcessor.startDisjointPrefetch(HierarchicalObjectResolver.java:121)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:206)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
org.apache.cayenne.access.HierarchicalObjectResolver.resolveObjectTree(HierarchicalObjectResolver.java:96)
org.apache.cayenne.access.HierarchicalObjectResolver.synchronizedRootResultNodeFromDataRows(HierarchicalObjectResolver.java:78)
org.apache.cayenne.access.DataDomainQueryAction$ObjectConversionStrategy.toResultsTree(DataDomainQueryAction.java:605)
org.apache.cayenne.access.DataDomainQueryAction$SingleObjectConversionStrategy.convert(DataDomainQueryAction.java:643)
org.apache.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:468)
org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:129)
org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:610)
org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:847)
org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:602)
org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
org.apache.cayenne.access.DataContext.onQuery(DataContext.java:968)
org.apache.cayenne.access.DataContext.performQuery(DataContext.java:957)
{code}
> Multi-step prefetching NPE : 1..N..1 with absent N and root with no qualifier
> -----------------------------------------------------------------------------
>
> Key: CAY-1905
> URL: https://issues.apache.org/jira/browse/CAY-1905
> Project: Cayenne
> Issue Type: Bug
> Affects Versions: 3.1RC1, 3.2M1
> Reporter: Andrus Adamchik
> Assignee: Andrus Adamchik
> Fix For: 3.1 (final), 3.2.M2
>
>
> When all of these conditions are true in a query with prefetching, the query fails with
an NPE:
> 1. Disjoint Prefetching is done as 1..N..1 (actually cardinality may not a q requirement)
> 2. Intermediate entity has no rows. Root entity and final entity do.
> 3. Root query has no qualifier.
> SelectQuery<Gallery> q = SelectQuery.query(Gallery.class);
> q.addPrefetch(Gallery.PAINTING_ARRAY.disjoint());
> q.addPrefetch(Gallery.PAINTING_ARRAY.dot(Painting.TO_ARTIST).disjoint());
> List<Gallery> galleries = context.select(q);
> INFO: SELECT t0.GALLERY_NAME, t0.GALLERY_ID FROM GALLERY t0
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logSelectCount
> INFO: === returned 3 rows. - took 7 ms.
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
> INFO: SELECT t0.ESTIMATED_PRICE, t0.PAINTING_DESCRIPTION, t0.PAINTING_TITLE, t0.ARTIST_ID,
t0.GALLERY_ID, t0.PAINTING_ID, t1.GALLERY_ID FROM PAINTING t0 JOIN GALLERY t1 ON (t0.GALLERY_ID
= t1.GALLERY_ID)
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logSelectCount
> INFO: === returned 0 rows. - took 6 ms.
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
> INFO: SELECT t0.ARTIST_NAME, t0.DATE_OF_BIRTH, t0.ARTIST_ID FROM ARTIST t0
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logSelectCount
> INFO: === returned 2 rows. - took 2 ms.
> Mar 11, 2014 2:59:01 PM org.apache.cayenne.log.CommonsJdbcEventLogger logCommitTransaction
> INFO: +++ transaction committed.
> java.lang.NullPointerException
> at org.apache.cayenne.access.ResultScanParentAttachmentStrategy.indexParents(ResultScanParentAttachmentStrategy.java:104)
> at org.apache.cayenne.access.ResultScanParentAttachmentStrategy.linkToParent(ResultScanParentAttachmentStrategy.java:72)
> at org.apache.cayenne.access.HierarchicalObjectResolverNode.objectsFromDataRows(HierarchicalObjectResolverNode.java:70)
> at org.apache.cayenne.access.HierarchicalObjectResolver$DisjointProcessor.startDisjointPrefetch(HierarchicalObjectResolver.java:121)
> at org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:206)
> at org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
> at org.apache.cayenne.query.PrefetchTreeNode.traverse(PrefetchTreeNode.java:221)
> at org.apache.cayenne.access.HierarchicalObjectResolver.resolveObjectTree(HierarchicalObjectResolver.java:96)
> at org.apache.cayenne.access.HierarchicalObjectResolver.synchronizedRootResultNodeFromDataRows(HierarchicalObjectResolver.java:78)
> at org.apache.cayenne.access.DataDomainQueryAction$ObjectConversionStrategy.toResultsTree(DataDomainQueryAction.java:605)
> at org.apache.cayenne.access.DataDomainQueryAction$SingleObjectConversionStrategy.convert(DataDomainQueryAction.java:643)
> at org.apache.cayenne.access.DataDomainQueryAction.interceptObjectConversion(DataDomainQueryAction.java:468)
> at org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:129)
> at org.apache.cayenne.access.UnitTestDomainQueryAction.execute(UnitTestDomainQueryAction.java:47)
> at org.apache.cayenne.access.UnitTestDomain.onQueryNoFilters(UnitTestDomain.java:63)
> at org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:847)
> at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:602)
> at org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
> at org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
> at org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
> at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:962)
> at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:951)
> at org.apache.cayenne.BaseContext.select(BaseContext.java:302)
> at org.apache.cayenne.access.DataContextPrefetchMultistepTest.testToManyToOne_EmptyToMany_NoRootQualifier(DataContextPrefetchMultistepTest.java:300)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at junit.framework.TestCase.runTest(TestCase.java:154)
> at junit.framework.TestCase.runBare(TestCase.java:127)
> at junit.framework.TestResult$1.protect(TestResult.java:106)
> at junit.framework.TestResult.runProtected(TestResult.java:124)
> at junit.framework.TestResult.run(TestResult.java:109)
> at junit.framework.TestCase.run(TestCase.java:118)
> at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:131)
> at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
--
This message was sent by Atlassian JIRA
(v6.2#6252)
|