You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2007/12/27 12:12:03 UTC

svn commit: r607039 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src: main/java/org/apache/cayenne/access/jdbc/ test/java/org/apache/cayenne/access/

Author: aadamchik
Date: Thu Dec 27 03:12:03 2007
New Revision: 607039

URL: http://svn.apache.org/viewvc?rev=607039&view=rev
Log:
CAY-948 Implement flattened attributes in Cayenne
(preliminary refactoring EJBQL translator)

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLFromTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JdbcEJBQLTranslatorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLFromTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLFromTranslator.java?rev=607039&r1=607038&r2=607039&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLFromTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLFromTranslator.java Thu Dec 27 03:12:03 2007
@@ -18,17 +18,10 @@
  ****************************************************************/
 package org.apache.cayenne.access.jdbc;
 
-import java.util.Iterator;
-
 import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
-import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.ejbql.EJBQLExpression;
 import org.apache.cayenne.ejbql.parser.EJBQLFromItem;
 import org.apache.cayenne.ejbql.parser.EJBQLJoin;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.reflect.ClassDescriptor;
 
 /**
  * @since 3.0
@@ -38,20 +31,18 @@
 
     protected EJBQLTranslationContext context;
     private String lastId;
-
-    static String makeJoinTailMarker(String id) {
-        return "FROM_TAIL" + id;
-    }
+    private EJBQLJoinAppender joinAppender;
 
     public EJBQLFromTranslator(EJBQLTranslationContext context) {
         super(true);
         this.context = context;
+        this.joinAppender = context.getTranslatorFactory().getJoinAppender(context);
     }
 
     public boolean visitFrom(EJBQLExpression expression, int finishedChildIndex) {
         if (finishedChildIndex + 1 == expression.getChildrenCount()) {
             if (lastId != null) {
-                context.markCurrentPosition(makeJoinTailMarker(lastId));
+                context.markCurrentPosition(EJBQLJoinAppender.makeJoinTailMarker(lastId));
             }
         }
 
@@ -64,11 +55,11 @@
 
         if (lastId != null) {
             context.append(',');
-            context.markCurrentPosition(makeJoinTailMarker(lastId));
+            context.markCurrentPosition(EJBQLJoinAppender.makeJoinTailMarker(lastId));
         }
 
         this.lastId = id;
-        appendTable(id);
+        joinAppender.appendTable(id);
         return false;
     }
 
@@ -78,7 +69,8 @@
     }
 
     public boolean visitInnerJoin(EJBQLJoin join) {
-        appendJoin(join, "INNER JOIN");
+        joinAppender.appendInnerJoin(null, join.getLeftHandSideId(), join
+                .getRightHandSideId());
         return false;
     }
 
@@ -88,77 +80,8 @@
     }
 
     public boolean visitOuterJoin(EJBQLJoin join) {
-        appendJoin(join, "LEFT OUTER JOIN");
+        joinAppender.appendOuterJoin(null, join.getLeftHandSideId(), join
+                .getRightHandSideId());
         return false;
-    }
-
-    private void appendJoin(EJBQLJoin join, String semantics) {
-
-        String rhsId = join.getRightHandSideId();
-
-        ObjRelationship joinRelationship = context.getIncomingRelationship(rhsId);
-        if (joinRelationship == null) {
-            throw new EJBQLException("No join configured for id " + rhsId);
-        }
-
-        // TODO: andrus, 4/8/2007 - support for flattened relationships
-        DbRelationship incomingDB = joinRelationship.getDbRelationships().get(0);
-
-        String lhsId = join.getLeftHandSideId();
-        String sourceAlias = context.getTableAlias(lhsId, incomingDB
-                .getSourceEntity()
-                .getName());
-
-        context.append(" ").append(semantics);
-        String targetAlias = appendTable(rhsId);
-        context.append(" ON (");
-
-        Iterator<DbJoin> it = incomingDB.getJoins().iterator();
-        if (it.hasNext()) {
-            DbJoin dbJoin = it.next();
-            context
-                    .append(sourceAlias)
-                    .append('.')
-                    .append(dbJoin.getSourceName())
-                    .append(" = ")
-                    .append(targetAlias)
-                    .append('.')
-                    .append(dbJoin.getTargetName());
-        }
-
-        while (it.hasNext()) {
-            context.append(", ");
-            DbJoin dbJoin = it.next();
-            context
-                    .append(sourceAlias)
-                    .append('.')
-                    .append(dbJoin.getSourceName())
-                    .append(" = ")
-                    .append(targetAlias)
-                    .append('.')
-                    .append(dbJoin.getTargetName());
-        }
-
-        context.append(")");
-    }
-
-    protected String appendTable(String id) {
-        ClassDescriptor descriptor = context.getEntityDescriptor(id);
-
-        String tableName = descriptor.getEntity().getDbEntity().getFullyQualifiedName();
-
-        if (context.isUsingAliases()) {
-            String alias = context.getTableAlias(id, tableName);
-
-            // not using "AS" to separate table name and alias name - OpenBase doesn't
-            // support
-            // "AS", and the rest of the databases do not care
-            context.append(' ').append(tableName).append(' ').append(alias);
-            return alias;
-        }
-        else {
-            context.append(' ').append(tableName);
-            return tableName;
-        }
     }
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java?rev=607039&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLJoinAppender.java Thu Dec 27 03:12:03 2007
@@ -0,0 +1,133 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.jdbc;
+
+import java.util.Iterator;
+
+import org.apache.cayenne.ejbql.EJBQLException;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.reflect.ClassDescriptor;
+
+/**
+ * Handles appending joins to the content buffer at a marked position.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class EJBQLJoinAppender {
+
+    protected EJBQLTranslationContext context;
+
+    public EJBQLJoinAppender(EJBQLTranslationContext context) {
+        this.context = context;
+    }
+
+    public void appendInnerJoin(String marker, String lhsId, String rhsId) {
+        appendJoin(marker, lhsId, rhsId, "INNER JOIN");
+    }
+
+    public void appendOuterJoin(String marker, String lhsId, String rhsId) {
+        appendJoin(marker, lhsId, rhsId, "LEFT OUTER JOIN");
+    }
+
+    protected void appendJoin(String marker, String lhsId, String rhsId, String semantics) {
+
+        ObjRelationship joinRelationship = context.getIncomingRelationship(rhsId);
+        if (joinRelationship == null) {
+            throw new EJBQLException("No join configured for id " + rhsId);
+        }
+
+        // TODO: andrus, 4/8/2007 - support for flattened relationships
+        DbRelationship incomingDB = joinRelationship.getDbRelationships().get(0);
+
+        String sourceAlias = context.getTableAlias(lhsId, incomingDB
+                .getSourceEntity()
+                .getName());
+
+        if (marker != null) {
+            context.switchToMarker(marker, false);
+        }
+
+        try {
+
+            context.append(" ").append(semantics);
+            String targetAlias = appendTable(rhsId);
+            context.append(" ON (");
+
+            Iterator<DbJoin> it = incomingDB.getJoins().iterator();
+            if (it.hasNext()) {
+                DbJoin dbJoin = it.next();
+                context
+                        .append(sourceAlias)
+                        .append('.')
+                        .append(dbJoin.getSourceName())
+                        .append(" = ")
+                        .append(targetAlias)
+                        .append('.')
+                        .append(dbJoin.getTargetName());
+            }
+
+            while (it.hasNext()) {
+                context.append(", ");
+                DbJoin dbJoin = it.next();
+                context
+                        .append(sourceAlias)
+                        .append('.')
+                        .append(dbJoin.getSourceName())
+                        .append(" = ")
+                        .append(targetAlias)
+                        .append('.')
+                        .append(dbJoin.getTargetName());
+            }
+
+            context.append(")");
+        }
+        finally {
+            if (marker != null) {
+                context.switchToMainBuffer();
+            }
+        }
+    }
+
+    public String appendTable(String id) {
+        ClassDescriptor descriptor = context.getEntityDescriptor(id);
+
+        String tableName = descriptor.getEntity().getDbEntity().getFullyQualifiedName();
+
+        if (context.isUsingAliases()) {
+            String alias = context.getTableAlias(id, tableName);
+
+            // not using "AS" to separate table name and alias name - OpenBase doesn't
+            // support
+            // "AS", and the rest of the databases do not care
+            context.append(' ').append(tableName).append(' ').append(alias);
+            return alias;
+        }
+        else {
+            context.append(' ').append(tableName);
+            return tableName;
+        }
+    }
+
+    static String makeJoinTailMarker(String id) {
+        return "FROM_TAIL" + id;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java?rev=607039&r1=607038&r2=607039&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLPathTranslator.java Thu Dec 27 03:12:03 2007
@@ -26,13 +26,6 @@
 import org.apache.cayenne.ejbql.EJBQLBaseVisitor;
 import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.ejbql.EJBQLExpression;
-import org.apache.cayenne.ejbql.EJBQLExpressionVisitor;
-import org.apache.cayenne.ejbql.parser.EJBQLIdentificationVariable;
-import org.apache.cayenne.ejbql.parser.EJBQLIdentifier;
-import org.apache.cayenne.ejbql.parser.EJBQLInnerJoin;
-import org.apache.cayenne.ejbql.parser.EJBQLJoin;
-import org.apache.cayenne.ejbql.parser.EJBQLOuterJoin;
-import org.apache.cayenne.ejbql.parser.EJBQLPath;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
@@ -58,7 +51,6 @@
     protected String idPath;
     protected String joinMarker;
     private String fullPath;
-    private EJBQLExpressionVisitor joinAppender;
     private boolean usingAliases;
 
     public EJBQLPathTranslator(EJBQLTranslationContext context) {
@@ -93,7 +85,7 @@
 
         this.currentEntity = descriptor.getEntity();
         this.idPath = expression.getText();
-        this.joinMarker = EJBQLFromTranslator.makeJoinTailMarker(idPath);
+        this.joinMarker = EJBQLJoinAppender.makeJoinTailMarker(idPath);
         this.fullPath = idPath;
         return true;
     }
@@ -110,14 +102,6 @@
         return true;
     }
 
-    private EJBQLExpressionVisitor getJoinAppender() {
-        if (joinAppender == null) {
-            joinAppender = context.getTranslatorFactory().getFromTranslator(context);
-        }
-
-        return joinAppender;
-    }
-
     private void resolveJoin(boolean inner) {
 
         String newPath = idPath + '.' + lastPathComponent;
@@ -131,36 +115,19 @@
                     .getDbEntityName());
         }
         else {
-            // register join
-            EJBQLIdentifier id = new EJBQLIdentifier(-1);
-            id.setText(idPath);
-
-            EJBQLIdentificationVariable idVar = new EJBQLIdentificationVariable(-1);
-            idVar.setText(lastPathComponent);
 
-            EJBQLPath path = new EJBQLPath(-1);
-            path.jjtAddChild(id, 0);
-            path.jjtAddChild(idVar, 1);
-
-            EJBQLIdentifier joinId = new EJBQLIdentifier(-1);
-            joinId.setText(fullPath);
-
-            context.switchToMarker(joinMarker, false);
+            EJBQLJoinAppender joinAppender = context
+                    .getTranslatorFactory()
+                    .getJoinAppender(context);
 
+            // register join
             if (inner) {
-                EJBQLJoin join = new EJBQLInnerJoin(-1);
-                join.jjtAddChild(path, 0);
-                join.jjtAddChild(joinId, 1);
-                getJoinAppender().visitInnerJoin(join);
-
+                joinAppender.appendInnerJoin(joinMarker, idPath, fullPath);
                 this.lastAlias = context.getTableAlias(fullPath, currentEntity
                         .getDbEntityName());
             }
             else {
-                EJBQLJoin join = new EJBQLOuterJoin(-1);
-                join.jjtAddChild(path, 0);
-                join.jjtAddChild(joinId, 1);
-                getJoinAppender().visitOuterJoin(join);
+                joinAppender.appendOuterJoin(joinMarker, idPath, fullPath);
 
                 Relationship lastRelationship = currentEntity
                         .getRelationship(lastPathComponent);
@@ -170,10 +137,7 @@
                         .getDbEntityName());
             }
 
-            context.switchToMainBuffer();
-
             this.idPath = newPath;
-
         }
     }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorFactory.java?rev=607039&r1=607038&r2=607039&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EJBQLTranslatorFactory.java Thu Dec 27 03:12:03 2007
@@ -28,6 +28,8 @@
  * @author Andrus Adamchik
  */
 public interface EJBQLTranslatorFactory {
+    
+    EJBQLJoinAppender getJoinAppender(EJBQLTranslationContext context);
 
     EJBQLExpressionVisitor getSelectTranslator(EJBQLTranslationContext context);
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JdbcEJBQLTranslatorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JdbcEJBQLTranslatorFactory.java?rev=607039&r1=607038&r2=607039&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JdbcEJBQLTranslatorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JdbcEJBQLTranslatorFactory.java Thu Dec 27 03:12:03 2007
@@ -28,6 +28,20 @@
  */
 public class JdbcEJBQLTranslatorFactory implements EJBQLTranslatorFactory {
 
+    protected static final String JOIN_APPENDER_KEY = "$JoinAppender";
+
+    public EJBQLJoinAppender getJoinAppender(EJBQLTranslationContext context) {
+        EJBQLJoinAppender appender = (EJBQLJoinAppender) context
+                .getAttribute(JOIN_APPENDER_KEY);
+
+        if (appender == null) {
+            appender = new EJBQLJoinAppender(context);
+            context.setAttribute(JOIN_APPENDER_KEY, appender);
+        }
+
+        return appender;
+    }
+
     public EJBQLExpressionVisitor getDeleteTranslator(EJBQLTranslationContext context) {
         context.setUsingAliases(false);
         return new EJBQLDeleteTranslator(context);

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java?rev=607039&r1=607038&r2=607039&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesTest.java Thu Dec 27 03:12:03 2007
@@ -179,6 +179,41 @@
                     painting.getGalleryName());
         }
     }
