Repository: phoenix Updated Branches: refs/heads/master 0440aca51 -> 3f829751d
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/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 27fe0f9..e84ca2a 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 @@ -62,6 +62,7 @@ import org.apache.phoenix.parse.TableName; import org.apache.phoenix.parse.TableWildcardParseNode; import org.apache.phoenix.parse.WildcardParseNode; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.schema.AmbiguousColumnException; import org.apache.phoenix.schema.ArgumentTypeMismatchException; import org.apache.phoenix.schema.ColumnFamilyNotFoundException; import org.apache.phoenix.schema.ColumnNotFoundException; @@ -144,12 +145,21 @@ public class ProjectionCompiler { } ColumnRef ref = new ColumnRef(tableRef,i); String colName = ref.getColumn().getName().getString(); + String tableAlias = tableRef.getTableAlias(); if (resolveColumn) { - if (tableRef.getTableAlias() != null) { - ref = resolver.resolveColumn(null, tableRef.getTableAlias(), colName); - } else { - String schemaName = table.getSchemaName().getString(); - ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, table.getTableName().getString(), colName); + try { + if (tableAlias != null) { + ref = resolver.resolveColumn(null, tableAlias, colName); + } else { + String schemaName = table.getSchemaName().getString(); + ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, table.getTableName().getString(), colName); + } + } catch (AmbiguousColumnException e) { + if (column.getFamilyName() != null) { + ref = resolver.resolveColumn(tableAlias != null ? tableAlias : table.getTableName().getString(), column.getFamilyName().getString(), colName); + } else { + throw e; + } } } Expression expression = ref.newColumnExpression(); @@ -219,12 +229,21 @@ public class ProjectionCompiler { } } String colName = tableColumn.getName().getString(); + String tableAlias = tableRef.getTableAlias(); if (resolveColumn) { - if (tableRef.getTableAlias() != null) { - ref = resolver.resolveColumn(null, tableRef.getTableAlias(), indexColName); - } else { - String schemaName = index.getSchemaName().getString(); - ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, index.getTableName().getString(), indexColName); + try { + if (tableAlias != null) { + ref = resolver.resolveColumn(null, tableAlias, indexColName); + } else { + String schemaName = index.getSchemaName().getString(); + ref = resolver.resolveColumn(schemaName.length() == 0 ? null : schemaName, index.getTableName().getString(), indexColName); + } + } catch (AmbiguousColumnException e) { + if (indexColumn.getFamilyName() != null) { + ref = resolver.resolveColumn(tableAlias != null ? tableAlias : index.getTableName().getString(), indexColumn.getFamilyName().getString(), indexColName); + } else { + throw e; + } } } Expression expression = ref.newColumnExpression(); @@ -238,11 +257,14 @@ public class ProjectionCompiler { } } - private static void projectTableColumnFamily(StatementContext context, String cfName, TableRef tableRef, List<Expression> projectedExpressions, List<ExpressionProjector> projectedColumns) throws SQLException { + private static void projectTableColumnFamily(StatementContext context, String cfName, TableRef tableRef, boolean resolveColumn, List<Expression> projectedExpressions, List<ExpressionProjector> projectedColumns) throws SQLException { PTable table = tableRef.getTable(); PColumnFamily pfamily = table.getColumnFamily(cfName); for (PColumn column : pfamily.getColumns()) { ColumnRef ref = new ColumnRef(tableRef, column.getPosition()); + if (resolveColumn) { + ref = context.getResolver().resolveColumn(table.getTableName().getString(), cfName, column.getName().getString()); + } Expression expression = ref.newColumnExpression(); projectedExpressions.add(expression); String colName = column.getName().toString(); @@ -252,7 +274,7 @@ public class ProjectionCompiler { } } - private static void projectIndexColumnFamily(StatementContext context, String cfName, TableRef tableRef, List<Expression> projectedExpressions, List<ExpressionProjector> projectedColumns) throws SQLException { + private static void projectIndexColumnFamily(StatementContext context, String cfName, TableRef tableRef, boolean resolveColumn, List<Expression> projectedExpressions, List<ExpressionProjector> projectedColumns) throws SQLException { PTable index = tableRef.getTable(); PhoenixConnection conn = context.getConnection(); String tableName = index.getParentName().getString(); @@ -277,6 +299,9 @@ public class ProjectionCompiler { throw e; } } + if (resolveColumn) { + ref = context.getResolver().resolveColumn(index.getTableName().getString(), indexColumn.getFamilyName() == null ? null : indexColumn.getFamilyName().getString(), indexColName); + } Expression expression = ref.newColumnExpression(); projectedExpressions.add(expression); String colName = column.getName().toString(); @@ -322,6 +347,7 @@ public class ProjectionCompiler { ColumnResolver resolver = context.getResolver(); TableRef tableRef = context.getCurrentTable(); PTable table = tableRef.getTable(); + boolean resolveColumn = !tableRef.equals(resolver.getTables().get(0)); boolean isWildcard = false; Scan scan = context.getScan(); int index = 0; @@ -336,9 +362,9 @@ public class ProjectionCompiler { } isWildcard = true; if (tableRef.getTable().getType() == PTableType.INDEX && ((WildcardParseNode)node).isRewrite()) { - projectAllIndexColumns(context, tableRef, false, projectedExpressions, projectedColumns, targetColumns); + projectAllIndexColumns(context, tableRef, resolveColumn, projectedExpressions, projectedColumns, targetColumns); } else { - projectAllTableColumns(context, tableRef, false, projectedExpressions, projectedColumns, targetColumns); + projectAllTableColumns(context, tableRef, resolveColumn, projectedExpressions, projectedColumns, targetColumns); } } else if (node instanceof TableWildcardParseNode) { TableName tName = ((TableWildcardParseNode) node).getTableName(); @@ -362,9 +388,9 @@ public class ProjectionCompiler { // columns are projected (which is currently true, but could change). projectedFamilies.add(Bytes.toBytes(cfName)); if (tableRef.getTable().getType() == PTableType.INDEX && ((FamilyWildcardParseNode)node).isRewrite()) { - projectIndexColumnFamily(context, cfName, tableRef, projectedExpressions, projectedColumns); + projectIndexColumnFamily(context, cfName, tableRef, resolveColumn, projectedExpressions, projectedColumns); } else { - projectTableColumnFamily(context, cfName, tableRef, projectedExpressions, projectedColumns); + projectTableColumnFamily(context, cfName, tableRef, resolveColumn, projectedExpressions, projectedColumns); } } else { Expression expression = node.accept(selectVisitor); http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/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 137f4e9..2276f4e 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 @@ -28,9 +28,6 @@ import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.compile.GroupByCompiler.GroupBy; import org.apache.phoenix.compile.JoinCompiler.JoinSpec; import org.apache.phoenix.compile.JoinCompiler.JoinTable; -import org.apache.phoenix.compile.JoinCompiler.JoinedTableColumnResolver; -import org.apache.phoenix.compile.JoinCompiler.PTableWrapper; -import org.apache.phoenix.compile.JoinCompiler.ProjectedPTableWrapper; import org.apache.phoenix.compile.JoinCompiler.Table; import org.apache.phoenix.compile.OrderByCompiler.OrderBy; import org.apache.phoenix.execute.AggregatePlan; @@ -100,14 +97,23 @@ public class QueryCompiler { private final List<? extends PDatum> targetColumns; private final ParallelIteratorFactory parallelIteratorFactory; private final SequenceManager sequenceManager; + private final boolean projectTuples; private final boolean useSortMergeJoin; private final boolean noChildParentJoinOptimization; public QueryCompiler(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver) throws SQLException { - this(statement, select, resolver, Collections.<PDatum>emptyList(), null, new SequenceManager(statement)); + this(statement, select, resolver, Collections.<PDatum>emptyList(), null, new SequenceManager(statement), true); + } + + public QueryCompiler(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver, boolean projectTuples) throws SQLException { + this(statement, select, resolver, Collections.<PDatum>emptyList(), null, new SequenceManager(statement), projectTuples); } public QueryCompiler(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver, List<? extends PDatum> targetColumns, ParallelIteratorFactory parallelIteratorFactory, SequenceManager sequenceManager) throws SQLException { + this(statement, select, resolver, targetColumns, parallelIteratorFactory, sequenceManager, true); + } + + public QueryCompiler(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver, List<? extends PDatum> targetColumns, ParallelIteratorFactory parallelIteratorFactory, SequenceManager sequenceManager, boolean projectTuples) throws SQLException { this.statement = statement; this.select = select; this.resolver = resolver; @@ -115,6 +121,7 @@ public class QueryCompiler { this.targetColumns = targetColumns; this.parallelIteratorFactory = parallelIteratorFactory; this.sequenceManager = sequenceManager; + this.projectTuples = projectTuples; this.useSortMergeJoin = select.getHint().hasHint(Hint.USE_SORT_MERGE_JOIN); this.noChildParentJoinOptimization = select.getHint().hasHint(Hint.NO_CHILD_PARENT_JOIN_OPTIMIZATION); if (statement.getConnection().getQueryServices().getLowestClusterHBaseVersion() >= PhoenixDatabaseMetaData.ESSENTIAL_FAMILY_VERSION_THRESHOLD) { @@ -194,30 +201,32 @@ public class QueryCompiler { SelectStatement subquery = table.getAsSubquery(orderBy); if (!table.isSubselect()) { context.setCurrentTable(table.getTableRef()); - ProjectedPTableWrapper projectedTable = table.createProjectedTable(!projectPKColumns, context); - TupleProjector.serializeProjectorIntoScan(context.getScan(), projectedTable.createTupleProjector()); - context.setResolver(projectedTable.createColumnResolver()); + PTable projectedTable = table.createProjectedTable(!projectPKColumns, context); + TupleProjector.serializeProjectorIntoScan(context.getScan(), new TupleProjector(projectedTable)); + context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable)); table.projectColumns(context.getScan()); return compileSingleQuery(context, subquery, binds, asSubquery, !asSubquery); } QueryPlan plan = compileSubquery(subquery); - ProjectedPTableWrapper projectedTable = table.createProjectedTable(plan.getProjector()); - context.setResolver(projectedTable.createColumnResolver()); - return new TupleProjectionPlan(plan, projectedTable.createTupleProjector(), table.compilePostFilterExpression(context)); + PTable projectedTable = table.createProjectedTable(plan.getProjector()); + context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable)); + return new TupleProjectionPlan(plan, new TupleProjector(plan.getProjector()), table.compilePostFilterExpression(context)); } boolean[] starJoinVector; if (!this.useSortMergeJoin && (starJoinVector = joinTable.getStarJoinVector()) != null) { Table table = joinTable.getTable(); - ProjectedPTableWrapper initialProjectedTable; + PTable initialProjectedTable; TableRef tableRef; SelectStatement query; + TupleProjector tupleProjector; if (!table.isSubselect()) { context.setCurrentTable(table.getTableRef()); initialProjectedTable = table.createProjectedTable(!projectPKColumns, context); tableRef = table.getTableRef(); table.projectColumns(context.getScan()); query = joinTable.getAsSingleSubquery(table.getAsSubquery(orderBy), asSubquery); + tupleProjector = new TupleProjector(initialProjectedTable); } else { SelectStatement subquery = table.getAsSubquery(orderBy); QueryPlan plan = compileSubquery(subquery); @@ -225,9 +234,10 @@ public class QueryCompiler { tableRef = plan.getTableRef(); context.getScan().setFamilyMap(plan.getContext().getScan().getFamilyMap()); query = joinTable.getAsSingleSubquery((SelectStatement) plan.getStatement(), asSubquery); + tupleProjector = new TupleProjector(plan.getProjector()); } context.setCurrentTable(tableRef); - PTableWrapper projectedTable = initialProjectedTable; + PTable projectedTable = initialProjectedTable; int count = joinSpecs.size(); ImmutableBytesPtr[] joinIds = new ImmutableBytesPtr[count]; List<Expression>[] joinExpressions = new List[count]; @@ -235,9 +245,7 @@ public class QueryCompiler { PTable[] tables = new PTable[count]; int[] fieldPositions = new int[count]; HashSubPlan[] subPlans = new HashSubPlan[count]; - fieldPositions[0] = projectedTable.getTable().getColumns().size() - projectedTable.getTable().getPKColumns().size(); - boolean forceProjection = table.isSubselect(); - boolean needsProject = forceProjection || asSubquery; + fieldPositions[0] = projectedTable.getColumns().size() - projectedTable.getPKColumns().size(); for (int i = 0; i < count; i++) { JoinSpec joinSpec = joinSpecs.get(i); Scan subScan = ScanUtil.newScan(originalScan); @@ -245,17 +253,12 @@ public class QueryCompiler { QueryPlan joinPlan = compileJoinQuery(subContext, binds, joinSpec.getJoinTable(), true, true, null); boolean hasPostReference = joinSpec.getJoinTable().hasPostReference(); if (hasPostReference) { - PTableWrapper subProjTable = ((JoinedTableColumnResolver) subContext.getResolver()).getPTableWrapper(); - tables[i] = subProjTable.getTable(); - projectedTable = projectedTable.mergeProjectedTables(subProjTable, joinSpec.getType()); - needsProject = true; + tables[i] = subContext.getResolver().getTables().get(0).getTable(); + projectedTable = JoinCompiler.joinProjectedTables(projectedTable, tables[i], joinSpec.getType()); } else { tables[i] = null; } - if (!starJoinVector[i]) { - needsProject = true; - } - context.setResolver((!forceProjection && starJoinVector[i]) ? joinTable.getOriginalResolver() : projectedTable.createColumnResolver()); + context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable)); joinIds[i] = new ImmutableBytesPtr(emptyByteArray); // place-holder Pair<List<Expression>, List<Expression>> joinConditions = joinSpec.compileJoinConditions(context, subContext, true); joinExpressions[i] = joinConditions.getFirst(); @@ -270,17 +273,14 @@ public class QueryCompiler { } subPlans[i] = new HashSubPlan(i, joinPlan, optimized ? null : hashExpressions, joinSpec.isSingleValueOnly(), keyRangeLhsExpression, keyRangeRhsExpression); } - if (needsProject) { - TupleProjector.serializeProjectorIntoScan(context.getScan(), initialProjectedTable.createTupleProjector()); - } - context.setResolver(needsProject ? projectedTable.createColumnResolver() : joinTable.getOriginalResolver()); + TupleProjector.serializeProjectorIntoScan(context.getScan(), tupleProjector); QueryPlan plan = compileSingleQuery(context, query, binds, asSubquery, !asSubquery && joinTable.isAllLeftJoin()); Expression postJoinFilterExpression = joinTable.compilePostFilterExpression(context, table); Integer limit = null; if (!query.isAggregate() && !query.isDistinct() && query.getOrderBy().isEmpty()) { limit = plan.getLimit(); } - HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, joinExpressions, joinTypes, starJoinVector, tables, fieldPositions, postJoinFilterExpression, limit, forceProjection); + HashJoinInfo joinInfo = new HashJoinInfo(projectedTable, joinIds, joinExpressions, joinTypes, starJoinVector, tables, fieldPositions, postJoinFilterExpression, limit); return HashJoinPlan.create(joinTable.getStatement(), plan, joinInfo, subPlans); } @@ -296,16 +296,17 @@ public class QueryCompiler { Scan subScan = ScanUtil.newScan(originalScan); StatementContext lhsCtx = new StatementContext(statement, context.getResolver(), subScan, new SequenceManager(statement)); QueryPlan lhsPlan = compileJoinQuery(lhsCtx, binds, lhsJoin, true, true, null); - PTableWrapper lhsProjTable = ((JoinedTableColumnResolver) lhsCtx.getResolver()).getPTableWrapper(); - ProjectedPTableWrapper rhsProjTable; + PTable rhsProjTable; TableRef rhsTableRef; SelectStatement rhs; + TupleProjector tupleProjector; if (!rhsTable.isSubselect()) { context.setCurrentTable(rhsTable.getTableRef()); rhsProjTable = rhsTable.createProjectedTable(!projectPKColumns, context); rhsTableRef = rhsTable.getTableRef(); rhsTable.projectColumns(context.getScan()); rhs = rhsJoinTable.getAsSingleSubquery(rhsTable.getAsSubquery(orderBy), asSubquery); + tupleProjector = new TupleProjector(rhsProjTable); } else { SelectStatement subquery = rhsTable.getAsSubquery(orderBy); QueryPlan plan = compileSubquery(subquery); @@ -313,30 +314,27 @@ public class QueryCompiler { rhsTableRef = plan.getTableRef(); context.getScan().setFamilyMap(plan.getContext().getScan().getFamilyMap()); rhs = rhsJoinTable.getAsSingleSubquery((SelectStatement) plan.getStatement(), asSubquery); + tupleProjector = new TupleProjector(plan.getProjector()); } context.setCurrentTable(rhsTableRef); - boolean forceProjection = rhsTable.isSubselect(); - context.setResolver(forceProjection ? rhsProjTable.createColumnResolver() : joinTable.getOriginalResolver()); + context.setResolver(FromCompiler.getResolverForProjectedTable(rhsProjTable)); ImmutableBytesPtr[] joinIds = new ImmutableBytesPtr[] {new ImmutableBytesPtr(emptyByteArray)}; Pair<List<Expression>, List<Expression>> joinConditions = lastJoinSpec.compileJoinConditions(lhsCtx, context, true); List<Expression> joinExpressions = joinConditions.getSecond(); List<Expression> hashExpressions = joinConditions.getFirst(); boolean needsMerge = lhsJoin.hasPostReference(); - boolean needsProject = forceProjection || asSubquery || needsMerge; - PTable lhsTable = needsMerge ? lhsProjTable.getTable() : null; - int fieldPosition = needsMerge ? rhsProjTable.getTable().getColumns().size() - rhsProjTable.getTable().getPKColumns().size() : 0; - PTableWrapper projectedTable = needsMerge ? rhsProjTable.mergeProjectedTables(lhsProjTable, type == JoinType.Right ? JoinType.Left : type) : rhsProjTable; - if (needsProject) { - TupleProjector.serializeProjectorIntoScan(context.getScan(), rhsProjTable.createTupleProjector()); - } - context.setResolver(needsProject ? projectedTable.createColumnResolver() : joinTable.getOriginalResolver()); + PTable lhsTable = needsMerge ? lhsCtx.getResolver().getTables().get(0).getTable() : null; + int fieldPosition = needsMerge ? rhsProjTable.getColumns().size() - rhsProjTable.getPKColumns().size() : 0; + PTable projectedTable = needsMerge ? JoinCompiler.joinProjectedTables(rhsProjTable, lhsTable, type == JoinType.Right ? JoinType.Left : type) : rhsProjTable; + TupleProjector.serializeProjectorIntoScan(context.getScan(), tupleProjector); + context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable)); QueryPlan rhsPlan = compileSingleQuery(context, rhs, binds, asSubquery, !asSubquery && type == JoinType.Right); Expression postJoinFilterExpression = joinTable.compilePostFilterExpression(context, rhsTable); Integer limit = null; if (!rhs.isAggregate() && !rhs.isDistinct() && rhs.getOrderBy().isEmpty()) { limit = rhsPlan.getLimit(); } - HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, new List[] {joinExpressions}, new JoinType[] {type == JoinType.Right ? JoinType.Left : type}, new boolean[] {true}, new PTable[] {lhsTable}, new int[] {fieldPosition}, postJoinFilterExpression, limit, forceProjection); + HashJoinInfo joinInfo = new HashJoinInfo(projectedTable, joinIds, new List[] {joinExpressions}, new JoinType[] {type == JoinType.Right ? JoinType.Left : type}, new boolean[] {true}, new PTable[] {lhsTable}, new int[] {fieldPosition}, postJoinFilterExpression, limit); Pair<Expression, Expression> keyRangeExpressions = new Pair<Expression, Expression>(null, null); getKeyExpressionCombinations(keyRangeExpressions, context, joinTable.getStatement(), rhsTableRef, type, joinExpressions, hashExpressions); return HashJoinPlan.create(joinTable.getStatement(), rhsPlan, joinInfo, new HashSubPlan[] {new HashSubPlan(0, lhsPlan, hashExpressions, false, keyRangeExpressions.getFirst(), keyRangeExpressions.getSecond())}); @@ -362,28 +360,27 @@ public class QueryCompiler { StatementContext lhsCtx = new StatementContext(statement, context.getResolver(), lhsScan, new SequenceManager(statement)); boolean preserveRowkey = !projectPKColumns && type != JoinType.Full; QueryPlan lhsPlan = compileJoinQuery(lhsCtx, binds, lhsJoin, true, !preserveRowkey, lhsOrderBy); - PTableWrapper lhsProjTable = ((JoinedTableColumnResolver) lhsCtx.getResolver()).getPTableWrapper(); + PTable lhsProjTable = lhsCtx.getResolver().getTables().get(0).getTable(); boolean isInRowKeyOrder = preserveRowkey && lhsPlan.getOrderBy().getOrderByExpressions().isEmpty(); Scan rhsScan = ScanUtil.newScan(originalScan); StatementContext rhsCtx = new StatementContext(statement, context.getResolver(), rhsScan, new SequenceManager(statement)); QueryPlan rhsPlan = compileJoinQuery(rhsCtx, binds, rhsJoin, true, true, rhsOrderBy); - PTableWrapper rhsProjTable = ((JoinedTableColumnResolver) rhsCtx.getResolver()).getPTableWrapper(); + PTable rhsProjTable = rhsCtx.getResolver().getTables().get(0).getTable(); Pair<List<Expression>, List<Expression>> joinConditions = lastJoinSpec.compileJoinConditions(type == JoinType.Right ? rhsCtx : lhsCtx, type == JoinType.Right ? lhsCtx : rhsCtx, false); List<Expression> lhsKeyExpressions = type == JoinType.Right ? joinConditions.getSecond() : joinConditions.getFirst(); List<Expression> rhsKeyExpressions = type == JoinType.Right ? joinConditions.getFirst() : joinConditions.getSecond(); boolean needsMerge = rhsJoin.hasPostReference(); - PTable rhsTable = needsMerge ? rhsProjTable.getTable() : null; - int fieldPosition = needsMerge ? lhsProjTable.getTable().getColumns().size() - lhsProjTable.getTable().getPKColumns().size() : 0; - PTableWrapper projectedTable = needsMerge ? lhsProjTable.mergeProjectedTables(rhsProjTable, type == JoinType.Right ? JoinType.Left : type) : lhsProjTable; + int fieldPosition = needsMerge ? lhsProjTable.getColumns().size() - lhsProjTable.getPKColumns().size() : 0; + PTable projectedTable = needsMerge ? JoinCompiler.joinProjectedTables(lhsProjTable, rhsProjTable, type == JoinType.Right ? JoinType.Left : type) : lhsProjTable; - ColumnResolver resolver = projectedTable.createColumnResolver(); - TableRef tableRef = ((JoinedTableColumnResolver) resolver).getTableRef(); + ColumnResolver resolver = FromCompiler.getResolverForProjectedTable(projectedTable); + TableRef tableRef = resolver.getTables().get(0); StatementContext subCtx = new StatementContext(statement, resolver, ScanUtil.newScan(originalScan), new SequenceManager(statement)); subCtx.setCurrentTable(tableRef); - QueryPlan innerPlan = new SortMergeJoinPlan(subCtx, joinTable.getStatement(), tableRef, type == JoinType.Right ? JoinType.Left : type, lhsPlan, rhsPlan, lhsKeyExpressions, rhsKeyExpressions, projectedTable.getTable(), lhsProjTable.getTable(), rhsTable, fieldPosition, lastJoinSpec.isSingleValueOnly()); + QueryPlan innerPlan = new SortMergeJoinPlan(subCtx, joinTable.getStatement(), tableRef, type == JoinType.Right ? JoinType.Left : type, lhsPlan, rhsPlan, lhsKeyExpressions, rhsKeyExpressions, projectedTable, lhsProjTable, needsMerge ? rhsProjTable : null, fieldPosition, lastJoinSpec.isSingleValueOnly()); context.setCurrentTable(tableRef); context.setResolver(resolver); TableNode from = NODE_FACTORY.namedTable(tableRef.getTableAlias(), NODE_FACTORY.table(tableRef.getTable().getSchemaName().getString(), tableRef.getTable().getTableName().getString())); @@ -440,7 +437,7 @@ public class QueryCompiler { } int maxRows = this.statement.getMaxRows(); this.statement.setMaxRows(0); // overwrite maxRows to avoid its impact on inner queries. - QueryPlan plan = new QueryCompiler(this.statement, subquery, resolver).compile(); + QueryPlan plan = new QueryCompiler(this.statement, subquery, resolver, false).compile(); plan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, plan); this.statement.setMaxRows(maxRows); // restore maxRows. return plan; @@ -467,7 +464,14 @@ public class QueryCompiler { } protected QueryPlan compileSingleFlatQuery(StatementContext context, SelectStatement select, List<Object> binds, boolean asSubquery, boolean allowPageFilter, QueryPlan innerPlan, TupleProjector innerPlanTupleProjector, boolean isInRowKeyOrder) throws SQLException{ - PhoenixConnection connection = statement.getConnection(); + PTable projectedTable = null; + if (this.projectTuples) { + projectedTable = TupleProjectionCompiler.createProjectedTable(select, context); + if (projectedTable != null) { + context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable)); + } + } + ColumnResolver resolver = context.getResolver(); TableRef tableRef = context.getCurrentTable(); PTable table = tableRef.getTable(); @@ -485,15 +489,14 @@ public class QueryCompiler { Expression having = HavingCompiler.compile(context, select, groupBy); // Don't pass groupBy when building where clause expression, because we do not want to wrap these // expressions as group by key expressions since they're pre, not post filtered. - if (innerPlan == null) { - context.setResolver(FromCompiler.getResolverForQuery(select, connection)); + if (innerPlan == null && !tableRef.equals(resolver.getTables().get(0))) { + context.setResolver(FromCompiler.getResolverForQuery(select, this.statement.getConnection())); } Set<SubqueryParseNode> subqueries = Sets.<SubqueryParseNode> newHashSet(); Expression where = WhereCompiler.compile(context, select, viewWhere, subqueries); context.setResolver(resolver); // recover resolver OrderBy orderBy = OrderByCompiler.compile(context, select, groupBy, limit, isInRowKeyOrder); RowProjector projector = ProjectionCompiler.compile(context, select, groupBy, asSubquery ? Collections.<PDatum>emptyList() : targetColumns); - // Final step is to build the query plan if (!asSubquery) { int maxRows = statement.getMaxRows(); @@ -506,6 +509,10 @@ public class QueryCompiler { } } + if (projectedTable != null) { + TupleProjector.serializeProjectorIntoScan(context.getScan(), new TupleProjector(projectedTable)); + } + QueryPlan plan = innerPlan; if (plan == null) { ParallelIteratorFactory parallelIteratorFactory = asSubquery ? null : this.parallelIteratorFactory; http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java new file mode 100644 index 0000000..72e2a26 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TupleProjectionCompiler.java @@ -0,0 +1,214 @@ +/* + * 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.compile; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.phoenix.execute.TupleProjector; +import org.apache.phoenix.parse.AliasedNode; +import org.apache.phoenix.parse.ColumnParseNode; +import org.apache.phoenix.parse.FamilyWildcardParseNode; +import org.apache.phoenix.parse.OrderByNode; +import org.apache.phoenix.parse.ParseNode; +import org.apache.phoenix.parse.ParseNodeFactory; +import org.apache.phoenix.parse.SelectStatement; +import org.apache.phoenix.parse.StatelessTraverseAllParseNodeVisitor; +import org.apache.phoenix.parse.TableName; +import org.apache.phoenix.parse.WildcardParseNode; +import org.apache.phoenix.schema.ColumnFamilyNotFoundException; +import org.apache.phoenix.schema.ColumnNotFoundException; +import org.apache.phoenix.schema.ColumnRef; +import org.apache.phoenix.schema.LocalIndexDataColumnRef; +import org.apache.phoenix.schema.PColumn; +import org.apache.phoenix.schema.PName; +import org.apache.phoenix.schema.PNameFactory; +import org.apache.phoenix.schema.PTable; +import org.apache.phoenix.schema.PTableImpl; +import org.apache.phoenix.schema.PTableType; +import org.apache.phoenix.schema.ProjectedColumn; +import org.apache.phoenix.schema.TableRef; +import org.apache.phoenix.schema.PTable.IndexType; +import org.apache.phoenix.util.IndexUtil; +import org.apache.phoenix.util.SchemaUtil; + +import com.google.common.base.Preconditions; + +public class TupleProjectionCompiler { + public static final PName PROJECTED_TABLE_SCHEMA = PNameFactory.newName("."); + private static final ParseNodeFactory NODE_FACTORY = new ParseNodeFactory(); + + public static PTable createProjectedTable(SelectStatement select, StatementContext context) throws SQLException { + Preconditions.checkArgument(!select.isJoin()); + // Non-group-by or group-by aggregations will create its own projected result. + if (select.getInnerSelectStatement() != null + || select.isAggregate() + || select.isDistinct() + || (context.getResolver().getTables().get(0).getTable().getType() != PTableType.TABLE + && context.getResolver().getTables().get(0).getTable().getType() != PTableType.INDEX && context.getResolver().getTables().get(0).getTable().getType() != PTableType.VIEW)) + return null; + + List<PColumn> projectedColumns = new ArrayList<PColumn>(); + boolean isWildcard = false; + Set<String> families = new HashSet<String>(); + ColumnRefVisitor visitor = new ColumnRefVisitor(context); + TableRef tableRef = context.getCurrentTable(); + PTable table = tableRef.getTable(); + + for (AliasedNode aliasedNode : select.getSelect()) { + ParseNode node = aliasedNode.getNode(); + if (node instanceof WildcardParseNode) { + if (((WildcardParseNode) node).isRewrite()) { + TableRef parentTableRef = FromCompiler.getResolver( + NODE_FACTORY.namedTable(null, TableName.create(table.getSchemaName().getString(), + table.getParentTableName().getString())), context.getConnection()).resolveTable( + table.getSchemaName().getString(), + table.getParentTableName().getString()); + for (PColumn column : parentTableRef.getTable().getColumns()) { + NODE_FACTORY.column(null, '"' + IndexUtil.getIndexColumnName(column) + '"', null).accept(visitor); + } + } + isWildcard = true; + } else if (node instanceof FamilyWildcardParseNode) { + FamilyWildcardParseNode familyWildcardNode = (FamilyWildcardParseNode) node; + String familyName = familyWildcardNode.getName(); + if (familyWildcardNode.isRewrite()) { + TableRef parentTableRef = FromCompiler.getResolver( + NODE_FACTORY.namedTable(null, TableName.create(table.getSchemaName().getString(), + table.getParentTableName().getString())), context.getConnection()).resolveTable( + table.getSchemaName().getString(), + table.getParentTableName().getString()); + for (PColumn column : parentTableRef.getTable().getColumnFamily(familyName).getColumns()) { + NODE_FACTORY.column(null, '"' + IndexUtil.getIndexColumnName(column) + '"', null).accept(visitor); + } + } + families.add(familyName); + } else { + node.accept(visitor); + } + } + if (!isWildcard) { + for (OrderByNode orderBy : select.getOrderBy()) { + orderBy.getNode().accept(visitor); + } + } + + boolean hasSaltingColumn = table.getBucketNum() != null; + int position = hasSaltingColumn ? 1 : 0; + // Always project PK columns first in case there are some PK columns added by alter table. + for (int i = position; i < table.getPKColumns().size(); i++) { + PColumn sourceColumn = table.getPKColumns().get(i); + ColumnRef sourceColumnRef = new ColumnRef(tableRef, sourceColumn.getPosition()); + PColumn column = new ProjectedColumn(sourceColumn.getName(), sourceColumn.getFamilyName(), + position++, sourceColumn.isNullable(), sourceColumnRef); + projectedColumns.add(column); + } + for (PColumn sourceColumn : table.getColumns()) { + if (SchemaUtil.isPKColumn(sourceColumn)) + continue; + ColumnRef sourceColumnRef = new ColumnRef(tableRef, sourceColumn.getPosition()); + if (!isWildcard + && !visitor.columnRefSet.contains(sourceColumnRef) + && !families.contains(sourceColumn.getFamilyName().getString())) + continue; + PColumn column = new ProjectedColumn(sourceColumn.getName(), sourceColumn.getFamilyName(), + position++, sourceColumn.isNullable(), sourceColumnRef); + projectedColumns.add(column); + // Wildcard or FamilyWildcard will be handled by ProjectionCompiler. + if (!isWildcard && !families.contains(sourceColumn.getFamilyName())) { + context.getScan().addColumn(sourceColumn.getFamilyName().getBytes(), sourceColumn.getName().getBytes()); + } + } + // add LocalIndexDataColumnRef + for (LocalIndexDataColumnRef sourceColumnRef : visitor.localIndexColumnRefSet) { + PColumn column = new ProjectedColumn(sourceColumnRef.getColumn().getName(), + sourceColumnRef.getColumn().getFamilyName(), position++, + sourceColumnRef.getColumn().isNullable(), sourceColumnRef); + projectedColumns.add(column); + } + + return PTableImpl.makePTable(table.getTenantId(), table.getSchemaName(), table.getName(), PTableType.PROJECTED, + table.getIndexState(), table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), + table.getBucketNum(), projectedColumns, table.getParentSchemaName(), + table.getParentName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), + table.getIndexType()); + } + + public static PTable createProjectedTable(TableRef tableRef, List<ColumnRef> sourceColumnRefs, boolean retainPKColumns) throws SQLException { + PTable table = tableRef.getTable(); + boolean hasSaltingColumn = retainPKColumns && table.getBucketNum() != null; + List<PColumn> projectedColumns = new ArrayList<PColumn>(); + int position = hasSaltingColumn ? 1 : 0; + for (int i = position; i < sourceColumnRefs.size(); i++) { + ColumnRef sourceColumnRef = sourceColumnRefs.get(i); + PColumn sourceColumn = sourceColumnRef.getColumn(); + String colName = sourceColumn.getName().getString(); + String aliasedName = tableRef.getTableAlias() == null ? + SchemaUtil.getColumnName(table.getName().getString(), colName) + : SchemaUtil.getColumnName(tableRef.getTableAlias(), colName); + + PColumn column = new ProjectedColumn(PNameFactory.newName(aliasedName), + retainPKColumns && SchemaUtil.isPKColumn(sourceColumn) ? + null : PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), + position++, sourceColumn.isNullable(), sourceColumnRef); + projectedColumns.add(column); + } + return PTableImpl.makePTable(table.getTenantId(), PROJECTED_TABLE_SCHEMA, table.getName(), PTableType.PROJECTED, + null, table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), + retainPKColumns ? table.getBucketNum() : null, projectedColumns, null, + null, Collections.<PTable>emptyList(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), + null); + } + + // For extracting column references from single select statement + private static class ColumnRefVisitor extends StatelessTraverseAllParseNodeVisitor { + private final StatementContext context; + private final Set<ColumnRef> columnRefSet; + private final Set<LocalIndexDataColumnRef> localIndexColumnRefSet; + + private ColumnRefVisitor(StatementContext context) { + this.context = context; + this.columnRefSet = new HashSet<ColumnRef>(); + this.localIndexColumnRefSet = new HashSet<LocalIndexDataColumnRef>(); + } + + @Override + public Void visit(ColumnParseNode node) throws SQLException { + try { + columnRefSet.add(context.getResolver().resolveColumn(node.getSchemaName(), node.getTableName(), node.getName())); + } catch (ColumnNotFoundException e) { + if (context.getCurrentTable().getTable().getIndexType() == IndexType.LOCAL) { + try { + localIndexColumnRefSet.add(new LocalIndexDataColumnRef(context, node.getName())); + } catch (ColumnFamilyNotFoundException c) { + throw e; + } + } else { + throw e; + } + } + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java index b21cc2f..8a76564 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java @@ -419,11 +419,11 @@ public class UpsertCompiler { // Pass scan through if same table in upsert and select so that projection is computed correctly // Use optimizer to choose the best plan try { - QueryCompiler compiler = new QueryCompiler(statement, select, selectResolver, targetColumns, parallelIteratorFactoryToBe, new SequenceManager(statement)); + QueryCompiler compiler = new QueryCompiler(statement, select, selectResolver, targetColumns, parallelIteratorFactoryToBe, new SequenceManager(statement), false); queryPlanToBe = compiler.compile(); // This is post-fix: if the tableRef is a projected table, this means there are post-processing // steps and parallelIteratorFactory did not take effect. - if (queryPlanToBe.getTableRef().getTable().getType() == PTableType.JOIN || queryPlanToBe.getTableRef().getTable().getType() == PTableType.SUBQUERY) { + if (queryPlanToBe.getTableRef().getTable().getType() == PTableType.PROJECTED || queryPlanToBe.getTableRef().getTable().getType() == PTableType.SUBQUERY) { parallelIteratorFactoryToBe = null; } } catch (MetaDataEntityNotFoundException e) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java index 406b567..9631850 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/WhereCompiler.java @@ -145,7 +145,7 @@ public class WhereCompiler { expression = AndExpression.create(filters); } - if (context.getCurrentTable().getTable().getType() != PTableType.JOIN && context.getCurrentTable().getTable().getType() != PTableType.SUBQUERY) { + if (context.getCurrentTable().getTable().getType() != PTableType.PROJECTED && context.getCurrentTable().getTable().getType() != PTableType.SUBQUERY) { expression = WhereOptimizer.pushKeyExpressionsToScan(context, statement, expression, extractedNodes); } setScanFilter(context, statement, expression, whereCompiler.disambiguateWithFamily, hashJoinOptimization); http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java index 69cdcb6..25ac408 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/BaseScannerRegionObserver.java @@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue.Type; +import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver; import org.apache.hadoop.hbase.coprocessor.ObserverContext; @@ -47,6 +48,8 @@ import org.apache.phoenix.schema.KeyValueSchema; import org.apache.phoenix.schema.StaleRegionBoundaryCacheException; import org.apache.phoenix.schema.ValueBitSet; import org.apache.phoenix.schema.tuple.MultiKeyValueTuple; +import org.apache.phoenix.schema.tuple.ResultTuple; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.ScanUtil; import org.apache.phoenix.util.ServerUtil; @@ -216,9 +219,10 @@ abstract public class BaseScannerRegionObserver extends BaseRegionObserver { final RegionScanner s, final int offset, final Scan scan, final ColumnReference[] dataColumns, final TupleProjector tupleProjector, final HRegion dataRegion, final IndexMaintainer indexMaintainer, - final byte[][] viewConstants, final ImmutableBytesWritable ptr) { + final byte[][] viewConstants, final TupleProjector projector, + final ImmutableBytesWritable ptr) { return getWrappedScanner(c, s, null, null, offset, scan, dataColumns, tupleProjector, - dataRegion, indexMaintainer, viewConstants, null, null, ptr); + dataRegion, indexMaintainer, viewConstants, null, null, projector, ptr); } /** @@ -241,7 +245,8 @@ abstract public class BaseScannerRegionObserver extends BaseRegionObserver { final ColumnReference[] dataColumns, final TupleProjector tupleProjector, final HRegion dataRegion, final IndexMaintainer indexMaintainer, final byte[][] viewConstants, final KeyValueSchema kvSchema, - final ValueBitSet kvSchemaBitSet, final ImmutableBytesWritable ptr) { + final ValueBitSet kvSchemaBitSet, final TupleProjector projector, + final ImmutableBytesWritable ptr) { return new RegionScanner() { @Override @@ -303,6 +308,11 @@ abstract public class BaseScannerRegionObserver extends BaseRegionObserver { IndexUtil.wrapResultUsingOffset(c, result, offset, dataColumns, tupleProjector, dataRegion, indexMaintainer, viewConstants, ptr); } + if (projector != null) { + Tuple tuple = projector.projectResults(new ResultTuple(Result.create(result))); + result.clear(); + result.add(tuple.getValue(0)); + } // There is a scanattribute set to retrieve the specific array element return next; } catch (Throwable t) { @@ -325,6 +335,11 @@ abstract public class BaseScannerRegionObserver extends BaseRegionObserver { IndexUtil.wrapResultUsingOffset(c, result, offset, dataColumns, tupleProjector, dataRegion, indexMaintainer, viewConstants, ptr); } + if (projector != null) { + Tuple tuple = projector.projectResults(new ResultTuple(Result.create(result))); + result.clear(); + result.add(tuple.getValue(0)); + } // There is a scanattribute set to retrieve the specific array element return next; } catch (Throwable t) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/GroupedAggregateRegionObserver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/GroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/GroupedAggregateRegionObserver.java index 0984b06..1f1ba36 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/GroupedAggregateRegionObserver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/GroupedAggregateRegionObserver.java @@ -131,7 +131,10 @@ public class GroupedAggregateRegionObserver extends BaseScannerRegionObserver { HRegion dataRegion = null; byte[][] viewConstants = null; ColumnReference[] dataColumns = IndexUtil.deserializeDataTableColumnsToJoin(scan); - if (ScanUtil.isLocalIndex(scan)) { + + final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); + final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); + if (ScanUtil.isLocalIndex(scan) || (j == null && p != null)) { if (dataColumns != null) { tupleProjector = IndexUtil.getTupleProjector(scan, dataColumns); dataRegion = IndexUtil.getDataRegion(c.getEnvironment()); @@ -140,12 +143,10 @@ public class GroupedAggregateRegionObserver extends BaseScannerRegionObserver { ImmutableBytesWritable tempPtr = new ImmutableBytesWritable(); innerScanner = getWrappedScanner(c, innerScanner, offset, scan, dataColumns, tupleProjector, - dataRegion, indexMaintainers == null ? null : indexMaintainers.get(0), viewConstants, tempPtr); + dataRegion, indexMaintainers == null ? null : indexMaintainers.get(0), viewConstants, p, tempPtr); } - final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); - final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); - if (p != null || j != null) { + if (j != null) { innerScanner = new HashJoinRegionScanner(innerScanner, p, j, ScanUtil.getTenantId(scan), c.getEnvironment()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/HashJoinRegionScanner.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/HashJoinRegionScanner.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/HashJoinRegionScanner.java index 176520e..cdfc771 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/HashJoinRegionScanner.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/HashJoinRegionScanner.java @@ -70,39 +70,37 @@ public class HashJoinRegionScanner implements RegionScanner { this.hasMore = true; this.count = 0; this.limit = Long.MAX_VALUE; - if (joinInfo != null) { - for (JoinType type : joinInfo.getJoinTypes()) { - if (type != JoinType.Inner && type != JoinType.Left && type != JoinType.Semi && type != JoinType.Anti) - throw new DoNotRetryIOException("Got join type '" + type + "'. Expect only INNER or LEFT with hash-joins."); - } - if (joinInfo.getLimit() != null) { - this.limit = joinInfo.getLimit(); - } - int count = joinInfo.getJoinIds().length; - this.tempTuples = new List[count]; - this.hashCaches = new HashCache[count]; - this.tempSrcBitSet = new ValueBitSet[count]; - TenantCache cache = GlobalCache.getTenantCache(env, tenantId); - for (int i = 0; i < count; i++) { - ImmutableBytesPtr joinId = joinInfo.getJoinIds()[i]; - if (joinId.getLength() == 0) { // semi-join optimized into skip-scan - hashCaches[i] = null; - tempSrcBitSet[i] = null; - tempTuples[i] = null; - continue; - } - HashCache hashCache = (HashCache)cache.getServerCache(joinId); - if (hashCache == null) - throw new DoNotRetryIOException("Could not find hash cache for joinId: " - + Bytes.toString(joinId.get(), joinId.getOffset(), joinId.getLength()) - + ". The cache might have expired and have been removed."); - hashCaches[i] = hashCache; - tempSrcBitSet[i] = ValueBitSet.newInstance(joinInfo.getSchemas()[i]); - } - if (this.projector != null) { - this.tempDestBitSet = ValueBitSet.newInstance(joinInfo.getJoinedSchema()); - this.projector.setValueBitSet(tempDestBitSet); + for (JoinType type : joinInfo.getJoinTypes()) { + if (type != JoinType.Inner && type != JoinType.Left && type != JoinType.Semi && type != JoinType.Anti) + throw new DoNotRetryIOException("Got join type '" + type + "'. Expect only INNER or LEFT with hash-joins."); + } + if (joinInfo.getLimit() != null) { + this.limit = joinInfo.getLimit(); + } + int count = joinInfo.getJoinIds().length; + this.tempTuples = new List[count]; + this.hashCaches = new HashCache[count]; + this.tempSrcBitSet = new ValueBitSet[count]; + TenantCache cache = GlobalCache.getTenantCache(env, tenantId); + for (int i = 0; i < count; i++) { + ImmutableBytesPtr joinId = joinInfo.getJoinIds()[i]; + if (joinId.getLength() == 0) { // semi-join optimized into skip-scan + hashCaches[i] = null; + tempSrcBitSet[i] = null; + tempTuples[i] = null; + continue; } + HashCache hashCache = (HashCache)cache.getServerCache(joinId); + if (hashCache == null) + throw new DoNotRetryIOException("Could not find hash cache for joinId: " + + Bytes.toString(joinId.get(), joinId.getOffset(), joinId.getLength()) + + ". The cache might have expired and have been removed."); + hashCaches[i] = hashCache; + tempSrcBitSet[i] = ValueBitSet.newInstance(joinInfo.getSchemas()[i]); + } + if (this.projector != null) { + this.tempDestBitSet = ValueBitSet.newInstance(joinInfo.getJoinedSchema()); + this.projector.setValueBitSet(tempDestBitSet); } } @@ -111,13 +109,11 @@ public class HashJoinRegionScanner implements RegionScanner { return; Tuple tuple = new ResultTuple(Result.create(result)); - if (joinInfo == null || joinInfo.forceProjection()) { + // For backward compatibility. In new versions, HashJoinInfo.forceProjection() + // always returns true. + if (joinInfo.forceProjection()) { tuple = projector.projectResults(tuple); } - if (joinInfo == null) { - resultQueue.offer(tuple); - return; - } if (hasBatchLimit) throw new UnsupportedOperationException("Cannot support join operations in scans with limit"); @@ -147,7 +143,7 @@ public class HashJoinRegionScanner implements RegionScanner { } } else { KeyValueSchema schema = joinInfo.getJoinedSchema(); - if (!joinInfo.forceProjection()) { + if (!joinInfo.forceProjection()) { // backward compatibility tuple = projector.projectResults(tuple); } resultQueue.offer(tuple); http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/ScanRegionObserver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/ScanRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/ScanRegionObserver.java index 9270495..ddde407 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/ScanRegionObserver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/ScanRegionObserver.java @@ -199,15 +199,16 @@ public class ScanRegionObserver extends BaseScannerRegionObserver { indexMaintainer = indexMaintainers.get(0); viewConstants = IndexUtil.deserializeViewConstantsFromScan(scan); } + + final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); + final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); innerScanner = getWrappedScanner(c, innerScanner, arrayKVRefs, arrayFuncRefs, offset, scan, dataColumns, tupleProjector, dataRegion, indexMaintainer, viewConstants, - kvSchema, kvSchemaBitSet, ptr); + kvSchema, kvSchemaBitSet, j == null ? p : null, ptr); - final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); - final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); final ImmutableBytesWritable tenantId = ScanUtil.getTenantId(scan); - if (p != null || j != null) { + if (j != null) { innerScanner = new HashJoinRegionScanner(innerScanner, p, j, tenantId, c.getEnvironment()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java index 71c4dc6..72a0a64 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java @@ -214,7 +214,9 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{ byte[][] viewConstants = null; ColumnReference[] dataColumns = IndexUtil.deserializeDataTableColumnsToJoin(scan); boolean localIndexScan = ScanUtil.isLocalIndex(scan); - if (localIndexScan && !isDelete) { + final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); + final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); + if ((localIndexScan && !isDelete) || (j == null && p != null)) { if (dataColumns != null) { tupleProjector = IndexUtil.getTupleProjector(scan, dataColumns); dataRegion = IndexUtil.getDataRegion(c.getEnvironment()); @@ -223,12 +225,10 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver{ ImmutableBytesWritable tempPtr = new ImmutableBytesWritable(); theScanner = getWrappedScanner(c, theScanner, offset, scan, dataColumns, tupleProjector, - dataRegion, indexMaintainers == null ? null : indexMaintainers.get(0), viewConstants, tempPtr); + dataRegion, indexMaintainers == null ? null : indexMaintainers.get(0), viewConstants, p, tempPtr); } - final TupleProjector p = TupleProjector.deserializeProjectorFromScan(scan); - final HashJoinInfo j = HashJoinInfo.deserializeHashJoinFromScan(scan); - if (p != null || j != null) { + if (j != null) { theScanner = new HashJoinRegionScanner(theScanner, p, j, ScanUtil.getTenantId(scan), c.getEnvironment()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjector.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjector.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjector.java index 77682e4..a4728e9 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjector.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjector.java @@ -32,19 +32,23 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.WritableUtils; import org.apache.phoenix.compile.ColumnProjector; -import org.apache.phoenix.compile.JoinCompiler.ProjectedPTableWrapper; import org.apache.phoenix.compile.RowProjector; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.ExpressionType; import org.apache.phoenix.schema.KeyValueSchema; import org.apache.phoenix.schema.KeyValueSchema.KeyValueSchemaBuilder; import org.apache.phoenix.schema.PColumn; +import org.apache.phoenix.schema.PTable; +import org.apache.phoenix.schema.PTableType; +import org.apache.phoenix.schema.ProjectedColumn; import org.apache.phoenix.schema.ValueBitSet; import org.apache.phoenix.schema.tuple.BaseTuple; import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.KeyValueUtil; import org.apache.phoenix.util.SchemaUtil; +import com.google.common.base.Preconditions; + public class TupleProjector { public static final byte[] VALUE_COLUMN_FAMILY = Bytes.toBytes("_v"); public static final byte[] VALUE_COLUMN_QUALIFIER = new byte[0]; @@ -70,16 +74,16 @@ public class TupleProjector { valueSet = ValueBitSet.newInstance(schema); } - public TupleProjector(ProjectedPTableWrapper projected) { - List<PColumn> columns = projected.getTable().getColumns(); - expressions = new Expression[columns.size() - projected.getTable().getPKColumns().size()]; - // we do not count minNullableIndex for we might do later merge. + public TupleProjector(PTable projectedTable) { + Preconditions.checkArgument(projectedTable.getType() == PTableType.PROJECTED); + List<PColumn> columns = projectedTable.getColumns(); + this.expressions = new Expression[columns.size() - projectedTable.getPKColumns().size()]; KeyValueSchemaBuilder builder = new KeyValueSchemaBuilder(0); int i = 0; - for (PColumn column : projected.getTable().getColumns()) { + for (PColumn column : columns) { if (!SchemaUtil.isPKColumn(column)) { builder.addField(column); - expressions[i++] = projected.getSourceExpression(column); + expressions[i++] = ((ProjectedColumn) column).getSourceColumnRef().newColumnExpression(); } } schema = builder.build(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/join/HashJoinInfo.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/join/HashJoinInfo.java b/phoenix-core/src/main/java/org/apache/phoenix/join/HashJoinInfo.java index ad96061..ea78671 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/join/HashJoinInfo.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/join/HashJoinInfo.java @@ -50,10 +50,9 @@ public class HashJoinInfo { private int[] fieldPositions; private Expression postJoinFilterExpression; private Integer limit; - private boolean forceProjection; - public HashJoinInfo(PTable joinedTable, ImmutableBytesPtr[] joinIds, List<Expression>[] joinExpressions, JoinType[] joinTypes, boolean[] earlyEvaluation, PTable[] tables, int[] fieldPositions, Expression postJoinFilterExpression, Integer limit, boolean forceProjection) { - this(buildSchema(joinedTable), joinIds, joinExpressions, joinTypes, earlyEvaluation, buildSchemas(tables), fieldPositions, postJoinFilterExpression, limit, forceProjection); + public HashJoinInfo(PTable joinedTable, ImmutableBytesPtr[] joinIds, List<Expression>[] joinExpressions, JoinType[] joinTypes, boolean[] earlyEvaluation, PTable[] tables, int[] fieldPositions, Expression postJoinFilterExpression, Integer limit) { + this(buildSchema(joinedTable), joinIds, joinExpressions, joinTypes, earlyEvaluation, buildSchemas(tables), fieldPositions, postJoinFilterExpression, limit); } private static KeyValueSchema[] buildSchemas(PTable[] tables) { @@ -76,7 +75,7 @@ public class HashJoinInfo { return builder.build(); } - private HashJoinInfo(KeyValueSchema joinedSchema, ImmutableBytesPtr[] joinIds, List<Expression>[] joinExpressions, JoinType[] joinTypes, boolean[] earlyEvaluation, KeyValueSchema[] schemas, int[] fieldPositions, Expression postJoinFilterExpression, Integer limit, boolean forceProjection) { + private HashJoinInfo(KeyValueSchema joinedSchema, ImmutableBytesPtr[] joinIds, List<Expression>[] joinExpressions, JoinType[] joinTypes, boolean[] earlyEvaluation, KeyValueSchema[] schemas, int[] fieldPositions, Expression postJoinFilterExpression, Integer limit) { this.joinedSchema = joinedSchema; this.joinIds = joinIds; this.joinExpressions = joinExpressions; @@ -86,7 +85,6 @@ public class HashJoinInfo { this.fieldPositions = fieldPositions; this.postJoinFilterExpression = postJoinFilterExpression; this.limit = limit; - this.forceProjection = forceProjection; } public KeyValueSchema getJoinedSchema() { @@ -124,15 +122,11 @@ public class HashJoinInfo { public Integer getLimit() { return limit; } - - /* - * If the LHS table is a sub-select, we always do projection, since - * the ON expressions reference only projected columns. - */ + public boolean forceProjection() { - return forceProjection; + return true; } - + public static void serializeHashJoinIntoScan(Scan scan, HashJoinInfo joinInfo) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { @@ -159,7 +153,7 @@ public class HashJoinInfo { WritableUtils.writeVInt(output, -1); } WritableUtils.writeVInt(output, joinInfo.limit == null ? -1 : joinInfo.limit); - output.writeBoolean(joinInfo.forceProjection); + output.writeBoolean(true); scan.setAttribute(HASH_JOIN, stream.toByteArray()); } catch (IOException e) { throw new RuntimeException(e); @@ -216,17 +210,16 @@ public class HashJoinInfo { postJoinFilterExpression.readFields(input); } int limit = -1; - boolean forceProjection = false; // Read these and ignore if we don't find them as they were not // present in Apache Phoenix 3.0.0 release. This allows a newer // 3.1 server to work with an older 3.0 client without force // both to be upgraded in lock step. try { limit = WritableUtils.readVInt(input); - forceProjection = input.readBoolean(); + input.readBoolean(); // discarded info in new versions } catch (EOFException ignore) { } - return new HashJoinInfo(joinedSchema, joinIds, joinExpressions, joinTypes, earlyEvaluation, schemas, fieldPositions, postJoinFilterExpression, limit >= 0 ? limit : null, forceProjection); + return new HashJoinInfo(joinedSchema, joinIds, joinExpressions, joinTypes, earlyEvaluation, schemas, fieldPositions, postJoinFilterExpression, limit >= 0 ? limit : null); } catch (IOException e) { throw new RuntimeException(e); } finally { http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/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 a51723b..382bba5 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 @@ -113,14 +113,13 @@ public class QueryOptimizer { SelectStatement select = (SelectStatement)dataPlan.getStatement(); // Exit early if we have a point lookup as we can't get better than that if (!useIndexes - || select.isJoin() - || dataPlan.getContext().getResolver().getTables().size() > 1 - || select.getInnerSelectStatement() != null || (dataPlan.getContext().getScanRanges().isPointLookup() && stopAtBestPlan)) { return Collections.singletonList(dataPlan); } - PTable dataTable = dataPlan.getTableRef().getTable(); - List<PTable>indexes = Lists.newArrayList(dataTable.getIndexes()); + // For single query tuple projection, indexes are inherited from the original table to the projected + // table; otherwise not. So we pass projected table here, which is enough to tell if this is from a + // single query or a part of join query. + List<PTable>indexes = Lists.newArrayList(dataPlan.getContext().getResolver().getTables().get(0).getTable().getIndexes()); if (indexes.isEmpty() || dataPlan.isDegenerate() || dataPlan.getTableRef().hasDynamicCols() || select.getHint().hasHint(Hint.NO_INDEX)) { return Collections.singletonList(dataPlan); } @@ -138,7 +137,7 @@ public class QueryOptimizer { targetColumns = targetDatums; } - SelectStatement translatedIndexSelect = IndexStatementRewriter.translate(select, dataPlan.getContext().getResolver()); + SelectStatement translatedIndexSelect = IndexStatementRewriter.translate(select, FromCompiler.getResolver(dataPlan.getTableRef())); List<QueryPlan> plans = Lists.newArrayListWithExpectedSize(1 + indexes.size()); plans.add(dataPlan); QueryPlan hintedPlan = getHintedQueryPlan(statement, translatedIndexSelect, indexes, targetColumns, parallelIteratorFactory, plans); @@ -230,12 +229,14 @@ public class QueryOptimizer { TableNode table = FACTORY.namedTable(alias, FACTORY.table(schemaName, tableName)); SelectStatement indexSelect = FACTORY.select(select, table); ColumnResolver resolver = FromCompiler.getResolverForQuery(indexSelect, statement.getConnection()); + // We will or will not do tuple projection according to the data plan. + boolean isProjected = dataPlan.getContext().getResolver().getTables().get(0).getTable().getType() == PTableType.PROJECTED; // Check index state of now potentially updated index table to make sure it's active if (PIndexState.ACTIVE.equals(resolver.getTables().get(0).getTable().getIndexState())) { try { // translate nodes that match expressions that are indexed to the associated column parse node indexSelect = ParseNodeRewriter.rewrite(indexSelect, new IndexExpressionParseNodeRewriter(index, statement.getConnection())); - QueryCompiler compiler = new QueryCompiler(statement, indexSelect, resolver, targetColumns, parallelIteratorFactory, dataPlan.getContext().getSequenceManager()); + QueryCompiler compiler = new QueryCompiler(statement, indexSelect, resolver, targetColumns, parallelIteratorFactory, dataPlan.getContext().getSequenceManager(), isProjected); QueryPlan plan = compiler.compile(); // If query doesn't have where clause and some of columns to project are missing @@ -267,7 +268,7 @@ public class QueryOptimizer { ParseNode where = dataSelect.getWhere(); if (isHinted && where != null) { StatementContext context = new StatementContext(statement, resolver); - WhereConditionRewriter whereRewriter = new WhereConditionRewriter(dataPlan.getContext().getResolver(), context); + WhereConditionRewriter whereRewriter = new WhereConditionRewriter(FromCompiler.getResolver(dataPlan.getTableRef()), context); where = where.accept(whereRewriter); if (where != null) { PTable dataTable = dataPlan.getTableRef().getTable(); @@ -301,7 +302,7 @@ public class QueryOptimizer { query = SubqueryRewriter.transform(query, queryResolver, statement.getConnection()); queryResolver = FromCompiler.getResolverForQuery(query, statement.getConnection()); query = StatementNormalizer.normalize(query, queryResolver); - QueryPlan plan = new QueryCompiler(statement, query, queryResolver).compile(); + QueryPlan plan = new QueryCompiler(statement, query, queryResolver, targetColumns, parallelIteratorFactory, dataPlan.getContext().getSequenceManager(), isProjected).compile(); return plan; } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/ColumnRef.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/ColumnRef.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/ColumnRef.java index c6dd1f4..76f6218 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/ColumnRef.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/ColumnRef.java @@ -105,7 +105,7 @@ public class ColumnRef { displayName); } - if (table.getType() == PTableType.JOIN || table.getType() == PTableType.SUBQUERY) { + if (table.getType() == PTableType.PROJECTED || table.getType() == PTableType.SUBQUERY) { return new ProjectedColumnExpression(column, table, displayName); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/LocalIndexDataColumnRef.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/LocalIndexDataColumnRef.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/LocalIndexDataColumnRef.java index 62ef431..270c66d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/LocalIndexDataColumnRef.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/LocalIndexDataColumnRef.java @@ -20,16 +20,13 @@ package org.apache.phoenix.schema; import java.sql.SQLException; import java.util.Set; -import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.compile.FromCompiler; import org.apache.phoenix.compile.StatementContext; import org.apache.phoenix.expression.ColumnExpression; import org.apache.phoenix.expression.ProjectedColumnExpression; import org.apache.phoenix.parse.ParseNodeFactory; import org.apache.phoenix.parse.TableName; -import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.util.IndexUtil; -import org.apache.phoenix.util.SchemaUtil; public class LocalIndexDataColumnRef extends ColumnRef { final private int position; @@ -62,11 +59,7 @@ public class LocalIndexDataColumnRef extends ColumnRef { @Override public ColumnExpression newColumnExpression(boolean schemaNameCaseSensitive, boolean colNameCaseSensitive) { - PTable table = this.getTable(); - PColumn column = this.getColumn(); - // TODO: util for this or store in member variable - byte[] defaultFamily = table.getDefaultFamilyName() == null ? QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES : table.getDefaultFamilyName().getBytes(); - String displayName = SchemaUtil.getColumnDisplayName(Bytes.compareTo(defaultFamily, column.getFamilyName().getBytes()) == 0 ? null : column.getFamilyName().getBytes(), column.getName().getBytes()); + String displayName = this.getTableRef().getColumnDisplayName(this, schemaNameCaseSensitive, colNameCaseSensitive); return new ProjectedColumnExpression(this.getColumn(), columns, position, displayName); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java index 831616b..e133433 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java @@ -764,7 +764,7 @@ public class MetaDataClient { String tableName = getFullTableName(dataTableRef); String query = "SELECT count(*) FROM " + tableName; final QueryPlan plan = statement.compileQuery(query); - TableRef tableRef = plan.getContext().getResolver().getTables().get(0); + TableRef tableRef = plan.getTableRef(); // Set attribute on scan that UngroupedAggregateRegionObserver will switch on. // We'll detect that this attribute was set the server-side and write the index // rows per region as a result. The value of the attribute will be our persisted http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableType.java index 23ba829..019c0e1 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableType.java @@ -27,7 +27,7 @@ public enum PTableType { TABLE("u", "TABLE"), VIEW("v", "VIEW"), INDEX("i", "INDEX"), - JOIN("j", "JOIN"), + PROJECTED("p", "PROJECTED"), SUBQUERY("q", "SUBQUERY"); private final PName value; http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/ProjectedColumn.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/ProjectedColumn.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/ProjectedColumn.java new file mode 100644 index 0000000..19dd1c1 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/ProjectedColumn.java @@ -0,0 +1,59 @@ +/* + * 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.schema; + +public class ProjectedColumn extends DelegateColumn { + + private final PName name; + private final PName familyName; + private final int position; + private final boolean nullable; + private final ColumnRef sourceColumnRef; + + public ProjectedColumn(PName name, PName familyName, int position, boolean nullable, ColumnRef sourceColumnRef) { + super(sourceColumnRef.getColumn()); + this.name = name; + this.familyName = familyName; + this.position = position; + this.nullable = nullable; + this.sourceColumnRef = sourceColumnRef; + } + + @Override + public PName getName() { + return name; + } + + public PName getFamilyName() { + return familyName; + } + + @Override + public int getPosition() { + return position; + } + + @Override + public boolean isNullable() { + return nullable; + } + + public ColumnRef getSourceColumnRef() { + return sourceColumnRef; + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java index b64912b..bd88770 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/TableRef.java @@ -18,6 +18,7 @@ package org.apache.phoenix.schema; import org.apache.hadoop.hbase.HConstants; +import org.apache.phoenix.compile.TupleProjectionCompiler; import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.SchemaUtil; @@ -73,9 +74,10 @@ public class TableRef { String cq = null; PColumn column = ref.getColumn(); String name = column.getName().getString(); - boolean isIndex = table.getType() == PTableType.INDEX; - if (table.getType() == PTableType.JOIN || table.getType() == PTableType.SUBQUERY) { - cq = column.getName().getString(); + boolean isIndex = IndexUtil.isIndexColumn(name); + if ((table.getType() == PTableType.PROJECTED && TupleProjectionCompiler.PROJECTED_TABLE_SCHEMA.equals(table.getSchemaName())) + || table.getType() == PTableType.SUBQUERY) { + cq = name; } else if (SchemaUtil.isPKColumn(column)) { cq = isIndex ? IndexUtil.getDataColumnName(name) : name; http://git-wip-us.apache.org/repos/asf/phoenix/blob/3f829751/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java index 01f28ae..3a012fb 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/WhereCompilerTest.java @@ -619,7 +619,7 @@ public class WhereCompilerTest extends BaseConnectionlessQueryTest { pointRange(tenantId1), pointRange(tenantId2), pointRange(tenantId3))), - plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()), + plan.getTableRef().getTable().getRowKeySchema()), filter); } @@ -642,7 +642,7 @@ public class WhereCompilerTest extends BaseConnectionlessQueryTest { pointRange(tenantId1), pointRange(tenantId2), pointRange(tenantId3))), - plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()), + plan.getTableRef().getTable().getRowKeySchema()), filter); byte[] startRow = PVarchar.INSTANCE.toBytes(tenantId1); @@ -705,7 +705,7 @@ public class WhereCompilerTest extends BaseConnectionlessQueryTest { true, Bytes.toBytes(entityId2), true))), - plan.getContext().getResolver().getTables().get(0).getTable().getRowKeySchema()), + plan.getTableRef().getTable().getRowKeySchema()), filter); }