Return-Path: X-Original-To: apmail-phoenix-commits-archive@minotaur.apache.org Delivered-To: apmail-phoenix-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 76EB110F3F for ; Wed, 12 Feb 2014 05:00:25 +0000 (UTC) Received: (qmail 6461 invoked by uid 500); 12 Feb 2014 05:00:23 -0000 Delivered-To: apmail-phoenix-commits-archive@phoenix.apache.org Received: (qmail 6422 invoked by uid 500); 12 Feb 2014 05:00:23 -0000 Mailing-List: contact commits-help@phoenix.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@phoenix.incubator.apache.org Delivered-To: mailing list commits@phoenix.incubator.apache.org Received: (qmail 6359 invoked by uid 99); 12 Feb 2014 05:00:21 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 12 Feb 2014 05:00:21 +0000 X-ASF-Spam-Status: No, hits=-2000.6 required=5.0 tests=ALL_TRUSTED,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 12 Feb 2014 05:00:17 +0000 Received: (qmail 6171 invoked by uid 99); 12 Feb 2014 04:59:57 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 12 Feb 2014 04:59:57 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id C5BA255032; Wed, 12 Feb 2014 04:59:56 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: maryannxue@apache.org To: commits@phoenix.incubator.apache.org Date: Wed, 12 Feb 2014 04:59:57 -0000 Message-Id: In-Reply-To: <3f9ff94718794665acd1bd85c5570ee9@git.apache.org> References: <3f9ff94718794665acd1bd85c5570ee9@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/4] git commit: Fix PHOENIX-33 Support table-wildcard select in join queries X-Virus-Checked: Checked by ClamAV on apache.org Fix PHOENIX-33 Support table-wildcard select in join queries Project: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/commit/7ac4ee2d Tree: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/tree/7ac4ee2d Diff: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/diff/7ac4ee2d Branch: refs/heads/master Commit: 7ac4ee2dffea9f1f67462f999870fd7431658eb5 Parents: a977a75 Author: maryannxue Authored: Tue Feb 11 22:58:18 2014 -0500 Committer: maryannxue Committed: Tue Feb 11 22:58:18 2014 -0500 ---------------------------------------------------------------------- phoenix-core/src/main/antlr3/PhoenixSQL.g | 1 + .../apache/phoenix/compile/ColumnResolver.java | 10 + .../apache/phoenix/compile/FromCompiler.java | 14 +- .../phoenix/compile/IndexStatementRewriter.java | 40 +- .../apache/phoenix/compile/JoinCompiler.java | 119 ++--- .../apache/phoenix/compile/PostDDLCompiler.java | 5 + .../phoenix/compile/ProjectionCompiler.java | 56 ++- .../apache/phoenix/compile/QueryCompiler.java | 18 +- .../phoenix/compile/StatementNormalizer.java | 89 +++- .../org/apache/phoenix/parse/BindTableNode.java | 10 +- .../apache/phoenix/parse/ConcreteTableNode.java | 4 +- .../apache/phoenix/parse/DerivedTableNode.java | 4 +- .../org/apache/phoenix/parse/JoinTableNode.java | 2 +- .../apache/phoenix/parse/NamedTableNode.java | 12 +- .../apache/phoenix/parse/ParseNodeFactory.java | 4 + .../apache/phoenix/parse/ParseNodeRewriter.java | 5 + .../apache/phoenix/parse/ParseNodeVisitor.java | 3 +- .../org/apache/phoenix/parse/TableNode.java | 10 - .../phoenix/parse/TableWildcardParseNode.java | 52 ++ .../parse/TraverseAllParseNodeVisitor.java | 5 + .../parse/TraverseNoParseNodeVisitor.java | 5 + .../parse/UnsupportedAllParseNodeVisitor.java | 5 + .../phoenix/compile/JoinQueryCompileTest.java | 38 +- .../apache/phoenix/end2end/HashJoinTest.java | 495 ++++++++++++------- ...RangeParallelIteratorRegionSplitterTest.java | 7 + .../query/BaseConnectionlessQueryTest.java | 16 +- .../java/org/apache/phoenix/query/BaseTest.java | 16 +- .../java/org/apache/phoenix/util/TestUtil.java | 21 +- 28 files changed, 720 insertions(+), 346 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 53abed6..5370673 100644 --- a/phoenix-core/src/main/antlr3/PhoenixSQL.g +++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g @@ -600,6 +600,7 @@ select_list returns [List ret] selectable returns [AliasedNode ret] : field=expression (a=parseAlias)? { $ret = factory.aliasedNode(a, field); } | familyName=identifier DOT ASTERISK { $ret = factory.aliasedNode(null, factory.family(familyName));} // i.e. the 'cf.*' in 'select cf.* from' cf being column family of an hbase table + | tableName=table_name DOT ASTERISK { $ret = factory.aliasedNode(null, factory.tableWildcard(tableName)); } ; http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/compile/ColumnResolver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ColumnResolver.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ColumnResolver.java index 6c8abe7..2ba418e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ColumnResolver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ColumnResolver.java @@ -43,6 +43,16 @@ public interface ColumnResolver { public List getTables(); /** + * Resolves table using name or alias. + * @param schemaName the schema name + * @param tableName the table name or table alias + * @return the resolved TableRef + * @throws TableNotFoundException if the table could not be resolved + * @throws AmbiguousTableException if the table name is ambiguous + */ + public TableRef resolveTable(String schemaName, String tableName) throws SQLException; + + /** * Resolves column using name and alias. * @param schemaName TODO * @param tableName TODO http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 92f11bc..296ce79 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 @@ -87,6 +87,12 @@ public class FromCompiler { } @Override + public TableRef resolveTable(String schemaName, String tableName) + throws SQLException { + throw new UnsupportedOperationException(); + } + + @Override public ColumnRef resolveColumn(String schemaName, String tableName, String colName) throws SQLException { throw new UnsupportedOperationException(); } @@ -237,6 +243,12 @@ public class FromCompiler { return tableRefs; } + @Override + public TableRef resolveTable(String schemaName, String tableName) + throws SQLException { + throw new UnsupportedOperationException(); + } + @Override public ColumnRef resolveColumn(String schemaName, String tableName, String colName) throws SQLException { @@ -388,7 +400,7 @@ public class FromCompiler { } } - private TableRef resolveTable(String schemaName, String tableName) throws SQLException { + public TableRef resolveTable(String schemaName, String tableName) throws SQLException { String fullTableName = SchemaUtil.getTableName(schemaName, tableName); List tableRefs = tableMap.get(fullTableName); if (tableRefs.size() == 0) { http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexStatementRewriter.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexStatementRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexStatementRewriter.java index 66349f7..c4a690a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexStatementRewriter.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexStatementRewriter.java @@ -10,6 +10,7 @@ import org.apache.phoenix.parse.ParseNodeFactory; import org.apache.phoenix.parse.ParseNodeRewriter; import org.apache.phoenix.parse.SelectStatement; import org.apache.phoenix.parse.TableName; +import org.apache.phoenix.parse.TableWildcardParseNode; import org.apache.phoenix.parse.WildcardParseNode; import org.apache.phoenix.schema.ColumnRef; import org.apache.phoenix.schema.PDataType; @@ -54,20 +55,10 @@ public class IndexStatementRewriter extends ParseNodeRewriter { @Override public ParseNode visit(ColumnParseNode node) throws SQLException { ColumnRef dataColRef = getResolver().resolveColumn(node.getSchemaName(), node.getTableName(), node.getName()); - TableName tName = null; - if (multiTableRewriteMap != null) { - TableRef origRef = dataColRef.getTableRef(); - TableRef tableRef = multiTableRewriteMap.get(origRef); - if (tableRef == null) - return node; - - if (origRef.getTableAlias() != null) { - tName = TableName.create(null, origRef.getTableAlias()); - } else { - String schemaName = tableRef.getTable().getSchemaName().getString(); - tName = TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString()); - } - } + TableName tName = getReplacedTableName(dataColRef.getTableRef()); + if (multiTableRewriteMap != null && tName == null) + return node; + String indexColName = IndexUtil.getIndexColumnName(dataColRef.getColumn()); // Same alias as before, but use the index column name instead of the data column name ParseNode indexColNode = new ColumnParseNode(tName, node.isCaseSensitive() ? '"' + indexColName + '"' : indexColName, node.getAlias()); @@ -94,9 +85,30 @@ public class IndexStatementRewriter extends ParseNodeRewriter { } @Override + public ParseNode visit(TableWildcardParseNode node) throws SQLException { + TableName tName = getReplacedTableName(getResolver().resolveTable(node.getTableName().getSchemaName(), node.getTableName().getTableName())); + return tName == null ? node : TableWildcardParseNode.create(tName, true); + } + + @Override public ParseNode visit(FamilyWildcardParseNode node) throws SQLException { return multiTableRewriteMap != null ? node : new FamilyWildcardParseNode(node, true); } + private TableName getReplacedTableName(TableRef origRef) { + if (multiTableRewriteMap == null) + return null; + + TableRef tableRef = multiTableRewriteMap.get(origRef); + if (tableRef == null) + return null; + + if (origRef.getTableAlias() != null) + return TableName.create(null, origRef.getTableAlias()); + + String schemaName = tableRef.getTable().getSchemaName().getString(); + return TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString()); + } + } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 bea89da..e0b3704 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 @@ -71,6 +71,7 @@ import org.apache.phoenix.parse.StatelessTraverseAllParseNodeVisitor; 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.TraverseNoParseNodeVisitor; import org.apache.phoenix.parse.WildcardParseNode; import org.apache.phoenix.schema.AmbiguousColumnException; @@ -85,11 +86,9 @@ import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableImpl; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.TableRef; -import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.SchemaUtil; import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; @@ -205,11 +204,11 @@ public class JoinCompiler { for (ColumnRef ref : prefilterRefVisitor.getColumnRefMap().keySet()) { if (!columnRefs.containsKey(ref)) columnRefs.put(ref, ColumnRefType.PREFILTER); - } + } } private JoinSpec(ColumnResolver resolver, TableNode tableNode, TableRef table, List select, List preFilters, - List postFilters, List joinTables, Map columnRefs) { + List postFilters, List joinTables, Map tableRefToJoinTableMap, Map columnRefs) { this.origResolver = resolver; this.mainTableNode = tableNode; this.mainTable = table; @@ -217,6 +216,7 @@ public class JoinCompiler { this.preFilters = preFilters; this.postFilters = postFilters; this.joinTables = joinTables; + this.tableRefToJoinTableMap = tableRefToJoinTableMap; this.columnRefs = columnRefs; } @@ -275,9 +275,14 @@ public class JoinCompiler { return AndExpression.create(expressions); } + + protected boolean isWildCardSelect(TableRef table) { + List selectList = table.equals(mainTable) ? this.select : tableRefToJoinTableMap.get(table).getSelect(); + return (selectList.size() == 1 && selectList.get(0).getNode() instanceof TableWildcardParseNode); + } public void projectColumns(Scan scan, TableRef table) { - if (isWildCardSelect(select)) { + if (isWildCardSelect(table)) { scan.getFamilyMap().clear(); return; } @@ -289,7 +294,7 @@ public class JoinCompiler { } } - public ProjectedPTableWrapper createProjectedTable(TableRef tableRef, boolean retainPKColumns, boolean isRewrite) throws SQLException { + public ProjectedPTableWrapper createProjectedTable(TableRef tableRef, boolean retainPKColumns) throws SQLException { List projectedColumns = new ArrayList(); List sourceExpressions = new ArrayList(); ListMultimap columnNameMap = ArrayListMultimap.create(); @@ -298,14 +303,14 @@ public class JoinCompiler { if (retainPKColumns) { for (PColumn column : table.getPKColumns()) { addProjectedColumn(projectedColumns, sourceExpressions, columnNameMap, - column, tableRef, column.getFamilyName(), hasSaltingColumn, isRewrite); + column, tableRef, column.getFamilyName(), hasSaltingColumn); } } - if (isWildCardSelect(select)) { + if (isWildCardSelect(tableRef)) { for (PColumn column : table.getColumns()) { if (!retainPKColumns || !SchemaUtil.isPKColumn(column)) { addProjectedColumn(projectedColumns, sourceExpressions, columnNameMap, - column, tableRef, PNameFactory.newName(ScanProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn, isRewrite); + column, tableRef, PNameFactory.newName(ScanProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn); } } } else { @@ -316,7 +321,7 @@ public class JoinCompiler { && (!retainPKColumns || !SchemaUtil.isPKColumn(columnRef.getColumn()))) { PColumn column = columnRef.getColumn(); addProjectedColumn(projectedColumns, sourceExpressions, columnNameMap, - column, tableRef, PNameFactory.newName(ScanProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn, isRewrite); + column, tableRef, PNameFactory.newName(ScanProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn); } } } @@ -329,7 +334,7 @@ public class JoinCompiler { } private static void addProjectedColumn(List projectedColumns, List sourceExpressions, - ListMultimap columnNameMap, PColumn sourceColumn, TableRef sourceTable, PName familyName, boolean hasSaltingColumn, boolean isRewrite) + ListMultimap columnNameMap, PColumn sourceColumn, TableRef sourceTable, PName familyName, boolean hasSaltingColumn) throws SQLException { if (sourceColumn == SALTING_COLUMN) return; @@ -341,21 +346,13 @@ public class JoinCompiler { String colName = sourceColumn.getName().getString(); String fullName = getProjectedColumnName(schemaName, tableName, colName); String aliasedName = sourceTable.getTableAlias() == null ? fullName : getProjectedColumnName(null, sourceTable.getTableAlias(), colName); - String displayName = aliasedName; - if (isRewrite) { - String dataColName = IndexUtil.getDataColumnName(colName); - displayName = sourceTable.getTableAlias() == null ? getProjectedColumnName(schemaName, table.getParentTableName().getString(), dataColName) : getProjectedColumnName(null, sourceTable.getTableAlias(), dataColName); - } - columnNameMap.put(colName, displayName); - if (!fullName.equals(displayName)) { - columnNameMap.put(fullName, displayName); - } - if (!aliasedName.equals(displayName) && !aliasedName.equals(fullName)) { - columnNameMap.put(aliasedName, displayName); + columnNameMap.put(colName, aliasedName); + if (!fullName.equals(aliasedName)) { + columnNameMap.put(fullName, aliasedName); } - PName name = PNameFactory.newName(displayName); + PName name = PNameFactory.newName(aliasedName); PColumnImpl column = new PColumnImpl(name, familyName, sourceColumn.getDataType(), sourceColumn.getMaxLength(), sourceColumn.getScale(), sourceColumn.isNullable(), position, sourceColumn.getColumnModifier(), sourceColumn.getArraySize()); @@ -364,8 +361,12 @@ public class JoinCompiler { sourceExpressions.add(sourceExpression); } + public ColumnResolver getColumnResolver(PTableWrapper table) { + return new JoinedTableColumnResolver(table, origResolver); + } + public boolean hasPostReference(TableRef table) { - if (isWildCardSelect(select)) + if (isWildCardSelect(table)) return true; for (Map.Entry e : columnRefs.entrySet()) { @@ -492,7 +493,7 @@ public class JoinCompiler { public static JoinSpec getSubJoinSpecWithoutPostFilters(JoinSpec join) { return new JoinSpec(join.origResolver, join.mainTableNode, join.mainTable, join.select, join.preFilters, new ArrayList(), - join.joinTables.subList(0, join.joinTables.size() - 1), join.columnRefs); + join.joinTables.subList(0, join.joinTables.size() - 1), join.tableRefToJoinTableMap, join.columnRefs); } public static class JoinTable { @@ -870,23 +871,25 @@ public class JoinCompiler { // for creation of new statements private static ParseNodeFactory NODE_FACTORY = new ParseNodeFactory(); - private static boolean isWildCardSelect(List select) { - return (select.size() == 1 && select.get(0).getNode() == WildcardParseNode.INSTANCE); - } - private static List extractFromSelect(List select, TableRef table, ColumnResolver resolver) throws SQLException { List ret = new ArrayList(); - if (isWildCardSelect(select)) { - ret.add(NODE_FACTORY.aliasedNode(null, WildcardParseNode.INSTANCE)); - return ret; - } - ColumnParseNodeVisitor visitor = new ColumnParseNodeVisitor(resolver); - for (AliasedNode node : select) { - node.getNode().accept(visitor); + for (AliasedNode aliasedNode : select) { + ParseNode node = aliasedNode.getNode(); + if (node instanceof TableWildcardParseNode) { + TableName tableName = ((TableWildcardParseNode) node).getTableName(); + if (table.equals(resolver.resolveTable(tableName.getSchemaName(), tableName.getTableName()))) { + ret.clear(); + ret.add(aliasedNode); + return ret; + } + continue; + } + + node.accept(visitor); ColumnParseNodeVisitor.ContentType type = visitor.getContentType(table); if (type == ColumnParseNodeVisitor.ContentType.SELF_ONLY) { - ret.add(node); + ret.add(aliasedNode); } else if (type == ColumnParseNodeVisitor.ContentType.COMPLEX) { for (Map.Entry entry : visitor.getColumnRefMap().entrySet()) { if (entry.getKey().getTableRef().equals(table)) { @@ -961,7 +964,7 @@ public class JoinCompiler { @Override public void visit(BindTableNode boundTableNode) throws SQLException { String alias = boundTableNode.getAlias(); - replaced = BindTableNode.create(alias == null ? null : '"' + alias + '"', getReplacedTableName(), true); + replaced = NODE_FACTORY.bindTable(alias == null ? null : '"' + alias + '"', getReplacedTableName()); } @Override @@ -974,7 +977,7 @@ public class JoinCompiler { public void visit(NamedTableNode namedTableNode) throws SQLException { String alias = namedTableNode.getAlias(); - replaced = NamedTableNode.create(alias == null ? null : '"' + alias + '"', getReplacedTableName(), namedTableNode.getDynamicColumns(), true); + replaced = NODE_FACTORY.namedTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(), namedTableNode.getDynamicColumns()); } @Override @@ -1000,7 +1003,7 @@ public class JoinCompiler { TableRef table = jTable.getTable(); List groupBy = table.equals(groupByTableRef) ? select.getGroupBy() : null; List orderBy = table.equals(orderByTableRef) ? select.getOrderBy() : null; - SelectStatement stmt = getSubqueryForOptimizedPlan(select, table, join.columnRefs, jTable.getPreFiltersCombined(), groupBy, orderBy); + SelectStatement stmt = getSubqueryForOptimizedPlan(select, table, join.columnRefs, jTable.getPreFiltersCombined(), groupBy, orderBy, join.isWildCardSelect(table)); QueryPlan plan = context.getConnection().getQueryServices().getOptimizer().optimize(stmt, statement); if (!plan.getTableRef().equals(table)) { TableNodeRewriter rewriter = new TableNodeRewriter(plan.getTableRef()); @@ -1016,7 +1019,7 @@ public class JoinCompiler { TableRef table = join.getMainTable(); List groupBy = table.equals(groupByTableRef) ? select.getGroupBy() : null; List orderBy = table.equals(orderByTableRef) ? select.getOrderBy() : null; - SelectStatement stmt = getSubqueryForOptimizedPlan(select, table, join.columnRefs, join.getPreFiltersCombined(), groupBy, orderBy); + SelectStatement stmt = getSubqueryForOptimizedPlan(select, table, join.columnRefs, join.getPreFiltersCombined(), groupBy, orderBy, join.isWildCardSelect(table)); QueryPlan plan = context.getConnection().getQueryServices().getOptimizer().optimize(stmt, statement); if (!plan.getTableRef().equals(table)) { TableNodeRewriter rewriter = new TableNodeRewriter(plan.getTableRef()); @@ -1033,11 +1036,11 @@ public class JoinCompiler { return IndexStatementRewriter.translate(NODE_FACTORY.select(select, newFrom), resolver, replacement); } - private static SelectStatement getSubqueryForOptimizedPlan(SelectStatement select, TableRef table, Map columnRefs, ParseNode where, List groupBy, List orderBy) { + private static SelectStatement getSubqueryForOptimizedPlan(SelectStatement select, TableRef table, Map columnRefs, ParseNode where, List groupBy, List orderBy, boolean isWildCardSelect) { String schemaName = table.getTable().getSchemaName().getString(); TableName tName = TableName.create(schemaName.length() == 0 ? null : schemaName, table.getTable().getTableName().getString()); List selectList = new ArrayList(); - if (isWildCardSelect(select.getSelect())) { + if (isWildCardSelect) { selectList.add(NODE_FACTORY.aliasedNode(null, WildcardParseNode.INSTANCE)); } else { for (ColumnRef colRef : columnRefs.keySet()) { @@ -1190,34 +1193,36 @@ public class JoinCompiler { } } - public static ColumnResolver getColumnResolver(PTableWrapper table) { - return new JoinedTableColumnResolver(table); - } - public static class JoinedTableColumnResolver implements ColumnResolver { private PTableWrapper table; - private List tableRefs; + private ColumnResolver tableResolver; + private TableRef tableRef; - private JoinedTableColumnResolver(PTableWrapper table) { + private JoinedTableColumnResolver(PTableWrapper table, ColumnResolver tableResolver) { this.table = table; - TableRef tableRef = new TableRef(null, table.getTable(), 0, false); - this.tableRefs = ImmutableList.of(tableRef); + this.tableResolver = tableResolver; + this.tableRef = new TableRef(null, table.getTable(), 0, false); } + + public PTableWrapper getPTableWrapper() { + return table; + } @Override public List getTables() { - return tableRefs; - } - - public PTableWrapper getPTableWrapper() { - return table; + return tableResolver.getTables(); } + @Override + public TableRef resolveTable(String schemaName, String tableName) + throws SQLException { + return tableResolver.resolveTable(schemaName, tableName); + } + @Override public ColumnRef resolveColumn(String schemaName, String tableName, String colName) throws SQLException { String name = getProjectedColumnName(schemaName, tableName, colName); - TableRef tableRef = tableRefs.get(0); try { PColumn column = tableRef.getTable().getColumn(name); return new ColumnRef(tableRef, column.getPosition()); http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/compile/PostDDLCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/PostDDLCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/PostDDLCompiler.java index bf8c2e5..6c4452a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/PostDDLCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/PostDDLCompiler.java @@ -118,6 +118,11 @@ public class PostDDLCompiler { return Collections.singletonList(tableRef); } @Override + public TableRef resolveTable(String schemaName, String tableName) + throws SQLException { + throw new UnsupportedOperationException(); + } + @Override public ColumnRef resolveColumn(String schemaName, String tableName, String colName) throws SQLException { PColumn column = tableName != null ? tableRef.getTable().getColumnFamily(tableName).getColumn(colName) http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java index d617b5e..72f5c1a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ProjectionCompiler.java @@ -34,6 +34,7 @@ import org.apache.hadoop.hbase.util.Bytes; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.google.common.collect.Sets; + import org.apache.phoenix.compile.GroupByCompiler.GroupBy; import org.apache.phoenix.coprocessor.GroupedAggregateRegionObserver; import org.apache.phoenix.exception.SQLExceptionCode; @@ -51,6 +52,8 @@ import org.apache.phoenix.parse.FamilyWildcardParseNode; import org.apache.phoenix.parse.ParseNode; import org.apache.phoenix.parse.SelectStatement; import org.apache.phoenix.parse.SequenceValueParseNode; +import org.apache.phoenix.parse.TableName; +import org.apache.phoenix.parse.TableWildcardParseNode; import org.apache.phoenix.parse.WildcardParseNode; import org.apache.phoenix.schema.ArgumentTypeMismatchException; import org.apache.phoenix.schema.ColumnNotFoundException; @@ -99,7 +102,8 @@ public class ProjectionCompiler { return compile(context, statement, groupBy, Collections.emptyList()); } - private static void projectAllTableColumns(StatementContext context, TableRef tableRef, List projectedExpressions, List projectedColumns) throws SQLException { + private static void projectAllTableColumns(StatementContext context, TableRef tableRef, boolean resolveColumn, List projectedExpressions, List projectedColumns) throws SQLException { + ColumnResolver resolver = context.getResolver(); PTable table = tableRef.getTable(); int posOffset = table.getBucketNum() == null ? 0 : 1; // In SELECT *, don't include tenant column for tenant connection @@ -108,15 +112,26 @@ public class ProjectionCompiler { } for (int i = posOffset; i < table.getColumns().size(); i++) { ColumnRef ref = new ColumnRef(tableRef,i); + String colName = ref.getColumn().getName().getString(); + if (resolveColumn) { + if (tableRef.getTableAlias() != null) { + ref = resolver.resolveColumn(null, tableRef.getTableAlias(), colName); + colName = SchemaUtil.getColumnName(tableRef.getTableAlias(), colName); + } else { + String schemaName = table.getSchemaName().getString(); + ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, table.getTableName().getString(), colName); + colName = SchemaUtil.getColumnName(table.getName().getString(), colName); + } + } Expression expression = ref.newColumnExpression(); projectedExpressions.add(expression); - String colName = ref.getColumn().getName().getString(); boolean isCaseSensitive = !SchemaUtil.normalizeIdentifier(colName).equals(colName); projectedColumns.add(new ExpressionProjector(colName, table.getName().getString(), expression, isCaseSensitive)); } } - private static void projectAllIndexColumns(StatementContext context, TableRef tableRef, List projectedExpressions, List projectedColumns) throws SQLException { + private static void projectAllIndexColumns(StatementContext context, TableRef tableRef, boolean resolveColumn, List projectedExpressions, List projectedColumns) throws SQLException { + ColumnResolver resolver = context.getResolver(); PTable index = tableRef.getTable(); PTable table = context.getConnection().getPMetaData().getTable(index.getParentName().getString()); int tableOffset = table.getBucketNum() == null ? 0 : 1; @@ -127,11 +142,22 @@ public class ProjectionCompiler { } for (int i = tableOffset; i < table.getColumns().size(); i++) { PColumn tableColumn = table.getColumns().get(i); - PColumn indexColumn = index.getColumn(IndexUtil.getIndexColumnName(tableColumn)); + String indexColName = IndexUtil.getIndexColumnName(tableColumn); + PColumn indexColumn = index.getColumn(indexColName); ColumnRef ref = new ColumnRef(tableRef,indexColumn.getPosition()); + String colName = tableColumn.getName().getString(); + if (resolveColumn) { + if (tableRef.getTableAlias() != null) { + ref = resolver.resolveColumn(null, tableRef.getTableAlias(), indexColName); + colName = SchemaUtil.getColumnName(tableRef.getTableAlias(), colName); + } else { + String schemaName = index.getSchemaName().getString(); + ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, index.getTableName().getString(), indexColName); + colName = SchemaUtil.getColumnName(table.getName().getString(), colName); + } + } Expression expression = ref.newColumnExpression(); projectedExpressions.add(expression); - String colName = tableColumn.getName().getString(); boolean isCaseSensitive = !SchemaUtil.normalizeIdentifier(colName).equals(colName); ExpressionProjector projector = new ExpressionProjector(colName, table.getName().getString(), expression, isCaseSensitive); projectedColumns.add(projector); @@ -183,7 +209,8 @@ public class ProjectionCompiler { // Setup projected columns in Scan SelectClauseVisitor selectVisitor = new SelectClauseVisitor(context, groupBy); List projectedColumns = new ArrayList(); - TableRef tableRef = context.getResolver().getTables().get(0); + ColumnResolver resolver = context.getResolver(); + TableRef tableRef = context.getCurrentTable(); PTable table = tableRef.getTable(); boolean isWildcard = false; Scan scan = context.getScan(); @@ -199,13 +226,23 @@ public class ProjectionCompiler { } isWildcard = true; if (tableRef.getTable().getType() == PTableType.INDEX && ((WildcardParseNode)node).isRewrite()) { - projectAllIndexColumns(context, tableRef, projectedExpressions, projectedColumns); + projectAllIndexColumns(context, tableRef, false, projectedExpressions, projectedColumns); } else { - projectAllTableColumns(context, tableRef, projectedExpressions, projectedColumns); + projectAllTableColumns(context, tableRef, false, projectedExpressions, projectedColumns); + } + } else if (node instanceof TableWildcardParseNode) { + TableName tName = ((TableWildcardParseNode) node).getTableName(); + TableRef tRef = resolver.resolveTable(tName.getSchemaName(), tName.getTableName()); + if (tRef.equals(tableRef)) { + isWildcard = true; } + if (tRef.getTable().getType() == PTableType.INDEX && ((TableWildcardParseNode)node).isRewrite()) { + projectAllIndexColumns(context, tRef, true, projectedExpressions, projectedColumns); + } else { + projectAllTableColumns(context, tRef, true, projectedExpressions, projectedColumns); + } } else if (node instanceof FamilyWildcardParseNode){ // Project everything for SELECT cf.* - // TODO: support cf.* expressions for multiple tables the same way with *. String cfName = ((FamilyWildcardParseNode) node).getName(); // Delay projecting to scan, as when any other column in the column family gets // added to the scan, it overwrites that we want to project the entire column @@ -252,7 +289,6 @@ public class ProjectionCompiler { index++; } - table = context.getCurrentTable().getTable(); // switch to current table for scan projection // TODO make estimatedByteSize more accurate by counting the joined columns. int estimatedKeySize = table.getRowKeySchema().getEstimatedValueLength(); int estimatedByteSize = 0; http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 e264c0a..17e954e 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 @@ -144,17 +144,17 @@ public class QueryCompiler { byte[] emptyByteArray = new byte[0]; List joinTables = join.getJoinTables(); if (joinTables.isEmpty()) { - ProjectedPTableWrapper projectedTable = join.createProjectedTable(join.getMainTable(), !asSubquery, join.getMainTableNode().isRewrite()); + ProjectedPTableWrapper projectedTable = join.createProjectedTable(join.getMainTable(), !asSubquery); ScanProjector.serializeProjectorIntoScan(context.getScan(), JoinCompiler.getScanProjector(projectedTable)); context.setCurrentTable(join.getMainTable()); - context.setResolver(JoinCompiler.getColumnResolver(projectedTable)); + context.setResolver(join.getColumnResolver(projectedTable)); join.projectColumns(context.getScan(), join.getMainTable()); return compileSingleQuery(context, select, binds, null); } boolean[] starJoinVector = JoinCompiler.getStarJoinVector(join); if (starJoinVector != null) { - ProjectedPTableWrapper initialProjectedTable = join.createProjectedTable(join.getMainTable(), !asSubquery, join.getMainTableNode().isRewrite()); + ProjectedPTableWrapper initialProjectedTable = join.createProjectedTable(join.getMainTable(), !asSubquery); PTableWrapper projectedTable = initialProjectedTable; int count = joinTables.size(); ImmutableBytesPtr[] joinIds = new ImmutableBytesPtr[count]; @@ -171,8 +171,8 @@ public class QueryCompiler { SelectStatement subStatement = joinTable.getAsSubquery(); if (subStatement.getFrom().size() > 1) throw new SQLFeatureNotSupportedException("Sub queries not supported."); - ProjectedPTableWrapper subProjTable = join.createProjectedTable(joinTable.getTable(), false, joinTable.getTableNode().isRewrite()); - ColumnResolver resolver = JoinCompiler.getColumnResolver(subProjTable); + ProjectedPTableWrapper subProjTable = join.createProjectedTable(joinTable.getTable(), false); + ColumnResolver resolver = join.getColumnResolver(subProjTable); Scan subScan = ScanUtil.newScan(scanCopy); ScanProjector.serializeProjectorIntoScan(subScan, JoinCompiler.getScanProjector(subProjTable)); StatementContext subContext = new StatementContext(statement, resolver, binds, subScan); @@ -190,7 +190,7 @@ public class QueryCompiler { if (!starJoinVector[i]) { needsProject = true; } - ColumnResolver leftResolver = starJoinVector[i] ? join.getOriginalResolver() : JoinCompiler.getColumnResolver(projectedTable); + ColumnResolver leftResolver = starJoinVector[i] ? join.getOriginalResolver() : join.getColumnResolver(projectedTable); joinIds[i] = new ImmutableBytesPtr(emptyByteArray); // place-holder Pair, List> joinConditions = joinTable.compileJoinConditions(context, leftResolver, resolver); joinExpressions[i] = joinConditions.getFirst(); @@ -204,7 +204,7 @@ public class QueryCompiler { ScanProjector.serializeProjectorIntoScan(context.getScan(), JoinCompiler.getScanProjector(initialProjectedTable)); } context.setCurrentTable(join.getMainTable()); - context.setResolver(needsProject ? JoinCompiler.getColumnResolver(projectedTable) : join.getOriginalResolver()); + context.setResolver(needsProject ? join.getColumnResolver(projectedTable) : join.getOriginalResolver()); join.projectColumns(context.getScan(), join.getMainTable()); BasicQueryPlan plan = compileSingleQuery(context, JoinCompiler.getSubqueryWithoutJoin(select, join), binds, parallelIteratorFactory); Expression postJoinFilterExpression = join.compilePostFilterExpression(context); @@ -226,7 +226,7 @@ public class QueryCompiler { QueryPlan lhsPlan = compileJoinQuery(lhsCtx, lhs, binds, lhsJoin, true); ColumnResolver lhsResolver = lhsCtx.getResolver(); PTableWrapper lhsProjTable = ((JoinedTableColumnResolver) (lhsResolver)).getPTableWrapper(); - ProjectedPTableWrapper rhsProjTable = join.createProjectedTable(lastJoinTable.getTable(), !asSubquery, lastJoinTable.getTableNode().isRewrite()); + ProjectedPTableWrapper rhsProjTable = join.createProjectedTable(lastJoinTable.getTable(), !asSubquery); ColumnResolver rhsResolver = join.getOriginalResolver(); ImmutableBytesPtr[] joinIds = new ImmutableBytesPtr[] {new ImmutableBytesPtr(emptyByteArray)}; Pair, List> joinConditions = lastJoinTable.compileJoinConditions(context, lhsResolver, rhsResolver); @@ -236,7 +236,7 @@ public class QueryCompiler { PTableWrapper projectedTable = JoinCompiler.mergeProjectedTables(rhsProjTable, lhsProjTable, type == JoinType.Inner); ScanProjector.serializeProjectorIntoScan(context.getScan(), JoinCompiler.getScanProjector(rhsProjTable)); context.setCurrentTable(lastJoinTable.getTable()); - context.setResolver(JoinCompiler.getColumnResolver(projectedTable)); + context.setResolver(join.getColumnResolver(projectedTable)); join.projectColumns(context.getScan(), lastJoinTable.getTable()); BasicQueryPlan rhsPlan = compileSingleQuery(context, rhs, binds, parallelIteratorFactory); Expression postJoinFilterExpression = join.compilePostFilterExpression(context); http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 01e54a9..be22405 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 @@ -20,18 +20,29 @@ package org.apache.phoenix.compile; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.util.List; import com.google.common.collect.Lists; +import org.apache.phoenix.parse.AliasedNode; import org.apache.phoenix.parse.BetweenParseNode; +import org.apache.phoenix.parse.BindTableNode; import org.apache.phoenix.parse.ColumnParseNode; import org.apache.phoenix.parse.ComparisonParseNode; +import org.apache.phoenix.parse.DerivedTableNode; +import org.apache.phoenix.parse.FamilyWildcardParseNode; +import org.apache.phoenix.parse.JoinTableNode; import org.apache.phoenix.parse.LessThanOrEqualParseNode; +import org.apache.phoenix.parse.NamedTableNode; 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; import org.apache.phoenix.util.SchemaUtil; @@ -45,11 +56,11 @@ import org.apache.phoenix.util.SchemaUtil; * @since 0.1 */ public class StatementNormalizer extends ParseNodeRewriter { - private boolean useFullNameForAlias; + private boolean multiTable; - public StatementNormalizer(ColumnResolver resolver, int expectedAliasCount, boolean useFullNameForAlias) { + public StatementNormalizer(ColumnResolver resolver, int expectedAliasCount, boolean multiTable) { super(resolver, expectedAliasCount); - this.useFullNameForAlias = useFullNameForAlias; + this.multiTable = multiTable; } public static ParseNode normalize(ParseNode where, ColumnResolver resolver) throws SQLException { @@ -65,8 +76,68 @@ public class StatementNormalizer extends ParseNodeRewriter { * @throws SQLException */ public static SelectStatement normalize(SelectStatement statement, ColumnResolver resolver) throws SQLException { - return rewrite(statement, new StatementNormalizer(resolver, statement.getSelect().size(), statement.getFrom().size() > 1)); + List from = statement.getFrom(); + boolean multiTable = from.size() > 1; + // Replace WildcardParse with a list of TableWildcardParseNode for multi-table queries + if (multiTable) { + List selectNodes = statement.getSelect(); + List normSelectNodes = selectNodes; + for (int i = 0; i < selectNodes.size(); i++) { + AliasedNode aliasedNode = selectNodes.get(i); + ParseNode selectNode = aliasedNode.getNode(); + if (selectNode == WildcardParseNode.INSTANCE) { + if (selectNodes == normSelectNodes) { + normSelectNodes = Lists.newArrayList(selectNodes.subList(0, i)); + } + for (TableNode tNode : from) { + TableNameVisitor visitor = new TableNameVisitor(); + tNode.accept(visitor); + TableWildcardParseNode node = NODE_FACTORY.tableWildcard(visitor.getTableName()); + normSelectNodes.add(NODE_FACTORY.aliasedNode(null, node)); + } + } else if (selectNodes != normSelectNodes) { + normSelectNodes.add(aliasedNode); + } + } + if (selectNodes != normSelectNodes) { + statement = NODE_FACTORY.select(statement.getFrom(), statement.getHint(), statement.isDistinct(), + normSelectNodes, statement.getWhere(), statement.getGroupBy(), statement.getHaving(), statement.getOrderBy(), + statement.getLimit(), statement.getBindCount(), statement.isAggregate()); + } + } + + return rewrite(statement, new StatementNormalizer(resolver, statement.getSelect().size(), multiTable)); } + + private static class TableNameVisitor implements TableNodeVisitor { + private TableName tableName; + + public TableName getTableName() { + return tableName; + } + + @Override + public void visit(BindTableNode boundTableNode) throws SQLException { + tableName = boundTableNode.getAlias() == null ? boundTableNode.getName() : TableName.create(null, boundTableNode.getAlias()); + } + + @Override + public void visit(JoinTableNode joinNode) throws SQLException { + joinNode.getTable().accept(this); + } + + @Override + public void visit(NamedTableNode namedTableNode) + throws SQLException { + tableName = namedTableNode.getAlias() == null ? namedTableNode.getName() : TableName.create(null, namedTableNode.getAlias()); + } + + @Override + public void visit(DerivedTableNode subselectNode) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + }; @Override public ParseNode visitLeave(ComparisonParseNode node, List nodes) throws SQLException { @@ -93,7 +164,7 @@ public class StatementNormalizer extends ParseNodeRewriter { @Override public ParseNode visit(ColumnParseNode node) throws SQLException { - if (useFullNameForAlias + if (multiTable && node.getAlias() != null && node.getTableName() != null && SchemaUtil.normalizeIdentifier(node.getAlias()).equals(node.getName())) { @@ -103,5 +174,13 @@ public class StatementNormalizer extends ParseNodeRewriter { } return super.visit(node); } + + @Override + public ParseNode visit(FamilyWildcardParseNode node) throws SQLException { + if (!multiTable) + return super.visit(node); + + return super.visit(NODE_FACTORY.tableWildcard(NODE_FACTORY.table(null, node.isCaseSensitive() ? '"' + node.getName() + '"' : node.getName()))); + } } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/BindTableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/BindTableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/BindTableNode.java index 4ea51a7..968c64c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/BindTableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/BindTableNode.java @@ -31,17 +31,9 @@ import java.sql.SQLException; * @since 0.1 */ public class BindTableNode extends ConcreteTableNode { - - public static BindTableNode create(String alias, TableName name, boolean isRewrite) { - return new BindTableNode(alias, name, isRewrite); - } BindTableNode(String alias, TableName name) { - this(alias, name, false); - } - - BindTableNode(String alias, TableName name, boolean isRewrite) { - super(alias, name, isRewrite); + super(alias, name); } @Override http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/ConcreteTableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ConcreteTableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ConcreteTableNode.java index b110f2a..b6671b5 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ConcreteTableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ConcreteTableNode.java @@ -31,8 +31,8 @@ import org.apache.phoenix.util.SchemaUtil; public abstract class ConcreteTableNode extends TableNode { private final TableName name; - ConcreteTableNode(String alias, TableName name, boolean isRewrite) { - super(SchemaUtil.normalizeIdentifier(alias), isRewrite); + ConcreteTableNode(String alias, TableName name) { + super(SchemaUtil.normalizeIdentifier(alias)); this.name = name; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/DerivedTableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/DerivedTableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/DerivedTableNode.java index 8d9383c..f1b5282 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/DerivedTableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/DerivedTableNode.java @@ -21,6 +21,8 @@ package org.apache.phoenix.parse; import java.sql.SQLException; +import org.apache.phoenix.util.SchemaUtil; + /** @@ -35,7 +37,7 @@ public class DerivedTableNode extends TableNode { private final SelectStatement select; DerivedTableNode(String alias, SelectStatement select) { - super(alias); + super(SchemaUtil.normalizeIdentifier(alias)); this.select = select; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinTableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinTableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinTableNode.java index 54840be..6a993c4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinTableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/JoinTableNode.java @@ -38,7 +38,7 @@ public class JoinTableNode extends TableNode { private final TableNode table; JoinTableNode(JoinType type, ParseNode on, TableNode table) { - super(table.getAlias(), table.isRewrite()); + super(table.getAlias()); this.type = type; this.on = on; this.table = table; http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/NamedTableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/NamedTableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/NamedTableNode.java index 86fdc94..7bc2bd6 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/NamedTableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/NamedTableNode.java @@ -38,22 +38,14 @@ public class NamedTableNode extends ConcreteTableNode { public static NamedTableNode create (String alias, TableName name, List dynColumns) { return new NamedTableNode(alias, name, dynColumns); } - - public static NamedTableNode create (String alias, TableName name, List dynColumns, boolean isRewrite) { - return new NamedTableNode(alias, name, dynColumns, isRewrite); - } NamedTableNode(String alias, TableName name) { - super(alias, name, false); + super(alias, name); dynColumns = Collections. emptyList(); } NamedTableNode(String alias, TableName name, List dynColumns) { - this(alias, name, dynColumns, false); - } - - NamedTableNode(String alias, TableName name, List dynColumns, boolean isRewrite) { - super(alias, name, isRewrite); + super(alias, name); if (dynColumns != null) { this.dynColumns = ImmutableList.copyOf(dynColumns); } else { http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 7b7589f..dc0f586 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 @@ -208,6 +208,10 @@ public class ParseNodeFactory { public FamilyWildcardParseNode family(String familyName){ return new FamilyWildcardParseNode(familyName, false); } + + public TableWildcardParseNode tableWildcard(TableName tableName) { + return new TableWildcardParseNode(tableName, false); + } public WildcardParseNode wildcard() { return WildcardParseNode.INSTANCE; http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/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 20e8c74..8519866 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 @@ -420,6 +420,11 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor { } @Override + public ParseNode visit(TableWildcardParseNode node) throws SQLException { + return node; + } + + @Override public ParseNode visit(FamilyWildcardParseNode node) throws SQLException { return node; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java index 38eb2fa..b8511ed 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java @@ -86,7 +86,8 @@ public interface ParseNodeVisitor { public E visit(ColumnParseNode node) throws SQLException; public E visit(LiteralParseNode node) throws SQLException; public E visit(BindParseNode node) throws SQLException; - public E visit(WildcardParseNode node) throws SQLException; + public E visit(WildcardParseNode node) throws SQLException; + public E visit(TableWildcardParseNode node) throws SQLException; public E visit(FamilyWildcardParseNode node) throws SQLException; public E visit(ParseNode node) throws SQLException; http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/TableNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TableNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TableNode.java index 8a592ae..8130d65 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/TableNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TableNode.java @@ -32,24 +32,14 @@ import java.sql.SQLException; */ public abstract class TableNode { private final String alias; - private final boolean isRewrite; TableNode(String alias) { - this(alias, false); - } - - TableNode(String alias, boolean isRewrite) { this.alias = alias; - this.isRewrite = isRewrite; } public String getAlias() { return alias; } - - public boolean isRewrite() { - return isRewrite; - } public abstract void accept(TableNodeVisitor visitor) throws SQLException; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/TableWildcardParseNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TableWildcardParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TableWildcardParseNode.java new file mode 100644 index 0000000..af72b15 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TableWildcardParseNode.java @@ -0,0 +1,52 @@ +/* + * Copyright 2014 The Apache Software Foundation + * + * 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 java.sql.SQLException; + +public class TableWildcardParseNode extends NamedParseNode { + private final TableName tableName; + private final boolean isRewrite; + + public static TableWildcardParseNode create(TableName tableName, boolean isRewrite) { + return new TableWildcardParseNode(tableName, isRewrite); + } + + TableWildcardParseNode(TableName tableName, boolean isRewrite) { + super(tableName.toString()); + this.tableName = tableName; + this.isRewrite = isRewrite; + } + + public TableName getTableName() { + return tableName; + } + + public boolean isRewrite() { + return isRewrite; + } + + @Override + public T accept(ParseNodeVisitor visitor) throws SQLException { + return visitor.visit(this); + } + +} + http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java index 5e85f9d..14f9784 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java @@ -132,6 +132,11 @@ public abstract class TraverseAllParseNodeVisitor extends BaseParseNodeVisito } @Override + public T visit(TableWildcardParseNode node) throws SQLException { + return null; + } + + @Override public T visit(FamilyWildcardParseNode node) throws SQLException { return null; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java index f64fb97..cc38562 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java @@ -132,6 +132,11 @@ public abstract class TraverseNoParseNodeVisitor extends BaseParseNodeVisitor } @Override + public T visit(TableWildcardParseNode node) throws SQLException { + return null; + } + + @Override public T visit(FamilyWildcardParseNode node) throws SQLException { return null; } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java index b408f91..0cb1b31 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java @@ -68,6 +68,11 @@ abstract public class UnsupportedAllParseNodeVisitor extends BaseParseNodeVis } @Override + public E visit(TableWildcardParseNode node) throws SQLException { + throw new SQLFeatureNotSupportedException(node.toString()); + } + + @Override public E visit(FamilyWildcardParseNode node) throws SQLException { throw new SQLFeatureNotSupportedException(node.toString()); } http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/7ac4ee2d/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java index b515697..63ddcdc 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/JoinQueryCompileTest.java @@ -19,14 +19,14 @@ */ package org.apache.phoenix.compile; -import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE; -import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_NORMALIZED; -import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE; -import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_NORMALIZED; -import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE; -import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_NORMALIZED; -import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE; -import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_NORMALIZED; +import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_CUSTOMER_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ITEM_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_ORDER_TABLE_DISPLAY_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_FULL_NAME; +import static org.apache.phoenix.util.TestUtil.JOIN_SUPPLIER_TABLE_DISPLAY_NAME; import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; import static org.junit.Assert.assertEquals; @@ -55,32 +55,32 @@ public class JoinQueryCompileTest extends BaseConnectionlessQueryTest { @Test public void testExplainPlan() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); - String query = "EXPLAIN SELECT s.\"supplier_id\", \"order_id\", c.name, i.name, quantity, o.date FROM " + JOIN_ORDER_TABLE + " o LEFT JOIN " - + JOIN_CUSTOMER_TABLE + " c ON o.\"customer_id\" = c.\"customer_id\" AND c.name LIKE 'C%' LEFT JOIN " - + JOIN_ITEM_TABLE + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN " - + JOIN_SUPPLIER_TABLE + " s ON s.\"supplier_id\" = i.\"supplier_id\" WHERE i.name LIKE 'T%'"; + String query = "EXPLAIN SELECT s.\"supplier_id\", \"order_id\", c.name, i.name, quantity, o.date FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o LEFT JOIN " + + JOIN_CUSTOMER_TABLE_FULL_NAME + " c ON o.\"customer_id\" = c.\"customer_id\" AND c.name LIKE 'C%' LEFT JOIN " + + JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN " + + JOIN_SUPPLIER_TABLE_FULL_NAME + " s ON s.\"supplier_id\" = i.\"supplier_id\" WHERE i.name LIKE 'T%'"; ResultSet rs = conn.createStatement().executeQuery(query); assertEquals( - "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_NORMALIZED + "\n" + + "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_DISPLAY_NAME + "\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + " PARALLEL EQUI-JOIN 1 HASH TABLES:\n" + " BUILD HASH TABLE 0\n" + - " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_NORMALIZED + "\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" + " PARALLEL EQUI-JOIN 2 HASH TABLES:\n" + " BUILD HASH TABLE 0\n" + - " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_NORMALIZED + "\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_DISPLAY_NAME + "\n" + " SERVER FILTER BY NAME LIKE 'C%'\n" + " BUILD HASH TABLE 1\n" + - " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_NORMALIZED + "\n" + + " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_DISPLAY_NAME + "\n" + " AFTER-JOIN SERVER FILTER BY I.NAME LIKE 'T%'", QueryUtil.getExplainPlan(rs)); } @Test public void testWhereClauseOptimization() throws Exception { PhoenixConnection pconn = DriverManager.getConnection(getUrl(), TEST_PROPERTIES).unwrap(PhoenixConnection.class); - String queryTemplate = "SELECT t1.\"item_id\", t2.\"item_id\", t3.\"item_id\" FROM " + JOIN_ITEM_TABLE + " t1 " - + "%s JOIN " + JOIN_ITEM_TABLE + " t2 ON t1.\"item_id\" = t2.\"item_id\" " - + "%s JOIN " + JOIN_ITEM_TABLE + " t3 ON t1.\"item_id\" = t3.\"item_id\" " + String queryTemplate = "SELECT t1.\"item_id\", t2.\"item_id\", t3.\"item_id\" FROM " + JOIN_ITEM_TABLE_FULL_NAME + " t1 " + + "%s JOIN " + JOIN_ITEM_TABLE_FULL_NAME + " t2 ON t1.\"item_id\" = t2.\"item_id\" " + + "%s JOIN " + JOIN_ITEM_TABLE_FULL_NAME + " t3 ON t1.\"item_id\" = t3.\"item_id\" " + "WHERE t1.\"item_id\" = '0000000001' AND t2.\"item_id\" = '0000000002' AND t3.\"item_id\" = '0000000003'"; String query = String.format(queryTemplate, "INNER", "INNER");