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 2015/01/17 09:05:43 UTC

[1/4] cayenne git commit: fix relationships loading

Repository: cayenne
Updated Branches:
  refs/heads/master 44642ea58 -> c8ff4355f


fix relationships loading


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

Branch: refs/heads/master
Commit: aaafe117143e256a7b48692485b22c9d10538477
Parents: 44642ea
Author: alexkolonitsky <Al...@gmail.com>
Authored: Thu Jan 8 20:49:26 2015 +0300
Committer: alexkolonitsky <Al...@gmail.com>
Committed: Thu Jan 8 20:49:26 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/access/DbLoader.java     |  69 ++++-----
 .../access/loader/LoggingDbLoaderDelegate.java  |  20 +--
 .../org/apache/cayenne/map/DbRelationship.java  |  40 ++++--
 .../org/apache/cayenne/map/Relationship.java    |   6 +-
 .../apache/cayenne/map/naming/ExportedKey.java  |  18 ++-
 .../merge/DropRelationshipToModelIT.java        |   7 +-
 .../apache/cayenne/merge/MergerFactoryIT.java   |  13 +-
 cayenne-tools/pom.xml                           |   5 +
 .../cayenne/tools/CayenneGeneratorTask.java     |  11 +-
 .../cayenne/tools/dbimport/DbImportAction.java  |  30 ++--
 .../dbimport/DbImportDbLoaderDelegate.java      |   1 -
 .../src/main/resources/reverseEngineering.xsd   | 139 +++++++++++++++++++
 .../cayenne/tools/DbImporterMojoTest.java       |   4 +
 .../cayenne/tools/dbimport/testOneToOne-pom.xml |  39 ++++++
 .../tools/dbimport/testOneToOne.map.xml-result  |  58 ++++++++
 .../cayenne/tools/dbimport/testOneToOne.sql     |  24 ++++
 16 files changed, 400 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
index 864e4f0..f86692f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
@@ -49,14 +49,12 @@ import org.apache.commons.logging.LogFactory;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -325,9 +323,8 @@ public class DbLoader {
 
             loadDbAttributes(config.getFiltersConfig(), tablesMap.getKey(), tablesMap.getValue());
 
-            if (!config.isSkipPrimaryKeyLoading()) {
-                getPrimaryKeyForTable(tablesMap.getValue());
-            }
+            // get primary keys for each table and store it in dbEntity
+            getPrimaryKeyForTable(tablesMap.getValue());
         }
 
         return dbEntityList;
