http://git-wip-us.apache.org/repos/asf/phoenix/blob/9cd7e86b/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 ecc66dd..445edd8 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 @@ -102,20 +102,20 @@ import com.google.common.collect.Sets; public class JoinCompiler { - + public enum ColumnRefType { PREFILTER, JOINLOCAL, GENERAL, } - + private final PhoenixStatement statement; private final SelectStatement select; private final ColumnResolver origResolver; private final boolean useStarJoin; private final Map<ColumnRef, ColumnRefType> columnRefs; - - + + private JoinCompiler(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver) { this.statement = statement; this.select = select; @@ -123,20 +123,20 @@ public class JoinCompiler { this.useStarJoin = !select.getHint().hasHint(Hint.NO_STAR_JOIN); this.columnRefs = new HashMap<ColumnRef, ColumnRefType>(); } - + public static JoinTable compile(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver) throws SQLException { - JoinCompiler compiler = new JoinCompiler(statement, select, resolver); + JoinCompiler compiler = new JoinCompiler(statement, select, resolver); JoinTableConstructor constructor = compiler.new JoinTableConstructor(); Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor); JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond()); if (select.getWhere() != null) { joinTable.addFilter(select.getWhere()); } - + ColumnRefParseNodeVisitor generalRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); ColumnRefParseNodeVisitor joinLocalRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); - + joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor); for (AliasedNode node : select.getSelect()) { @@ -155,7 +155,7 @@ public class JoinCompiler { node.getNode().accept(generalRefVisitor); } } - + for (ColumnRef ref : generalRefVisitor.getColumnRefMap().keySet()) { compiler.columnRefs.put(ref, ColumnRefType.GENERAL); } @@ -167,16 +167,16 @@ public class JoinCompiler { if (!compiler.columnRefs.containsKey(ref)) compiler.columnRefs.put(ref, ColumnRefType.PREFILTER); } - + return joinTable; } private class JoinTableConstructor implements TableNodeVisitor<Pair<Table, List<JoinSpec>>> { - + private TableRef resolveTable(String alias, TableName name) throws SQLException { if (alias != null) return origResolver.resolveTable(null, alias); - + return origResolver.resolveTable(name.getSchemaName(), name.getTableName()); } @@ -198,7 +198,7 @@ public class JoinCompiler { joinSpecs = new ArrayList<JoinSpec>(); } joinSpecs.add(new JoinSpec(joinNode.getType(), joinNode.getOnNode(), joinTable, joinNode.isSingleValueOnly(), origResolver)); - + return new Pair<Table, List<JoinSpec>>(lhs.getFirst(), joinSpecs); } @@ -220,7 +220,7 @@ public class JoinCompiler { return new Pair<Table, List<JoinSpec>>(table, null); } } - + public class JoinTable { private final Table table; private final List<JoinSpec> joinSpecs; @@ -230,7 +230,7 @@ public class JoinCompiler { private final boolean allLeftJoin; private final boolean isPrefilterAccepted; private final List<JoinSpec> prefilterAcceptedTables; - + private JoinTable(Table table) { this.table = table; this.joinSpecs = Collections.<JoinSpec>emptyList(); @@ -241,7 +241,7 @@ public class JoinCompiler { this.isPrefilterAccepted = true; this.prefilterAcceptedTables = Collections.<JoinSpec>emptyList(); } - + private JoinTable(Table table, List<JoinSpec> joinSpecs) { this.table = table; this.joinSpecs = joinSpecs; @@ -274,57 +274,57 @@ public class JoinCompiler { } } } - + public Table getTable() { return table; } - + public List<JoinSpec> getJoinSpecs() { return joinSpecs; } - + public List<Table> getTables() { return tables; } - + public List<TableRef> getTableRefs() { return tableRefs; } - + public boolean isAllLeftJoin() { return allLeftJoin; } - + public SelectStatement getStatement() { return select; } - + public ColumnResolver getOriginalResolver() { return origResolver; } - + public Map<ColumnRef, ColumnRefType> getColumnRefs() { return columnRefs; } - + public ParseNode getPostFiltersCombined() { return combine(postFilters); } - + public void addFilter(ParseNode filter) throws SQLException { if (joinSpecs.isEmpty()) { table.addFilter(filter); return; } - + WhereNodeVisitor visitor = new WhereNodeVisitor(origResolver, table, - postFilters, Collections.<TableRef>singletonList(table.getTableRef()), + postFilters, Collections.<TableRef>singletonList(table.getTableRef()), isPrefilterAccepted, prefilterAcceptedTables, statement.getConnection()); filter.accept(visitor); } - - public void pushDownColumnRefVisitors(ColumnRefParseNodeVisitor generalRefVisitor, - ColumnRefParseNodeVisitor joinLocalRefVisitor, + + public void pushDownColumnRefVisitors(ColumnRefParseNodeVisitor generalRefVisitor, + ColumnRefParseNodeVisitor joinLocalRefVisitor, ColumnRefParseNodeVisitor prefilterRefVisitor) throws SQLException { for (ParseNode node : table.getPreFilters()) { node.accept(prefilterRefVisitor); @@ -349,7 +349,7 @@ public class JoinCompiler { joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor); } } - + public Expression compilePostFilterExpression(StatementContext context, Table table) throws SQLException { List<ParseNode> filtersCombined = Lists.<ParseNode> newArrayList(postFilters); if (table != null) { @@ -357,18 +357,18 @@ public class JoinCompiler { } return JoinCompiler.compilePostFilterExpression(context, filtersCombined); } - + /** * Returns a boolean vector indicating whether the evaluation of join expressions * can be evaluated at an early stage if the input JoinSpec can be taken as a - * star join. Otherwise returns null. + * star join. Otherwise returns null. * @return a boolean vector for a star join; or null for non star join. */ public boolean[] getStarJoinVector() { int count = joinSpecs.size(); if (!table.isFlat() || - (!useStarJoin - && count > 1 + (!useStarJoin + && count > 1 && joinSpecs.get(count - 1).getType() != JoinType.Left && joinSpecs.get(count - 1).getType() != JoinType.Semi && joinSpecs.get(count - 1).getType() != JoinType.Anti @@ -378,7 +378,7 @@ public class JoinCompiler { boolean[] vector = new boolean[count]; for (int i = 0; i < count; i++) { JoinSpec joinSpec = joinSpecs.get(i); - if (joinSpec.getType() != JoinType.Left + if (joinSpec.getType() != JoinType.Left && joinSpec.getType() != JoinType.Inner && joinSpec.getType() != JoinType.Semi && joinSpec.getType() != JoinType.Anti) @@ -392,56 +392,56 @@ public class JoinCompiler { } } } - + return vector; } - + public JoinTable getSubJoinTableWithoutPostFilters() { return joinSpecs.size() > 1 ? new JoinTable(table, joinSpecs.subList(0, joinSpecs.size() - 1)) : new JoinTable(table); } - + public SelectStatement getAsSingleSubquery(SelectStatement query, boolean asSubquery) throws SQLException { assert (isFlat(query)); - + if (asSubquery) return query; - - return NODE_FACTORY.select(select, query.getFrom(), query.getWhere()); + + return NODE_FACTORY.select(select, query.getFrom(), query.getWhere()); } - + public boolean hasPostReference() { for (Table table : tables) { if (table.isWildCardSelect()) { return true; } } - + for (Map.Entry<ColumnRef, ColumnRefType> e : columnRefs.entrySet()) { if (e.getValue() == ColumnRefType.GENERAL && tableRefs.contains(e.getKey().getTableRef())) { return true; } } - + return false; } - + public boolean hasFilters() { if (!postFilters.isEmpty()) return true; - + if (isPrefilterAccepted && table.hasFilters()) return true; - + for (JoinSpec joinSpec : prefilterAcceptedTables) { if (joinSpec.getJoinTable().hasFilters()) return true; } - + return false; } } - + public class JoinSpec { private final JoinType type; private final List<EqualParseNode> onConditions; @@ -449,8 +449,8 @@ public class JoinCompiler { private final boolean singleValueOnly; private Set<TableRef> dependencies; private OnNodeVisitor onNodeVisitor; - - private JoinSpec(JoinType type, ParseNode onNode, JoinTable joinTable, + + private JoinSpec(JoinType type, ParseNode onNode, JoinTable joinTable, boolean singleValueOnly, ColumnResolver resolver) throws SQLException { this.type = type; this.onConditions = new ArrayList<EqualParseNode>(); @@ -462,38 +462,38 @@ public class JoinCompiler { onNode.accept(this.onNodeVisitor); } } - + public void addOnCondition(ParseNode node) throws SQLException { node.accept(onNodeVisitor); } - + public JoinType getType() { return type; } - + public List<EqualParseNode> getOnConditions() { return onConditions; } - + public JoinTable getJoinTable() { return joinTable; } - + public boolean isSingleValueOnly() { return singleValueOnly; } - + public Set<TableRef> getDependencies() { return dependencies; } - + public Pair<List<Expression>, List<Expression>> compileJoinConditions(StatementContext lhsCtx, StatementContext rhsCtx, boolean sortExpressions) throws SQLException { if (onConditions.isEmpty()) { return new Pair<List<Expression>, List<Expression>>( - Collections.<Expression> singletonList(LiteralExpression.newConstant(1)), + Collections.<Expression> singletonList(LiteralExpression.newConstant(1)), Collections.<Expression> singletonList(LiteralExpression.newConstant(1))); } - + List<Pair<Expression, Expression>> compiled = Lists.<Pair<Expression, Expression>> newArrayListWithExpectedSize(onConditions.size()); ExpressionCompiler lhsCompiler = new ExpressionCompiler(lhsCtx); ExpressionCompiler rhsCompiler = new ExpressionCompiler(rhsCtx); @@ -546,11 +546,11 @@ public class JoinCompiler { return new Pair<List<Expression>, List<Expression>>(lConditions, rConditions); } - + private PDataType getCommonType(PDataType lType, PDataType rType) throws SQLException { if (lType == rType) return lType; - + if (!lType.isComparableTo(rType)) throw new SQLExceptionInfo.Builder(SQLExceptionCode.TYPE_MISMATCH) .setMessage("On-clause LHS expression and RHS expression must be comparable. LHS type: " + lType + ", RHS type: " + rType) @@ -609,7 +609,7 @@ public class JoinCompiler { return PVarbinary.INSTANCE; } } - + public class Table { private final TableNode tableNode; private final List<ColumnDef> dynamicColumns; @@ -619,8 +619,8 @@ public class JoinCompiler { private final List<ParseNode> preFilters; private final List<ParseNode> postFilters; private final boolean isPostFilterConvertible; - - private Table(TableNode tableNode, List<ColumnDef> dynamicColumns, + + private Table(TableNode tableNode, List<ColumnDef> dynamicColumns, List<AliasedNode> selectNodes, TableRef tableRef) { this.tableNode = tableNode; this.dynamicColumns = dynamicColumns; @@ -631,8 +631,8 @@ public class JoinCompiler { this.postFilters = Collections.<ParseNode>emptyList(); this.isPostFilterConvertible = false; } - - private Table(DerivedTableNode tableNode, + + private Table(DerivedTableNode tableNode, List<AliasedNode> selectNodes, TableRef tableRef) throws SQLException { this.tableNode = tableNode; this.dynamicColumns = Collections.<ColumnDef>emptyList(); @@ -643,35 +643,35 @@ public class JoinCompiler { this.postFilters = new ArrayList<ParseNode>(); this.isPostFilterConvertible = SubselectRewriter.isPostFilterConvertible(subselect); } - + public TableNode getTableNode() { return tableNode; } - + public List<ColumnDef> getDynamicColumns() { return dynamicColumns; } - + public boolean isSubselect() { return subselect != null; } - + public List<AliasedNode> getSelectNodes() { return selectNodes; } - + public List<ParseNode> getPreFilters() { return preFilters; } - + public List<ParseNode> getPostFilters() { return postFilters; } - + public TableRef getTableRef() { return tableRef; } - + public void addFilter(ParseNode filter) { if (!isSubselect() || isPostFilterConvertible) { preFilters.add(filter); @@ -679,30 +679,30 @@ public class JoinCompiler { postFilters.add(filter); } } - + public ParseNode getPreFiltersCombined() { return combine(preFilters); } - + public Expression compilePostFilterExpression(StatementContext context) throws SQLException { return JoinCompiler.compilePostFilterExpression(context, postFilters); } - + public SelectStatement getAsSubquery(List<OrderByNode> orderBy) throws SQLException { if (isSubselect()) return SubselectRewriter.applyOrderBy(SubselectRewriter.applyPostFilters(subselect, preFilters, tableNode.getAlias()), orderBy, tableNode.getAlias()); - + return NODE_FACTORY.select(tableNode, select.getHint(), false, selectNodes, getPreFiltersCombined(), null, null, orderBy, null, 0, false, select.hasSequence()); } - + public boolean hasFilters() { return isSubselect() ? (!postFilters.isEmpty() || subselect.getWhere() != null || subselect.getHaving() != null) : !preFilters.isEmpty(); } - + public boolean isFlat() { return subselect == null || JoinCompiler.isFlat(subselect); } - + protected boolean isWildCardSelect() { return (selectNodes.size() == 1 && selectNodes.get(0).getNode() instanceof TableWildcardParseNode); } @@ -721,7 +721,7 @@ public class JoinCompiler { } } } - + public ProjectedPTableWrapper createProjectedTable(boolean retainPKColumns, StatementContext context) throws SQLException { assert(!isSubselect()); List<PColumn> projectedColumns = new ArrayList<PColumn>(); @@ -745,31 +745,33 @@ public class JoinCompiler { } else { for (Map.Entry<ColumnRef, ColumnRefType> e : columnRefs.entrySet()) { ColumnRef columnRef = e.getKey(); - if (e.getValue() != ColumnRefType.PREFILTER + if (e.getValue() != ColumnRefType.PREFILTER && columnRef.getTableRef().equals(tableRef) && (!retainPKColumns || !SchemaUtil.isPKColumn(columnRef.getColumn()))) { PColumn column = columnRef.getColumn(); addProjectedColumn(projectedColumns, sourceExpressions, columnNameMap, - column, PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn, + column, PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), hasSaltingColumn, columnRef instanceof LocalIndexColumnRef, context); } - } + } } - + PTable t = PTableImpl.makePTable(table.getTenantId(), PNameFactory.newName(PROJECTED_TABLE_SCHEMA), table.getName(), PTableType.JOIN, table.getIndexState(), table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), retainPKColumns ? table.getBucketNum() : null, projectedColumns, table.getParentSchemaName(), - table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, table.isWALDisabled(), table.isMultiTenant(), table.getViewType(), table.getViewIndexId(), table.getIndexType()); + table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), table.getViewIndexId(), + table.getIndexType()); return new ProjectedPTableWrapper(t, columnNameMap, sourceExpressions); } - + private void addProjectedColumn(List<PColumn> projectedColumns, List<Expression> sourceExpressions, - ListMultimap<String, String> columnNameMap, PColumn sourceColumn, PName familyName, boolean hasSaltingColumn, - boolean isLocalIndexColumnRef, StatementContext context) + ListMultimap<String, String> columnNameMap, PColumn sourceColumn, PName familyName, boolean hasSaltingColumn, + boolean isLocalIndexColumnRef, StatementContext context) throws SQLException { if (sourceColumn == SALTING_COLUMN) return; - + int position = projectedColumns.size() + (hasSaltingColumn ? 1 : 0); PTable table = tableRef.getTable(); String schemaName = table.getSchemaName().getString(); @@ -777,23 +779,23 @@ public class JoinCompiler { String colName = isLocalIndexColumnRef ? IndexUtil.getIndexColumnName(sourceColumn) : sourceColumn.getName().getString(); String fullName = getProjectedColumnName(schemaName, tableName, colName); String aliasedName = tableRef.getTableAlias() == null ? fullName : getProjectedColumnName(null, tableRef.getTableAlias(), colName); - + columnNameMap.put(colName, aliasedName); if (!fullName.equals(aliasedName)) { columnNameMap.put(fullName, aliasedName); } - + PName name = PNameFactory.newName(aliasedName); - PColumnImpl column = new PColumnImpl(name, familyName, sourceColumn.getDataType(), - sourceColumn.getMaxLength(), sourceColumn.getScale(), sourceColumn.isNullable(), + PColumnImpl column = new PColumnImpl(name, familyName, sourceColumn.getDataType(), + sourceColumn.getMaxLength(), sourceColumn.getScale(), sourceColumn.isNullable(), position, sourceColumn.getSortOrder(), sourceColumn.getArraySize(), sourceColumn.getViewConstant(), sourceColumn.isViewReferenced()); - Expression sourceExpression = isLocalIndexColumnRef ? - NODE_FACTORY.column(TableName.create(schemaName, tableName), "\"" + colName + "\"", null).accept(new ExpressionCompiler(context)) + Expression sourceExpression = isLocalIndexColumnRef ? + NODE_FACTORY.column(TableName.create(schemaName, tableName), "\"" + colName + "\"", null).accept(new ExpressionCompiler(context)) : new ColumnRef(tableRef, sourceColumn.getPosition()).newColumnExpression(); projectedColumns.add(column); sourceExpressions.add(sourceExpression); } - + public ProjectedPTableWrapper createProjectedTable(RowProjector rowProjector) throws SQLException { assert(isSubselect()); List<PColumn> projectedColumns = new ArrayList<PColumn>(); @@ -803,20 +805,22 @@ public class JoinCompiler { for (PColumn column : table.getColumns()) { String colName = getProjectedColumnName(null, tableRef.getTableAlias(), column.getName().getString()); Expression sourceExpression = rowProjector.getColumnProjector(column.getPosition()).getExpression(); - PColumnImpl projectedColumn = new PColumnImpl(PNameFactory.newName(colName), PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), - sourceExpression.getDataType(), sourceExpression.getMaxLength(), sourceExpression.getScale(), sourceExpression.isNullable(), - column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced()); + PColumnImpl projectedColumn = new PColumnImpl(PNameFactory.newName(colName), PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), + sourceExpression.getDataType(), sourceExpression.getMaxLength(), sourceExpression.getScale(), sourceExpression.isNullable(), + column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced()); projectedColumns.add(projectedColumn); sourceExpressions.add(sourceExpression); } PTable t = PTableImpl.makePTable(table.getTenantId(), PNameFactory.newName(PROJECTED_TABLE_SCHEMA), table.getName(), PTableType.JOIN, table.getIndexState(), table.getTimeStamp(), table.getSequenceNumber(), table.getPKName(), null, projectedColumns, table.getParentSchemaName(), - table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, table.isWALDisabled(), table.isMultiTenant(), table.getViewType(), table.getViewIndexId(), table.getIndexType()); + table.getParentTableName(), table.getIndexes(), table.isImmutableRows(), Collections.<PName>emptyList(), null, null, + table.isWALDisabled(), table.isMultiTenant(), table.getStoreNulls(), table.getViewType(), + table.getViewIndexId(), table.getIndexType()); return new ProjectedPTableWrapper(t, columnNameMap, sourceExpressions); } } - + private static class WhereNodeVisitor extends BooleanParseNodeVisitor<Void> { private Table table; private List<ParseNode> postFilters; @@ -824,9 +828,9 @@ public class JoinCompiler { private boolean isPrefilterAccepted; private List<JoinSpec> prefilterAcceptedTables; ColumnRefParseNodeVisitor columnRefVisitor; - + public WhereNodeVisitor(ColumnResolver resolver, Table table, - List<ParseNode> postFilters, List<TableRef> selfTableRefs, boolean isPrefilterAccepted, + List<ParseNode> postFilters, List<TableRef> selfTableRefs, boolean isPrefilterAccepted, List<JoinSpec> prefilterAcceptedTables, PhoenixConnection connection) { this.table = table; this.postFilters = postFilters; @@ -835,12 +839,12 @@ public class JoinCompiler { this.prefilterAcceptedTables = prefilterAcceptedTables; this.columnRefVisitor = new ColumnRefParseNodeVisitor(resolver, connection); } - + @Override protected boolean enterBooleanNode(ParseNode node) throws SQLException { return false; } - + @Override protected Void leaveBooleanNode(ParseNode node, List<Void> l) throws SQLException { @@ -876,17 +880,17 @@ public class JoinCompiler { } return null; } - + @Override protected boolean enterNonBooleanNode(ParseNode node) throws SQLException { return false; } - + @Override protected Void leaveNonBooleanNode(ParseNode node, List<Void> l) throws SQLException { return null; } - + @Override public boolean visitEnter(AndParseNode node) throws SQLException { return true; @@ -896,38 +900,38 @@ public class JoinCompiler { public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException { return null; } - + @Override - public Void visitLeave(ComparisonParseNode node, List<Void> l) + public Void visitLeave(ComparisonParseNode node, List<Void> l) throws SQLException { if (!(node instanceof EqualParseNode)) return leaveBooleanNode(node, l); - + ListIterator<JoinSpec> iter = prefilterAcceptedTables.listIterator(prefilterAcceptedTables.size()); while (iter.hasPrevious()) { JoinSpec joinSpec = iter.previous(); if (joinSpec.getType() != JoinType.Inner || joinSpec.isSingleValueOnly()) { continue; } - + try { joinSpec.addOnCondition(node); return null; } catch (SQLException e) { } } - + return leaveBooleanNode(node, l); } } - + private static class OnNodeVisitor extends BooleanParseNodeVisitor<Void> { private List<EqualParseNode> onConditions; private Set<TableRef> dependencies; private JoinTable joinTable; private ColumnRefParseNodeVisitor columnRefVisitor; - - public OnNodeVisitor(ColumnResolver resolver, List<EqualParseNode> onConditions, + + public OnNodeVisitor(ColumnResolver resolver, List<EqualParseNode> onConditions, Set<TableRef> dependencies, JoinTable joinTable, PhoenixConnection connection) { this.onConditions = onConditions; this.dependencies = dependencies; @@ -1005,7 +1009,7 @@ public class JoinCompiler { /* * Conditions in the ON clause can only be: - * 1) an equal test between a self table expression and a foreign + * 1) an equal test between a self table expression and a foreign * table expression. * 2) a boolean condition referencing to the self table only. * Otherwise, it can be ambiguous. @@ -1014,16 +1018,16 @@ public class JoinCompiler { throw new SQLExceptionInfo.Builder(SQLExceptionCode.AMBIGUOUS_JOIN_CONDITION).build().buildException(); } } - + private static class LocalIndexColumnRef extends ColumnRef { private final TableRef indexTableRef; - + public LocalIndexColumnRef(TableRef tableRef, String familyName, String columnName, TableRef indexTableRef) throws MetaDataEntityNotFoundException { super(tableRef, familyName, columnName); this.indexTableRef = indexTableRef; } - + @Override public TableRef getTableRef() { return indexTableRef; @@ -1056,7 +1060,7 @@ public class JoinCompiler { try { columnRef = resolver.resolveColumn(node.getSchemaName(), node.getTableName(), node.getName()); } catch (ColumnNotFoundException e) { - // This could be a LocalIndexDataColumnRef. If so, the table name must have + // This could be a LocalIndexDataColumnRef. If so, the table name must have // been appended by the IndexStatementRewriter, and we can convert it into. TableRef tableRef = resolver.resolveTable(node.getSchemaName(), node.getTableName()); if (tableRef.getTable().getIndexType() == IndexType.LOCAL) { @@ -1066,8 +1070,8 @@ public class JoinCompiler { .getParentTableName().getString())), connection).resolveTable( tableRef.getTable().getSchemaName().getString(), tableRef.getTable().getParentTableName().getString()); - columnRef = new LocalIndexColumnRef(parentTableRef, - IndexUtil.getDataColumnFamilyName(node.getName()), + columnRef = new LocalIndexColumnRef(parentTableRef, + IndexUtil.getDataColumnFamilyName(node.getName()), IndexUtil.getDataColumnName(node.getName()), tableRef); } else { throw e; @@ -1075,7 +1079,7 @@ public class JoinCompiler { } columnRefMap.put(columnRef, node); tableRefSet.add(columnRef.getTableRef()); - return null; + return null; } public Set<TableRef> getTableRefSet() { @@ -1104,7 +1108,7 @@ public class JoinCompiler { ret = isSelf ? ColumnRefType.COMPLEX : ColumnRefType.FOREIGN_ONLY; break; default: // COMPLEX do nothing - break; + break; } if (ret == ColumnRefType.COMPLEX) { @@ -1115,29 +1119,29 @@ public class JoinCompiler { return ret; } } - + private static final String PROJECTED_TABLE_SCHEMA = "."; // for creation of new statements private static final ParseNodeFactory NODE_FACTORY = new ParseNodeFactory(); - + private static boolean isFlat(SelectStatement select) { - return !select.isJoin() - && !select.isAggregate() - && !select.isDistinct() + return !select.isJoin() + && !select.isAggregate() + && !select.isDistinct() && !(select.getFrom() instanceof DerivedTableNode) && select.getLimit() == null; } - + private static ParseNode combine(List<ParseNode> nodes) { if (nodes.isEmpty()) return null; - + if (nodes.size() == 1) return nodes.get(0); - + return NODE_FACTORY.and(nodes); } - + private List<AliasedNode> extractFromSelect(List<AliasedNode> select, TableRef tableRef, ColumnResolver resolver) throws SQLException { List<AliasedNode> ret = new ArrayList<AliasedNode>(); ColumnRefParseNodeVisitor visitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); @@ -1152,7 +1156,7 @@ public class JoinCompiler { } continue; } - + node.accept(visitor); ColumnRefParseNodeVisitor.ColumnRefType type = visitor.getContentType(Collections.singletonList(tableRef)); if (type == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { @@ -1168,11 +1172,11 @@ public class JoinCompiler { } return ret; } - + private static Expression compilePostFilterExpression(StatementContext context, List<ParseNode> postFilters) throws SQLException { if (postFilters.isEmpty()) return null; - + ExpressionCompiler expressionCompiler = new ExpressionCompiler(context); List<Expression> expressions = new ArrayList<Expression>(postFilters.size()); for (ParseNode postFilter : postFilters) { @@ -1180,13 +1184,13 @@ public class JoinCompiler { Expression expression = postFilter.accept(expressionCompiler); expressions.add(expression); } - + if (expressions.size() == 1) return expressions.get(0); - + return AndExpression.create(expressions); } - + public static SelectStatement optimize(PhoenixStatement statement, SelectStatement select, final ColumnResolver resolver) throws SQLException { TableRef groupByTableRef = null; TableRef orderByTableRef = null; @@ -1221,11 +1225,11 @@ public class JoinCompiler { } if (orderByTableRef != null && !orderByTableRef.equals(table)) { orderByTableRef = null; - } + } } - + final Map<TableRef, TableRef> replacement = new HashMap<TableRef, TableRef>(); - + for (Table table : join.getTables()) { if (table.isSubselect()) continue; @@ -1236,12 +1240,12 @@ public class JoinCompiler { QueryPlan plan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, stmt); if (!plan.getTableRef().equals(tableRef)) { replacement.put(tableRef, plan.getTableRef()); - } + } } - - if (replacement.isEmpty()) + + if (replacement.isEmpty()) return select; - + TableNode from = select.getFrom(); TableNode newFrom = from.accept(new TableNodeVisitor<TableNode>() { private TableRef resolveTable(String alias, TableName name) throws SQLException { @@ -1297,10 +1301,10 @@ public class JoinCompiler { return subselectNode; } }); - - return IndexStatementRewriter.translate(NODE_FACTORY.select(select, newFrom), resolver, replacement); + + return IndexStatementRewriter.translate(NODE_FACTORY.select(select, newFrom), resolver, replacement); } - + private static SelectStatement getSubqueryForOptimizedPlan(HintNode hintNode, List<ColumnDef> dynamicCols, TableRef tableRef, Map<ColumnRef, ColumnRefType> columnRefs, ParseNode where, List<ParseNode> groupBy, List<OrderByNode> orderBy, boolean isWildCardSelect, boolean hasSequence) { String schemaName = tableRef.getTable().getSchemaName().getString(); @@ -1324,20 +1328,20 @@ public class JoinCompiler { return NODE_FACTORY.select(from, hintNode, false, selectList, where, groupBy, null, orderBy, null, 0, groupBy != null, hasSequence); } - + public class PTableWrapper { protected PTable table; protected ListMultimap<String, String> columnNameMap; - + protected PTableWrapper(PTable table, ListMultimap<String, String> columnNameMap) { this.table = table; this.columnNameMap = columnNameMap; } - + public PTable getTable() { return table; } - + public ListMultimap<String, String> getColumnNameMap() { return columnNameMap; } @@ -1345,11 +1349,11 @@ public class JoinCompiler { public List<String> getMappedColumnName(String name) { return columnNameMap.get(name); } - + public ColumnResolver createColumnResolver() { return new JoinedTableColumnResolver(this, origResolver); } - + public PTableWrapper mergeProjectedTables(PTableWrapper rWrapper, JoinType type) throws SQLException { PTable left = this.getTable(); PTable right = rWrapper.getTable(); @@ -1361,8 +1365,8 @@ public class JoinCompiler { if (SchemaUtil.isPKColumn(c)) { merged.add(c); } else { - PColumnImpl column = new PColumnImpl(c.getName(), c.getFamilyName(), c.getDataType(), - c.getMaxLength(), c.getScale(), true, c.getPosition(), + PColumnImpl column = new PColumnImpl(c.getName(), c.getFamilyName(), c.getDataType(), + c.getMaxLength(), c.getScale(), true, c.getPosition(), c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced()); merged.add(column); } @@ -1371,9 +1375,9 @@ public class JoinCompiler { int position = merged.size(); for (PColumn c : right.getColumns()) { if (!SchemaUtil.isPKColumn(c)) { - PColumnImpl column = new PColumnImpl(c.getName(), - PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), c.getDataType(), - c.getMaxLength(), c.getScale(), type == JoinType.Inner ? c.isNullable() : true, position++, + PColumnImpl column = new PColumnImpl(c.getName(), + PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), c.getDataType(), + c.getMaxLength(), c.getScale(), type == JoinType.Inner ? c.isNullable() : true, position++, c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced()); merged.add(column); } @@ -1383,48 +1387,48 @@ public class JoinCompiler { } PTable t = PTableImpl.makePTable(left.getTenantId(), left.getSchemaName(), PNameFactory.newName(SchemaUtil.getTableName(left.getName().getString(), right.getName().getString())), left.getType(), left.getIndexState(), left.getTimeStamp(), left.getSequenceNumber(), left.getPKName(), left.getBucketNum(), merged, - left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(), left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL, left.isMultiTenant(), left.getViewType(), left.getViewIndexId(), left.getIndexType()); + left.getParentSchemaName(), left.getParentTableName(), left.getIndexes(), left.isImmutableRows(), Collections.<PName>emptyList(), null, null, PTable.DEFAULT_DISABLE_WAL, left.isMultiTenant(), left.getStoreNulls(), left.getViewType(), left.getViewIndexId(), left.getIndexType()); ListMultimap<String, String> mergedMap = ArrayListMultimap.<String, String>create(); mergedMap.putAll(this.getColumnNameMap()); mergedMap.putAll(rWrapper.getColumnNameMap()); - + return new PTableWrapper(t, mergedMap); } } - + public class ProjectedPTableWrapper extends PTableWrapper { private List<Expression> sourceExpressions; - + protected ProjectedPTableWrapper(PTable table, ListMultimap<String, String> columnNameMap, List<Expression> sourceExpressions) { super(table, columnNameMap); this.sourceExpressions = sourceExpressions; } - + public Expression getSourceExpression(PColumn column) { return sourceExpressions.get(column.getPosition() - (table.getBucketNum() == null ? 0 : 1)); } - + public TupleProjector createTupleProjector() { return new TupleProjector(this); } } - + public static class JoinedTableColumnResolver implements ColumnResolver { private PTableWrapper table; private ColumnResolver tableResolver; private TableRef tableRef; - + private JoinedTableColumnResolver(PTableWrapper table, ColumnResolver tableResolver) { this.table = table; this.tableResolver = tableResolver; this.tableRef = new TableRef(ParseNodeFactory.createTempAlias(), table.getTable(), 0, false); } - + public PTableWrapper getPTableWrapper() { return table; } - + public TableRef getTableRef() { return tableRef; } @@ -1451,18 +1455,18 @@ public class JoinCompiler { List<String> names = table.getMappedColumnName(name); if (names.size() == 1) { PColumn column = tableRef.getTable().getColumn(names.get(0)); - return new ColumnRef(tableRef, column.getPosition()); + return new ColumnRef(tableRef, column.getPosition()); } - + if (names.size() > 1) { throw new AmbiguousColumnException(name); } - + throw e; } } } - + private static String getProjectedColumnName(String schemaName, String tableName, String colName) { return SchemaUtil.getColumnName(SchemaUtil.getTableName(schemaName, tableName), colName);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/9cd7e86b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java index f2bc355..8145e67 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataEndpointImpl.java @@ -40,6 +40,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PK_NAME_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SALT_BUCKETS_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SCHEMA_NAME_INDEX; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SORT_ORDER_BYTES; +import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.STORE_NULLS_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_FAMILY_BYTES; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_NAME_INDEX; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.TABLE_SEQ_NUM_BYTES; @@ -155,7 +156,7 @@ import com.google.protobuf.RpcController; import com.google.protobuf.Service; /** - * + * * Endpoint co-processor through which all Phoenix metadata mutations flow. * We only allow mutations to the latest version of a Phoenix table (i.e. the * timeStamp must be increasing). @@ -166,7 +167,7 @@ import com.google.protobuf.Service; * any in use on the data table, b/c otherwise we can end up with data rows that * are not valid against a schema row. * - * + * * @since 0.1 */ @SuppressWarnings("deprecation") @@ -190,9 +191,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso private static final KeyValue VIEW_INDEX_ID_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, VIEW_INDEX_ID_BYTES); private static final KeyValue INDEX_TYPE_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, INDEX_TYPE_BYTES); private static final KeyValue INDEX_DISABLE_TIMESTAMP_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, INDEX_DISABLE_TIMESTAMP_BYTES); + private static final KeyValue STORE_NULLS_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, STORE_NULLS_BYTES); private static final KeyValue EMPTY_KEYVALUE_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES); private static final List<KeyValue> TABLE_KV_COLUMNS = Arrays.<KeyValue>asList( - EMPTY_KEYVALUE_KV, + EMPTY_KEYVALUE_KV, TABLE_TYPE_KV, TABLE_SEQ_NUM_KV, COLUMN_COUNT_KV, @@ -208,7 +210,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso VIEW_TYPE_KV, VIEW_INDEX_ID_KV, INDEX_TYPE_KV, - INDEX_DISABLE_TIMESTAMP_KV + INDEX_DISABLE_TIMESTAMP_KV, + STORE_NULLS_KV ); static { Collections.sort(TABLE_KV_COLUMNS, KeyValue.COMPARATOR); @@ -228,7 +231,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso private static final int VIEW_TYPE_INDEX = TABLE_KV_COLUMNS.indexOf(VIEW_TYPE_KV); private static final int VIEW_INDEX_ID_INDEX = TABLE_KV_COLUMNS.indexOf(VIEW_INDEX_ID_KV); private static final int INDEX_TYPE_INDEX = TABLE_KV_COLUMNS.indexOf(INDEX_TYPE_KV); - + private static final int STORE_NULLS_INDEX = TABLE_KV_COLUMNS.indexOf(STORE_NULLS_KV); + // KeyValues for Column private static final KeyValue DECIMAL_DIGITS_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, DECIMAL_DIGITS_BYTES); private static final KeyValue COLUMN_SIZE_KV = KeyValue.createFirstOnRow(ByteUtil.EMPTY_BYTE_ARRAY, TABLE_FAMILY_BYTES, COLUMN_SIZE_BYTES); @@ -263,7 +267,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso private static final int ARRAY_SIZE_INDEX = COLUMN_KV_COLUMNS.indexOf(ARRAY_SIZE_KV); private static final int VIEW_CONSTANT_INDEX = COLUMN_KV_COLUMNS.indexOf(VIEW_CONSTANT_KV); private static final int IS_VIEW_REFERENCED_INDEX = COLUMN_KV_COLUMNS.indexOf(IS_VIEW_REFERENCED_KV); - + private static final int LINK_TYPE_INDEX = 0; private static PName newPName(byte[] keyBuffer, int keyOffset, int keyLength) { @@ -339,7 +343,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } builder.setReturnCode(MetaDataProtos.MutationCode.TABLE_ALREADY_EXISTS); builder.setMutationTime(currentTime); - + if (table.getTimeStamp() != tableTimeStamp) { builder.setTable(PTableImpl.toProto(table)); } @@ -447,11 +451,11 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso sortOrderKv == null ? SortOrder.getDefault() : SortOrder.fromSystemValue(PInteger.INSTANCE .getCodec().decodeInt(sortOrderKv.getValueArray(), sortOrderKv.getValueOffset(), SortOrder.getDefault())); - + Cell arraySizeKv = colKeyValues[ARRAY_SIZE_INDEX]; Integer arraySize = arraySizeKv == null ? null : PInteger.INSTANCE.getCodec().decodeInt(arraySizeKv.getValueArray(), arraySizeKv.getValueOffset(), SortOrder.getDefault()); - + Cell viewConstantKv = colKeyValues[VIEW_CONSTANT_INDEX]; byte[] viewConstant = viewConstantKv == null ? null : viewConstantKv.getValue(); Cell isViewReferencedKv = colKeyValues[IS_VIEW_REFERENCED_INDEX]; @@ -459,7 +463,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso PColumn column = new PColumnImpl(colName, famName, dataType, maxLength, scale, isNullable, position-1, sortOrder, arraySize, viewConstant, isViewReferenced); columns.add(column); } - + private PTable getTable(RegionScanner scanner, long clientTimeStamp, long tableTimeStamp) throws IOException, SQLException { List<Cell> results = Lists.newArrayList(); @@ -469,7 +473,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } Cell[] tableKeyValues = new Cell[TABLE_KV_COLUMNS.size()]; Cell[] colKeyValues = new Cell[COLUMN_KV_COLUMNS.size()]; - + // Create PTable based on KeyValues from scan Cell keyValue = results.get(0); byte[] keyBuffer = keyValue.getRowArray(); @@ -487,7 +491,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso System.arraycopy(keyBuffer, keyOffset + schemaNameLength + 1 + tenantIdLength + 1, tableNameBytes, 0, tableNameLength); PName tableName = PNameFactory.newName(tableNameBytes); - + int offset = tenantIdLength + schemaNameLength + tableNameLength + 3; // This will prevent the client from continually looking for the current // table when we know that there will never be one since we disallow updates @@ -501,7 +505,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso // clientTimeStamp < tableTimeStamp // ? clientTimeStamp-1 // : keyValue.getTimestamp(); - + int i = 0; int j = 0; while (i < results.size() && j < TABLE_KV_COLUMNS.size()) { @@ -517,7 +521,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso tableKeyValues[j++] = kv; i++; } else if (cmp > 0) { - timeStamp = Math.max(timeStamp, kv.getTimestamp()); + timeStamp = Math.max(timeStamp, kv.getTimestamp()); tableKeyValues[j++] = null; } else { i++; // shouldn't happen - means unexpected KV in system table header row @@ -576,13 +580,16 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso PBoolean.INSTANCE.toObject(disableWALKv.getValueArray(), disableWALKv.getValueOffset(), disableWALKv.getValueLength())); Cell multiTenantKv = tableKeyValues[MULTI_TENANT_INDEX]; boolean multiTenant = multiTenantKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(multiTenantKv.getValueArray(), multiTenantKv.getValueOffset(), multiTenantKv.getValueLength())); + Cell storeNullsKv = tableKeyValues[STORE_NULLS_INDEX]; + boolean storeNulls = storeNullsKv == null ? false : Boolean.TRUE.equals(PBoolean.INSTANCE.toObject(storeNullsKv.getValueArray(), storeNullsKv.getValueOffset(), storeNullsKv.getValueLength())); Cell viewTypeKv = tableKeyValues[VIEW_TYPE_INDEX]; ViewType viewType = viewTypeKv == null ? null : ViewType.fromSerializedValue(viewTypeKv.getValueArray()[viewTypeKv.getValueOffset()]); Cell viewIndexIdKv = tableKeyValues[VIEW_INDEX_ID_INDEX]; Short viewIndexId = viewIndexIdKv == null ? null : (Short)MetaDataUtil.getViewIndexIdDataType().getCodec().decodeShort(viewIndexIdKv.getValueArray(), viewIndexIdKv.getValueOffset(), SortOrder.getDefault()); Cell indexTypeKv = tableKeyValues[INDEX_TYPE_INDEX]; IndexType indexType = indexTypeKv == null ? null : IndexType.fromSerializedValue(indexTypeKv.getValueArray()[indexTypeKv.getValueOffset()]); - + + List<PColumn> columns = Lists.newArrayListWithExpectedSize(columnCount); List<PTable> indexes = new ArrayList<PTable>(); List<PName> physicalTables = new ArrayList<PName>(); @@ -616,17 +623,17 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso try { statsHTable = ServerUtil.getHTableForCoprocessorScan(env, PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES); stats = StatisticsUtil.readStatistics(statsHTable, physicalTableName.getBytes(), clientTimeStamp); - timeStamp = Math.max(timeStamp, stats.getTimestamp()); + timeStamp = Math.max(timeStamp, stats.getTimestamp()); } catch (org.apache.hadoop.hbase.TableNotFoundException e) { logger.warn(PhoenixDatabaseMetaData.SYSTEM_STATS_NAME + " not online yet?"); } finally { if (statsHTable != null) statsHTable.close(); } } - return PTableImpl.makePTable(tenantId, schemaName, tableName, tableType, indexState, timeStamp, - tableSeqNum, pkName, saltBucketNum, columns, tableType == INDEX ? schemaName : null, - tableType == INDEX ? dataTableName : null, indexes, isImmutableRows, physicalTables, defaultFamilyName, viewStatement, - disableWAL, multiTenant, viewType, viewIndexId, indexType, stats); + return PTableImpl.makePTable(tenantId, schemaName, tableName, tableType, indexState, timeStamp, + tableSeqNum, pkName, saltBucketNum, columns, tableType == INDEX ? schemaName : null, + tableType == INDEX ? dataTableName : null, indexes, isImmutableRows, physicalTables, defaultFamilyName, viewStatement, + disableWAL, multiTenant, storeNulls, viewType, viewIndexId, indexType, stats); } private PTable buildDeletedTable(byte[] key, ImmutableBytesPtr cacheKey, HRegion region, @@ -634,7 +641,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (clientTimeStamp == HConstants.LATEST_TIMESTAMP) { return null; } - + Scan scan = MetaDataUtil.newTableRowsScan(key, clientTimeStamp, HConstants.LATEST_TIMESTAMP); scan.setFilter(new FirstKeyOnlyFilter()); scan.setRaw(true); @@ -681,8 +688,8 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } return null; } - - + + @Override public void createTable(RpcController controller, CreateTableRequest request, RpcCallback<MetaDataResponse> done) { @@ -813,7 +820,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso } locks.add(rowLock); } - + protected static final byte[] PHYSICAL_TABLE_BYTES = new byte[] {PTable.LinkType.PHYSICAL_TABLE.getSerializedValue()}; /** * @param tableName parent table's name @@ -877,7 +884,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso hTable.close(); } } - + @Override public void dropTable(RpcController controller, DropTableRequest request, RpcCallback<MetaDataResponse> done) { @@ -916,7 +923,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return; } List<RowLock> locks = Lists.newArrayList(); - + try { acquireLock(region, lockKey, locks); if (key != lockKey) { @@ -958,16 +965,16 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso byte[] tableName, byte[] parentTableName, PTableType tableType, List<Mutation> rowsToDelete, List<ImmutableBytesPtr> invalidateList, List<RowLock> locks, List<byte[]> tableNamesToDelete, boolean isCascade) throws IOException, SQLException { - - + + long clientTimeStamp = MetaDataUtil.getClientTimeStamp(rowsToDelete); - + HRegion region = env.getRegion(); ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(key); - + Cache<ImmutableBytesPtr,PTable> metaDataCache = GlobalCache.getInstance(this.env).getMetaDataCache(); PTable table = metaDataCache.getIfPresent(cacheKey); - + // We always cache the latest version - fault in if not in cache if (table != null || (table = buildTable(key, cacheKey, region, HConstants.LATEST_TIMESTAMP)) != null) { @@ -1008,7 +1015,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (tableViewFinderResult.hasViews()) { if (isCascade) { if (tableViewFinderResult.allViewsInMultipleRegions()) { - // We don't yet support deleting a table with views where SYSTEM.CATALOG has split and the + // We don't yet support deleting a table with views where SYSTEM.CATALOG has split and the // view metadata spans multiple regions return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); } else if (tableViewFinderResult.allViewsInSingleRegion()) { @@ -1030,13 +1037,13 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return result; } } - } + } } else { // DROP without CASCADE on tables with child views is not permitted return new MetaDataMutationResult(MutationCode.UNALLOWED_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), null); } - } - + } + if (tableType != PTableType.VIEW) { // Add to list of HTables to delete, unless it's a view tableNamesToDelete.add(table.getName().getBytes()); } @@ -1062,7 +1069,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso results.clear(); scanner.next(results); } while (!results.isEmpty()); - + // Recursively delete indexes for (byte[] indexName : indexNames) { byte[] indexKey = SchemaUtil.getTableKey(tenantId, schemaName, indexName); @@ -1080,7 +1087,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return result; } } - + return new MetaDataMutationResult(MutationCode.TABLE_ALREADY_EXISTS, EnvironmentEdgeManager.currentTimeMillis(), table, tableNamesToDelete); } @@ -1144,7 +1151,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return new MetaDataMutationResult(MutationCode.TABLE_NOT_FOUND, EnvironmentEdgeManager.currentTimeMillis(), null); } - + long expectedSeqNum = MetaDataUtil.getSequenceNumber(tableMetadata) - 1; // lookup // TABLE_SEQ_NUM // in @@ -1163,7 +1170,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return new MetaDataMutationResult(MutationCode.CONCURRENT_TABLE_MUTATION, EnvironmentEdgeManager.currentTimeMillis(), table); } - + PTableType type = table.getType(); if (type == PTableType.INDEX) { // Disallow mutation of an index table @@ -1186,7 +1193,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso if (result != null) { return result; } - + region.mutateRowsWithLocks(tableMetadata, Collections.<byte[]> emptySet()); // Invalidate from cache for (ImmutableBytesPtr invalidateKey : invalidateList) { @@ -1272,11 +1279,11 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso ProtobufUtil.setControllerException(controller, ioe); } } - + private PTable doGetTable(byte[] key, long clientTimeStamp) throws IOException, SQLException { return doGetTable(key, clientTimeStamp, null); } - + private PTable doGetTable(byte[] key, long clientTimeStamp, RowLock rowLock) throws IOException, SQLException { ImmutableBytesPtr cacheKey = new ImmutableBytesPtr(key); Cache<ImmutableBytesPtr, PTable> metaDataCache = @@ -1507,10 +1514,10 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso int disableTimeStampKVIndex = -1; int index = 0; for(Cell cell : newKVs){ - if(Bytes.compareTo(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(), + if(Bytes.compareTo(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(), INDEX_STATE_BYTES, 0, INDEX_STATE_BYTES.length) == 0){ newKV = cell; - } else if (Bytes.compareTo(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(), + } else if (Bytes.compareTo(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(), INDEX_DISABLE_TIMESTAMP_BYTES, 0, INDEX_DISABLE_TIMESTAMP_BYTES.length) == 0){ disableTimeStampKVIndex = index; } @@ -1538,14 +1545,14 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso Cell dataTableKV = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, DATA_TABLE_NAME_BYTES); Cell currentStateKV = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, INDEX_STATE_BYTES); Cell currentDisableTimeStamp = currentResult.getColumnLatestCell(TABLE_FAMILY_BYTES, INDEX_DISABLE_TIMESTAMP_BYTES); - + PIndexState currentState = PIndexState.fromSerializedValue(currentStateKV.getValueArray()[currentStateKV .getValueOffset()]); - + // check if we need reset disable time stamp - if( (newState == PIndexState.DISABLE) && - (currentState == PIndexState.DISABLE || currentState == PIndexState.INACTIVE) && + if( (newState == PIndexState.DISABLE) && + (currentState == PIndexState.DISABLE || currentState == PIndexState.INACTIVE) && (currentDisableTimeStamp != null && currentDisableTimeStamp.getValueLength() > 0) && (disableTimeStampKVIndex >= 0)) { Long curTimeStampVal = (Long) PLong.INSTANCE.toObject(currentDisableTimeStamp.getValueArray(), @@ -1559,7 +1566,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso newKVs.remove(disableTimeStampKVIndex); } } - + // Detect invalid transitions if (currentState == PIndexState.BUILDING) { if (newState == PIndexState.USABLE) { @@ -1595,7 +1602,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso newKVs.set(0, KeyValueUtil.newKeyValue(key, TABLE_FAMILY_BYTES, INDEX_STATE_BYTES, timeStamp, Bytes.toBytes(newState.getSerializedValue()))); } - + if (currentState != newState) { byte[] dataTableKey = null; if(dataTableKV != null) { @@ -1633,7 +1640,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso ServerUtil.createIOException(SchemaUtil.getTableName(schemaName, tableName), t)); } } - + private static MetaDataMutationResult checkTableKeyInRegion(byte[] key, HRegion region) { byte[] startKey = region.getStartKey(); byte[] endKey = region.getEndKey(); @@ -1645,7 +1652,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return new MetaDataMutationResult(MutationCode.TABLE_NOT_IN_REGION, EnvironmentEdgeManager.currentTimeMillis(), null); } - + /** * Certain operations, such as DROP TABLE are not allowed if there a table has child views. * This class wraps the Results of a scanning the Phoenix Metadata for child views for a specific table @@ -1686,7 +1693,7 @@ public class MetaDataEndpointImpl extends MetaDataProtocol implements Coprocesso return results.size() > 0 && allViewsNotInSingleRegion; } } - + @Override public void clearTableFromCache(RpcController controller, ClearTableFromCacheRequest request, RpcCallback<ClearTableFromCacheResponse> done) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/9cd7e86b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java index 1e34bc9..8df3748 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/generated/PTableProtos.java @@ -2933,6 +2933,16 @@ public final class PTableProtos { * <code>optional int64 statsTimeStamp = 23;</code> */ long getStatsTimeStamp(); + + // required bool storeNulls = 24; + /** + * <code>required bool storeNulls = 24;</code> + */ + boolean hasStoreNulls(); + /** + * <code>required bool storeNulls = 24;</code> + */ + boolean getStoreNulls(); } /** * Protobuf type {@code PTable} @@ -3118,6 +3128,11 @@ public final class PTableProtos { statsTimeStamp_ = input.readInt64(); break; } + case 192: { + bitField0_ |= 0x00080000; + storeNulls_ = input.readBool(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -3632,6 +3647,22 @@ public final class PTableProtos { return statsTimeStamp_; } + // required bool storeNulls = 24; + public static final int STORENULLS_FIELD_NUMBER = 24; + private boolean storeNulls_; + /** + * <code>required bool storeNulls = 24;</code> + */ + public boolean hasStoreNulls() { + return ((bitField0_ & 0x00080000) == 0x00080000); + } + /** + * <code>required bool storeNulls = 24;</code> + */ + public boolean getStoreNulls() { + return storeNulls_; + } + private void initFields() { schemaNameBytes_ = com.google.protobuf.ByteString.EMPTY; tableNameBytes_ = com.google.protobuf.ByteString.EMPTY; @@ -3656,6 +3687,7 @@ public final class PTableProtos { viewIndexId_ = 0; indexType_ = com.google.protobuf.ByteString.EMPTY; statsTimeStamp_ = 0L; + storeNulls_ = false; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -3698,6 +3730,10 @@ public final class PTableProtos { memoizedIsInitialized = 0; return false; } + if (!hasStoreNulls()) { + memoizedIsInitialized = 0; + return false; + } for (int i = 0; i < getColumnsCount(); i++) { if (!getColumns(i).isInitialized()) { memoizedIsInitialized = 0; @@ -3792,6 +3828,9 @@ public final class PTableProtos { if (((bitField0_ & 0x00040000) == 0x00040000)) { output.writeInt64(23, statsTimeStamp_); } + if (((bitField0_ & 0x00080000) == 0x00080000)) { + output.writeBool(24, storeNulls_); + } getUnknownFields().writeTo(output); } @@ -3898,6 +3937,10 @@ public final class PTableProtos { size += com.google.protobuf.CodedOutputStream .computeInt64Size(23, statsTimeStamp_); } + if (((bitField0_ & 0x00080000) == 0x00080000)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(24, storeNulls_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -4024,6 +4067,11 @@ public final class PTableProtos { result = result && (getStatsTimeStamp() == other.getStatsTimeStamp()); } + result = result && (hasStoreNulls() == other.hasStoreNulls()); + if (hasStoreNulls()) { + result = result && (getStoreNulls() + == other.getStoreNulls()); + } result = result && getUnknownFields().equals(other.getUnknownFields()); return result; @@ -4129,6 +4177,10 @@ public final class PTableProtos { hash = (37 * hash) + STATSTIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + hashLong(getStatsTimeStamp()); } + if (hasStoreNulls()) { + hash = (37 * hash) + STORENULLS_FIELD_NUMBER; + hash = (53 * hash) + hashBoolean(getStoreNulls()); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -4299,6 +4351,8 @@ public final class PTableProtos { bitField0_ = (bitField0_ & ~0x00200000); statsTimeStamp_ = 0L; bitField0_ = (bitField0_ & ~0x00400000); + storeNulls_ = false; + bitField0_ = (bitField0_ & ~0x00800000); return this; } @@ -4435,6 +4489,10 @@ public final class PTableProtos { to_bitField0_ |= 0x00040000; } result.statsTimeStamp_ = statsTimeStamp_; + if (((from_bitField0_ & 0x00800000) == 0x00800000)) { + to_bitField0_ |= 0x00080000; + } + result.storeNulls_ = storeNulls_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -4598,6 +4656,9 @@ public final class PTableProtos { if (other.hasStatsTimeStamp()) { setStatsTimeStamp(other.getStatsTimeStamp()); } + if (other.hasStoreNulls()) { + setStoreNulls(other.getStoreNulls()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -4639,6 +4700,10 @@ public final class PTableProtos { return false; } + if (!hasStoreNulls()) { + + return false; + } for (int i = 0; i < getColumnsCount(); i++) { if (!getColumns(i).isInitialized()) { @@ -6169,6 +6234,39 @@ public final class PTableProtos { return this; } + // required bool storeNulls = 24; + private boolean storeNulls_ ; + /** + * <code>required bool storeNulls = 24;</code> + */ + public boolean hasStoreNulls() { + return ((bitField0_ & 0x00800000) == 0x00800000); + } + /** + * <code>required bool storeNulls = 24;</code> + */ + public boolean getStoreNulls() { + return storeNulls_; + } + /** + * <code>required bool storeNulls = 24;</code> + */ + public Builder setStoreNulls(boolean value) { + bitField0_ |= 0x00800000; + storeNulls_ = value; + onChanged(); + return this; + } + /** + * <code>required bool storeNulls = 24;</code> + */ + public Builder clearStoreNulls() { + bitField0_ = (bitField0_ & ~0x00800000); + storeNulls_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:PTable) } @@ -6214,7 +6312,7 @@ public final class PTableProtos { "ats\022\013\n\003key\030\001 \002(\014\022\016\n\006values\030\002 \003(\014\022\033\n\023guid" + "ePostsByteCount\030\003 \001(\003\022\025\n\rkeyBytesCount\030\004" + " \001(\003\022\027\n\017guidePostsCount\030\005 \001(\005\022!\n\013pGuideP", - "osts\030\006 \001(\0132\014.PGuidePosts\"\242\004\n\006PTable\022\027\n\017s" + + "osts\030\006 \001(\0132\014.PGuidePosts\"\266\004\n\006PTable\022\027\n\017s" + "chemaNameBytes\030\001 \002(\014\022\026\n\016tableNameBytes\030\002" + " \002(\014\022\036\n\ttableType\030\003 \002(\0162\013.PTableType\022\022\n\n" + "indexState\030\004 \001(\t\022\026\n\016sequenceNumber\030\005 \002(\003" + @@ -6228,10 +6326,11 @@ public final class PTableProtos { "\021 \001(\014\022\025\n\rviewStatement\030\022 \001(\014\022\025\n\rphysical" + "Names\030\023 \003(\014\022\020\n\010tenantId\030\024 \001(\014\022\023\n\013viewInd" + "exId\030\025 \001(\005\022\021\n\tindexType\030\026 \001(\014\022\026\n\016statsTi" + - "meStamp\030\027 \001(\003*A\n\nPTableType\022\n\n\006SYSTEM\020\000\022" + - "\010\n\004USER\020\001\022\010\n\004VIEW\020\002\022\t\n\005INDEX\020\003\022\010\n\004JOIN\020\004" + - "B@\n(org.apache.phoenix.coprocessor.gener" + - "atedB\014PTableProtosH\001\210\001\001\240\001\001" + "meStamp\030\027 \001(\003\022\022\n\nstoreNulls\030\030 \002(\010*A\n\nPTa" + + "bleType\022\n\n\006SYSTEM\020\000\022\010\n\004USER\020\001\022\010\n\004VIEW\020\002\022" + + "\t\n\005INDEX\020\003\022\010\n\004JOIN\020\004B@\n(org.apache.phoen" + + "ix.coprocessor.generatedB\014PTableProtosH\001" + + "\210\001\001\240\001\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -6255,7 +6354,7 @@ public final class PTableProtos { internal_static_PTable_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_PTable_descriptor, - new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", }); + new java.lang.String[] { "SchemaNameBytes", "TableNameBytes", "TableType", "IndexState", "SequenceNumber", "TimeStamp", "PkNameBytes", "BucketNum", "Columns", "Indexes", "IsImmutableRows", "GuidePosts", "DataTableNameBytes", "DefaultFamilyName", "DisableWAL", "MultiTenant", "ViewType", "ViewStatement", "PhysicalNames", "TenantId", "ViewIndexId", "IndexType", "StatsTimeStamp", "StoreNulls", }); return null; } }; http://git-wip-us.apache.org/repos/asf/phoenix/blob/9cd7e86b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java index aa6fdf0..76a1ad1 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java @@ -72,7 +72,7 @@ import com.google.common.collect.Lists; /** - * + * * JDBC DatabaseMetaData implementation of Phoenix reflecting read-only nature of driver. * Supported metadata methods include: * {@link #getTables(String, String, String, String[])} @@ -94,8 +94,8 @@ import com.google.common.collect.Lists; * {@link #getSuperTables(String, String, String)} * {@link #getCatalogs()} * Other ResultSet methods return an empty result set. - * - * + * + * * @since 0.1 */ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.phoenix.jdbc.Jdbc7Shim.DatabaseMetaData { @@ -116,7 +116,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final String SYSTEM_STATS_TABLE = "STATS"; public static final String SYSTEM_STATS_NAME = SchemaUtil.getTableName(SYSTEM_CATALOG_SCHEMA, SYSTEM_STATS_TABLE); public static final byte[] SYSTEM_STATS_NAME_BYTES = Bytes.toBytes(SYSTEM_STATS_NAME); - + public static final String SYSTEM_CATALOG_ALIAS = "\"SYSTEM.TABLE\""; public static final String TABLE_NAME = "TABLE_NAME"; @@ -125,7 +125,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final byte[] TABLE_TYPE_BYTES = Bytes.toBytes(TABLE_TYPE); public static final String PHYSICAL_NAME = "PHYSICAL_NAME"; public static final byte[] PHYSICAL_NAME_BYTES = Bytes.toBytes(PHYSICAL_NAME); - + public static final String COLUMN_FAMILY = "COLUMN_FAMILY"; public static final String TABLE_CAT = "TABLE_CAT"; public static final String TABLE_CATALOG = "TABLE_CATALOG"; @@ -142,7 +142,9 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final byte[] COLUMN_COUNT_BYTES = Bytes.toBytes(COLUMN_COUNT); public static final String SALT_BUCKETS = "SALT_BUCKETS"; public static final byte[] SALT_BUCKETS_BYTES = Bytes.toBytes(SALT_BUCKETS); - + public static final String STORE_NULLS = "STORE_NULLS"; + public static final byte[] STORE_NULLS_BYTES = Bytes.toBytes(STORE_NULLS); + public static final String DATA_TABLE_NAME = "DATA_TABLE_NAME"; public static final byte[] DATA_TABLE_NAME_BYTES = Bytes.toBytes(DATA_TABLE_NAME); public static final String INDEX_STATE = "INDEX_STATE"; @@ -150,7 +152,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final String TENANT_ID = "TENANT_ID"; public static final byte[] TENANT_ID_BYTES = Bytes.toBytes(TENANT_ID); - + public static final String COLUMN_NAME = "COLUMN_NAME"; public static final String DATA_TYPE = "DATA_TYPE"; public static final byte[] DATA_TYPE_BYTES = Bytes.toBytes(DATA_TYPE); @@ -204,7 +206,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final String TABLE_FAMILY = QueryConstants.DEFAULT_COLUMN_FAMILY; public static final byte[] TABLE_FAMILY_BYTES = QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES; - + public static final String TYPE_SEQUENCE = "SEQUENCE"; public static final byte[] SEQUENCE_FAMILY_BYTES = QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES; public static final String SEQUENCE_SCHEMA_NAME = SYSTEM_CATALOG_SCHEMA; @@ -236,11 +238,11 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final String KEY_SEQ = "KEY_SEQ"; public static final byte[] KEY_SEQ_BYTES = Bytes.toBytes(KEY_SEQ); public static final String SUPERTABLE_NAME = "SUPERTABLE_NAME"; - + public static final String TYPE_ID = "TYPE_ID"; public static final String INDEX_DISABLE_TIMESTAMP = "INDEX_DISABLE_TIMESTAMP"; public static final byte[] INDEX_DISABLE_TIMESTAMP_BYTES = Bytes.toBytes(INDEX_DISABLE_TIMESTAMP); - + public static final String REGION_NAME = "REGION_NAME"; public static final byte[] REGION_NAME_BYTES = Bytes.toBytes(REGION_NAME); public static final String GUIDE_POSTS = "GUIDE_POSTS"; @@ -260,10 +262,10 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final String PARENT_TENANT_ID = "PARENT_TENANT_ID"; public static final byte[] PARENT_TENANT_ID_BYTES = Bytes.toBytes(PARENT_TENANT_ID); - + private static final String TENANT_POS_SHIFT = "TENANT_POS_SHIFT"; private static final byte[] TENANT_POS_SHIFT_BYTES = Bytes.toBytes(TENANT_POS_SHIFT); - + private final PhoenixConnection connection; private final ResultSet emptyResultSet; @@ -360,19 +362,19 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho throws SQLException { return emptyResultSet; } - + private static String escapePattern(String pattern) { return StringEscapeUtils.escapeSql(pattern); // Need to escape double quotes } - + public static final String GLOBAL_TENANANTS_ONLY = "null"; - + private void addTenantIdFilter(StringBuilder buf, String tenantIdPattern) { PName tenantId = connection.getTenantId(); if (tenantIdPattern == null) { if (tenantId != null) { appendConjunction(buf); - buf.append(" (" + TENANT_ID + " IS NULL " + + buf.append(" (" + TENANT_ID + " IS NULL " + " OR " + TENANT_ID + " = '" + escapePattern(tenantId.getString()) + "') "); } } else if (tenantIdPattern.length() == 0) { @@ -390,7 +392,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho private static void appendConjunction(StringBuilder buf) { buf.append(buf.length() == 0 ? "" : " and "); } - + @Override public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { @@ -416,7 +418,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho SCOPE_SCHEMA + "," + SCOPE_TABLE + "," + SOURCE_DATA_TYPE + "," + - IS_AUTOINCREMENT + "," + + IS_AUTOINCREMENT + "," + ARRAY_SIZE + "," + COLUMN_FAMILY + "," + DATA_TYPE + " " + TYPE_ID + "," +// raw type id for potential internal consumption @@ -659,7 +661,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho "true NON_UNIQUE,\n" + "null INDEX_QUALIFIER,\n" + TABLE_NAME + " INDEX_NAME,\n" + - DatabaseMetaData.tableIndexOther + " TYPE,\n" + + DatabaseMetaData.tableIndexOther + " TYPE,\n" + ORDINAL_POSITION + ",\n" + COLUMN_NAME + ",\n" + "CASE WHEN " + COLUMN_FAMILY + " IS NOT NULL THEN null WHEN " + SORT_ORDER + " = " + (SortOrder.DESC.getSystemValue()) + " THEN 'D' ELSE 'A' END ASC_OR_DESC,\n" + @@ -669,11 +671,11 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho // Include data type info, though not in spec ExternalSqlTypeIdFunction.NAME + "(" + DATA_TYPE + ") AS " + DATA_TYPE + ",\n" + SqlTypeNameFunction.NAME + "(" + DATA_TYPE + ") AS " + TYPE_NAME + ",\n" + - DATA_TYPE + " " + TYPE_ID + ",\n" + + DATA_TYPE + " " + TYPE_ID + ",\n" + COLUMN_FAMILY + ",\n" + COLUMN_SIZE + ",\n" + ARRAY_SIZE + - "\nfrom " + SYSTEM_CATALOG + + "\nfrom " + SYSTEM_CATALOG + "\nwhere "); buf.append(TABLE_SCHEM + (schema == null || schema.length() == 0 ? " is null" : " = '" + escapePattern(schema) + "'" )); buf.append("\nand " + DATA_TABLE_NAME + " = '" + escapePattern(table) + "'" ); @@ -817,7 +819,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho SqlTypeNameFunction.NAME + "(" + DATA_TYPE + ") AS " + TYPE_NAME + "," + COLUMN_SIZE + "," + DATA_TYPE + " " + TYPE_ID + "," + // raw type id - VIEW_CONSTANT + + VIEW_CONSTANT + " from " + SYSTEM_CATALOG + " " + SYSTEM_CATALOG_ALIAS + " where "); buf.append(TABLE_SCHEM + (schema == null || schema.length() == 0 ? " is null" : " = '" + escapePattern(schema) + "'" )); @@ -908,7 +910,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho TENANT_ID + " " + TABLE_CAT + "," + // Use tenantId for catalog TABLE_SCHEM + "," + TABLE_NAME + "," + - COLUMN_FAMILY + " " + SUPERTABLE_NAME + + COLUMN_FAMILY + " " + SUPERTABLE_NAME + " from " + SYSTEM_CATALOG + " " + SYSTEM_CATALOG_ALIAS + " where " + COLUMN_NAME + " is null" + " and " + LINK_TYPE + " = " + LinkType.PHYSICAL_TABLE.getSerializedValue()); @@ -923,7 +925,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho Statement stmt = connection.createStatement(); return stmt.executeQuery(buf.toString()); } - + @Override public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { return emptyResultSet; @@ -963,7 +965,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho } }; private static final RowProjector TABLE_TYPE_ROW_PROJECTOR = new RowProjector(Arrays.<ColumnProjector>asList( - new ExpressionProjector(TABLE_TYPE, SYSTEM_CATALOG, + new ExpressionProjector(TABLE_TYPE, SYSTEM_CATALOG, new RowKeyColumnExpression(TABLE_TYPE_DATUM, new RowKeyValueAccessor(Collections.<PDatum>singletonList(TABLE_TYPE_DATUM), 0)), false) ), 0, true);