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 2015/04/16 16:32:08 UTC
[27/50] [abbrv] phoenix git commit: PHOENIX-1807 Support UNION
queries in subquery
PHOENIX-1807 Support UNION queries in subquery
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/9ddb484a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/9ddb484a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/9ddb484a
Branch: refs/heads/calcite
Commit: 9ddb484aaf0b84b729be9b699b0528813b4ffb1b
Parents: 7aea692
Author: maryannxue <we...@intel.com>
Authored: Mon Apr 6 23:16:20 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Mon Apr 6 23:16:20 2015 -0400
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/UnionAllIT.java | 91 +++++++++++++++++---
phoenix-core/src/main/antlr3/PhoenixSQL.g | 2 +-
.../apache/phoenix/compile/DeleteCompiler.java | 2 +-
.../apache/phoenix/compile/FromCompiler.java | 2 +-
.../apache/phoenix/compile/JoinCompiler.java | 4 +-
.../apache/phoenix/compile/QueryCompiler.java | 4 +-
.../phoenix/compile/SubqueryRewriter.java | 19 ++--
.../apache/phoenix/compile/UnionCompiler.java | 6 +-
.../apache/phoenix/jdbc/PhoenixStatement.java | 10 +--
.../apache/phoenix/optimize/QueryOptimizer.java | 2 +-
.../apache/phoenix/parse/ParseNodeFactory.java | 72 ++++++++++------
.../apache/phoenix/parse/SelectStatement.java | 33 ++++---
12 files changed, 173 insertions(+), 74 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UnionAllIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UnionAllIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UnionAllIT.java
index b3b2f7d..1d4055a 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UnionAllIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UnionAllIT.java
@@ -28,7 +28,6 @@ import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.Collections;
import java.util.Map;
@@ -424,7 +423,7 @@ public class UnionAllIT extends BaseOwnClusterHBaseManagedTimeIT {
}
@Test
- public void testUnionAllInSubquery() throws Exception {
+ public void testUnionAllInDerivedTable() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
conn.setAutoCommit(false);
@@ -435,21 +434,63 @@ public class UnionAllIT extends BaseOwnClusterHBaseManagedTimeIT {
" CONSTRAINT pk PRIMARY KEY (a_string))\n";
createTestTable(getUrl(), ddl);
+ String dml = "UPSERT INTO test_table VALUES(?, ?)";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "a");
+ stmt.setInt(2, 10);
+ stmt.execute();
+ stmt.setString(1, "b");
+ stmt.setInt(2, 20);
+ stmt.execute();
+ conn.commit();
+
ddl = "CREATE TABLE b_table " +
- " (a_string varchar not null, col1 integer" +
+ " (a_string varchar not null, col2 integer" +
" CONSTRAINT pk PRIMARY KEY (a_string))\n";
createTestTable(getUrl(), ddl);
- ddl = "select a_string, col1 from test_table where a_string in (select a_string from test_table union all select a_string from b_table)";
- conn.createStatement().executeQuery(ddl);
- } catch (SQLFeatureNotSupportedException e) {
+ dml = "UPSERT INTO b_table VALUES(?, ?)";
+ stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "a");
+ stmt.setInt(2, 30);
+ stmt.execute();
+ stmt.setString(1, "c");
+ stmt.setInt(2, 60);
+ stmt.execute();
+ conn.commit();
+
+ String query = "select a_string from " +
+ "(select a_string, col1 from test_table union all select a_string, col2 from b_table order by a_string)";
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("b", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("c", rs.getString(1));
+ assertFalse(rs.next());
+
+ query = "select c from " +
+ "(select a_string, col1 c from test_table union all select a_string, col2 c from b_table order by c)";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(10, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(20, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(30, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(60, rs.getInt(1));
+ assertFalse(rs.next());
} finally {
conn.close();
}
}
@Test
- public void testUnionAllInSubqueryDerived() throws Exception {
+ public void testUnionAllInSubquery() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
conn.setAutoCommit(false);
@@ -460,15 +501,43 @@ public class UnionAllIT extends BaseOwnClusterHBaseManagedTimeIT {
" CONSTRAINT pk PRIMARY KEY (a_string))\n";
createTestTable(getUrl(), ddl);
+ String dml = "UPSERT INTO test_table VALUES(?, ?)";
+ PreparedStatement stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "a");
+ stmt.setInt(2, 10);
+ stmt.execute();
+ stmt.setString(1, "b");
+ stmt.setInt(2, 20);
+ stmt.execute();
+ conn.commit();
+
ddl = "CREATE TABLE b_table " +
" (a_string varchar not null, col1 integer" +
" CONSTRAINT pk PRIMARY KEY (a_string))\n";
createTestTable(getUrl(), ddl);
- ddl = "select a_string, col1 from test_table where a_string in (select a_string from " +
- "(select * from test_table union all select * from b_table))";
- conn.createStatement().executeQuery(ddl);
- } catch (SQLException e) {
+ dml = "UPSERT INTO b_table VALUES(?, ?)";
+ stmt = conn.prepareStatement(dml);
+ stmt.setString(1, "a");
+ stmt.setInt(2, 30);
+ stmt.execute();
+ stmt.setString(1, "c");
+ stmt.setInt(2, 60);
+ stmt.execute();
+ conn.commit();
+
+ String[] queries = new String[2];
+ queries[0] = "select a_string, col1 from test_table where a_string in " +
+ "(select a_string aa from b_table where a_string != 'a' union all select a_string bb from b_table)";
+ queries[1] = "select a_string, col1 from test_table where a_string in (select a_string from " +
+ "(select a_string from b_table where a_string != 'a' union all select a_string from b_table))";
+ for (String query : queries) {
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals(10, rs.getInt(2));
+ assertFalse(rs.next());
+ }
} finally {
conn.close();
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 295bd79..9f60424 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -586,7 +586,7 @@ single_select returns [SelectStatement ret]
(WHERE where=expression)?
(GROUP BY group=group_by)?
(HAVING having=expression)?
- { ParseContext context = contextStack.peek(); $ret = factory.select(from, h, d!=null, sel, where, group, having, null, null, getBindCount(), context.isAggregate(), context.hasSequences()); }
+ { ParseContext context = contextStack.peek(); $ret = factory.select(from, h, d!=null, sel, where, group, having, null, null, getBindCount(), context.isAggregate(), context.hasSequences(), null); }
;
finally{ contextStack.pop(); }
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 322d24a..b8e68f9 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
@@ -322,7 +322,7 @@ public class DeleteCompiler {
hint, false, aliasedNodes, delete.getWhere(),
Collections.<ParseNode>emptyList(), null,
delete.getOrderBy(), delete.getLimit(),
- delete.getBindCount(), false, false);
+ delete.getBindCount(), false, false, Collections.<SelectStatement>emptyList());
select = StatementNormalizer.normalize(select, resolver);
SelectStatement transformedSelect = SubqueryRewriter.transform(select, resolver, connection);
if (transformedSelect != select) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 98a1108..da78b24 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
@@ -469,7 +469,7 @@ public class FromCompiler {
if (node instanceof WildcardParseNode
|| node instanceof TableWildcardParseNode
|| node instanceof FamilyWildcardParseNode)
- throw new SQLException("Encountered wildcard in subqueries.");
+ throw new SQLFeatureNotSupportedException("Wildcard in subqueries not supported.");
alias = SchemaUtil.normalizeIdentifier(node.getAlias());
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 98b7edb..af6c712 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
@@ -688,7 +688,7 @@ public class JoinCompiler {
if (isSubselect())
return SubselectRewriter.applyOrderBy(SubselectRewriter.applyPostFilters(subselect, preFilters, tableNode.getAlias()), orderBy, tableNode.getAlias());
- return NODE_FACTORY.select(tableNode, select.getHint(), false, selectNodes, getPreFiltersCombined(), null, null, orderBy, null, 0, false, select.hasSequence());
+ return NODE_FACTORY.select(tableNode, select.getHint(), false, selectNodes, getPreFiltersCombined(), null, null, orderBy, null, 0, false, select.hasSequence(), Collections.<SelectStatement>emptyList());
}
public boolean hasFilters() {
@@ -1267,7 +1267,7 @@ public class JoinCompiler {
String tableAlias = tableRef.getTableAlias();
TableNode from = NODE_FACTORY.namedTable(tableAlias == null ? null : '"' + tableAlias + '"', tName, dynamicCols);
- return NODE_FACTORY.select(from, hintNode, false, selectList, where, groupBy, null, orderBy, null, 0, groupBy != null, hasSequence);
+ return NODE_FACTORY.select(from, hintNode, false, selectList, where, groupBy, null, orderBy, null, 0, groupBy != null, hasSequence, Collections.<SelectStatement>emptyList());
}
public static PTable joinProjectedTables(PTable left, PTable right, JoinType type) throws SQLException {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 f8177e6..16a7a33 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
@@ -174,7 +174,7 @@ public class QueryCompiler {
}
UnionCompiler.checkProjectionNumAndTypes(plans);
- TableRef tableRef = UnionCompiler.contructSchemaTable(statement, plans.get(0));
+ TableRef tableRef = UnionCompiler.contructSchemaTable(statement, plans.get(0), select.hasWildcard() ? null : select.getSelect());
ColumnResolver resolver = FromCompiler.getResolver(tableRef);
StatementContext context = new StatementContext(statement, resolver, scan, sequenceManager);
@@ -422,7 +422,7 @@ public class QueryCompiler {
context.setResolver(resolver);
TableNode from = NODE_FACTORY.namedTable(tableRef.getTableAlias(), NODE_FACTORY.table(tableRef.getTable().getSchemaName().getString(), tableRef.getTable().getTableName().getString()));
ParseNode where = joinTable.getPostFiltersCombined();
- SelectStatement select = asSubquery ? NODE_FACTORY.select(from, joinTable.getStatement().getHint(), false, Collections.<AliasedNode> emptyList(), where, null, null, orderBy, null, 0, false, joinTable.getStatement().hasSequence())
+ SelectStatement select = asSubquery ? NODE_FACTORY.select(from, joinTable.getStatement().getHint(), false, Collections.<AliasedNode> emptyList(), where, null, null, orderBy, null, 0, false, joinTable.getStatement().hasSequence(), Collections.<SelectStatement>emptyList())
: NODE_FACTORY.select(joinTable.getStatement(), from, where);
return compileSingleFlatQuery(context, select, binds, asSubquery, false, innerPlan, null, isInRowKeyOrder);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 60067e5..8e887a8 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
@@ -36,6 +36,7 @@ import org.apache.phoenix.parse.ColumnParseNode;
import org.apache.phoenix.parse.ComparisonParseNode;
import org.apache.phoenix.parse.CompoundParseNode;
import org.apache.phoenix.parse.ExistsParseNode;
+import org.apache.phoenix.parse.HintNode;
import org.apache.phoenix.parse.InParseNode;
import org.apache.phoenix.parse.JoinTableNode.JoinType;
import org.apache.phoenix.parse.LiteralParseNode;
@@ -139,7 +140,7 @@ public class SubqueryRewriter extends ParseNodeRewriter {
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) l.get(1);
- SelectStatement subquery = subqueryNode.getSelectNode();
+ SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
List<AliasedNode> selectNodes = fixAliasedNodes(subquery.getSelect(), true);
subquery = NODE_FACTORY.select(subquery, !node.isSubqueryDistinct(), selectNodes);
@@ -160,7 +161,7 @@ public class SubqueryRewriter extends ParseNodeRewriter {
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) l.get(0);
- SelectStatement subquery = subqueryNode.getSelectNode();
+ SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
JoinConditionExtractor conditionExtractor = new JoinConditionExtractor(subquery, resolver, connection, rhsTableAlias);
ParseNode where = subquery.getWhere() == null ? null : subquery.getWhere().accept(conditionExtractor);
@@ -199,7 +200,7 @@ public class SubqueryRewriter extends ParseNodeRewriter {
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) secondChild;
- SelectStatement subquery = subqueryNode.getSelectNode();
+ SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
JoinConditionExtractor conditionExtractor = new JoinConditionExtractor(subquery, resolver, connection, rhsTableAlias);
ParseNode where = subquery.getWhere() == null ? null : subquery.getWhere().accept(conditionExtractor);
@@ -282,7 +283,7 @@ public class SubqueryRewriter extends ParseNodeRewriter {
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) firstChild;
- SelectStatement subquery = subqueryNode.getSelectNode();
+ SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
JoinConditionExtractor conditionExtractor = new JoinConditionExtractor(subquery, resolver, connection, rhsTableAlias);
ParseNode where = subquery.getWhere() == null ? null : subquery.getWhere().accept(conditionExtractor);
@@ -339,7 +340,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(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, Collections.<SelectStatement>emptyList());
}
ParseNode onNode = conditionExtractor.getJoinCondition();
@@ -357,6 +358,14 @@ public class SubqueryRewriter extends ParseNodeRewriter {
return Lists.newArrayList(firstChild, secondChild);
}
+ private SelectStatement fixSubqueryStatement(SelectStatement select) {
+ if (!select.isUnion())
+ return select;
+
+ // Wrap as a derived table.
+ return NODE_FACTORY.select(NODE_FACTORY.derivedTable(ParseNodeFactory.createTempAlias(), select), HintNode.EMPTY_HINT_NODE, false, select.getSelect(), null, null, null, null, null, select.getBindCount(), false, false, Collections.<SelectStatement> emptyList());
+ }
+
private List<AliasedNode> fixAliasedNodes(List<AliasedNode> nodes, boolean addSelectOne) {
List<AliasedNode> normNodes = Lists.<AliasedNode> newArrayListWithExpectedSize(nodes.size() + (addSelectOne ? 1 : 0));
if (addSelectOne) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
index 3f069ff..269232e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UnionCompiler.java
@@ -26,6 +26,7 @@ import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.exception.SQLExceptionInfo;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.AliasedNode;
import org.apache.phoenix.schema.PColumn;
import org.apache.phoenix.schema.PColumnImpl;
import org.apache.phoenix.schema.PName;
@@ -66,12 +67,13 @@ public class UnionCompiler {
return selectPlans;
}
- public static TableRef contructSchemaTable(PhoenixStatement statement, QueryPlan plan) throws SQLException {
+ public static TableRef contructSchemaTable(PhoenixStatement statement, QueryPlan plan, List<AliasedNode> selectNodes) throws SQLException {
List<PColumn> projectedColumns = new ArrayList<PColumn>();
for (int i=0; i< plan.getProjector().getColumnCount(); i++) {
ColumnProjector colProj = plan.getProjector().getColumnProjector(i);
Expression sourceExpression = colProj.getExpression();
- PColumnImpl projectedColumn = new PColumnImpl(PNameFactory.newName(colProj.getName()), UNION_FAMILY_NAME,
+ String name = selectNodes == null ? colProj.getName() : selectNodes.get(i).getAlias();
+ PColumnImpl projectedColumn = new PColumnImpl(PNameFactory.newName(name), UNION_FAMILY_NAME,
sourceExpression.getDataType(), sourceExpression.getMaxLength(), sourceExpression.getScale(), sourceExpression.isNullable(),
i, sourceExpression.getSortOrder(), 500, null, false, sourceExpression.toString());
projectedColumns.add(projectedColumn);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 462e1f0..dfb9779 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
@@ -898,19 +898,11 @@ public class PhoenixStatement implements Statement, SQLCloseable, org.apache.pho
protected static class ExecutableNodeFactory extends ParseNodeFactory {
@Override
- 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 this.select(from, hint, isDistinct, select, where, groupBy, having, orderBy, limit, bindCount, isAggregate, hasSequence,
- Collections.<SelectStatement>emptyList());
- }
-
- @Override
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, List<SelectStatement> selects) {
return new ExecutableSelectStatement(from, hint, isDistinct, select, where, groupBy == null ? Collections.<ParseNode>emptyList() : groupBy,
- having, orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate, hasSequence, selects);
+ having, orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate, hasSequence, selects == null ? Collections.<SelectStatement>emptyList() : selects);
}
@Override
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 382bba5..7b3a63a 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
@@ -290,7 +290,7 @@ public class QueryOptimizer {
aliasedNodes.add(FACTORY.aliasedNode(null, indexColNode));
nodes.add(new ColumnParseNode(null, '"' + column.getName().getString() + '"'));
}
- SelectStatement innerSelect = FACTORY.select(indexSelect.getFrom(), indexSelect.getHint(), false, aliasedNodes, where, null, null, null, indexSelect.getLimit(), indexSelect.getBindCount(), false, indexSelect.hasSequence());
+ SelectStatement innerSelect = FACTORY.select(indexSelect.getFrom(), indexSelect.getHint(), false, aliasedNodes, where, null, null, null, indexSelect.getLimit(), indexSelect.getBindCount(), false, indexSelect.hasSequence(), Collections.<SelectStatement>emptyList());
ParseNode outerWhere = FACTORY.in(nodes.size() == 1 ? nodes.get(0) : FACTORY.rowValueConstructor(nodes), FACTORY.subquery(innerSelect, false), false, true);
ParseNode extractedCondition = whereRewriter.getExtractedCondition();
if (extractedCondition != null) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 0f5074e..5eb641e 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
@@ -20,7 +20,6 @@ package org.apache.phoenix.parse;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -29,6 +28,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.exception.SQLExceptionInfo;
import org.apache.phoenix.exception.UnknownFunctionException;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.expression.ExpressionType;
@@ -659,15 +660,8 @@ public class ParseNodeFactory {
boolean hasSequence, List<SelectStatement> selects) {
return new SelectStatement(from, hint, isDistinct, select, where, groupBy == null ? Collections.<ParseNode>emptyList() : groupBy, having,
- orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate, hasSequence, selects);
+ orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate, hasSequence, selects == null ? Collections.<SelectStatement>emptyList() : selects);
}
-
- 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,
- orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate, hasSequence);
- }
public UpsertStatement upsert(NamedTableNode table, HintNode hint, List<ColumnName> columns, List<ParseNode> values, SelectStatement select, int bindCount) {
return new UpsertStatement(table, hint, columns, values, select, bindCount);
@@ -679,53 +673,53 @@ public class ParseNodeFactory {
public SelectStatement select(SelectStatement statement, ParseNode where) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(), statement.getHaving(),
- statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, ParseNode where, ParseNode having) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(), having,
- statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, List<AliasedNode> select, ParseNode where, List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(),
- select, where, groupBy, having, orderBy, statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ select, where, groupBy, having, orderBy, statement.getLimit(), statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
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());
+ statement.hasSequence(), statement.getSelects());
}
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());
+ statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, boolean isDistinct, List<AliasedNode> select) {
return select(statement.getFrom(), statement.getHint(), isDistinct, select, statement.getWhere(), statement.getGroupBy(),
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(),
- statement.hasSequence());
+ statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, boolean isDistinct, List<AliasedNode> select, ParseNode where) {
return select(statement.getFrom(), statement.getHint(), isDistinct, select, where, statement.getGroupBy(),
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(),
- statement.hasSequence());
+ statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, boolean isDistinct, List<AliasedNode> select, ParseNode where, List<ParseNode> groupBy, boolean isAggregate) {
return select(statement.getFrom(), statement.getHint(), isDistinct, select, where, groupBy,
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), isAggregate,
- statement.hasSequence());
+ statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, List<OrderByNode> orderBy) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(),
statement.getWhere(), statement.getGroupBy(), statement.getHaving(), orderBy, statement.getLimit(),
- statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, HintNode hint) {
@@ -737,39 +731,65 @@ public class ParseNodeFactory {
public SelectStatement select(SelectStatement statement, HintNode hint, ParseNode where) {
return select(statement.getFrom(), hint, statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(),
statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate(),
- statement.hasSequence());
+ statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(),
statement.getWhere(), statement.getGroupBy(), statement.getHaving(), orderBy, limit,
- bindCount, isAggregate || statement.isAggregate(), statement.hasSequence());
+ bindCount, isAggregate || statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, LimitNode limit) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(),
statement.getWhere(), statement.getGroupBy(), statement.getHaving(), statement.getOrderBy(), limit,
- statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(SelectStatement statement, List<OrderByNode> orderBy, LimitNode limit) {
return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(),
statement.getWhere(), statement.getGroupBy(), statement.getHaving(), orderBy, limit,
- statement.getBindCount(), statement.isAggregate(), statement.hasSequence());
+ statement.getBindCount(), statement.isAggregate(), statement.hasSequence(), statement.getSelects());
}
public SelectStatement select(List<SelectStatement> statements, List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate) {
if (statements.size() == 1)
- return select(statements.get(0), orderBy, limit, bindCount, isAggregate);
+ return select(statements.get(0), orderBy, limit, bindCount, isAggregate);
+
+ // Get a list of adjusted aliases from a non-wildcard sub-select if any.
+ // We do not check the number of select nodes among all sub-selects, as
+ // it will be done later at compile stage. Empty or different aliases
+ // are ignored, since they cannot be referred by outer queries.
+ List<String> aliases = Lists.<String> newArrayList();
+ for (int i = 0; i < statements.size() && aliases.isEmpty(); i++) {
+ SelectStatement subselect = statements.get(i);
+ if (!subselect.hasWildcard()) {
+ for (AliasedNode aliasedNode : subselect.getSelect()) {
+ String alias = aliasedNode.getAlias();
+ if (alias == null) {
+ alias = SchemaUtil.normalizeIdentifier(aliasedNode.getNode().getAlias());
+ }
+ aliases.add(alias == null ? createTempAlias() : alias);
+ }
+ }
+ }
+
+ List<AliasedNode> aliasedNodes;
+ if (aliases.isEmpty()) {
+ aliasedNodes = Lists.newArrayList(aliasedNode(null, wildcard()));
+ } else {
+ aliasedNodes = Lists.newArrayListWithExpectedSize(aliases.size());
+ for (String alias : aliases) {
+ aliasedNodes.add(aliasedNode(alias, column(null, alias, alias)));
+ }
+ }
- return select(null, HintNode.EMPTY_HINT_NODE, false, Lists.newArrayList(aliasedNode(null, wildcard())),
+ return select(null, HintNode.EMPTY_HINT_NODE, false, aliasedNodes,
null, null, null, orderBy, limit, bindCount, false, false, statements);
}
public SubqueryParseNode subquery(SelectStatement select, boolean expectSingleRow) {
- if (select.isUnion())
- throw new RuntimeException(new SQLFeatureNotSupportedException());
return new SubqueryParseNode(select, expectSingleRow);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9ddb484a/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 08cec87..44b24af 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
@@ -42,7 +42,7 @@ public class SelectStatement implements FilterableStatement {
Collections.<AliasedNode>singletonList(new AliasedNode(null, LiteralParseNode.ONE)),
null, Collections.<ParseNode>emptyList(),
null, Collections.<OrderByNode>emptyList(),
- null, 0, false, false);
+ null, 0, false, false, Collections.<SelectStatement>emptyList());
public static final SelectStatement COUNT_ONE =
new SelectStatement(
null, null, false,
@@ -54,14 +54,14 @@ public class SelectStatement implements FilterableStatement {
new BuiltInFunctionInfo(CountAggregateFunction.class, CountAggregateFunction.class.getAnnotation(BuiltInFunction.class))))),
null, Collections.<ParseNode>emptyList(),
null, Collections.<OrderByNode>emptyList(),
- null, 0, true, false);
+ null, 0, true, false, Collections.<SelectStatement>emptyList());
public static SelectStatement create(SelectStatement select, HintNode hint) {
if (select.getHint() == hint || hint.isEmpty()) {
return select;
}
return new SelectStatement(select.getFrom(), hint, select.isDistinct(),
select.getSelect(), select.getWhere(), select.getGroupBy(), select.getHaving(),
- select.getOrderBy(), select.getLimit(), select.getBindCount(), select.isAggregate(), select.hasSequence());
+ select.getOrderBy(), select.getLimit(), select.getBindCount(), select.isAggregate(), select.hasSequence(), select.getSelects());
}
public SelectStatement combine(ParseNode where) {
@@ -73,13 +73,13 @@ public class SelectStatement implements FilterableStatement {
}
return new SelectStatement(this.getFrom(), this.getHint(), this.isDistinct(),
this.getSelect(), where, this.getGroupBy(), this.getHaving(),
- this.getOrderBy(), this.getLimit(), this.getBindCount(), this.isAggregate(), this.hasSequence());
+ this.getOrderBy(), this.getLimit(), this.getBindCount(), this.isAggregate(), this.hasSequence(), this.selects);
}
public static SelectStatement create(SelectStatement select, List<AliasedNode> selects) {
return new SelectStatement(select.getFrom(), select.getHint(), select.isDistinct(),
selects, select.getWhere(), select.getGroupBy(), select.getHaving(),
- select.getOrderBy(), select.getLimit(), select.getBindCount(), select.isAggregate(), select.hasSequence());
+ select.getOrderBy(), select.getLimit(), select.getBindCount(), select.isAggregate(), select.hasSequence(), select.getSelects());
}
// Copy constructor for sub select statements in a union
@@ -87,7 +87,7 @@ public class SelectStatement implements FilterableStatement {
List<OrderByNode> orderBy, LimitNode limit, boolean isAggregate) {
return new SelectStatement(select.getFrom(), select.getHint(), select.isDistinct(),
select.getSelect(), select.getWhere(), select.getGroupBy(), select.getHaving(),
- orderBy, limit, select.getBindCount(), isAggregate, select.hasSequence());
+ orderBy, limit, select.getBindCount(), isAggregate, select.hasSequence(), select.getSelects());
}
private final TableNode fromTable;
@@ -102,6 +102,7 @@ public class SelectStatement implements FilterableStatement {
private final int bindCount;
private final boolean isAggregate;
private final boolean hasSequence;
+ private final boolean hasWildcard;
private final List<SelectStatement> selects = new ArrayList<SelectStatement>();
@Override
@@ -228,17 +229,19 @@ public class SelectStatement implements FilterableStatement {
this.bindCount = bindCount;
this.isAggregate = isAggregate || groupBy.size() != countConstants(groupBy) || this.having != null;
this.hasSequence = hasSequence;
+ boolean hasWildcard = false;
+ for (AliasedNode aliasedNode : select) {
+ ParseNode node = aliasedNode.getNode();
+ if (node instanceof WildcardParseNode || node instanceof TableWildcardParseNode || node instanceof FamilyWildcardParseNode) {
+ hasWildcard = true;
+ break;
+ }
+ }
+ this.hasWildcard = hasWildcard;
if (!selects.isEmpty()) {
this.selects.addAll(selects);
}
}
-
- public 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(from, hint, isDistinct, select, where, groupBy, having, orderBy, limit, bindCount, isAggregate, hasSequence,
- Collections.<SelectStatement>emptyList());
- }
@Override
public boolean isDistinct() {
@@ -326,4 +329,8 @@ public class SelectStatement implements FilterableStatement {
public List<SelectStatement> getSelects() {
return selects;
}
+
+ public boolean hasWildcard() {
+ return hasWildcard;
+ }
}