@@ -366,8 +363,6 @@ public class DbLoader {
         ResultSet rs = getMetaData().getColumns(path.catalog, path.schema, WILDCARD, WILDCARD);
 
         try {
-            Set<String> columns = new HashSet<String>();
-
             while (rs.next()) {
                 // for a reason not quiet apparent to me, Oracle sometimes
                 // returns duplicate record sets for the same table, messing up table
@@ -382,7 +377,7 @@ public class DbLoader {
                     continue;
                 }
 
-                DbAttribute attr = loadDbAttribute(columns, rs);
+                DbAttribute attr = loadDbAttribute(rs);
                 attr.setEntity(dbEntity);
                 Filter<DbAttribute> filter = filters.filter(new DbPath(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName())).columnFilter();
                 if (!filter.isInclude(attr)) {
@@ -404,14 +399,7 @@ public class DbLoader {
         }
     }
 
-    private DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException {
-        if (columns.isEmpty()) {
-            ResultSetMetaData rsMetaData = rs.getMetaData();
-            for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
-                columns.add(rsMetaData.getColumnLabel(i));
-            }
-        }
-
+    private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException {
         // gets attribute's (column's) information
         int columnType = rs.getInt("DATA_TYPE");
 
@@ -433,7 +421,11 @@ public class DbLoader {
                 decimalDigits,
                 rs.getBoolean("NULLABLE"));
 
-        if (columns.contains("IS_AUTOINCREMENT")) {
+        if (adapter.supportsGeneratedKeys()) {
+
+            // TODO: this actually throws on some drivers... need to
+            // ensure that 'supportsGeneratedKeys' check is enough
+            // to prevent an exception here.
             String autoIncrement = rs.getString("IS_AUTOINCREMENT");
             if ("YES".equals(autoIncrement)) {
                 attr.setGenerated(true);
@@ -443,7 +435,8 @@ public class DbLoader {
     }
 
     /**
-     * Creates an ObjEntity for each DbEntity in the map.
+     * Creates an ObjEntity for each DbEntity in the map. ObjEntities are
+     * created empty without
      */
     protected Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config, Collection<DbEntity> entities) {
         if (entities.isEmpty()) {
@@ -518,28 +511,29 @@ public class DbLoader {
                     continue;
                 }
 
+                // forwardRelationship is a reference from table with primary key
                 DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true));
                 forwardRelationship.setSourceEntity(pkEntity);
                 forwardRelationship.setTargetEntity(fkEntity);
 
+                // forwardRelationship is a reference from table with foreign key, it is what exactly we load from db
                 DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
                 reverseRelationship.setFkName(key.getFKName());
                 reverseRelationship.setSourceEntity(fkEntity);
                 reverseRelationship.setTargetEntity(pkEntity);
                 reverseRelationship.setToMany(false);
-                if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
-                    fkEntity.addRelationship(reverseRelationship);
-                }
 
-                boolean toPK = createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);
+                createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);
 
-                forwardRelationship.setToDependentPK(toPK);
-
-                boolean isOneToOne = toPK && fkEntity.getPrimaryKeys().size()
-                        == forwardRelationship.getJoins().size();
+                boolean isOneToOne = isOneToOne(fkEntity, forwardRelationship);
 
+                forwardRelationship.setToDependentPK(isOneToOne);
                 forwardRelationship.setToMany(!isOneToOne);
                 forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
+
+                if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
+                    fkEntity.addRelationship(reverseRelationship);
+                }
                 if (delegate.dbRelationshipLoaded(pkEntity, forwardRelationship)) {
                     pkEntity.addRelationship(forwardRelationship);
                 }
@@ -547,8 +541,21 @@ public class DbLoader {
         }
     }
 
-    private boolean createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
-        boolean toPK = true;
+    private boolean isOneToOne(DbEntity fkEntity, DbRelationship forwardRelationship) {
+        if (fkEntity.getPrimaryKeys().size() != forwardRelationship.getJoins().size()) {
+            return false;
+        }
+
+        for (DbJoin dbJoin : forwardRelationship.getJoins()) {
+            if (!dbJoin.getTarget().isPrimaryKey()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
         for (ExportedKey exportedKey : exportedKeys) {
             // Create and append joins
             String pkName = exportedKey.getPKColumnName();
@@ -569,12 +576,7 @@ public class DbLoader {
 
             forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
             reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
-
-            if (!pkAtt.isPrimaryKey()) {
-                toPK = false;
-            }
         }
-        return toPK;
     }
 
     private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration config, DbPath dbPath, Map<String, DbEntity> tables) throws SQLException {
@@ -760,6 +762,7 @@ public class DbLoader {
      * @since 4.0
      */
     public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+        LOGGER.info("Schema loading...");
 
         Map<DbPath, Map<String, DbEntity>> tables = getTables(config, config.getTableTypes());
         List<DbEntity> entities = loadDbEntities(dataMap, config, tables);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
index d5e69f4..8c77a87 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
@@ -36,37 +36,41 @@ public class LoggingDbLoaderDelegate extends DefaultDbLoaderDelegate {
 
     @Override
     public void dbEntityAdded(DbEntity entity) {
-        logger.info("Add dbEntity: " + entity.getFullyQualifiedName());
+        logger.info("  Table: " + entity.getFullyQualifiedName());
     }
 
     @Override
     public void dbEntityRemoved(DbEntity entity) {
-        logger.info("Del dbEntity: " + entity.getFullyQualifiedName());
+        logger.info("  Table removed: " + entity.getFullyQualifiedName());
     }
 
     @Override
     public boolean dbRelationship(DbEntity entity) {
-        logger.info("    Relationships for " + entity.getFullyQualifiedName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("    Relationships for " + entity.getFullyQualifiedName());
+        }
 
         return true;
     }
 
     @Override
     public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
-        if (logger.isDebugEnabled()) {
-            logger.debug("    Relationship : " + entity.getName() + "; " + relationship.toString());
-        }
+        logger.info("    " + relationship);
 
         return true;
     }
 
     @Override
     public void objEntityAdded(ObjEntity entity) {
-        logger.info("Add objEntity: " + entity.getName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("  Class: " + entity.getName());
+        }
     }
 
     @Override
     public void objEntityRemoved(ObjEntity entity) {
-        logger.info("Del objEntity: " + entity.getName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("  Class removed: " + entity.getName());
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
index 5234ff4..12bfbf9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
@@ -33,6 +33,7 @@ import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Transformer;
+import org.apache.commons.lang.StringUtils;
 
 /**
  * A DbRelationship is a descriptor of a database inter-table relationship based
@@ -40,17 +41,18 @@ import org.apache.commons.collections.Transformer;
  */
 public class DbRelationship extends Relationship implements ConfigurationNode {
 
-    // The columns through which the join is implemented.
+    /**
+     * The columns through which the join is implemented.
+     */
     protected List<DbJoin> joins = new ArrayList<DbJoin>(2);
 
-    // Is relationship from source to target points to dependent primary
-    // key (primary key column of destination table that is also a FK to the
-    // source
-    // column)
+    /**
+     * Is relationship from source to target points to dependent primary key (primary key column of destination table
+     * that is also a FK to the source column)
+     */
     protected boolean toDependentPK;
 
     public DbRelationship() {
-        super();
     }
 
     public DbRelationship(String name) {
@@ -122,7 +124,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
      */
     public Collection<DbAttribute> getTargetAttributes() {
         if (joins.size() == 0) {
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
 
         return CollectionUtils.collect(joins, JoinTransformers.targetExtractor);
@@ -135,7 +137,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
      */
     public Collection<DbAttribute> getSourceAttributes() {
         if (joins.size() == 0) {
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
 
         return CollectionUtils.collect(joins, JoinTransformers.sourceExtractor);
@@ -148,7 +150,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
      * @since 1.0.5
      */
     public DbRelationship createReverseRelationship() {
-        DbEntity targetEntity = (DbEntity) getTargetEntity();
+        DbEntity targetEntity = getTargetEntity();
 
         DbRelationship reverse = new DbRelationship();
         reverse.setSourceEntity(targetEntity);
@@ -535,4 +537,24 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
                     && Util.nullSafeEquals(j.targetName, this.targetName);
         }
     }
+
+    @Override
+    public String toString() {
+        String res = "Db Relationship : " + (toMany ? "toMany" : "toOne ");
+
+        String sourceEntityName = getSourceEntityName();
+        String targetEntityName = getTargetEntityName();
+        for (DbJoin join : joins) {
+            res += " (" + sourceEntityName + "." + join.getSourceName() + ", " + targetEntityName + "." + join.getTargetName() + ")";
+        }
+
+        return res;
+    }
+
+    public String getSourceEntityName() {
+        if (this.sourceEntity == null) {
+            return null;
+        }
+        return this.sourceEntity.name;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
index 1c34172..ecc0f80 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
@@ -159,9 +159,9 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
      */
     @Override
     public String toString() {
-        return new ToStringBuilder(this).append("name", getName()).append(
-                "toMany",
-                isToMany()).toString();
+        return new ToStringBuilder(this)
+                .append("name", getName())
+                .append("toMany", isToMany()).toString();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
index 42697fe..ab8229f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
@@ -28,6 +28,19 @@ import java.sql.SQLException;
 /**
  * ExportedKey is an representation of relationship between two tables 
  * in database. It can be used for creating names for relationships
+ *
+ * Example:
+ *  Table A with primary key ID
+ *  Table B with primary key ID and foreign key A_ID
+ *
+ *  In that case ExportedKey will be:
+ *      pkTable:  A
+ *      pkColumn: A.ID
+ *      fkTable:  B
+ *      fkColumn: B.A_ID
+ *      fkName:   name of foreign key
+ *      pkName:
+ *      keySeq: TODO
  * 
  */
 public class ExportedKey implements Comparable {
@@ -200,11 +213,10 @@ public class ExportedKey implements Comparable {
 
     @Override
     public String toString() {
-        return getStrKey() + " # " + keySeq
-                + "(" + pkColumn + " <- " + fkColumn + ")";
+        return getStrKey() + " # " + keySeq;
     }
 
     public String getStrKey() {
-        return pkTable + "." + pkName + " <- " + fkTable + "." + fkName;
+        return pkTable + "." + pkColumn + " <- " + fkTable + "." + fkColumn;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
index e235109..3505971 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
@@ -130,7 +130,12 @@ public class DropRelationshipToModelIT extends MergeCase {
         dbEntity1.removeRelationship(rel1To2.getName());
         dbEntity2.removeAttribute(e2col2.getName());
         List<MergerToken> tokens = createMergeTokens();
-        assertTokens(tokens, 3, 0);
+        /**
+         * Add Relationship NEW_TABLE->NEW_TABLE2 To Model
+         * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
+         * Drop Column NEW_TABLE2.FK To DB
+         * */
+        assertTokens(tokens, 2, 1);
         for (MergerToken token : tokens) {
             if (token.getDirection().isToDb()) {
                 execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
index 409f1c9..e1db050 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
@@ -219,8 +219,11 @@ public class MergerFactoryIT extends MergeCase {
         dbEntity.removeRelationship(r1.getName());
         artistDbEntity.removeRelationship(r2.getName());
         resolver.refreshMappingCache();
-        assertTokensAndExecute(2, 0);
-//        assertTokensAndExecute(1, 1);
+        /*
+         * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST"
+r2 =     * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
+         * */
+        assertTokensAndExecute(1, 1);
         assertTokensAndExecute(0, 0);
 
         // clear up
@@ -277,7 +280,11 @@ public class MergerFactoryIT extends MergeCase {
         dbEntity.removeRelationship(r1.getName());
         artistDbEntity.removeRelationship(r2.getName());
         resolver.refreshMappingCache();
-        assertTokensAndExecute(2, 0);
+        /*
+        * Add Relationship ARTIST->NEW_TABLE To Model
+        * Drop Relationship NEW_TABLE->ARTIST To DB
+        * */
+        assertTokensAndExecute(1, 1);
         assertTokensAndExecute(0, 0);
 
         // clear up

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml
index a97dd13..630c92d 100644
--- a/cayenne-tools/pom.xml
+++ b/cayenne-tools/pom.xml
@@ -165,6 +165,11 @@
             <plugin>
                 <artifactId>maven-pmd-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>xsddoc</groupId>
+                <artifactId>maven-xsddoc-plugin</artifactId>
+                <version>1.0</version>
+            </plugin>
         </plugins>
 	</build>
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index dcd36e6..26ae00d 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -73,16 +73,9 @@ public class CayenneGeneratorTask extends CayenneTask {
     }
 
     protected ClassGenerationAction createGeneratorAction() {
-        ClassGenerationAction action;
-        if (client) {
-            action = new ClientClassGenerationAction();
-            action.setContext(getVppContext());
-        }
-        else {
-            action = new ClassGenerationAction();
-            action.setContext(getVppContext());
-        }
+        ClassGenerationAction action = client ? new ClientClassGenerationAction() : new ClassGenerationAction();
 
+        action.setContext(getVppContext());
         action.setDestDir(destDir);
         action.setEncoding(encoding);
         action.setMakePairs(makepairs);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
index bf981ee..3ff9278 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
@@ -110,7 +110,8 @@ public class DbImportAction {
             List<MergerToken> mergeTokens = new DbMerger(mergerFactory)
                     .createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig());
             if (mergeTokens.isEmpty()) {
-                logger.info("No changes to import.");
+                logger.info("");
+                logger.info("Detected changes: No changes to import.");
                 return;
             }
 
@@ -122,6 +123,7 @@ public class DbImportAction {
     }
 
     private Collection<MergerToken> log(List<MergerToken> tokens) {
+        logger.info("");
         logger.info("Detected changes: ");
         for (MergerToken token : tokens) {
             logger.info(String.format("    %-20s %s", token.getTokenName(), token.getTokenValue()));
@@ -154,7 +156,7 @@ public class DbImportAction {
     /**
      * Performs configured schema operations via DbGenerator.
      */
-    public DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken> tokens) {
+    private DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken> tokens) {
         MergerContext mergerContext = new ExecutingMergerContext(
                 dataMap, null, null, mergeDelegate);
 
@@ -190,18 +192,18 @@ public class DbImportAction {
         projectSaver.save(project);
     }
 
-	private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception {
-		DataMap dataMap = config.createDataMap();
+    private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception {
+        DataMap dataMap = config.createDataMap();
 
-		try {
-			DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate());
-			loader.load(dataMap, config.getDbLoaderConfig());
-		} finally {
-			if (connection != null) {
-				connection.close();
-			}
-		}
+        try {
+            DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate());
+            loader.load(dataMap, config.getDbLoaderConfig());
+        } finally {
+            if (connection != null) {
+                connection.close();
+            }
+        }
 
-		return dataMap;
-	}
+        return dataMap;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
index a97fd03..e3fbc01 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
@@ -19,7 +19,6 @@
 
 package org.apache.cayenne.tools.dbimport;
 
-import org.apache.cayenne.access.DbLoaderDelegate;
 import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/resources/reverseEngineering.xsd
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/resources/reverseEngineering.xsd b/cayenne-tools/src/main/resources/reverseEngineering.xsd
new file mode 100644
index 0000000..6905386
--- /dev/null
+++ b/cayenne-tools/src/main/resources/reverseEngineering.xsd
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:complexType name="PatternParamType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options ot fill pattern information should be used
+                1) &lt;tag>pattarn&lt;tag>
+                2) &lt;tag pattern="pattern" />
+                3) &lt;tag>
+                      &lt;pattern>pattern&lt;/pattern>
+                   &lt;/tag>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element type="xs:string" name="pattern" minOccurs="0"/>
+        </xs:sequence>
+        <xs:attribute type="xs:string" name="pattern" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="IncludeTableType" mixed="true">
+        <xs:complexContent>
+            <xs:extension base="PatternParamType">
+                <xs:sequence>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="includeColumn" type="PatternParamType" />
+                        <xs:element name="excludeColumn" type="PatternParamType" />
+                    </xs:choice>
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="FilterContainerType">
+        <xs:sequence>
+            <xs:choice minOccurs="1" maxOccurs="unbounded">
+                <xs:element name="includeTable" type="IncludeTableType" />
+                <xs:element name="excludeTable" type="PatternParamType" />
+                <xs:element name="includeColumn" type="PatternParamType" />
+                <xs:element name="excludeColumn" type="PatternParamType" />
+                <xs:element name="includeProcedure" type="PatternParamType" />
+                <xs:element name="excludeProcedure" type="PatternParamType" />
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="SchemaType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options to provide schema name can be used:
+                1) &lt;schema>name&lt;schema>
+                2) &lt;schema name="name" />
+                3) &lt;schema>
+                &lt;name>name&lt;/name>
+                &lt;/schema>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" />
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="CatalogType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options to provide schema name can be used:
+                1) &lt;catalog>name&lt;catalog>
+                2) &lt;catalog name="name" />
+                3) &lt;catalog>
+                &lt;name>name&lt;/name>
+                &lt;/catalog>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" />
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="schema" type="SchemaType" />
+                    </xs:choice>
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="ReverseEngineeringType">
+        <xs:annotation>
+            <xs:documentation>
+                <!-- TODO -->
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" />
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="catalog" type="CatalogType" />
+                        <xs:element name="schema" type="SchemaType" />
+                    </xs:choice>
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:element name="reverseEngineering" type="ReverseEngineeringType">
+        <xs:annotation>
+            <!-- TODO -->
+            <xs:documentation> </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
index cf17a84..e7fc592 100644
--- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
+++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
@@ -153,6 +153,10 @@ public class DbImporterMojoTest extends AbstractMojoTestCase {
 		test("testSkipPrimaryKeyLoading");
 	}
 
+	public void testOneToOne() throws Exception {
+		test("testOneToOne");
+	}
+
     /**
      * Q: what happens if a relationship existed over a column that was later deleted? and ‘skipRelLoading’ is true
      * A: it should remove relationship and column

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
new file mode 100644
index 0000000..bee8671
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
new file mode 100644
index 0000000..557423d
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+	<db-entity name="PICK_SCHEDULE" schema="APP">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+		<db-attribute name="OWNER_ID" type="INTEGER" length="10"/>
+		<db-attribute name="SELECTED_PLAYER_ID" type="INTEGER" length="10"/>
+	</db-entity>
+	<db-entity name="PLAYER" schema="APP">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<db-entity name="PLAYER_INFO" schema="APP">
+		<db-attribute name="PLAYER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<obj-entity name="PickSchedule" className="PickSchedule" dbEntityName="PICK_SCHEDULE">
+		<obj-attribute name="ownerId" type="java.lang.Integer" db-attribute-path="OWNER_ID"/>
+	</obj-entity>
+	<obj-entity name="Player" className="Player" dbEntityName="PLAYER">
+	</obj-entity>
+	<obj-entity name="PlayerInfo" className="PlayerInfo" dbEntityName="PLAYER_INFO">
+	</obj-entity>
+	<db-relationship name="toPlayer" source="PICK_SCHEDULE" target="PLAYER" toMany="false">
+		<db-attribute-pair source="SELECTED_PLAYER_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="pickScheduleArray" source="PLAYER" target="PICK_SCHEDULE" toMany="true">
+		<db-attribute-pair source="ID" target="SELECTED_PLAYER_ID"/>
+	</db-relationship>
+	<db-relationship name="toPlayer" source="PLAYER" target="PLAYER_INFO" toDependentPK="true" toMany="false">
+		<db-attribute-pair source="ID" target="PLAYER_ID"/>
+	</db-relationship>
+	<db-relationship name="toPlayer" source="PLAYER_INFO" target="PLAYER" toMany="false">
+		<db-attribute-pair source="PLAYER_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="toPlayer" source="PickSchedule" target="Player" deleteRule="Nullify" db-relationship-path="toPlayer"/>
+	<obj-relationship name="pickScheduleArray" source="Player" target="PickSchedule" deleteRule="Deny" db-relationship-path="pickScheduleArray"/>
+	<obj-relationship name="toPlayer" source="Player" target="PlayerInfo" deleteRule="Nullify" db-relationship-path="toPlayer"/>
+	<obj-relationship name="toPlayer" source="PlayerInfo" target="Player" deleteRule="Nullify" db-relationship-path="toPlayer"/>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
new file mode 100644
index 0000000..a279c65
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
@@ -0,0 +1,24 @@
+CREATE TABLE player (
+  id INTEGER NOT NULL,
+
+  PRIMARY KEY (id)
+);
+
+
+-- one-to-one relationship
+CREATE TABLE player_info (
+  player_id INTEGER NOT NULL,
+
+  PRIMARY KEY (player_id),
+  CONSTRAINT fk_player_info FOREIGN KEY (player_id) REFERENCES player (id)
+);
+
+-- one-to-many relationship
+CREATE TABLE pick_schedule (
+  id INTEGER NOT NULL,
+  owner_id INTEGER,
+  selected_player_id INTEGER,
+  PRIMARY KEY (id),
+
+  CONSTRAINT fk_pick_schedule_player1 FOREIGN KEY (selected_player_id) REFERENCES player (id)
+)


[2/4] cayenne git commit: CAY-1966 SQLTemplate/SQLSelect positional parameter binding

Posted by aa...@apache.org.
CAY-1966 SQLTemplate/SQLSelect positional parameter binding

* incorrect positional params translation from SQLSelect to SQLTemplate


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

Branch: refs/heads/master
Commit: 60f3f154fae265e971eb6c040bb0508ab86fc2a0
Parents: 44642ea
Author: aadamchik <aa...@apache.org>
Authored: Fri Jan 16 09:19:09 2015 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Fri Jan 16 09:19:09 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/query/SQLSelect.java     |  2 +-
 .../org/apache/cayenne/query/SQLSelectIT.java   | 46 +++++++++++++-------
 .../org/apache/cayenne/query/SQLSelectTest.java | 34 +++++++++++++--
 3 files changed, 62 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/60f3f154/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
index ebd5d58..754c4b6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLSelect.java
@@ -243,7 +243,7 @@ public class SQLSelect<T> extends IndirectQuery implements Select<T> {
 		template.setCacheStrategy(cacheStrategy);
 
 		if (positionalParams != null) {
-			template.setParamsArray(positionalParams);
+			template.setParamsList(positionalParams);
 		} else {
 			template.setParams(params);
 		}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/60f3f154/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
index b16c846..c17f153 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectIT.java
@@ -55,7 +55,7 @@ public class SQLSelectIT extends ServerCase {
 		}
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_DataMapNameRoot() throws Exception {
 
 		createArtistsDataSet();
@@ -68,7 +68,7 @@ public class SQLSelectIT extends ServerCase {
 		assertTrue(result.get(0) instanceof DataRow);
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_DefaultRoot() throws Exception {
 
 		createArtistsDataSet();
@@ -81,7 +81,7 @@ public class SQLSelectIT extends ServerCase {
 		assertTrue(result.get(0) instanceof DataRow);
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_ClassRoot() throws Exception {
 
 		createArtistsDataSet();
@@ -93,7 +93,7 @@ public class SQLSelectIT extends ServerCase {
 		assertTrue(result.get(0) instanceof Artist);
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_ClassRoot_Parameters() throws Exception {
 
 		createArtistsDataSet();
@@ -106,7 +106,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals("artist3", a.getArtistName());
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_ClassRoot_Bind() throws Exception {
 
 		createArtistsDataSet();
@@ -119,7 +119,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(2, result.size());
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_ColumnNameCaps() throws Exception {
 
 		SQLSelect<DataRow> q1 = SQLSelect.dataRowQuery("SELECT * FROM ARTIST WHERE ARTIST_NAME = 'artist2'");
@@ -133,7 +133,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(CapsStrategy.LOWER, r2.getColumnNamesCapitalization());
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_FetchLimit() throws Exception {
 
 		createArtistsDataSet();
@@ -144,7 +144,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(5, context.select(q1).size());
 	}
 
-    @Test
+	@Test
 	public void test_DataRows_FetchOffset() throws Exception {
 
 		createArtistsDataSet();
@@ -155,7 +155,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(16, context.select(q1).size());
 	}
 
-    @Test
+	@Test
 	public void test_Append() throws Exception {
 
 		createArtistsDataSet();
@@ -167,7 +167,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(1, result.size());
 	}
 
-    @Test
+	@Test
 	public void test_Select() throws Exception {
 
 		createArtistsDataSet();
@@ -178,7 +178,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(1, result.size());
 	}
 
-    @Test
+	@Test
 	public void test_SelectOne() throws Exception {
 
 		createArtistsDataSet();
@@ -189,7 +189,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals("artist3", a.getArtistName());
 	}
 
-    @Test
+	@Test
 	public void test_SelectLong() throws Exception {
 
 		createArtistsDataSet();
@@ -200,7 +200,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(3l, id);
 	}
 
-    @Test
+	@Test
 	public void test_SelectLongArray() throws Exception {
 
 		createArtistsDataSet();
@@ -212,7 +212,7 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(2l, ids.get(1).longValue());
 	}
 
-    @Test
+	@Test
 	public void test_SelectCount() throws Exception {
 
 		createArtistsDataSet();
@@ -222,8 +222,8 @@ public class SQLSelectIT extends ServerCase {
 		assertEquals(20, c);
 	}
 
-    @Test
-	public void testSQLTemplate_PositionalParams() throws Exception {
+	@Test
+	public void test_ParamsArray_Single() throws Exception {
 
 		createArtistsDataSet();
 
@@ -232,4 +232,18 @@ public class SQLSelectIT extends ServerCase {
 
 		assertEquals(3l, id.longValue());
 	}
+
+	@Test
+	public void test_ParamsArray_Multiple() throws Exception {
+
+		createArtistsDataSet();
+
+		List<Long> ids = SQLSelect
+				.scalarQuery(Long.class,
+						"SELECT ARTIST_ID FROM ARTIST WHERE ARTIST_NAME = #bind($a) OR ARTIST_NAME = #bind($b) ORDER BY ARTIST_ID")
+				.paramsArray("artist3", "artist2").select(context);
+
+		assertEquals(2l, ids.get(0).longValue());
+		assertEquals(3l, ids.get(1).longValue());
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/60f3f154/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
index 88e1b6a..439ff44 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
@@ -18,17 +18,21 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
+import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
 
 import java.util.Arrays;
 
 import org.apache.cayenne.DataRow;
+import org.apache.cayenne.map.EntityResolver;
 import org.junit.Test;
 
 public class SQLSelectTest {
-	
+
 	@Test
 	public void testCacheGroups_Collection() {
 		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla");
@@ -56,7 +60,7 @@ public class SQLSelectTest {
 		assertSame(QueryCacheStrategy.SHARED_CACHE, q.getCacheStrategy());
 		assertNull(q.getCacheGroups());
 	}
-	
+
 	@Test
 	public void testLocalCache() {
 		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla");
@@ -72,7 +76,7 @@ public class SQLSelectTest {
 		assertSame(QueryCacheStrategy.LOCAL_CACHE, q.getCacheStrategy());
 		assertNull(q.getCacheGroups());
 	}
-	
+
 	@Test
 	public void testSharedCache() {
 		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla");
@@ -88,4 +92,28 @@ public class SQLSelectTest {
 		assertSame(QueryCacheStrategy.SHARED_CACHE, q.getCacheStrategy());
 		assertNull(q.getCacheGroups());
 	}
+
+	@Test
+	public void testCreateReplacementQuery() {
+
+		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla");
+		Query replacement = q.createReplacementQuery(mock(EntityResolver.class));
+		assertThat(replacement, instanceOf(SQLTemplate.class));
+	}
+
+	@Test
+	public void testCreateReplacementQuery_ParamsArray_Single() {
+
+		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla").paramsArray("a");
+		SQLTemplate replacement = (SQLTemplate) q.createReplacementQuery(mock(EntityResolver.class));
+		assertArrayEquals(new Object[] { "a" }, replacement.getPositionalParams().toArray());
+	}
+
+	@Test
+	public void testCreateReplacementQuery_ParamsArray_Multiple() {
+
+		SQLSelect<DataRow> q = SQLSelect.dataRowQuery("bla").paramsArray("a", "b");
+		SQLTemplate replacement = (SQLTemplate) q.createReplacementQuery(mock(EntityResolver.class));
+		assertArrayEquals(new Object[] { "a", "b" }, replacement.getPositionalParams().toArray());
+	}
 }


[3/4] cayenne git commit: CAY-1966 SQLTemplate/SQLSelect positional parameter binding

Posted by aa...@apache.org.
CAY-1966 SQLTemplate/SQLSelect positional parameter binding

* positional parameters must be included in cache key


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

Branch: refs/heads/master
Commit: e2069efeb92b1684c548af50aefa508942b5d3b8
Parents: 60f3f15
Author: aadamchik <aa...@apache.org>
Authored: Fri Jan 16 09:19:09 2015 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Fri Jan 16 09:36:29 2015 +0300

----------------------------------------------------------------------
 .../cayenne/query/SQLTemplateMetadata.java      | 117 +++++++++----------
 .../org/apache/cayenne/query/SQLSelectTest.java |  19 +++
 2 files changed, 77 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/e2069efe/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
index 61a3a68..de106d5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplateMetadata.java
@@ -31,63 +31,62 @@ import org.apache.cayenne.map.ObjEntity;
  */
 class SQLTemplateMetadata extends BaseQueryMetadata {
 
-    boolean resolve(Object root, EntityResolver resolver, SQLTemplate query) {
-
-        if (super.resolve(root, resolver, null)) {
-
-            resultSetMapping = query.getResult() != null ? query
-                    .getResult()
-                    .getResolvedComponents(resolver) : null;
-
-            // generate unique cache key...
-            if (QueryCacheStrategy.NO_CACHE == getCacheStrategy()) {
-
-            }
-            else {
-
-                // create a unique key based on entity, SQL, and parameters
-
-                StringBuilder key = new StringBuilder();
-                ObjEntity entity = getObjEntity();
-                if (entity != null) {
-                    key.append(entity.getName());
-                }
-                else if (dbEntity != null) {
-                    key.append("db:").append(dbEntity.getName());
-                }
-
-                if (query.getDefaultTemplate() != null) {
-                    key.append('/').append(query.getDefaultTemplate());
-                }
-
-                Map<String, ?> parameters = query.getParams();
-                if (!parameters.isEmpty()) {
-
-                    List<String> keys = new ArrayList<String>(parameters.keySet());
-                    Collections.sort(keys);
-
-                    for (String parameterKey : keys) {
-                        key.append('/').append(parameterKey).append('=').append(
-                                parameters.get(parameterKey));
-                    }
-                }
-                
-                if (query.getFetchOffset() > 0 || query.getFetchLimit() > 0) {
-                    key.append('/');
-                    if (query.getFetchOffset() > 0) {
-                        key.append('o').append(query.getFetchOffset());
-                    }
-                    if (query.getFetchLimit() > 0) {
-                        key.append('l').append(query.getFetchLimit());
-                    }
-                }
-
-                this.cacheKey = key.toString();
-            }
-
-            return true;
-        }
-
-        return false;
-    }
+	boolean resolve(Object root, EntityResolver resolver, SQLTemplate query) {
+
+		if (super.resolve(root, resolver, null)) {
+
+			resultSetMapping = query.getResult() != null ? query.getResult().getResolvedComponents(resolver) : null;
+
+			// generate unique cache key...
+			if (QueryCacheStrategy.NO_CACHE == getCacheStrategy()) {
+
+			} else {
+
+				// create a unique key based on entity, SQL, and parameters
+
+				StringBuilder key = new StringBuilder();
+				ObjEntity entity = getObjEntity();
+				if (entity != null) {
+					key.append(entity.getName());
+				} else if (dbEntity != null) {
+					key.append("db:").append(dbEntity.getName());
+				}
+
+				if (query.getDefaultTemplate() != null) {
+					key.append('/').append(query.getDefaultTemplate());
+				}
+
+				Map<String, ?> parameters = query.getParams();
+				if (!parameters.isEmpty()) {
+
+					List<String> keys = new ArrayList<String>(parameters.keySet());
+					Collections.sort(keys);
+
+					for (String parameterKey : keys) {
+						key.append('/').append(parameterKey).append('=').append(parameters.get(parameterKey));
+					}
+				}
+
+				for (Object parameter : query.getPositionalParams()) {
+					key.append("/p:").append(parameter);
+				}
+
+				if (query.getFetchOffset() > 0 || query.getFetchLimit() > 0) {
+					key.append('/');
+					if (query.getFetchOffset() > 0) {
+						key.append('o').append(query.getFetchOffset());
+					}
+					if (query.getFetchLimit() > 0) {
+						key.append('l').append(query.getFetchLimit());
+					}
+				}
+
+				this.cacheKey = key.toString();
+			}
+
+			return true;
+		}
+
+		return false;
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e2069efe/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
index 439ff44..303d9e4 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLSelectTest.java
@@ -20,6 +20,8 @@ package org.apache.cayenne.query;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
@@ -116,4 +118,21 @@ public class SQLSelectTest {
 		SQLTemplate replacement = (SQLTemplate) q.createReplacementQuery(mock(EntityResolver.class));
 		assertArrayEquals(new Object[] { "a", "b" }, replacement.getPositionalParams().toArray());
 	}
+
+	@Test
+	public void testGetMetadata_ParamsArray_Multiple_Cache() {
+
+		EntityResolver resolver = mock(EntityResolver.class);
+		QueryMetadata md0 = SQLSelect.dataRowQuery("bla").localCache().getMetaData(resolver);
+		QueryMetadata md1 = SQLSelect.dataRowQuery("bla").localCache().paramsArray("a").getMetaData(resolver);
+		QueryMetadata md2 = SQLSelect.dataRowQuery("bla").localCache().paramsArray("a", "b").getMetaData(resolver);
+
+		assertNotNull(md0.getCacheKey());
+		assertNotNull(md1.getCacheKey());
+		assertNotNull(md2.getCacheKey());
+		
+		assertNotEquals(md0.getCacheKey(), md1.getCacheKey());
+		assertNotEquals(md0.getCacheKey(), md2.getCacheKey());
+		assertNotEquals(md1.getCacheKey(), md2.getCacheKey());
+	}
 }


[4/4] cayenne git commit: Merge branch '62'

Posted by aa...@apache.org.
Merge branch '62'


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

Branch: refs/heads/master
Commit: c8ff4355fa0d33480f80f341d3c593eb6794a2ee
Parents: e2069ef aaafe11
Author: aadamchik <aa...@apache.org>
Authored: Fri Jan 16 09:43:11 2015 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Fri Jan 16 09:43:11 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/access/DbLoader.java     |  69 ++++-----
 .../access/loader/LoggingDbLoaderDelegate.java  |  20 +--
 .../org/apache/cayenne/map/DbRelationship.java  |  40 ++++--
 .../org/apache/cayenne/map/Relationship.java    |   6 +-
 .../apache/cayenne/map/naming/ExportedKey.java  |  18 ++-
 .../merge/DropRelationshipToModelIT.java        |   7 +-
 .../apache/cayenne/merge/MergerFactoryIT.java   |  13 +-
 cayenne-tools/pom.xml                           |   5 +
 .../cayenne/tools/CayenneGeneratorTask.java     |  11 +-
 .../cayenne/tools/dbimport/DbImportAction.java  |  30 ++--
 .../dbimport/DbImportDbLoaderDelegate.java      |   1 -
 .../src/main/resources/reverseEngineering.xsd   | 139 +++++++++++++++++++
 .../cayenne/tools/DbImporterMojoTest.java       |   4 +
 .../cayenne/tools/dbimport/testOneToOne-pom.xml |  39 ++++++
 .../tools/dbimport/testOneToOne.map.xml-result  |  58 ++++++++
 .../cayenne/tools/dbimport/testOneToOne.sql     |  24 ++++
 16 files changed, 400 insertions(+), 84 deletions(-)
----------------------------------------------------------------------