You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2015/05/19 22:35:16 UTC
metamodel git commit: METAMODEL-133: Fixed. Fixes #20
Repository: metamodel
Updated Branches:
refs/heads/master 45edefe5a -> 76f6bb7b1
METAMODEL-133: Fixed.
Fixes #20
Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo
Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/76f6bb7b
Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/76f6bb7b
Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/76f6bb7b
Branch: refs/heads/master
Commit: 76f6bb7b1d9ac5a87d3138b8232bcc2943f7ef4d
Parents: 45edefe
Author: Hosur Narahari <hn...@gmail.com>
Authored: Tue May 19 22:34:55 2015 +0200
Committer: Kasper Sørensen <i....@gmail.com>
Committed: Tue May 19 22:34:55 2015 +0200
----------------------------------------------------------------------
CHANGES.md | 1 +
.../org/apache/metamodel/query/FromItem.java | 5 ++
.../metamodel/query/parser/FromItemParser.java | 50 +++++++++++++++-----
.../apache/metamodel/query/FromItemTest.java | 27 +++++++++++
4 files changed, 72 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/metamodel/blob/76f6bb7b/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 833b353..4b9acda 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -4,6 +4,7 @@
* [METAMODEL-138] - Allow empty characteres before AS keyword.
* [METAMODEL-141] - Improved mapping of ColumnType to SQL data types for Oracle, SQL Server, MySQL, DB2 and PostgreSQL
* [METAMODEL-142] - Ensured that JDBC schema refreshes in an UpdateScript is using same Connection/Transaction as rest of operations
+ * [METAMODEL-133] - Improved query parser support for multiple JOINs in same query.
### Apache MetaModel 4.3.3
http://git-wip-us.apache.org/repos/asf/metamodel/blob/76f6bb7b/core/src/main/java/org/apache/metamodel/query/FromItem.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/FromItem.java b/core/src/main/java/org/apache/metamodel/query/FromItem.java
index 8ee07fa..392c0bf 100644
--- a/core/src/main/java/org/apache/metamodel/query/FromItem.java
+++ b/core/src/main/java/org/apache/metamodel/query/FromItem.java
@@ -267,6 +267,11 @@ public class FromItem extends BaseObject implements QueryItem, Cloneable {
sb.append(superQueryAlias);
return;
}
+
+ if(_join != null && _leftSide.getJoin() != null) {
+ sb.append(onItem.toSql());
+ return;
+ }
if (sideAlias != null) {
sb.append(sideAlias);
http://git-wip-us.apache.org/repos/asf/metamodel/blob/76f6bb7b/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
index 76ff4f2..cc8916a 100644
--- a/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
+++ b/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
@@ -18,6 +18,11 @@
*/
package org.apache.metamodel.query.parser;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import org.apache.metamodel.DataContext;
import org.apache.metamodel.query.FromItem;
import org.apache.metamodel.query.JoinType;
@@ -66,7 +71,7 @@ final class FromItemParser implements QueryPartProcessor {
fromItem.setAlias(alias);
}
} else if (itemToken.toUpperCase().indexOf(" JOIN ") != -1) {
- fromItem = parseJoinItem(itemToken);
+ fromItem = parseAllJoinItems(itemToken);
} else {
fromItem = parseTableItem(itemToken);
}
@@ -95,10 +100,32 @@ final class FromItemParser implements QueryPartProcessor {
result.setQuery(_query);
return result;
}
+
+ private FromItem parseAllJoinItems(final String itemToken) {
+ String[] joinSplit = itemToken.split("(?i) JOIN ");
+ List<String> joinsList = new ArrayList<String>();
+ for(int i = 0 ; i < joinSplit.length -1 ; i++) {
+ joinSplit[i] = joinSplit[i].trim();
+ joinSplit[i+1] = joinSplit[i+1].trim();
+ String leftPart = joinSplit[i].substring(0, joinSplit[i].lastIndexOf(" "));
+ String joinType = joinSplit[i].substring(joinSplit[i].lastIndexOf(" "));
+ String rightPart = (i+1 == joinSplit.length-1) ? joinSplit[i+1] : joinSplit[i+1].substring(0, joinSplit[i+1].lastIndexOf(" "));
+ joinsList.add((leftPart + " " + joinType + " JOIN " + rightPart).replaceAll(" +", " "));
+ String rightTable = rightPart.substring(0, rightPart.toUpperCase().lastIndexOf(" ON "));
+ String nextJoinType = joinSplit[i+1].substring(joinSplit[i+1].lastIndexOf(" "));
+ joinSplit[i+1] = rightTable + " " + nextJoinType;
+ }
+ Set<FromItem> fromItems = new HashSet<FromItem>();
+ FromItem leftFromItem = null;
+ for(String token : joinsList) {
+ leftFromItem = parseJoinItem(leftFromItem, token, fromItems);
+ }
+ return leftFromItem;
+ }
// this method will be documented based on this example itemToken: FOO f
// INNER JOIN BAR b ON f.id = b.id
- private FromItem parseJoinItem(final String itemToken) {
+ private FromItem parseJoinItem(final FromItem leftFromItem, final String itemToken, Set<FromItem> fromItems) {
final int indexOfJoin = itemToken.toUpperCase().indexOf(" JOIN ");
// firstPart = "FOO f INNER"
@@ -123,6 +150,9 @@ final class FromItemParser implements QueryPartProcessor {
final FromItem leftSide = parseTableItem(firstTableToken);
final FromItem rightSide = parseTableItem(secondTableToken);
+
+ fromItems.add(leftSide);
+ fromItems.add(rightSide);
// onClausess = ["f.id = b.id"]
final String[] onClauses = secondPart.substring(indexOfOn + " ON ".length()).split(" AND ");
@@ -136,16 +166,17 @@ final class FromItemParser implements QueryPartProcessor {
// rightPart = "b.id"
final String rightPart = onClause.substring(indexOfEquals + 1).trim();
- leftOn[i] = findSelectItem(leftPart, leftSide, rightSide);
- rightOn[i] = findSelectItem(rightPart, leftSide, rightSide);
+ leftOn[i] = findSelectItem(leftPart, fromItems.toArray(new FromItem[fromItems.size()]));
+ rightOn[i] = findSelectItem(rightPart, fromItems.toArray(new FromItem[fromItems.size()]));
}
-
- final FromItem result = new FromItem(joinType, leftSide, rightSide, leftOn, rightOn);
+
+ final FromItem leftItem = (leftFromItem != null) ? leftFromItem : leftSide;
+ final FromItem result = new FromItem(joinType, leftItem, rightSide, leftOn, rightOn);
result.setQuery(_query);
return result;
}
- private SelectItem findSelectItem(String token, FromItem leftSide, FromItem rightSide) {
+ private SelectItem findSelectItem(String token, FromItem[] joinTables) {
// first look in the original query
SelectItemParser selectItemParser = new SelectItemParser(_query, false);
SelectItem result = selectItemParser.findSelectItem(token);
@@ -153,18 +184,15 @@ final class FromItemParser implements QueryPartProcessor {
if (result == null) {
// fail over and try with the from items available in the join that
// is being built.
- final Query temporaryQuery = new Query().from(leftSide, rightSide);
+ final Query temporaryQuery = new Query().from(joinTables);
selectItemParser = new SelectItemParser(temporaryQuery, false);
result = selectItemParser.findSelectItem(token);
-
if (result == null) {
throw new QueryParserException("Not capable of parsing ON token: " + token);
}
// set the query on the involved query parts (since they have been
// temporarily moved to the searched query).
- leftSide.setQuery(_query);
- rightSide.setQuery(_query);
result.setQuery(_query);
}
return result;
http://git-wip-us.apache.org/repos/asf/metamodel/blob/76f6bb7b/core/src/test/java/org/apache/metamodel/query/FromItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/metamodel/query/FromItemTest.java b/core/src/test/java/org/apache/metamodel/query/FromItemTest.java
index 4967841..b026f8d 100644
--- a/core/src/test/java/org/apache/metamodel/query/FromItemTest.java
+++ b/core/src/test/java/org/apache/metamodel/query/FromItemTest.java
@@ -18,7 +18,10 @@
*/
package org.apache.metamodel.query;
+import org.apache.metamodel.MetaModelException;
import org.apache.metamodel.MetaModelTestCase;
+import org.apache.metamodel.QueryPostprocessDataContext;
+import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.Relationship;
import org.apache.metamodel.schema.Schema;
@@ -98,4 +101,28 @@ public class FromItemTest extends MetaModelTestCase {
"MetaModelSchema.project a LEFT JOIN (SELECT c.contributor_id, c.project_id AS foobar, c.name FROM MetaModelSchema.role c) b ON a.project_id = b.foobar",
from.toString());
}
+
+ public void testCompoundJoin() {
+ final Schema schema = getExampleSchema();
+
+ final QueryPostprocessDataContext dc = new QueryPostprocessDataContext() {
+ @Override
+ protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows) {
+ throw new UnsupportedOperationException("This method is not used");
+ }
+
+ @Override
+ protected String getMainSchemaName() throws MetaModelException {
+ return "MetaModelSchema";
+ }
+
+ @Override
+ protected Schema getMainSchema() throws MetaModelException {
+ return schema;
+ }
+ };
+
+ Query query = dc.parseQuery("SELECT c.contributor_id,p.project_id from contributor c INNER JOIN role r ON c.contributor_id=r.contributor_id INNER JOIN project p ON p.project_id=r.project_id");
+ assertEquals("SELECT c.contributor_id, p.project_id FROM MetaModelSchema.contributor c INNER JOIN MetaModelSchema.role r ON c.contributor_id = r.contributor_id INNER JOIN MetaModelSchema.project p ON p.project_id = r.project_id", query.toSql());
+ }
}
\ No newline at end of file