You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/08/31 09:28:22 UTC
[1/3] cayenne git commit: CAY-2357 Generic select queries silently
convert result to nulls
Repository: cayenne
Updated Branches:
refs/heads/master e44f2fab5 -> 66e2727e8
CAY-2357 Generic select queries silently convert result to nulls
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/8452d41d
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/8452d41d
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/8452d41d
Branch: refs/heads/master
Commit: 8452d41def3796502d297456043d97822665e3b3
Parents: e44f2fa
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Aug 31 12:19:33 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Aug 31 12:19:33 2017 +0300
----------------------------------------------------------------------
.../apache/cayenne/access/ObjectResolver.java | 9 +++++-
.../ejbql/EJBQLOrderByTranslator.java | 5 ++++
.../org/apache/cayenne/query/EJBQLQueryIT.java | 30 ++++++++++++++++++++
.../org/apache/cayenne/query/SQLTemplateIT.java | 29 +++++++++++++++++++
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
5 files changed, 73 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8452d41d/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectResolver.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectResolver.java
index efcac6e..af5949b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectResolver.java
@@ -113,7 +113,8 @@ class ObjectResolver {
List<Persistent> results = new ArrayList<>(rows.size());
for (DataRow row : rows) {
- // nulls are possible here since 3.0 for soem varieties of EJBQL
+ // nulls are possible here since 3.0 for some varieties of EJBQL,
+ // simple example of this: "select p.toGallery+ from Painting p" where toGallery is null.
results.add(objectFromDataRow(row));
}
@@ -212,6 +213,9 @@ class ObjectResolver {
// this is possible when processing left outer joint prefetches
if (val == null) {
+ if(!dataRow.containsKey(key)) {
+ throw new CayenneRuntimeException("No PK column '%s' found in data row.", key);
+ }
return null;
}
@@ -230,6 +234,9 @@ class ObjectResolver {
// this is possible when processing left outer joint prefetches
if (val == null) {
+ if(!dataRow.containsKey(key)) {
+ throw new CayenneRuntimeException("No PK column '%s' found in data row.", key);
+ }
return null;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8452d41d/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
index 41ca358..6b004f9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/ejbql/EJBQLOrderByTranslator.java
@@ -69,4 +69,9 @@ class EJBQLOrderByTranslator extends EJBQLBaseVisitor {
expression.visit(childVisitor);
return false;
}
+
+ @Override
+ public boolean visitDbPath(EJBQLExpression expression, int finishedChildIndex) {
+ return super.visitDbPath(expression, finishedChildIndex);
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8452d41d/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
index d2ae8f8..2e148ef 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
@@ -615,4 +615,34 @@ public class EJBQLQueryIT extends ServerCase {
assertEquals(1L, artistAsc.get(1)[1]);
assertEquals(0L, artistAsc.get(2)[1]);
}
+
+ @Test
+ public void testNullObjects() throws Exception {
+ tArtist.insert(1, "a1");
+ tArtist.insert(2, "a2");
+ tArtist.insert(3, "a3");
+
+ tPainting.insert(1, 2, "title1");
+ tPainting.insert(2, 1, "title2");
+ tPainting.insert(3, 1, "title3");
+
+ EJBQLQuery queryFullProduct = new EJBQLQuery("select a, p from Artist a, Painting p");
+ List<Object[]> result1 = context.performQuery(queryFullProduct);
+ assertEquals(9, result1.size());
+ for(Object[] next : result1) {
+ assertEquals(2, next.length);
+ assertNotNull(next[0]);
+ assertNotNull(next[1]);
+ }
+
+ EJBQLQuery queryToOneRel = new EJBQLQuery("select p.toGallery+, p.toArtist+, p from Painting p");
+ List<Object[]> result2 = context.performQuery(queryToOneRel);
+ assertEquals(3, result2.size());
+ for(Object[] next : result2) {
+ assertNull(next[0]); // Gallery
+ assertTrue(next[1] instanceof Artist);
+ assertTrue(next[2] instanceof Painting);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8452d41d/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
index 902ff04..020364a 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Gallery;
import org.apache.cayenne.testdo.testmap.Painting;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
@@ -33,11 +34,13 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
import org.junit.Before;
import org.junit.Test;
+import java.math.BigInteger;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -155,4 +158,30 @@ public class SQLTemplateIT extends ServerCase {
// expected
}
}
+
+ @Test
+ public void testSQLTemplateSelectNullObjects() throws Exception {
+ tPainting.insert(1, null, "p1", BigInteger.valueOf(10L));
+
+
+ String sql = "SELECT p.GALLERY_ID FROM PAINTING p";
+ SQLTemplate q1 = new SQLTemplate(Gallery.class, sql);
+ q1.setColumnNamesCapitalization(CapsStrategy.UPPER);
+ List<Gallery> galleries = context.performQuery(q1);
+
+ assertEquals(1, galleries.size());
+ assertNull(galleries.get(0));
+ }
+
+ @Test(expected = CayenneRuntimeException.class)
+ public void testSQLTemplateSelectInvalid() throws Exception {
+ tPainting.insert(1, null, "p1", BigInteger.valueOf(10L));
+
+ String sql = "SELECT p.PAINTING_TITLE FROM PAINTING p";
+ SQLTemplate q1 = new SQLTemplate(Gallery.class, sql);
+ q1.setColumnNamesCapitalization(CapsStrategy.UPPER);
+
+ // this should fail as result can't be converted to Gallery class
+ context.performQuery(q1);
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8452d41d/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 06b5ffb..77e14a3 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -37,6 +37,7 @@ CAY-2350 Expression: NotIn with empty collection returns empty result
CAY-2353 Broken paginated column select with only one entity in the result
CAY-2354 DbGenerator.runGenerator must commit its connection
CAY-2356 EJBQL: Incorrect COUNT() on outer joined table
+CAY-2357 Generic select queries silently convert result to nulls if no PK column found
----------------------------------
Release: 4.0.B1
[2/3] cayenne git commit: CAY-2358 NPE when callbacks invoked on null
objects
Posted by nt...@apache.org.
CAY-2358 NPE when callbacks invoked on null objects
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/65ebda99
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/65ebda99
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/65ebda99
Branch: refs/heads/master
Commit: 65ebda996b5dff7b9887a45fc1d5c5759192f8e3
Parents: 8452d41
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Aug 31 12:20:49 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Aug 31 12:20:49 2017 +0300
----------------------------------------------------------------------
.../reflect/LifecycleCallbackEventHandler.java | 16 +++++------
.../org/apache/cayenne/query/EJBQLQueryIT.java | 29 ++++++++++++++++++++
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
3 files changed, 37 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/65ebda99/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
index db596bb..fd044a6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
@@ -20,7 +20,6 @@ package org.apache.cayenne.reflect;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.ObjEntity;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -111,14 +110,8 @@ class LifecycleCallbackEventHandler {
* Registers a callback object to be invoked when a lifecycle event occurs.
*/
private void addCallback(Class<?> entityClass, AbstractCallback callback) {
- Collection<AbstractCallback> entityListeners = listeners.get(entityClass
- .getName());
-
- if (entityListeners == null) {
- entityListeners = new ArrayList<>(3);
- listeners.put(entityClass.getName(), entityListeners);
- }
-
+ Collection<AbstractCallback> entityListeners = listeners
+ .computeIfAbsent(entityClass.getName(), k -> new ArrayList<>(3));
entityListeners.add(callback);
}
@@ -126,6 +119,11 @@ class LifecycleCallbackEventHandler {
* Invokes callbacks for a given entity object.
*/
void performCallbacks(Persistent object) {
+ if(object == null) {
+ // this can happen if object resolved to null from some query with outer join
+ // (e.g. in EJBQL or SQLTemplate)
+ return;
+ }
// default listeners are invoked first
if (!defaultListeners.isEmpty()) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/65ebda99/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
index 2e148ef..a760f3c 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
@@ -28,6 +28,8 @@ import org.apache.cayenne.ejbql.EJBQLException;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.map.EJBQLQueryDescriptor;
import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.LifecycleEvent;
+import org.apache.cayenne.reflect.LifecycleCallbackRegistry;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import org.apache.cayenne.testdo.testmap.Artist;
@@ -645,4 +647,31 @@ public class EJBQLQueryIT extends ServerCase {
}
}
+ @Test
+ public void testNullObjectsCallback() throws Exception {
+ tArtist.insert(1, "a1");
+ tArtist.insert(2, "a2");
+ tArtist.insert(3, "a3");
+
+ tPainting.insert(1, 2, "title1");
+ tPainting.insert(2, 1, "title2");
+ tPainting.insert(3, 1, "title3");
+
+ // set callback to be called
+ LifecycleCallbackRegistry registry = runtime
+ .getDataDomain()
+ .getEntityResolver()
+ .getCallbackRegistry();
+ registry.addCallback(LifecycleEvent.POST_LOAD, Painting.class, "postAddCallback");
+
+ // select Paintings, where one of it will be null
+ EJBQLQuery queryFullProduct = new EJBQLQuery("select a.paintingArray+ from Artist a order by a.artistName");
+ List<Painting> result1 = context.performQuery(queryFullProduct);
+ assertEquals(4, result1.size());
+ assertNull(result1.get(3));
+ for(int i=0; i<3; i++) {
+ assertNotNull(result1.get(i));
+ assertTrue(result1.get(i).isPostAdded());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/65ebda99/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 77e14a3..d80050a 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -38,6 +38,7 @@ CAY-2353 Broken paginated column select with only one entity in the result
CAY-2354 DbGenerator.runGenerator must commit its connection
CAY-2356 EJBQL: Incorrect COUNT() on outer joined table
CAY-2357 Generic select queries silently convert result to nulls if no PK column found
+CAY-2358 NPE when callbacks invoked on null objects
----------------------------------
Release: 4.0.B1
[3/3] cayenne git commit: Change superclass to BaseDataObject
Posted by nt...@apache.org.
Change superclass to BaseDataObject
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/66e2727e
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/66e2727e
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/66e2727e
Branch: refs/heads/master
Commit: 66e2727e8b6c3481518d6fe7450530924d566ade
Parents: 65ebda9
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Aug 31 12:21:16 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Aug 31 12:21:16 2017 +0300
----------------------------------------------------------------------
.../java/org/apache/cayenne/testdo/testmap/ArtDataObject.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/66e2727e/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/ArtDataObject.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/ArtDataObject.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/ArtDataObject.java
index 0923d7c..2658ecc 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/ArtDataObject.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/ArtDataObject.java
@@ -18,13 +18,13 @@
****************************************************************/
package org.apache.cayenne.testdo.testmap;
-import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.BaseDataObject;
/**
* This class exists solely to enable testing of arbitrary superclasses for
* ObjEntities. It has no functionality at this stage (nor is any likely)
*/
-public class ArtDataObject extends CayenneDataObject {
+public class ArtDataObject extends BaseDataObject {
private static final long serialVersionUID = -1350981440925237535L;