cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject svn commit: r561927 - in /cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src: main/java/org/apache/cayenne/access/jdbc/ test/java/org/apache/cayenne/access/ test/resources/dml/
Date Wed, 01 Aug 2007 19:35:06 GMT
Author: aadamchik
Date: Wed Aug  1 12:35:02 2007
New Revision: 561927

URL: http://svn.apache.org/viewvc?view=rev&rev=561927
Log:
CAY-837 EJBQL Update Statement Support
(binding parameters and updating FK's)

Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLUpdateTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLUpdateTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLUpdateTest.xml

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLUpdateTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLUpdateTranslator.java?view=diff&rev=561927&r1=561926&r2=561927
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLUpdateTranslator.java
(original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLUpdateTranslator.java
Wed Aug  1 12:35:02 2007
@@ -19,10 +19,14 @@
 package org.apache.cayenne.access.jdbc;
 
 import java.math.BigDecimal;
+import java.util.Map;
 
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
 import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
 import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.ejbql.EJBQLExpression;
+import org.apache.cayenne.ejbql.parser.EJBQLPositionalInputParameter;
 
 /**
  * A translator of EJBQL UPDATE statements into SQL.
@@ -47,7 +51,7 @@
         context.append("UPDATE");
         return true;
     }
-    
+
     public boolean visitWhere(EJBQLExpression expression) {
         context.append(" WHERE");
         expression.visit(new EJBQLConditionTranslator(context));
@@ -76,7 +80,8 @@
         EJBQLPathTranslator pathTranslator = new EJBQLPathTranslator(context) {
 
             protected void appendMultiColumnPath(EJBQLMultiColumnOperand operand) {
-                throw new EJBQLException("Multi-column paths are unsupported in UPDATEs");
+                throw new EJBQLException(
+                        "Multi-column paths are not yet supported in UPDATEs");
             }
 
             public boolean visitUpdateField(
@@ -96,7 +101,8 @@
     }
 
     // TODO: andrus, 7/31/2007 - all literal processing (visitStringLiteral,
-    // visitIntegerLiteral, visitDecimalLiteral, visitBooleanLiteral) is duplicated in
+    // visitIntegerLiteral, visitDecimalLiteral, visitBooleanLiteral,
+    // visitPositionalInputParameter, visitnamedInputParameter) is duplicated in
     // EJBQLConditionalTranslator - may need to refactor
     public boolean visitStringLiteral(EJBQLExpression expression) {
         if (expression.getText() == null) {
@@ -162,5 +168,57 @@
             context.append(" #bind($").append(var).append(" 'DECIMAL')");
         }
         return true;
+    }
+
+    public boolean visitPositionalInputParameter(EJBQLPositionalInputParameter expression)
{
+
+        String parameter = context.bindPositionalParameter(expression.getPosition());
+        processParameter(parameter);
+        return true;
+    }
+
+    public boolean visitNamedInputParameter(EJBQLExpression expression) {
+        String parameter = context.bindNamedParameter(expression.getText());
+        processParameter(parameter);
+        return true;
+    }
+
+    private void processParameter(String boundName) {
+        Object object = context.getBoundParameter(boundName);
+
+        Map map = null;
+        if (object instanceof Persistent) {
+            map = ((Persistent) object).getObjectId().getIdSnapshot();
+        }
+        else if (object instanceof ObjectId) {
+            map = ((ObjectId) object).getIdSnapshot();
+        }
+        else if (object instanceof Map) {
+            map = (Map) object;
+        }
+
+        if (map != null) {
+            if (map.size() == 1) {
+                context.rebindParameter(boundName, map.values().iterator().next());
+            }
+            else {
+                throw new EJBQLException(
+                        "Multi-column paths are not yet supported in UPDATEs");
+            }
+        }
+
+        if (object != null) {
+            context.append(" #bind($").append(boundName).append(")");
+        }
+        else {
+            // this is a hack to prevent execptions on DB's like Derby for expressions
+            // "X = NULL". The 'VARCHAR' parameter is totally bogus, but seems to work on
+            // all tested DB's... Also note what JPA spec, chapter 4.11 says: "Comparison
+            // or arithmetic operations with a NULL value always yield an unknown value."
+
+            // TODO: andrus 6/28/2007 Ideally we should track the type of the current
+            // expression to provide a meaningful type.
+            context.append(" #bind($").append(boundName).append(" 'VARCHAR')");
+        }
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLUpdateTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLUpdateTest.java?view=diff&rev=561927&r1=561926&r2=561927
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLUpdateTest.java
(original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/access/DataContextEJBQLUpdateTest.java
Wed Aug  1 12:35:02 2007
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
+import org.apache.art.Artist;
 import org.apache.art.BooleanTestEntity;
 import org.apache.cayenne.DataObjectUtils;
 import org.apache.cayenne.ObjectContext;
@@ -30,7 +31,7 @@
     protected void setUp() throws Exception {
         deleteTestData();
     }
-    
+
     public void testUpdateQualifier() throws Exception {
         createTestData("prepare");
 
@@ -80,7 +81,7 @@
         notUpdated = DataObjectUtils.objectForQuery(context, check);
         assertEquals(new Long(0l), notUpdated);
     }
-    
+
     public void testUpdateNoQualifierMultipleItems() throws Exception {
         createTestData("prepare");
 
@@ -105,7 +106,7 @@
         notUpdated = DataObjectUtils.objectForQuery(context, check);
         assertEquals(new Long(0l), notUpdated);
     }
-    
+
     public void testUpdateNoQualifierDecimal() throws Exception {
         createTestData("prepare");
 
@@ -130,20 +131,22 @@
         notUpdated = DataObjectUtils.objectForQuery(context, check);
         assertEquals(new Long(0l), notUpdated);
     }
-    
+
     public void testUpdateNoQualifierBoolean() throws Exception {
-       
 
         ObjectContext context = createDataContext();
-        BooleanTestEntity o1 = (BooleanTestEntity) context.newObject(BooleanTestEntity.class);
+        BooleanTestEntity o1 = (BooleanTestEntity) context
+                .newObject(BooleanTestEntity.class);
         o1.setBooleanColumn(Boolean.TRUE);
-        
-        BooleanTestEntity o2 = (BooleanTestEntity) context.newObject(BooleanTestEntity.class);
+
+        BooleanTestEntity o2 = (BooleanTestEntity) context
+                .newObject(BooleanTestEntity.class);
         o2.setBooleanColumn(Boolean.FALSE);
-        
-        BooleanTestEntity o3 = (BooleanTestEntity) context.newObject(BooleanTestEntity.class);
+
+        BooleanTestEntity o3 = (BooleanTestEntity) context
+                .newObject(BooleanTestEntity.class);
         o3.setBooleanColumn(Boolean.FALSE);
-        
+
         context.commitChanges();
 
         EJBQLQuery check = new EJBQLQuery("select count(p) from BooleanTestEntity p "
@@ -164,5 +167,34 @@
 
         notUpdated = DataObjectUtils.objectForQuery(context, check);
         assertEquals(new Long(3l), notUpdated);
+    }
+
+    public void testUpdateNoQualifierToOne() throws Exception {
+        createTestData("prepare");
+
+        ObjectContext context = createDataContext();
+        Artist object = (Artist) DataObjectUtils
+                .objectForPK(context, Artist.class, 33003);
+
+        EJBQLQuery check = new EJBQLQuery("select count(p) from Painting p "
+                + "WHERE p.toArtist <> :artist");
+        check.setParameter("artist", object);
+
+        Object notUpdated = DataObjectUtils.objectForQuery(context, check);
+        assertEquals(new Long(2l), notUpdated);
+
+        String ejbql = "UPDATE Painting AS p SET p.toArtist = :artist";
+        EJBQLQuery query = new EJBQLQuery(ejbql);
+        query.setParameter("artist", object);
+
+        QueryResponse result = context.performGenericQuery(query);
+
+        int[] count = result.firstUpdateCount();
+        assertNotNull(count);
+        assertEquals(1, count.length);
+        assertEquals(2, count[0]);
+
+        notUpdated = DataObjectUtils.objectForQuery(context, check);
+        assertEquals(new Long(0l), notUpdated);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLUpdateTest.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLUpdateTest.xml?view=diff&rev=561927&r1=561926&r2=561927
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLUpdateTest.xml
(original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/access.DataContextEJBQLUpdateTest.xml
Wed Aug  1 12:35:02 2007
@@ -6,17 +6,38 @@
 	<!-- Named Queries -->
 	<!-- ======================================= -->
 	
+	<bean id="A1" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class"><value>org.apache.art.Artist</value></constructor-arg>
+		<constructor-arg><value>
+		insert into ARTIST (ARTIST_ID, ARTIST_NAME) values (33001, 'AA1')
+		</value></constructor-arg>
+	</bean>
+	
+	<bean id="A2" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class"><value>org.apache.art.Artist</value></constructor-arg>
+		<constructor-arg><value>
+		insert into ARTIST (ARTIST_ID, ARTIST_NAME) values (33002, 'AA2')
+		</value></constructor-arg>
+	</bean>
+	
+	<bean id="A3" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class"><value>org.apache.art.Artist</value></constructor-arg>
+		<constructor-arg><value>
+		insert into ARTIST (ARTIST_ID, ARTIST_NAME) values (33003, 'BB1')
+		</value></constructor-arg>
+	</bean>
+	
 	<bean id="P11" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
 		<constructor-arg type="java.lang.Class"><value>org.apache.art.Painting</value></constructor-arg>
 		<constructor-arg><value>
-		INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33001,
'P1', NULL, 3000)
+		INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33001,
'P1', 33001, 3000)
 		</value></constructor-arg>
 	</bean>
 	
 	<bean id="P12" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
 		<constructor-arg type="java.lang.Class"><value>org.apache.art.Painting</value></constructor-arg>
 		<constructor-arg><value>
-		INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33002,
'P2', NULL, 5000)
+		INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) VALUES (33002,
'P2', 33002, 5000)
 		</value></constructor-arg>
 	</bean>
 	
@@ -28,9 +49,14 @@
 	<bean id="prepare" class="java.util.ArrayList">
 		<constructor-arg>
 			<list>
+				<ref bean="A1"/>
+				<ref bean="A2"/>
+				<ref bean="A3"/>
 				<ref bean="P11"/>
 				<ref bean="P12"/>
 			</list>
 		</constructor-arg>
 	</bean>
+	
+	
 </beans>



Mime
View raw message