git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@393 f203690c-595d-4dc9-a70b-905162fa7fd2tags/rel_1_1_19
@@ -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(); |
@@ -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); |
@@ -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)); |