You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by to...@apache.org on 2008/07/03 22:21:41 UTC

svn commit: r673788 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne: access/trans/ dba/openbase/

Author: torehalset
Date: Thu Jul  3 13:21:40 2008
New Revision: 673788

URL: http://svn.apache.org/viewvc?rev=673788&view=rev
Log:
1. CAY-1084: openbase does not like our join syntax
   * implemented openbase join syntax
2. Merge support for openbase

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java?rev=673788&r1=673787&r2=673788&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java Thu Jul  3 13:21:40 2008
@@ -34,14 +34,14 @@
  * @since 3.0
  * @author Andrus Adamchik
  */
-class JoinStack {
+public class JoinStack {
 
-    private JoinTreeNode rootNode;
-    private JoinTreeNode topNode;
+    protected JoinTreeNode rootNode;
+    protected JoinTreeNode topNode;
 
     private int aliasCounter;
-
-    JoinStack() {
+    
+    protected JoinStack() {
         this.rootNode = new JoinTreeNode(this);
         this.rootNode.setTargetTableAlias(newAlias());
         resetStack();
@@ -54,7 +54,7 @@
     /**
      * Returns the number of configured joins.
      */
-    int size() {
+    protected int size() {
         // do not count root as a join
         return rootNode.size() - 1;
     }
@@ -67,7 +67,7 @@
     /**
      * Appends all configured joins to the provided output object.
      */
-    void appendJoins(Appendable out) throws IOException {
+    protected void appendJoins(Appendable out) throws IOException {
 
         // skip root, recursively append its children
         for (JoinTreeNode child : rootNode.getChildren()) {
@@ -75,7 +75,7 @@
         }
     }
 
-    private void appendJoinSubtree(Appendable out, JoinTreeNode node) throws IOException {
+    protected void appendJoinSubtree(Appendable out, JoinTreeNode node) throws IOException {
 
         DbRelationship relationship = node.getRelationship();
 
@@ -123,6 +123,14 @@
             appendJoinSubtree(out, child);
         }
     }
+    
+    /**
+     * Append join information to the qualifier - the part after "WHERE".
+     */
+    protected void appendQualifier(Appendable out, boolean firstQualifyerElement)
+            throws IOException {
+        // nothing as standard join is performed before "WHERE"
+    }
 
     /**
      * Pops the stack all the way to the root node.

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java?rev=673788&r1=673787&r2=673788&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java Thu Jul  3 13:21:40 2008
@@ -30,7 +30,7 @@
  * @since 3.0
  * @author Andrus Adamchik
  */
-final class JoinTreeNode {
+public final class JoinTreeNode {
 
     private String targetTableAlias;
     private String sourceTableAlias;
@@ -64,7 +64,7 @@
         return i;
     }
 
-    Collection<JoinTreeNode> getChildren() {
+    public Collection<JoinTreeNode> getChildren() {
         return children != null ? children : Collections.<JoinTreeNode> emptyList();
     }
 
@@ -102,7 +102,7 @@
                 && Util.nullSafeEquals(this.alias, alias);
     }
 
-    String getTargetTableAlias() {
+    public String getTargetTableAlias() {
         return targetTableAlias;
     }
 
@@ -110,7 +110,7 @@
         this.targetTableAlias = targetTableAlias;
     }
 
-    String getSourceTableAlias() {
+    public String getSourceTableAlias() {
         return sourceTableAlias;
     }
 
@@ -118,7 +118,7 @@
         this.sourceTableAlias = sourceTableAlias;
     }
 
-    DbRelationship getRelationship() {
+    public DbRelationship getRelationship() {
         return relationship;
     }
 
@@ -126,7 +126,7 @@
         return alias;
     }
 
-    JoinType getJoinType() {
+    public JoinType getJoinType() {
         return joinType;
     }
 }
\ No newline at end of file

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java?rev=673788&r1=673787&r2=673788&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java Thu Jul  3 13:21:40 2008
@@ -76,10 +76,10 @@
         return false;
     }
 
-    JoinStack joinStack = new JoinStack();
+    JoinStack joinStack = createJoinStack();
 
     List<ColumnDescriptor> resultColumns;
-    Map attributeOverrides;
+    Map<ObjAttribute, ColumnDescriptor> attributeOverrides;
     Map<ColumnDescriptor, ObjAttribute> defaultAttributesByColumn;
 
     boolean suppressingDistinct;
@@ -90,7 +90,11 @@
      * created using "to-many" relationships.
      */
     boolean forcingDistinct;
-
+    
+    protected JoinStack createJoinStack() {
+        return new JoinStack();
+    }
+    
     /**
      * Returns query translated to SQL. This is a main work method of the
      * SelectTranslator.
@@ -166,6 +170,7 @@
         // append tables and joins
         joinStack.appendRoot(queryBuf, getRootDbEntity());
         joinStack.appendJoins(queryBuf);
+        joinStack.appendQualifier(qualifierBuffer, qualifierBuffer.length() == 0);
 
         // append qualifier
         if (qualifierBuffer.length() > 0) {
@@ -206,8 +211,13 @@
      * 
      * @since 1.2
      */
-    public Map getAttributeOverrides() {
-        return attributeOverrides != null ? attributeOverrides : Collections.EMPTY_MAP;
+    public Map<ObjAttribute, ColumnDescriptor> getAttributeOverrides() {
+        if (attributeOverrides != null) {
+            return attributeOverrides;
+        }
+        else {
+            return Collections.emptyMap();
+        }
     }
 
     /**
@@ -559,7 +569,7 @@
 
                     if (original != null) {
                         if (attributeOverrides == null) {
-                            attributeOverrides = new HashMap();
+                            attributeOverrides = new HashMap<ObjAttribute, ColumnDescriptor>();
                         }
 
                         attributeOverrides.put(original, column);

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java?rev=673788&r1=673787&r2=673788&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java Thu Jul  3 13:21:40 2008
@@ -38,6 +38,7 @@
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.merge.MergerFactory;
 import org.apache.cayenne.query.Query;
 import org.apache.cayenne.query.SQLAction;
 
@@ -46,11 +47,11 @@
  * Sample connection settings to use with OpenBase are shown below:
  * 
 <pre>
-test-openbase.cayenne.adapter = org.apache.cayenne.dba.openbase.OpenBaseAdapter
-test-openbase.jdbc.username = test
-test-openbase.jdbc.password = secret
-test-openbase.jdbc.url = jdbc:openbase://serverhostname/cayenne
-test-openbase.jdbc.driver = com.openbase.jdbc.ObDriver
+openbase.cayenne.adapter = org.apache.cayenne.dba.openbase.OpenBaseAdapter
+openbase.jdbc.username = test
+openbase.jdbc.password = secret
+openbase.jdbc.url = jdbc:openbase://serverhostname/cayenne
+openbase.jdbc.driver = com.openbase.jdbc.ObDriver
 </pre>
  * 
  * @author <a href="mailto:mkienenb@alaska.net">Mike Kienenberger</a>
@@ -311,4 +312,10 @@
             }
         }
     }
+    
+    @Override
+    public MergerFactory mergerFactory() {
+        return new OpenBaseMergerFactory();
+    }
+
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java?rev=673788&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java Thu Jul  3 13:21:40 2008
@@ -0,0 +1,115 @@
+/*****************************************************************
+ *   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.dba.openbase;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.cayenne.access.trans.JoinStack;
+import org.apache.cayenne.access.trans.JoinTreeNode;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+
+/**
+ * OpenBase does not support standard JOIN keyword and have strange syntax for defining
+ * inner/outer joins
+ * 
+ * @see http://www.openbase.com/help/KnowledgeBase/400_OpenBaseSQL/401_SelectStatements.html
+ */
+public class OpenBaseJoinStack extends JoinStack {
+
+    public OpenBaseJoinStack() {
+        super();
+    }
+
+    @Override
+    protected void appendJoinSubtree(Appendable out, JoinTreeNode node)
+            throws IOException {
+        DbRelationship relationship = node.getRelationship();
+
+        if (relationship == null) {
+            return;
+        }
+
+        DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
+        String targetAlias = node.getTargetTableAlias();
+
+        out.append(", ").append(targetEntity.getFullyQualifiedName()).append(' ').append(
+                targetAlias);
+
+        for (JoinTreeNode child : node.getChildren()) {
+            appendJoinSubtree(out, child);
+        }
+    }
+
+    @Override
+    protected void appendQualifier(Appendable out, boolean firstQualifyerElement) throws IOException {
+        boolean first = firstQualifyerElement;
+        for (JoinTreeNode node : rootNode.getChildren()) {
+            if (!first) {
+                out.append(" AND ");
+            }
+            appendQualifierSubtree(out, node);
+            first = false;
+        }
+    }
+
+    protected void appendQualifierSubtree(Appendable out, JoinTreeNode node)
+            throws IOException {
+        DbRelationship relationship = node.getRelationship();
+
+        String srcAlias = node.getSourceTableAlias();
+        String targetAlias = node.getTargetTableAlias();
+
+        List<DbJoin> joins = relationship.getJoins();
+        int len = joins.size();
+        for (int i = 0; i < len; i++) {
+            DbJoin join = joins.get(i);
+
+            if (i > 0) {
+                out.append(" AND ");
+            }
+
+            out.append(srcAlias).append('.').append(join.getSourceName());
+
+            switch (node.getJoinType()) {
+                case INNER:
+                    out.append(" = ");
+                    break;
+                case LEFT_OUTER:
+                    out.append(" * ");
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unsupported join type: "
+                            + node.getJoinType());
+            }
+            
+            out.append(targetAlias).append('.').append(join.getTargetName());
+
+        }
+
+        for (JoinTreeNode child : node.getChildren()) {
+            out.append(" AND ");
+            appendQualifierSubtree(out, child);
+        }
+
+    }
+
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java?rev=673788&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java Thu Jul  3 13:21:40 2008
@@ -0,0 +1,171 @@
+/*****************************************************************
+ *   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.dba.openbase;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.merge.CreateTableToDb;
+import org.apache.cayenne.merge.DropRelationshipToDb;
+import org.apache.cayenne.merge.MergerFactory;
+import org.apache.cayenne.merge.MergerToken;
+import org.apache.cayenne.merge.SetAllowNullToDb;
+import org.apache.cayenne.merge.SetColumnTypeToDb;
+import org.apache.cayenne.merge.SetNotNullToDb;
+
+public class OpenBaseMergerFactory extends MergerFactory {
+
+    @Override
+    public MergerToken createCreateTableToDb(DbEntity entity) {
+        return new CreateTableToDb(entity) {
+
+            @Override
+            public List<String> createSql(DbAdapter adapter) {
+                List<String> sqls = new ArrayList<String>();
+                // create table first as OpenBase adapter created primary key in its
+                // getPkGenerator().createAutoPkStatements
+                sqls.add(adapter.createTable(getEntity()));
+                sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
+                        Collections.singletonList(getEntity())));
+                return sqls;
+            }
+
+        };
+    }
+
+    @Override
+    public MergerToken createDropRelationshipToDb(
+            final DbEntity entity,
+            final DbRelationship rel) {
+        return new DropRelationshipToDb(entity, rel) {
+
+            @Override
+            public List<String> createSql(DbAdapter adapter) {
+
+                StringBuilder buf = new StringBuilder();
+
+                buf.append("delete from _SYS_RELATIONSHIP where ");
+
+                // FK_NAME form jdbc metadata seem to be wrong. It contain a column name
+                // and not the 'relationshipName'
+                // TODO: tell openbase developer mail list
+
+                DbEntity source = getEntity();
+                DbEntity dest = (DbEntity) rel.getTargetEntity();
+
+                // only use the first. See adapter
+                // TODO: can we be sure this is the first and same as used by the adapter?
+                DbJoin join = rel.getJoins().get(0);
+
+                // see comment in adapter for why source and dest is switched around..
+
+                buf.append(" source_table = '");
+                buf.append(dest.getFullyQualifiedName());
+                buf.append("'");
+
+                buf.append(" and source_column = '");
+                buf.append(join.getTargetName());
+                buf.append("'");
+
+                buf.append(" and dest_table = '");
+                buf.append(source.getFullyQualifiedName());
+                buf.append("'");
+
+                buf.append(" and dest_column = '");
+                buf.append(join.getSourceName());
+                buf.append("'");
+
+                return Collections.singletonList(buf.toString());
+            }
+
+        };
+    }
+
+    @Override
+    public MergerToken createSetColumnTypeToDb(
+            final DbEntity entity,
+            final DbAttribute columnOriginal,
+            final DbAttribute columnNew) {
+        return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+            @Override
+            public List<String> createSql(DbAdapter adapter) {
+                List<String> sqls = new ArrayList<String>();
+
+                if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
+                    sqls.add("ALTER TABLE "
+                            + entity.getFullyQualifiedName()
+                            + " COLUMN "
+                            + columnNew.getName()
+                            + " SET LENGTH "
+                            + columnNew.getMaxLength());
+                }
+
+                return sqls;
+            }
+
+        };
+    }
+
+    @Override
+    public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+        return new SetNotNullToDb(entity, column) {
+
+            @Override
+            public List<String> createSql(DbAdapter adapter) {
+                StringBuilder sqlBuffer = new StringBuilder();
+
+                sqlBuffer.append("ALTER TABLE ");
+                sqlBuffer.append(getEntity().getFullyQualifiedName());
+                sqlBuffer.append(" COLUMN ");
+                sqlBuffer.append(getColumn().getName());
+                sqlBuffer.append(" SET NOT NULL");
+
+                return Collections.singletonList(sqlBuffer.toString());
+            }
+
+        };
+    }
+
+    @Override
+    public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+        return new SetAllowNullToDb(entity, column) {
+
+            @Override
+            public List<String> createSql(DbAdapter adapter) {
+                StringBuilder sqlBuffer = new StringBuilder();
+
+                sqlBuffer.append("ALTER TABLE ");
+                sqlBuffer.append(getEntity().getFullyQualifiedName());
+                sqlBuffer.append(" COLUMN ");
+                sqlBuffer.append(getColumn().getName());
+                sqlBuffer.append(" SET NULL");
+
+                return Collections.singletonList(sqlBuffer.toString());
+            }
+
+        };
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java?rev=673788&r1=673787&r2=673788&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java Thu Jul  3 13:21:40 2008
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.dba.openbase;
 
+import org.apache.cayenne.access.trans.JoinStack;
 import org.apache.cayenne.access.trans.SelectTranslator;
 
 /**
@@ -28,6 +29,11 @@
 class OpenBaseSelectTranslator extends SelectTranslator {
 
     @Override
+    protected JoinStack createJoinStack() {
+        return new OpenBaseJoinStack();
+    }
+    
+    @Override
     public String createSqlString() throws Exception {
         String sql = super.createSqlString();