+    
+    public void testSelectEJQBQL() throws Exception {
+//        populateTables();
+//        EJBQLQuery query = new EJBQLQuery("SELECT a FROM CompoundPainting a WHERE a.artistName = 'artist2'");
+//        List<?> objects = context.performQuery(query);
+//
+//        assertNotNull(objects);
+//        assertEquals(1, objects.size());
+//        assertTrue("CompoundPainting expected, got " + objects.get(0).getClass(), objects
+//                .get(0) instanceof CompoundPainting);
+//
+//        for (Iterator<?> i = objects.iterator(); i.hasNext();) {
+//            CompoundPainting painting = (CompoundPainting) i.next();
+//            Number id = (Number) painting
+//                    .getObjectId()
+//                    .getIdSnapshot()
+//                    .get("PAINTING_ID");
+//            assertEquals("CompoundPainting.getObjectId(): " + id, id.intValue(), 2);
+//            assertEquals("CompoundPainting.getPaintingTitle(): "
+//                    + painting.getPaintingTitle(), "painting" + id, painting
+//                    .getPaintingTitle());
+//            assertEquals(
+//                    "CompoundPainting.getTextReview(): " + painting.getTextReview(),
+//                    "painting review" + id,
+//                    painting.getTextReview());
+//            assertEquals(
+//                    "CompoundPainting.getArtistName(): " + painting.getArtistName(),
+//                    "artist2",
+//                    painting.getArtistName());
+//            assertEquals(
+//                    "CompoundPainting.getArtistName(): " + painting.getGalleryName(),
+//                    painting.getToGallery().getGalleryName(),
+//                    painting.getGalleryName());
+//        }
+    }
 
     public void testInsert() {
         CompoundPainting o1 = context.newObject(CompoundPainting.class);