]> source.dussan.org Git - jackcess.git/commitdiff
add initial test for reading queries; add support for multicolumn joins
authorJames Ahlborn <jtahlborn@yahoo.com>
Thu, 28 May 2009 02:57:33 +0000 (02:57 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Thu, 28 May 2009 02:57:33 +0000 (02:57 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@393 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/query/Query.java
test/data/queryTest.mdb [new file with mode: 0755]
test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
test/src/java/com/healthmarketscience/jackcess/query/QueryTest.java

index 78538598cdec56361022dd687f3fa41e3c5d7f7e..08f6f484b23d068e046716fa4f78f0b849111185 100644 (file)
@@ -28,10 +28,12 @@ King of Prussia, PA 19406
 package com.healthmarketscience.jackcess.query;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -224,7 +226,31 @@ public abstract class Query
     List<Row> joins = getJoinRows();
     if(!joins.isEmpty()) {
 
-      for(Row join : joins) {
+      // combine any multi-column joins
+      Collection<List<Row>> comboJoins = combineJoins(joins);
+      
+      for(List<Row> comboJoin : comboJoins) {
+
+        Row join = comboJoin.get(0);
+        String joinExpr = join.expression;
+
+        if(comboJoin.size() > 1) {
+
+          // combine all the join expressions with "AND"
+          AppendableList<String> comboExprs = new AppendableList<String>() {
+            private static final long serialVersionUID = 0L;
+            @Override
+            protected String getSeparator() {
+              return ") AND (";
+            }
+          };
+          for(Row tmpJoin : comboJoin) {
+            comboExprs.add(tmpJoin.expression);
+          }
+
+          joinExpr = new StringBuilder().append("(")
+            .append(comboExprs).append(")").toString();
+        }
 
         String fromTable = join.name1;
         String toTable = join.name2;
@@ -238,7 +264,7 @@ public abstract class Query
 
         String expr = new StringBuilder().append(fromExpr)
           .append(joinType).append(toExpr).append(" ON ")
-          .append(join.expression).toString();
+          .append(joinExpr).toString();
 
         fromExpr.join(toExpr, expr);
         joinExprs.add(fromExpr);
@@ -265,6 +291,28 @@ public abstract class Query
     throw new IllegalStateException("Cannot find join table " + table);
   }
 
+  private Collection<List<Row>> combineJoins(List<Row> joins)
+  {
+    // combine joins with the same to/from tables
+    Map<List<String>,List<Row>> comboJoinMap = 
+      new LinkedHashMap<List<String>,List<Row>>();
+    for(Row join : joins) {
+      List<String> key = Arrays.asList(join.name1, join.name2);
+      List<Row> comboJoins = comboJoinMap.get(key);
+      if(comboJoins == null) {
+        comboJoins = new ArrayList<Row>();
+        comboJoinMap.put(key, comboJoins);
+      } else {
+        if(comboJoins.get(0).flag != join.flag) {
+          throw new IllegalStateException(
+              "Mismatched join flags for combo joins");
+        }
+      }
+      comboJoins.add(join);
+    }
+    return comboJoinMap.values();
+  }
+
   protected String getFromRemoteDbPath() 
   {
     return getRemoteDatabaseRow().name1;
@@ -610,13 +658,17 @@ public abstract class Query
       super(c);
     }
 
+    protected String getSeparator() {
+      return ", ";
+    }
+
     @Override
     public String toString() {
       StringBuilder builder = new StringBuilder();
       for(Iterator<E> iter = iterator(); iter.hasNext(); ) {
         builder.append(iter.next().toString());
         if(iter.hasNext()) {
-          builder.append(", ");
+          builder.append(getSeparator());
         }
       }
       return builder.toString();
diff --git a/test/data/queryTest.mdb b/test/data/queryTest.mdb
new file mode 100755 (executable)
index 0000000..5bb6b28
Binary files /dev/null and b/test/data/queryTest.mdb differ
index aedf3e7b4e59168a95203225ca73d81da1b785a5..5b5d343c934ae376e24ab950bbcb98425f877331 100644 (file)
@@ -66,27 +66,29 @@ public class DatabaseTest extends TestCase {
     super(name);
   }
    
-  static Database open() throws Exception {
+  public static Database open() throws Exception {
     return open(new File("test/data/test.mdb"));
   }
   
-  static Database open(File file) throws Exception {
+  public static Database open(File file) throws Exception {
     return Database.open(file, true, _autoSync);
   }
   
-  static Database create() throws Exception {
+  public static Database create() throws Exception {
     return create(false);
   }
 
-  static Database create(boolean keep) throws Exception {
+  public static Database create(boolean keep) throws Exception {
     return Database.create(createTempFile(keep), _autoSync);
   }
 
-  static Database openCopy(File srcFile) throws Exception {
+  public static Database openCopy(File srcFile) throws Exception {
     return openCopy(srcFile, false);
   }
   
-  static Database openCopy(File srcFile, boolean keep) throws Exception {
+  public static Database openCopy(File srcFile, boolean keep) 
+    throws Exception 
+  {
     File tmp = createTempFile(keep);
     copyFile(srcFile, tmp);
     return Database.open(tmp, false, _autoSync);
index 10d976c6ca18d994cf6bfc5355219779e7aa993a..5d243074b03ed9fb76b21342a31a67576777dec0 100644 (file)
@@ -27,12 +27,17 @@ King of Prussia, PA 19406
 
 package com.healthmarketscience.jackcess.query;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import com.healthmarketscience.jackcess.DataType;
+import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.DatabaseTest;
 import com.healthmarketscience.jackcess.query.Query.Row;
 import junit.framework.TestCase;
 import org.apache.commons.lang.StringUtils;
@@ -192,6 +197,49 @@ public class QueryTest extends TestCase
 
   }
 
+  public void testReadQueries() throws Exception
+  {
+    Map<String,String> expectedQueries = new HashMap<String,String>();
+    expectedQueries.put(
+        "SelectQuery", multiline(
+            "SELECT Table1.*, Table2.col1, Table2.col2, Table3.col3",
+            "FROM (Table1 LEFT OUTER JOIN Table3 ON Table1.col1 = Table3.col1) INNER JOIN Table2 ON (Table3.col1 = Table2.col1) AND (Table3.col1 = Table2.col2)",
+            "WHERE (((Table2.col2)=\"foo\" Or (Table2.col2) In (\"buzz\",\"bazz\")))",
+            "ORDER BY Table2.col1;"));
+    expectedQueries.put(
+        "DeleteQuery", multiline(
+            "DELETE Table1.col1, Table1.col2, Table1.col3",
+            "FROM Table1", 
+            "WHERE (((Table1.col1)>\"blah\"));"));
+    expectedQueries.put(
+        "AppendQuery",multiline(
+            "INSERT INTO Table3",
+            "SELECT [Table1].[col2], [Table2].[col2], [Table2].[col3]",
+            "FROM Table3, Table1 INNER JOIN Table2 ON [Table1].[col1]=[Table2].[col1];"));
+    expectedQueries.put(
+        "UpdateQuery",multiline(
+            "UPDATE Table1",
+            "SET Table1.col1 = \"foo\", Table1.col2 = [Table2].[col3]",
+            "WHERE (([Table2].[col1] Is Not Null));"));
+    expectedQueries.put(
+        "MakeTableQuery",multiline(
+            "SELECT Max(Table2.col1) AS MaxOfcol1, Table2.col2, Table3.col2 INTO Table4",
+            "FROM (Table2 INNER JOIN Table1 ON Table2.col1 = Table1.col2) RIGHT OUTER JOIN Table3 ON Table1.col2 = Table3.col3",
+            "GROUP BY Table2.col2, Table3.col2",
+            "HAVING (((Max(Table2.col1))=\"buzz\") AND ((Table2.col2)<>\"blah\"));"));
+
+    Database db = DatabaseTest.open(new File("test/data/queryTest.mdb"));
+
+    Map<String,String> foundQueries = new HashMap<String,String>();
+    for(Query q : db.getQueries()) {
+      assertNull(foundQueries.put(q.getName(), q.toSQLString()));
+    }
+
+    assertEquals(expectedQueries, foundQueries);
+
+    db.close();
+  }
+
   private void doTestColumns(SelectQuery query) throws Exception
   {
     addRows(query, newRow(COLUMN_ATTRIBUTE, "Table1.id", null, null));