@Override public TableRef getTargetRef() { return context.getCurrentTable(); }
protected void addColumn(PColumn column) { EncodedColumnsUtil.setColumns(column, context.getCurrentTable().getTable(), context.getScan()); }
public long getCurrentTime() throws SQLException { long ts = this.getCurrentTable().getCurrentTime(); // if the table is transactional then it is only resolved once per query, so we can't use the table timestamp if (this.getCurrentTable().getTable().getType() != PTableType.PROJECTED && !this .getCurrentTable().getTable().isTransactional() && ts != QueryConstants .UNSET_TIMESTAMP) { return ts; } if (currentTime != QueryConstants.UNSET_TIMESTAMP) { return currentTime; } /* * For an UPSERT VALUES where autocommit off, we won't hit the server until the commit. * However, if the statement has a CURRENT_DATE() call as a value, we need to know the * current time at execution time. In that case, we'll call MetaDataClient.updateCache * purely to bind the current time based on the server time. */ PTable table = this.getCurrentTable().getTable(); PhoenixConnection connection = getConnection(); MetaDataClient client = new MetaDataClient(connection); currentTime = client.getCurrentTime(table.getSchemaName().getString(), table.getTableName().getString()); return currentTime; }
@Override public Void visit(ProjectedColumnExpression expression) { if (expression.getDataType().isArrayType()) { indexProjectedColumns.add(expression); PColumn col = expression.getColumn(); PTable table = context.getCurrentTable().getTable(); KeyValueColumnExpression keyValueColumnExpression; if (table.getImmutableStorageScheme() != ImmutableStorageScheme.ONE_CELL_PER_COLUMN) { keyValueColumnExpression = new SingleCellColumnExpression(col, col.getName().getString(), table.getEncodingScheme(), table.getImmutableStorageScheme()); } else { keyValueColumnExpression = new KeyValueColumnExpression(col); } indexKVs.add(keyValueColumnExpression); copyOfChildren.set(0, keyValueColumnExpression); Integer count = arrayExpressionCounts.get(expression); arrayExpressionCounts.put(expression, count != null ? (count - 1) : -1); } return null; } });
@Override public Void visit(ColumnParseNode node) throws SQLException { try { ColumnRef resolveColumn = context.getResolver().resolveColumn(node.getSchemaName(), node.getTableName(), node.getName()); if (!SchemaUtil.isPKColumn(resolveColumn.getColumn())) { nonPkColumnRefSet.add(resolveColumn); } } catch (ColumnNotFoundException e) { if (context.getCurrentTable().getTable().getIndexType() == IndexType.LOCAL) { try { localIndexColumnRefSet.add(new LocalIndexDataColumnRef(context, context.getCurrentTable(), node.getName())); } catch (ColumnFamilyNotFoundException c) { throw e; } } else { throw e; } } return null; } }
addBindParamMetaData(lhsNode, rhsNode, lhsExpr, rhsExpr); return wrapGroupByExpression(ComparisonExpression.create(op, children, context.getTempPtr(), context.getCurrentTable().getTable().rowKeyOrderOptimizable()));
@Override public Expression visitLeave(CastParseNode node, List<Expression> children) throws SQLException { ParseNode childNode = node.getChildren().get(0); PDataType targetDataType = node.getDataType(); Expression childExpr = children.get(0); PDataType fromDataType = childExpr.getDataType(); if (childNode instanceof BindParseNode) { context.getBindManager().addParamMetaData((BindParseNode)childNode, childExpr); } Expression expr = childExpr; if(fromDataType != null) { /* * IndexStatementRewriter creates a CAST parse node when rewriting the query to use * indexed columns. Without this check present we wrongly and unnecessarily * end up creating a RoundExpression. */ if (context.getCurrentTable().getTable().getType() != PTableType.INDEX) { expr = convertToRoundExpressionIfNeeded(fromDataType, targetDataType, children); } } boolean rowKeyOrderOptimizable = context.getCurrentTable().getTable().rowKeyOrderOptimizable(); return wrapGroupByExpression(CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength(), rowKeyOrderOptimizable)); }
@Override public Expression visitLeave(InListParseNode node, List<Expression> l) throws SQLException { List<Expression> inChildren = l; Expression firstChild = inChildren.get(0); ImmutableBytesWritable ptr = context.getTempPtr(); PDataType firstChildType = firstChild.getDataType(); ParseNode firstChildNode = node.getChildren().get(0); if (firstChildNode instanceof BindParseNode) { PDatum datum = firstChild; if (firstChildType == null) { datum = inferBindDatum(inChildren); } context.getBindManager().addParamMetaData((BindParseNode)firstChildNode, datum); } for (int i = 1; i < l.size(); i++) { ParseNode childNode = node.getChildren().get(i); if (childNode instanceof BindParseNode) { context.getBindManager().addParamMetaData((BindParseNode)childNode, firstChild); } } return wrapGroupByExpression(InListExpression.create(inChildren, node.isNegate(), ptr, context.getCurrentTable().getTable().rowKeyOrderOptimizable())); }
private void serializeIndexMaintainerIntoScan(Scan scan, PTable dataTable) throws SQLException { PName name = context.getCurrentTable().getTable().getName(); List<PTable> indexes = Lists.newArrayListWithExpectedSize(1); for (PTable index : dataTable.getIndexes()) { if (index.getName().equals(name) && index.getIndexType() == IndexType.LOCAL) { indexes.add(index); break; } } ImmutableBytesWritable ptr = new ImmutableBytesWritable(); IndexMaintainer.serialize(dataTable, ptr, indexes, context.getConnection()); scan.setAttribute(BaseScannerRegionObserver.LOCAL_INDEX_BUILD_PROTO, ByteUtil.copyKeyBytesIfNecessary(ptr)); if (dataTable.isTransactional()) { scan.setAttribute(BaseScannerRegionObserver.TX_STATE, context.getConnection().getMutationState().encodeTransaction()); } }
private void testHintForIndexOnView(boolean includeColumns) throws Exception { Properties props = new Properties(); Connection conn1 = DriverManager.getConnection(getUrl(), props); conn1.setAutoCommit(true); String tableName = SchemaUtil.getTableName(SCHEMA1, generateUniqueName()); String viewName = SchemaUtil.getTableName(SCHEMA2, generateUniqueName()); String indexName = generateUniqueName(); String fullIndexName = SchemaUtil.getTableName(SCHEMA2, indexName); conn1.createStatement().execute( "CREATE TABLE "+tableName+" (k VARCHAR PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) UPDATE_CACHE_FREQUENCY=1000000"); conn1.createStatement().execute("upsert into "+tableName+" values ('row1', 'value1', 'key1')"); conn1.createStatement().execute( "CREATE VIEW "+viewName+" (v3 VARCHAR, v4 VARCHAR) AS SELECT * FROM "+tableName+" WHERE v1 = 'value1'"); conn1.createStatement().execute("CREATE INDEX " + indexName + " ON " + viewName + "(v3)" + (includeColumns ? " INCLUDE(v4)" : "")); PhoenixStatement stmt = conn1.createStatement().unwrap(PhoenixStatement.class); ResultSet rs = stmt.executeQuery("SELECT /*+ INDEX(" + viewName + " " + fullIndexName + ") */ v1 FROM " + viewName + " WHERE v3 = 'foo' ORDER BY v4"); assertFalse(rs.next()); assertEquals(fullIndexName, stmt.getQueryPlan().getContext().getCurrentTable().getTable().getName().getString()); }
@Test public void testSingleColLocalIndexPruning() throws SQLException { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); try (Connection conn = DriverManager.getConnection(getUrl(), props)) { conn.createStatement().execute("CREATE TABLE T (\n" + " A CHAR(1) NOT NULL,\n" + " B CHAR(1) NOT NULL,\n" + " C CHAR(1) NOT NULL,\n" + " CONSTRAINT PK PRIMARY KEY (\n" + " A,\n" + " B,\n" + " C\n" + " )\n" + ") SPLIT ON ('A','C','E','G','I')"); conn.createStatement().execute("CREATE LOCAL INDEX IDX ON T(A,C)"); String query = "SELECT * FROM T WHERE A = 'B' and C='C'"; PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans(); assertEquals(1, outerScans.size()); List<Scan> innerScans = outerScans.get(0); assertEquals(1, innerScans.size()); Scan scan = innerScans.get(0); assertEquals("A", Bytes.toString(scan.getStartRow()).trim()); assertEquals("C", Bytes.toString(scan.getStopRow()).trim()); } }
PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans();
PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans();
PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans();
@Test public void testNoLocalIndexPruning() throws SQLException { Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); try (Connection conn = DriverManager.getConnection(getUrl(), props)) { conn.createStatement().execute("CREATE TABLE T (\n" + " A CHAR(1) NOT NULL,\n" + " B CHAR(1) NOT NULL,\n" + " C CHAR(1) NOT NULL,\n" + " CONSTRAINT PK PRIMARY KEY (\n" + " A,\n" + " B,\n" + " C\n" + " )\n" + ") SPLIT ON ('A','C','E','G','I')"); conn.createStatement().execute("CREATE LOCAL INDEX IDX ON T(C)"); String query = "SELECT * FROM T WHERE C='C'"; PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans(); assertEquals(6, outerScans.size()); } }
PhoenixStatement statement = conn.createStatement().unwrap(PhoenixStatement.class); QueryPlan plan = statement.optimizeQuery(query); assertEquals("IDX", plan.getContext().getCurrentTable().getTable().getName().getString()); plan.iterator(); List<List<Scan>> outerScans = plan.getScans();
private void assertRowCount(Connection conn, String fullTableName, String fullBaseName, int expectedCount) throws SQLException { PhoenixStatement stmt = conn.createStatement().unwrap(PhoenixStatement.class); ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + fullTableName); assertTrue(rs.next()); assertEquals(expectedCount, rs.getInt(1)); // Ensure that index is being used rs = stmt.executeQuery("EXPLAIN SELECT COUNT(*) FROM " + fullTableName); if (fullBaseName != null) { // Uses index and finds correct number of rows assertTrue(QueryUtil.getExplainPlan(rs).startsWith("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + Bytes.toString(MetaDataUtil.getViewIndexPhysicalName(Bytes.toBytes(fullBaseName))))); } // Force it not to use index and still finds correct number of rows rs = stmt.executeQuery("SELECT /*+ NO_INDEX */ * FROM " + fullTableName); int count = 0; while (rs.next()) { count++; } assertEquals(expectedCount, count); // Ensure that the table, not index is being used assertEquals(fullTableName, stmt.getQueryPlan().getContext().getCurrentTable().getTable().getName().getString()); }
@Override public Expression visit(ColumnParseNode node) throws SQLException { ColumnRef ref = resolveColumn(node); TableRef tableRef = ref.getTableRef(); Expression newColumnExpression = ref.newColumnExpression(node.isTableNameCaseSensitive(), node.isCaseSensitive()); if (tableRef.equals(context.getCurrentTable()) && !SchemaUtil.isPKColumn(ref.getColumn())) { byte[] cq = tableRef.getTable().getImmutableStorageScheme() == ImmutableStorageScheme.SINGLE_CELL_ARRAY_WITH_OFFSETS ? QueryConstants.SINGLE_KEYVALUE_COLUMN_QUALIFIER_BYTES : ref.getColumn().getColumnQualifierBytes(); // track the where condition columns. Later we need to ensure the Scan in HRS scans these column CFs context.addWhereConditionColumn(ref.getColumn().getFamilyName().getBytes(), cq); } return newColumnExpression; }
@Override public Expression visit(ColumnParseNode node) throws SQLException { ColumnRef ref = resolveColumn(node); TableRef tableRef = ref.getTableRef(); ImmutableBytesWritable ptr = context.getTempPtr(); PColumn column = ref.getColumn(); // If we have an UPDATABLE view, then we compile those view constants (i.e. columns in equality constraints // in the view) to constants. This allows the optimize to optimize out reference to them in various scenarios. // If the column is matched in a WHERE clause against a constant not equal to it's constant, then the entire // query would become degenerate. if (!resolveViewConstants && IndexUtil.getViewConstantValue(column, ptr)) { return LiteralExpression.newConstant(column.getDataType().toObject(ptr), column.getDataType()); } if (tableRef.equals(context.getCurrentTable()) && !SchemaUtil.isPKColumn(column)) { // project only kv columns addColumn(column); } Expression expression = ref.newColumnExpression(node.isTableNameCaseSensitive(), node.isCaseSensitive()); Expression wrappedExpression = wrapGroupByExpression(expression); // If we're in an aggregate expression // and we're not in the context of an aggregate function // and we didn't just wrap our column reference // then we're mixing aggregate and non aggregate expressions in the same expression. // This catches cases like this: SELECT sum(a_integer) + a_integer FROM atable GROUP BY a_string if (isAggregate && aggregateFunction == null && wrappedExpression == expression) { throwNonAggExpressionInAggException(expression.toString()); } return wrappedExpression; }
public LocalIndexDataColumnRef(StatementContext context, TableRef tRef, String indexColumnName) throws MetaDataEntityNotFoundException, SQLException { super(FromCompiler.getResolver( FACTORY.namedTable( null, TableName.create(tRef.getTable().getSchemaName().getString(), tRef.getTable() .getParentTableName().getString())), context.getConnection(), false) .resolveTable(context.getCurrentTable().getTable().getSchemaName().getString(), tRef.getTable().getParentTableName().getString()), IndexUtil.getDataColumnFamilyName(indexColumnName), IndexUtil .getDataColumnName(indexColumnName)); position = context.getDataColumnPosition(this.getColumn()); columns = context.getDataColumns(); }