You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2014/11/01 19:45:26 UTC
git commit: PHOENIX-1399 Support cross joins and comma-separated
table list
Repository: phoenix
Updated Branches:
refs/heads/master 4de425131 -> bfc92b045
PHOENIX-1399 Support cross joins and comma-separated table list
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/bfc92b04
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/bfc92b04
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/bfc92b04
Branch: refs/heads/master
Commit: bfc92b045fb27b6b3cdd4ffd9b8d523afd0e88dd
Parents: 4de4251
Author: maryannxue <ma...@apache.org>
Authored: Sat Nov 1 14:44:26 2014 -0400
Committer: maryannxue <ma...@apache.org>
Committed: Sat Nov 1 14:44:26 2014 -0400
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/HashJoinIT.java | 70 +++++-
phoenix-core/src/main/antlr3/PhoenixSQL.g | 30 +--
.../apache/phoenix/compile/DeleteCompiler.java | 2 +-
.../apache/phoenix/compile/FromCompiler.java | 10 +-
.../apache/phoenix/compile/JoinCompiler.java | 231 ++++++++++---------
.../apache/phoenix/compile/QueryCompiler.java | 4 +-
.../phoenix/compile/StatementNormalizer.java | 12 +-
.../phoenix/compile/SubqueryRewriter.java | 6 +-
.../phoenix/compile/SubselectRewriter.java | 6 +-
.../apache/phoenix/compile/UpsertCompiler.java | 2 +-
.../phoenix/exception/SQLExceptionCode.java | 1 +
.../apache/phoenix/jdbc/PhoenixStatement.java | 4 +-
.../apache/phoenix/optimize/QueryOptimizer.java | 4 +-
.../org/apache/phoenix/parse/JoinPartNode.java | 53 -----
.../apache/phoenix/parse/ParseNodeFactory.java | 21 +-
.../apache/phoenix/parse/ParseNodeRewriter.java | 25 +-
.../apache/phoenix/parse/SelectStatement.java | 18 +-
17 files changed, 239 insertions(+), 260 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
index 3850ac9..5190c18 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
@@ -41,7 +41,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Collection;
@@ -1810,13 +1809,22 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
@Test
public void testStarJoin() throws Exception {
- String[] query = new String[2];
+ String[] query = new String[5];
query[0] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o JOIN "
+ JOIN_CUSTOMER_TABLE_FULL_NAME + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
- query[1] = "SELECT /*+ NO_STAR_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o JOIN "
+ query[1] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o, "
+ + JOIN_CUSTOMER_TABLE_FULL_NAME + " c, "
+ + JOIN_ITEM_TABLE_FULL_NAME + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[2] = "SELECT /*+ NO_STAR_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o JOIN "
+ JOIN_CUSTOMER_TABLE_FULL_NAME + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
+ query[3] = "SELECT /*+ NO_STAR_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.date FROM (" + JOIN_ORDER_TABLE_FULL_NAME + " o, "
+ + JOIN_CUSTOMER_TABLE_FULL_NAME + " c), "
+ + JOIN_ITEM_TABLE_FULL_NAME + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[4] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o, ("
+ + JOIN_CUSTOMER_TABLE_FULL_NAME + " c, "
+ + JOIN_ITEM_TABLE_FULL_NAME + " i) WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
try {
@@ -1860,8 +1868,10 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
assertFalse(rs.next());
- rs = conn.createStatement().executeQuery("EXPLAIN " + query[i]);
- assertEquals(plans[11 + i], QueryUtil.getExplainPlan(rs));
+ if (i < 4) {
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query[i]);
+ assertEquals(plans[11 + (i/2)], QueryUtil.getExplainPlan(rs));
+ }
}
} finally {
conn.close();
@@ -3828,17 +3838,56 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
}
@Test
- public void testUnsupportedJoinConditions() throws Exception {
- String query = "SELECT * FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item JOIN " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON (item.\"supplier_id\" || supp.\"supplier_id\") = ''";
+ public void testNonEquiJoin() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
try {
+ String query = "SELECT item.name, supp.name FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item, " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp WHERE item.\"supplier_id\" > supp.\"supplier_id\"";
PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getString(2), "S3");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getString(2), "S4");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "S3");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "S4");
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "S5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT item.name, supp.name FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item JOIN " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON item.\"supplier_id\" > supp.\"supplier_id\"";
+ statement = conn.prepareStatement(query);
try {
statement.executeQuery();
- fail("Should have got SQLFeatureNotSupportedException.");
- } catch (SQLFeatureNotSupportedException e) {
- assertEquals("Does not support non-standard or non-equi join conditions.", e.getMessage());
+ fail("Should have got SQLException.");
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.AMBIGUOUS_JOIN_CONDITION.getErrorCode(), e.getErrorCode());
}
} finally {
conn.close();
@@ -3847,3 +3896,4 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
}
+
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index e2636fb..aa7fdc6 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -647,31 +647,25 @@ parseOrderByField returns [OrderByNode ret]
{ $ret = factory.orderBy(expr, nullsLast, isAscending); }
;
-parseFrom returns [List<TableNode> ret]
-@init{ret = new ArrayList<TableNode>(4); }
- : t=table_ref {$ret.add(t);} (COMMA s=table_ref { $ret.add(s); })*
+parseFrom returns [TableNode ret]
+ : t=table_list {$ret = t;}
+ ;
+
+table_list returns [TableNode ret]
+ : t=table_ref {$ret = t;} (COMMA s=table_ref { $ret = factory.join(JoinTableNode.JoinType.Inner, ret, s, null, false); })*
;
table_ref returns [TableNode ret]
- : t=single_table_ref p=join_parts { $ret = factory.table(t, p); }
- ;
+ : l=table_factor { $ret = l; } (j=join_type JOIN r=table_factor ON e=expression { $ret = factory.join(j, ret, r, e, false); })*
+ ;
-single_table_ref returns [TableNode ret]
- : n=bind_name ((AS)? alias=identifier)? { $ret = factory.bindTable(alias, factory.table(null,n)); } // TODO: review
- | t=from_table_name ((AS)? alias=identifier)? (LPAREN cdefs=dyn_column_defs RPAREN)? { $ret = factory.namedTable(alias,t,cdefs); }
+table_factor returns [TableNode ret]
+ : LPAREN t=table_list RPAREN { $ret = t; }
+ | n=bind_name ((AS)? alias=identifier)? { $ret = factory.bindTable(alias, factory.table(null,n)); } // TODO: review
+ | f=from_table_name ((AS)? alias=identifier)? (LPAREN cdefs=dyn_column_defs RPAREN)? { $ret = factory.namedTable(alias,f,cdefs); }
| LPAREN SELECT s=hinted_select_node RPAREN ((AS)? alias=identifier)? { $ret = factory.derivedTable(alias, s); }
;
-join_parts returns [List<JoinPartNode> ret]
-@init{ret = new ArrayList<JoinPartNode>(4); }
- : (p=join_part { $ret.add(p); })*
- ;
-
-join_part returns [JoinPartNode ret]
- : j=join_type JOIN r=single_table_ref ON e=expression { $ret = factory.joinPart(j, e, r); }
- | j=join_type JOIN LPAREN r=table_ref RPAREN ON e=expression { $ret = factory.joinPart(j, e, r); }
- ;
-
join_type returns [JoinTableNode.JoinType ret]
: INNER? { $ret = JoinTableNode.JoinType.Inner; }
| LEFT OUTER? { $ret = JoinTableNode.JoinType.Left; }
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index 1331a2a..6638819 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -315,7 +315,7 @@ public class DeleteCompiler {
aliasedNodes.add(FACTORY.aliasedNode(null, FACTORY.column(null, '"' + column.getName().getString() + '"', null)));
}
select = FACTORY.select(
- Collections.singletonList(delete.getTable()),
+ delete.getTable(),
hint, false, aliasedNodes, delete.getWhere(),
Collections.<ParseNode>emptyList(), null,
delete.getOrderBy(), delete.getLimit(),
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index 1627f45..b9246c9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -155,14 +155,12 @@ public class FromCompiler {
*/
public static ColumnResolver getResolverForQuery(SelectStatement statement, PhoenixConnection connection)
throws SQLException {
- List<TableNode> fromNodes = statement.getFrom();
- if (!statement.isJoin() && fromNodes.get(0) instanceof NamedTableNode)
- return new SingleTableColumnResolver(connection, (NamedTableNode) fromNodes.get(0), true, 1);
+ TableNode fromNode = statement.getFrom();
+ if (fromNode instanceof NamedTableNode)
+ return new SingleTableColumnResolver(connection, (NamedTableNode) fromNode, true, 1);
MultiTableColumnResolver visitor = new MultiTableColumnResolver(connection, 1);
- for (TableNode node : fromNodes) {
- node.accept(visitor);
- }
+ fromNode.accept(visitor);
return visitor;
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
index 140146c..b519dc4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
@@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
@@ -39,6 +40,7 @@ import org.apache.phoenix.execute.TupleProjector;
import org.apache.phoenix.expression.AndExpression;
import org.apache.phoenix.expression.CoerceExpression;
import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
import org.apache.phoenix.expression.function.CountAggregateFunction;
import org.apache.phoenix.jdbc.PhoenixStatement;
import org.apache.phoenix.parse.AliasedNode;
@@ -109,15 +111,9 @@ public class JoinCompiler {
}
public static JoinTable compile(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver) throws SQLException {
- JoinCompiler compiler = new JoinCompiler(statement, select, resolver);
-
- List<TableNode> from = select.getFrom();
- if (from.size() > 1) {
- throw new SQLFeatureNotSupportedException("Cross join not supported.");
- }
-
+ JoinCompiler compiler = new JoinCompiler(statement, select, resolver);
JoinTableConstructor constructor = compiler.new JoinTableConstructor();
- Pair<Table, List<JoinSpec>> res = from.get(0).accept(constructor);
+ Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor);
JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond());
if (select.getWhere() != null) {
joinTable.addFilter(select.getWhere());
@@ -218,8 +214,8 @@ public class JoinCompiler {
private final List<Table> tables;
private final List<TableRef> tableRefs;
private final boolean allLeftJoin;
- private final boolean hasRightJoin;
- private final List<JoinTable> prefilterAcceptedTables;
+ private final boolean isPrefilterAccepted;
+ private final List<JoinSpec> prefilterAcceptedTables;
private JoinTable(Table table) {
this.table = table;
@@ -228,8 +224,8 @@ public class JoinCompiler {
this.tables = Collections.<Table>singletonList(table);
this.tableRefs = Collections.<TableRef>singletonList(table.getTableRef());
this.allLeftJoin = false;
- this.hasRightJoin = false;
- this.prefilterAcceptedTables = Collections.<JoinTable>emptyList();
+ this.isPrefilterAccepted = true;
+ this.prefilterAcceptedTables = Collections.<JoinSpec>emptyList();
}
private JoinTable(Table table, List<JoinSpec> joinSpecs) {
@@ -241,10 +237,12 @@ public class JoinCompiler {
this.tables.add(table);
boolean allLeftJoin = true;
int lastRightJoinIndex = -1;
+ boolean hasFullJoin = false;
for (int i = 0; i < joinSpecs.size(); i++) {
JoinSpec joinSpec = joinSpecs.get(i);
this.tables.addAll(joinSpec.getJoinTable().getTables());
allLeftJoin = allLeftJoin && joinSpec.getType() == JoinType.Left;
+ hasFullJoin = hasFullJoin || joinSpec.getType() == JoinType.Full;
if (joinSpec.getType() == JoinType.Right) {
lastRightJoinIndex = i;
}
@@ -253,12 +251,12 @@ public class JoinCompiler {
this.tableRefs.add(t.getTableRef());
}
this.allLeftJoin = allLeftJoin;
- this.hasRightJoin = lastRightJoinIndex > -1;
- this.prefilterAcceptedTables = new ArrayList<JoinTable>();
+ this.isPrefilterAccepted = !hasFullJoin && lastRightJoinIndex == -1;
+ this.prefilterAcceptedTables = new ArrayList<JoinSpec>();
for (int i = lastRightJoinIndex == -1 ? 0 : lastRightJoinIndex; i < joinSpecs.size(); i++) {
JoinSpec joinSpec = joinSpecs.get(i);
- if (joinSpec.getType() != JoinType.Left && joinSpec.getType() != JoinType.Anti) {
- prefilterAcceptedTables.add(joinSpec.getJoinTable());
+ if (joinSpec.getType() != JoinType.Left && joinSpec.getType() != JoinType.Anti && joinSpec.getType() != JoinType.Full) {
+ prefilterAcceptedTables.add(joinSpec);
}
}
}
@@ -303,7 +301,7 @@ public class JoinCompiler {
WhereNodeVisitor visitor = new WhereNodeVisitor(origResolver, table,
postFilters, Collections.<TableRef>singletonList(table.getTableRef()),
- hasRightJoin, prefilterAcceptedTables);
+ isPrefilterAccepted, prefilterAcceptedTables);
filter.accept(visitor);
}
@@ -415,11 +413,11 @@ public class JoinCompiler {
if (!postFilters.isEmpty())
return true;
- if (!hasRightJoin && table.hasFilters())
+ if (isPrefilterAccepted && table.hasFilters())
return true;
- for (JoinTable joinTable : prefilterAcceptedTables) {
- if (joinTable.hasFilters())
+ for (JoinSpec joinSpec : prefilterAcceptedTables) {
+ if (joinSpec.getJoinTable().hasFilters())
return true;
}
@@ -433,6 +431,7 @@ public class JoinCompiler {
private final JoinTable joinTable;
private final boolean singleValueOnly;
private Set<TableRef> dependencies;
+ private OnNodeVisitor onNodeVisitor;
private JoinSpec(JoinType type, ParseNode onNode, JoinTable joinTable,
boolean singleValueOnly, ColumnResolver resolver) throws SQLException {
@@ -441,13 +440,16 @@ public class JoinCompiler {
this.joinTable = joinTable;
this.singleValueOnly = singleValueOnly;
this.dependencies = new HashSet<TableRef>();
- OnNodeVisitor visitor = new OnNodeVisitor(resolver, onConditions, dependencies, joinTable);
- onNode.accept(visitor);
- if (onConditions.isEmpty()) {
- visitor.throwUnsupportedJoinConditionException();
+ this.onNodeVisitor = new OnNodeVisitor(resolver, onConditions, dependencies, joinTable);
+ if (onNode != null) {
+ onNode.accept(this.onNodeVisitor);
}
}
+ public void addOnCondition(ParseNode node) throws SQLException {
+ node.accept(onNodeVisitor);
+ }
+
public JoinType getType() {
return type;
}
@@ -469,6 +471,12 @@ public class JoinCompiler {
}
public Pair<List<Expression>, List<Expression>> compileJoinConditions(StatementContext context, ColumnResolver leftResolver, ColumnResolver rightResolver) throws SQLException {
+ if (onConditions.isEmpty()) {
+ return new Pair<List<Expression>, List<Expression>>(
+ Collections.<Expression> singletonList(LiteralExpression.newConstant(1)),
+ Collections.<Expression> singletonList(LiteralExpression.newConstant(1)));
+ }
+
ColumnResolver resolver = context.getResolver();
List<Pair<Expression, Expression>> compiled = new ArrayList<Pair<Expression, Expression>>(onConditions.size());
context.setResolver(leftResolver);
@@ -679,8 +687,7 @@ public class JoinCompiler {
if (isSubselect())
return SubselectRewriter.applyPostFilters(subselect, preFilters, tableNode.getAlias());
- List<TableNode> from = Collections.<TableNode>singletonList(tableNode);
- return NODE_FACTORY.select(from, select.getHint(), false, selectNodes, getPreFiltersCombined(), null, null, null, null, 0, false, select.hasSequence());
+ return NODE_FACTORY.select(tableNode, select.getHint(), false, selectNodes, getPreFiltersCombined(), null, null, null, null, 0, false, select.hasSequence());
}
public boolean hasFilters() {
@@ -804,17 +811,17 @@ public class JoinCompiler {
private Table table;
private List<ParseNode> postFilters;
private List<TableRef> selfTableRefs;
- private boolean hasRightJoin;
- private List<JoinTable> prefilterAcceptedTables;
+ private boolean isPrefilterAccepted;
+ private List<JoinSpec> prefilterAcceptedTables;
ColumnRefParseNodeVisitor columnRefVisitor;
public WhereNodeVisitor(ColumnResolver resolver, Table table,
- List<ParseNode> postFilters, List<TableRef> selfTableRefs, boolean hasRightJoin,
- List<JoinTable> prefilterAcceptedTables) {
+ List<ParseNode> postFilters, List<TableRef> selfTableRefs, boolean isPrefilterAccepted,
+ List<JoinSpec> prefilterAcceptedTables) {
this.table = table;
this.postFilters = postFilters;
this.selfTableRefs = selfTableRefs;
- this.hasRightJoin = hasRightJoin;
+ this.isPrefilterAccepted = isPrefilterAccepted;
this.prefilterAcceptedTables = prefilterAcceptedTables;
this.columnRefVisitor = new ColumnRefParseNodeVisitor(resolver);
}
@@ -833,7 +840,7 @@ public class JoinCompiler {
switch (type) {
case NONE:
case SELF_ONLY:
- if (!hasRightJoin) {
+ if (isPrefilterAccepted) {
table.addFilter(node);
} else {
postFilters.add(node);
@@ -841,9 +848,9 @@ public class JoinCompiler {
break;
case FOREIGN_ONLY:
JoinTable matched = null;
- for (JoinTable joinTable : prefilterAcceptedTables) {
- if (columnRefVisitor.getContentType(joinTable.getTableRefs()) == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
- matched = joinTable;
+ for (JoinSpec joinSpec : prefilterAcceptedTables) {
+ if (columnRefVisitor.getContentType(joinSpec.getJoinTable().getTableRefs()) == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
+ matched = joinSpec.getJoinTable();
break;
}
}
@@ -879,6 +886,29 @@ public class JoinCompiler {
public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException {
return null;
}
+
+ @Override
+ public Void visitLeave(ComparisonParseNode node, List<Void> l)
+ throws SQLException {
+ if (!(node instanceof EqualParseNode))
+ return leaveBooleanNode(node, l);
+
+ ListIterator<JoinSpec> iter = prefilterAcceptedTables.listIterator(prefilterAcceptedTables.size());
+ while (iter.hasPrevious()) {
+ JoinSpec joinSpec = iter.previous();
+ if (joinSpec.getType() != JoinType.Inner || joinSpec.isSingleValueOnly()) {
+ continue;
+ }
+
+ try {
+ joinSpec.addOnCondition(node);
+ return null;
+ } catch (SQLException e) {
+ }
+ }
+
+ return leaveBooleanNode(node, l);
+ }
}
private static class OnNodeVisitor extends BooleanParseNodeVisitor<Void> {
@@ -894,49 +924,47 @@ public class JoinCompiler {
this.joinTable = joinTable;
this.columnRefVisitor = new ColumnRefParseNodeVisitor(resolver);
}
-
@Override
protected boolean enterBooleanNode(ParseNode node) throws SQLException {
return false;
}
-
+
@Override
protected Void leaveBooleanNode(ParseNode node,
List<Void> l) throws SQLException {
columnRefVisitor.reset();
node.accept(columnRefVisitor);
ColumnRefParseNodeVisitor.ColumnRefType type = columnRefVisitor.getContentType(joinTable.getTableRefs());
- if (type == ColumnRefParseNodeVisitor.ColumnRefType.NONE
+ if (type == ColumnRefParseNodeVisitor.ColumnRefType.NONE
|| type == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
joinTable.addFilter(node);
} else {
- throwUnsupportedJoinConditionException();
+ throwAmbiguousJoinConditionException();
}
return null;
}
-
+
@Override
protected boolean enterNonBooleanNode(ParseNode node) throws SQLException {
return false;
}
-
+
@Override
protected Void leaveNonBooleanNode(ParseNode node, List<Void> l) throws SQLException {
return null;
}
-
+
@Override
public boolean visitEnter(AndParseNode node) throws SQLException {
return true;
}
-
@Override
public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException {
return null;
}
-
+
@Override
- public Void visitLeave(ComparisonParseNode node, List<Void> l)
+ public Void visitLeave(ComparisonParseNode node, List<Void> l)
throws SQLException {
if (!(node instanceof EqualParseNode))
return leaveBooleanNode(node, l);
@@ -951,16 +979,16 @@ public class JoinCompiler {
if ((lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || lhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE)
&& (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || rhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE)) {
joinTable.addFilter(node);
- } else if (lhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY
+ } else if (lhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY
&& rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
onConditions.add(node);
dependencies.addAll(lhsTableRefSet);
- } else if (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY
+ } else if (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY
&& lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
onConditions.add(NODE_FACTORY.equal(node.getRHS(), node.getLHS()));
dependencies.addAll(rhsTableRefSet);
} else {
- throwUnsupportedJoinConditionException();
+ throwAmbiguousJoinConditionException();
}
return null;
}
@@ -972,10 +1000,9 @@ public class JoinCompiler {
* 2) a boolean condition referencing to the self table only.
* Otherwise, it can be ambiguous.
*/
- public void throwUnsupportedJoinConditionException()
- throws SQLFeatureNotSupportedException {
- throw new SQLFeatureNotSupportedException("Does not support non-standard or non-equi join conditions.");
- }
+ public void throwAmbiguousJoinConditionException() throws SQLException {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.AMBIGUOUS_JOIN_CONDITION).build().buildException();
+ }
}
private static class ColumnRefParseNodeVisitor extends StatelessTraverseAllParseNodeVisitor {
@@ -1050,7 +1077,7 @@ public class JoinCompiler {
return !select.isJoin()
&& !select.isAggregate()
&& !select.isDistinct()
- && !(select.getFrom().get(0) instanceof DerivedTableNode)
+ && !(select.getFrom() instanceof DerivedTableNode)
&& select.getLimit() == null;
}
@@ -1168,64 +1195,61 @@ public class JoinCompiler {
if (replacement.isEmpty())
return select;
- List<TableNode> from = select.getFrom();
- List<TableNode> newFrom = Lists.newArrayListWithExpectedSize(from.size());
- for (TableNode node : from) {
- newFrom.add(node.accept(new TableNodeVisitor<TableNode>() {
- private TableRef resolveTable(String alias, TableName name) throws SQLException {
- if (alias != null)
- return resolver.resolveTable(null, alias);
+ TableNode from = select.getFrom();
+ TableNode newFrom = from.accept(new TableNodeVisitor<TableNode>() {
+ private TableRef resolveTable(String alias, TableName name) throws SQLException {
+ if (alias != null)
+ return resolver.resolveTable(null, alias);
- return resolver.resolveTable(name.getSchemaName(), name.getTableName());
- }
+ return resolver.resolveTable(name.getSchemaName(), name.getTableName());
+ }
- private TableName getReplacedTableName(TableRef tableRef) {
- String schemaName = tableRef.getTable().getSchemaName().getString();
- return TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString());
- }
+ private TableName getReplacedTableName(TableRef tableRef) {
+ String schemaName = tableRef.getTable().getSchemaName().getString();
+ return TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString());
+ }
- @Override
- public TableNode visit(BindTableNode boundTableNode) throws SQLException {
- TableRef tableRef = resolveTable(boundTableNode.getAlias(), boundTableNode.getName());
- TableRef replaceRef = replacement.get(tableRef);
- if (replaceRef == null)
- return boundTableNode;
+ @Override
+ public TableNode visit(BindTableNode boundTableNode) throws SQLException {
+ TableRef tableRef = resolveTable(boundTableNode.getAlias(), boundTableNode.getName());
+ TableRef replaceRef = replacement.get(tableRef);
+ if (replaceRef == null)
+ return boundTableNode;
- String alias = boundTableNode.getAlias();
- return NODE_FACTORY.bindTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef));
- }
+ String alias = boundTableNode.getAlias();
+ return NODE_FACTORY.bindTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef));
+ }
- @Override
- public TableNode visit(JoinTableNode joinNode) throws SQLException {
- TableNode lhs = joinNode.getLHS();
- TableNode rhs = joinNode.getRHS();
- TableNode lhsReplace = lhs.accept(this);
- TableNode rhsReplace = rhs.accept(this);
- if (lhs == lhsReplace && rhs == rhsReplace)
- return joinNode;
+ @Override
+ public TableNode visit(JoinTableNode joinNode) throws SQLException {
+ TableNode lhs = joinNode.getLHS();
+ TableNode rhs = joinNode.getRHS();
+ TableNode lhsReplace = lhs.accept(this);
+ TableNode rhsReplace = rhs.accept(this);
+ if (lhs == lhsReplace && rhs == rhsReplace)
+ return joinNode;
- return NODE_FACTORY.join(joinNode.getType(), lhsReplace, rhsReplace, joinNode.getOnNode(), joinNode.isSingleValueOnly());
- }
+ return NODE_FACTORY.join(joinNode.getType(), lhsReplace, rhsReplace, joinNode.getOnNode(), joinNode.isSingleValueOnly());
+ }
- @Override
- public TableNode visit(NamedTableNode namedTableNode)
- throws SQLException {
- TableRef tableRef = resolveTable(namedTableNode.getAlias(), namedTableNode.getName());
- TableRef replaceRef = replacement.get(tableRef);
- if (replaceRef == null)
- return namedTableNode;
+ @Override
+ public TableNode visit(NamedTableNode namedTableNode)
+ throws SQLException {
+ TableRef tableRef = resolveTable(namedTableNode.getAlias(), namedTableNode.getName());
+ TableRef replaceRef = replacement.get(tableRef);
+ if (replaceRef == null)
+ return namedTableNode;
- String alias = namedTableNode.getAlias();
- return NODE_FACTORY.namedTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef), namedTableNode.getDynamicColumns());
- }
+ String alias = namedTableNode.getAlias();
+ return NODE_FACTORY.namedTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef), namedTableNode.getDynamicColumns());
+ }
- @Override
- public TableNode visit(DerivedTableNode subselectNode)
- throws SQLException {
- return subselectNode;
- }
- }));
- }
+ @Override
+ public TableNode visit(DerivedTableNode subselectNode)
+ throws SQLException {
+ return subselectNode;
+ }
+ });
return IndexStatementRewriter.translate(NODE_FACTORY.select(select, newFrom), resolver, replacement);
}
@@ -1249,9 +1273,8 @@ public class JoinCompiler {
}
}
String tableAlias = tableRef.getTableAlias();
- List<? extends TableNode> from = Collections.singletonList(NODE_FACTORY.namedTable(tableAlias == null ? null : '"' + tableAlias + '"', tName, dynamicCols));
+ TableNode from = NODE_FACTORY.namedTable(tableAlias == null ? null : '"' + tableAlias + '"', tName, dynamicCols);
- // TODO: review, as it seems like we're potentially losing if the select statement is an aggregate (i.e. if it's an ungrouped aggregate for example)
return NODE_FACTORY.select(from, hintNode, false, selectList, where, groupBy, null, orderBy, null, 0, groupBy != null, hasSequence);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
index 214330c..b9ca813 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
@@ -247,7 +247,7 @@ public class QueryCompiler {
JoinSpec lastJoinSpec = joinSpecs.get(joinSpecs.size() - 1);
JoinType type = lastJoinSpec.getType();
if (type == JoinType.Full)
- throw new SQLFeatureNotSupportedException("Full joins not supported.");
+ throw new SQLFeatureNotSupportedException(type + " joins not supported.");
if (type == JoinType.Right || type == JoinType.Inner) {
if (!lastJoinSpec.getJoinTable().getJoinSpecs().isEmpty())
@@ -294,7 +294,7 @@ public class QueryCompiler {
if (rhs.getLimit() != null && !rhs.isAggregate() && !rhs.isDistinct() && rhs.getOrderBy().isEmpty()) {
limit = LimitCompiler.compile(context, rhs);
}
- HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, new List[] {joinExpressions}, new JoinType[] {type == JoinType.Inner ? type : JoinType.Left}, new boolean[] {true}, new PTable[] {lhsProjTable.getTable()}, new int[] {fieldPosition}, postJoinFilterExpression, limit, forceProjection);
+ HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, new List[] {joinExpressions}, new JoinType[] {type == JoinType.Right ? JoinType.Left : type}, new boolean[] {true}, new PTable[] {lhsProjTable.getTable()}, new int[] {fieldPosition}, postJoinFilterExpression, limit, forceProjection);
Pair<Expression, Expression> keyRangeExpressions = new Pair<Expression, Expression>(null, null);
getKeyExpressionCombinations(keyRangeExpressions, context, rhsTableRef, type, joinExpressions, hashExpressions);
return HashJoinPlan.create(joinTable.getStatement(), rhsPlan, joinInfo, new HashSubPlan[] {new HashSubPlan(0, lhsPlan, hashExpressions, false, keyRangeExpressions.getFirst(), keyRangeExpressions.getSecond(), lhsJoin.hasFilters())});
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
index 803f554..f6a6f7a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
@@ -37,7 +37,6 @@ import org.apache.phoenix.parse.ParseNode;
import org.apache.phoenix.parse.ParseNodeRewriter;
import org.apache.phoenix.parse.SelectStatement;
import org.apache.phoenix.parse.TableName;
-import org.apache.phoenix.parse.TableNode;
import org.apache.phoenix.parse.TableNodeVisitor;
import org.apache.phoenix.parse.TableWildcardParseNode;
import org.apache.phoenix.parse.WildcardParseNode;
@@ -88,13 +87,10 @@ public class StatementNormalizer extends ParseNodeRewriter {
if (selectNodes == normSelectNodes) {
normSelectNodes = Lists.newArrayList(selectNodes.subList(0, i));
}
- for (TableNode tNode : statement.getFrom()) {
- TableNameVisitor visitor = new TableNameVisitor();
- List<TableName> tableNames = tNode.accept(visitor);
- for (TableName tableName : tableNames) {
- TableWildcardParseNode node = NODE_FACTORY.tableWildcard(tableName);
- normSelectNodes.add(NODE_FACTORY.aliasedNode(null, node));
- }
+ List<TableName> tableNames = statement.getFrom().accept(new TableNameVisitor());
+ for (TableName tableName : tableNames) {
+ TableWildcardParseNode node = NODE_FACTORY.tableWildcard(tableName);
+ normSelectNodes.add(NODE_FACTORY.aliasedNode(null, node));
}
} else if (selectNodes != normSelectNodes) {
normSelectNodes.add(aliasedNode);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/SubqueryRewriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/SubqueryRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/SubqueryRewriter.java
index 3e470ce..01aca00 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/SubqueryRewriter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/SubqueryRewriter.java
@@ -83,13 +83,13 @@ public class SubqueryRewriter extends ParseNodeRewriter {
if (normWhere == where)
return select;
- return NODE_FACTORY.select(select, Collections.singletonList(rewriter.tableNode), normWhere);
+ return NODE_FACTORY.select(select, rewriter.tableNode, normWhere);
}
protected SubqueryRewriter(SelectStatement select, ColumnResolver resolver, PhoenixConnection connection) {
this.resolver = resolver;
this.connection = connection;
- this.tableNode = select.getFrom().get(0);
+ this.tableNode = select.getFrom();
this.topNode = null;
}
@@ -339,7 +339,7 @@ public class SubqueryRewriter extends ParseNodeRewriter {
groupbyNodes.set(i - 1, aliasedNode.getNode());
}
SelectStatement derivedTableStmt = NODE_FACTORY.select(subquery, subquery.isDistinct(), derivedTableSelect, where, derivedTableGroupBy, true);
- subquery = NODE_FACTORY.select(Collections.singletonList(NODE_FACTORY.derivedTable(derivedTableAlias, derivedTableStmt)), subquery.getHint(), false, selectNodes, null, groupbyNodes, null, Collections.<OrderByNode> emptyList(), null, subquery.getBindCount(), true, false);
+ subquery = NODE_FACTORY.select(NODE_FACTORY.derivedTable(derivedTableAlias, derivedTableStmt), subquery.getHint(), false, selectNodes, null, groupbyNodes, null, Collections.<OrderByNode> emptyList(), null, subquery.getBindCount(), true, false);
}
ParseNode onNode = conditionExtractor.getJoinCondition();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/SubselectRewriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/SubselectRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/SubselectRewriter.java
index 35ea900..d229478 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/SubselectRewriter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/SubselectRewriter.java
@@ -59,9 +59,9 @@ public class SubselectRewriter extends ParseNodeRewriter {
}
public static SelectStatement flatten(SelectStatement select, PhoenixConnection connection) throws SQLException {
- List<TableNode> from = select.getFrom();
- while (from.size() == 1 && from.get(0) instanceof DerivedTableNode) {
- DerivedTableNode derivedTable = (DerivedTableNode) from.get(0);
+ TableNode from = select.getFrom();
+ while (from != null && from instanceof DerivedTableNode) {
+ DerivedTableNode derivedTable = (DerivedTableNode) from;
SelectStatement subselect = derivedTable.getSelect();
ColumnResolver resolver = FromCompiler.getResolverForQuery(subselect, connection);
SubselectRewriter rewriter = new SubselectRewriter(resolver, subselect.getSelect(), derivedTable.getAlias());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index 44f62da..0be40b8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -381,7 +381,7 @@ public class UpsertCompiler {
selectResolver = FromCompiler.getResolverForQuery(transformedSelect, connection);
select = StatementNormalizer.normalize(transformedSelect, selectResolver);
}
- sameTable = select.getFrom().size() == 1
+ sameTable = !select.isJoin()
&& tableRefToBe.equals(selectResolver.getTables().get(0));
tableRefToBe = adjustTimestampToMinOfSameTable(tableRefToBe, selectResolver.getTables());
/* We can run the upsert in a coprocessor if:
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
index bf13eec..5c6018d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
@@ -80,6 +80,7 @@ public enum SQLExceptionCode {
VALUE_IN_LIST_NOT_CONSTANT(214, "22008", "Values in IN must evaluate to a constant."),
SINGLE_ROW_SUBQUERY_RETURNS_MULTIPLE_ROWS(215, "22015", "Single-row sub-query returns more than one row."),
SUBQUERY_RETURNS_DIFFERENT_NUMBER_OF_FIELDS(216, "22016", "Sub-query must return the same number of fields as the left-hand-side expression of 'IN'."),
+ AMBIGUOUS_JOIN_CONDITION(217, "22017", "Amibiguous or non-equi join condition specified. Consider using table list with where clause."),
/**
* Constraint Violation (errorcode 03, sqlstate 23)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
index f6b7736..c369be8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
@@ -292,7 +292,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
}
private static class ExecutableSelectStatement extends SelectStatement implements CompilableStatement {
- private ExecutableSelectStatement(List<? extends TableNode> from, HintNode hint, boolean isDistinct, List<AliasedNode> select, ParseNode where,
+ private ExecutableSelectStatement(TableNode from, HintNode hint, boolean isDistinct, List<AliasedNode> select, ParseNode where,
List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate, boolean hasSequence) {
super(from, hint, isDistinct, select, where, groupBy, having, orderBy, limit, bindCount, isAggregate, hasSequence);
}
@@ -796,7 +796,7 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
protected static class ExecutableNodeFactory extends ParseNodeFactory {
@Override
- public ExecutableSelectStatement select(List<? extends TableNode> from, HintNode hint, boolean isDistinct, List<AliasedNode> select,
+ public ExecutableSelectStatement select(TableNode from, HintNode hint, boolean isDistinct, List<AliasedNode> select,
ParseNode where, List<ParseNode> groupBy, ParseNode having,
List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate, boolean hasSequence) {
return new ExecutableSelectStatement(from, hint, isDistinct, select, where, groupBy == null ? Collections.<ParseNode>emptyList() : groupBy,
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java b/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
index f027ab3..8f6d026 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
@@ -214,9 +214,9 @@ public class QueryOptimizer {
schemaName = schemaName.length() == 0 ? null : '"' + schemaName + '"';
String tableName = '"' + index.getTableName().getString() + '"';
- List<? extends TableNode> tables = Collections.singletonList(FACTORY.namedTable(alias, FACTORY.table(schemaName, tableName)));
+ TableNode table = FACTORY.namedTable(alias, FACTORY.table(schemaName, tableName));
try {
- SelectStatement indexSelect = FACTORY.select(select, tables);
+ SelectStatement indexSelect = FACTORY.select(select, table);
ColumnResolver resolver = FromCompiler.getResolverForQuery(indexSelect, statement.getConnection());
// Check index state of now potentially updated index table to make sure it's active
if (PIndexState.ACTIVE.equals(resolver.getTables().get(0).getTable().getIndexState())) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinPartNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinPartNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinPartNode.java
deleted file mode 100644
index cdbaaea..0000000
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinPartNode.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.phoenix.parse;
-
-import org.apache.phoenix.parse.JoinTableNode.JoinType;
-
-/**
- *
- * Node representing the partial join clause in the FROM clause of SQL
- *
- *
- * @since 0.1
- */
-class JoinPartNode {
-
- private final JoinType type;
- private final ParseNode onNode;
- private final TableNode table;
-
- JoinPartNode(JoinType type, ParseNode onNode, TableNode table) {
- this.type = type;
- this.onNode = onNode;
- this.table = table;
- }
-
- JoinType getType() {
- return type;
- }
-
- ParseNode getOnNode() {
- return onNode;
- }
-
- TableNode getTable() {
- return table;
- }
-}
-
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
index 6f8339e..cc0b455 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -415,17 +415,6 @@ public class ParseNodeFactory {
return new IsNullParseNode(child, negate);
}
- public TableNode table(TableNode table, List<JoinPartNode> parts) {
- for (JoinPartNode part : parts) {
- table = new JoinTableNode(part.getType(), table, part.getTable(), part.getOnNode(), false);
- }
- return table;
- }
-
- JoinPartNode joinPart(JoinType type, ParseNode onNode, TableNode table) {
- return new JoinPartNode(type, onNode, table);
- }
-
public JoinTableNode join(JoinType type, TableNode lhs, TableNode rhs, ParseNode on, boolean singleValueOnly) {
return new JoinTableNode(type, lhs, rhs, on, singleValueOnly);
}
@@ -586,7 +575,7 @@ public class ParseNodeFactory {
return new OuterJoinParseNode(node);
}
- public SelectStatement select(List<? extends TableNode> from, HintNode hint, boolean isDistinct, List<AliasedNode> select, ParseNode where,
+ public SelectStatement select(TableNode from, HintNode hint, boolean isDistinct, List<AliasedNode> select, ParseNode where,
List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate, boolean hasSequence) {
return new SelectStatement(from, hint, isDistinct, select, where, groupBy == null ? Collections.<ParseNode>emptyList() : groupBy, having,
@@ -606,14 +595,14 @@ public class ParseNodeFactory {
statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
}
- public SelectStatement select(SelectStatement statement, List<? extends TableNode> tables) {
- return select(tables, statement.getHint(), statement.isDistinct(), statement.getSelect(), statement.getWhere(), statement.getGroupBy(),
+ public SelectStatement select(SelectStatement statement, TableNode table) {
+ return select(table, statement.getHint(), statement.isDistinct(), statement.getSelect(), statement.getWhere(), statement.getGroupBy(),
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(),
statement.hasSequence());
}
- public SelectStatement select(SelectStatement statement, List<? extends TableNode> tables, ParseNode where) {
- return select(tables, statement.getHint(), statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(),
+ public SelectStatement select(SelectStatement statement, TableNode table, ParseNode where) {
+ return select(table, statement.getHint(), statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(),
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(),
statement.hasSequence());
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
index 338a45b..809480f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
@@ -57,24 +57,8 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
*/
public static SelectStatement rewrite(SelectStatement statement, ParseNodeRewriter rewriter) throws SQLException {
Map<String,ParseNode> aliasMap = rewriter.getAliasMap();
- List<TableNode> from = statement.getFrom();
- List<TableNode> normFrom = from;
- TableNodeRewriter tableNodeRewriter = new TableNodeRewriter(rewriter);
- for (int i = 0; i < from.size(); i++) {
- TableNode tableNode = from.get(i);
- tableNodeRewriter.reset();
- TableNode normTableNode = tableNode.accept(tableNodeRewriter);
- if (normTableNode == tableNode) {
- if (from != normFrom) {
- normFrom.add(tableNode);
- }
- continue;
- }
- if (from == normFrom) {
- normFrom = Lists.newArrayList(from.subList(0, i));
- }
- normFrom.add(normTableNode);
- }
+ TableNode from = statement.getFrom();
+ TableNode normFrom = from.accept(new TableNodeRewriter(rewriter));
ParseNode where = statement.getWhere();
ParseNode normWhere = where;
if (where != null) {
@@ -541,9 +525,6 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
this.parseNodeRewriter = parseNodeRewriter;
}
- public void reset() {
- }
-
@Override
public TableNode visit(BindTableNode boundTableNode) throws SQLException {
return boundTableNode;
@@ -557,7 +538,7 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
TableNode normLhsNode = lhsNode.accept(this);
TableNode normRhsNode = rhsNode.accept(this);
parseNodeRewriter.reset();
- ParseNode normOnNode = onNode.accept(parseNodeRewriter);
+ ParseNode normOnNode = onNode == null ? null : onNode.accept(parseNodeRewriter);
if (lhsNode == normLhsNode && rhsNode == normRhsNode && onNode == normOnNode)
return joinNode;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/bfc92b04/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
index e7302dc..961846b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/SelectStatement.java
@@ -36,14 +36,14 @@ import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo;
public class SelectStatement implements FilterableStatement {
public static final SelectStatement SELECT_ONE =
new SelectStatement(
- Collections.<TableNode>emptyList(), null, false,
+ null, null, false,
Collections.<AliasedNode>singletonList(new AliasedNode(null, LiteralParseNode.ONE)),
null, Collections.<ParseNode>emptyList(),
null, Collections.<OrderByNode>emptyList(),
null, 0, false, false);
public static final SelectStatement COUNT_ONE =
new SelectStatement(
- Collections.<TableNode>emptyList(), null, false,
+ null, null, false,
Collections.<AliasedNode>singletonList(
new AliasedNode(null,
new AggregateFunctionParseNode(
@@ -80,7 +80,7 @@ public class SelectStatement implements FilterableStatement {
select.getOrderBy(), select.getLimit(), select.getBindCount(), select.isAggregate(), select.hasSequence());
}
- private final List<TableNode> fromTable;
+ private final TableNode fromTable;
private final HintNode hint;
private final boolean isDistinct;
private final List<AliasedNode> select;
@@ -104,10 +104,10 @@ public class SelectStatement implements FilterableStatement {
return count;
}
- protected SelectStatement(List<? extends TableNode> from, HintNode hint, boolean isDistinct, List<AliasedNode> select,
+ protected SelectStatement(TableNode from, HintNode hint, boolean isDistinct, List<AliasedNode> select,
ParseNode where, List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy, LimitNode limit,
int bindCount, boolean isAggregate, boolean hasSequence) {
- this.fromTable = Collections.unmodifiableList(from);
+ this.fromTable = from;
this.hint = hint == null ? HintNode.EMPTY_HINT_NODE : hint;
this.isDistinct = isDistinct;
this.select = Collections.unmodifiableList(select);
@@ -136,7 +136,7 @@ public class SelectStatement implements FilterableStatement {
return bindCount;
}
- public List<TableNode> getFrom() {
+ public TableNode getFrom() {
return fromTable;
}
@@ -190,13 +190,13 @@ public class SelectStatement implements FilterableStatement {
}
public boolean isJoin() {
- return fromTable.size() > 1 || (fromTable.size() > 0 && fromTable.get(0) instanceof JoinTableNode);
+ return fromTable != null && fromTable instanceof JoinTableNode;
}
public SelectStatement getInnerSelectStatement() {
- if (fromTable.size() != 1 || !(fromTable.get(0) instanceof DerivedTableNode))
+ if (fromTable == null || !(fromTable instanceof DerivedTableNode))
return null;
- return ((DerivedTableNode) fromTable.get(0)).getSelect();
+ return ((DerivedTableNode) fromTable).getSelect();
}
}