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:38:04 UTC

[1/2] cayenne git commit: CAY-2357 Generic select queries silently convert result to nulls

Repository: cayenne
Updated Branches:
  refs/heads/STABLE-4.0 77fc8b79d -> 084baf620


CAY-2357 Generic select queries silently convert result to nulls

(cherry picked from commit 8452d41)


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/d51c51a5
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/d51c51a5
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/d51c51a5

Branch: refs/heads/STABLE-4.0
Commit: d51c51a5709611b233c431f15e2beb7c4346dab8
Parents: 77fc8b7
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:31:02 2017 +0300

----------------------------------------------------------------------
 .../apache/cayenne/access/ObjectResolver.java   |  9 +++++-
 .../org/apache/cayenne/query/EJBQLQueryIT.java  | 30 ++++++++++++++++++++
 .../org/apache/cayenne/query/SQLTemplateIT.java | 29 +++++++++++++++++++
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 4 files changed, 68 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/d51c51a5/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/d51c51a5/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 8e4f989..ade5461 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
@@ -625,4 +625,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/d51c51a5/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/d51c51a5/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 04490b2..dbb7e15 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -24,6 +24,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/2] 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

(cherry picked from commit 65ebda9)


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/084baf62
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/084baf62
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/084baf62

Branch: refs/heads/STABLE-4.0
Commit: 084baf620fb55f7f34b9c51e950ce2e901ad60fb
Parents: d51c51a
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Aug 31 12:33:02 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Aug 31 12:33:02 2017 +0300

----------------------------------------------------------------------
 .../reflect/LifecycleCallbackEventHandler.java  |  5 ++++
 .../org/apache/cayenne/query/EJBQLQueryIT.java  | 29 ++++++++++++++++++++
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 3 files changed, 35 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/084baf62/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 429efdb..28006b1 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
@@ -138,6 +138,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/084baf62/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 ade5461..a60e9d2 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
@@ -26,6 +26,8 @@ import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
 import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.exp.Expression;
 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;
@@ -655,4 +657,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/084baf62/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 dbb7e15..5dc9861 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -25,6 +25,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