@Override public boolean isDegenerate() { return context.getScanRanges() == ScanRanges.NOTHING; }
public UnionPlan(StatementContext context, FilterableStatement statement, TableRef table, RowProjector projector, Integer limit, Integer offset, OrderBy orderBy, GroupBy groupBy, List<QueryPlan> plans, ParameterMetaData paramMetaData) throws SQLException { this.parentContext = context; this.statement = statement; this.tableRef = table; this.projector = projector; this.limit = limit; this.orderBy = orderBy; this.groupBy = groupBy; this.plans = plans; this.offset= offset; this.paramMetaData = paramMetaData; boolean isDegen = true; for (QueryPlan plan : plans) { if (plan.getContext().getScanRanges() != ScanRanges.NOTHING) { isDegen = false; break; } } this.isDegenerate = isDegen; }
private void appendKeyRanges(StringBuilder buf) { ScanRanges scanRanges = context.getScanRanges(); if (scanRanges.isDegenerate() || scanRanges.isEverything()) { return; } buf.append(" ["); StringBuilder buf1 = new StringBuilder(); appendScanRow(buf1, Bound.LOWER); buf.append(buf1); buf.setCharAt(buf.length()-1, ']'); StringBuilder buf2 = new StringBuilder(); appendScanRow(buf2, Bound.UPPER); if (!StringUtil.equals(buf1, buf2)) { buf.append( " - ["); buf.append(buf2); } buf.setCharAt(buf.length()-1, ']'); } }
private boolean explainSkipScan(StringBuilder buf) { ScanRanges scanRanges = context.getScanRanges(); if (scanRanges.isPointLookup()) { int keyCount = scanRanges.getPointLookupCount(); buf.append("POINT LOOKUP ON " + keyCount + " KEY" + (keyCount > 1 ? "S " : " ")); } else if (scanRanges.useSkipScanFilter()) { buf.append("SKIP SCAN "); int count = 1; boolean hasRanges = false; int nSlots = scanRanges.getBoundSlotCount(); for (int i = 0; i < nSlots; i++) { List<KeyRange> ranges = scanRanges.getRanges().get(i); count *= ranges.size(); for (KeyRange range : ranges) { hasRanges |= !range.isSingleKey(); } } buf.append("ON "); buf.append(count); buf.append(hasRanges ? " RANGE" : " KEY"); buf.append(count > 1 ? "S " : " "); } else { buf.append("RANGE SCAN "); } return scanRanges.useSkipScanFilter(); }
private void appendScanRow(StringBuilder buf, Bound bound) { ScanRanges scanRanges = context.getScanRanges(); Iterator<byte[]> minMaxIterator = Collections.emptyIterator(); boolean isLocalIndex = ScanUtil.isLocalIndex(context.getScan());
private boolean hasEqualityConstraints(int startPos, int endPos) { ScanRanges ranges = context.getScanRanges(); // If a GROUP BY is being done, then the rows are ordered according to the GROUP BY key, // not by the original row key order of the table (see PHOENIX-3451). // We check each GROUP BY expression to see if it only references columns that are // matched by equality constraints, in which case the expression itself would be constant. if (!groupBy.isEmpty()) { for (int pos = startPos; pos < endPos; pos++) { IsConstantVisitor visitor = new IsConstantVisitor(ranges, whereExpression); List<Expression> groupByExpressions = groupBy.getExpressions(); if (pos >= groupByExpressions.size()) { // sanity check - shouldn't be necessary return false; } Expression groupByExpression = groupByExpressions.get(pos); Boolean isConstant = groupByExpression.accept(visitor); if (!Boolean.TRUE.equals(isConstant)) { return false; } } return true; } for (int pos = startPos; pos < endPos; pos++) { if (!ranges.hasEqualityConstraint(pos)) { return false; } } return true; }
private void appendPKColumnValue(StringBuilder buf, byte[] range, Boolean isNull, int slotIndex, boolean changeViewIndexId) { if (Boolean.TRUE.equals(isNull)) { buf.append("null"); return; } if (Boolean.FALSE.equals(isNull)) { buf.append("not null"); return; } if (range.length == 0) { buf.append('*'); return; } ScanRanges scanRanges = context.getScanRanges(); PDataType type = scanRanges.getSchema().getField(slotIndex).getDataType(); SortOrder sortOrder = tableRef.getTable().getPKColumns().get(slotIndex).getSortOrder(); if (sortOrder == SortOrder.DESC) { buf.append('~'); ImmutableBytesWritable ptr = new ImmutableBytesWritable(range); type.coerceBytes(ptr, type, sortOrder, SortOrder.getDefault()); range = ptr.get(); } if (changeViewIndexId) { buf.append(getViewIndexValue(type, range).toString()); } else { Format formatter = context.getConnection().getFormatter(type); buf.append(type.toStringLiteral(range, formatter)); } }
private List<QueryPlan> getApplicablePlansForSingleFlatQuery(QueryPlan dataPlan, PhoenixStatement statement, List<? extends PDatum> targetColumns, ParallelIteratorFactory parallelIteratorFactory, boolean stopAtBestPlan) throws SQLException { SelectStatement select = (SelectStatement)dataPlan.getStatement(); if (dataPlan.getContext().getScanRanges().isPointLookup() && stopAtBestPlan) { return Collections.<QueryPlan> singletonList(dataPlan);
@Override public ExplainPlan getExplainPlan() throws SQLException { if (context.getScanRanges() == ScanRanges.NOTHING) { return new ExplainPlan(Collections.singletonList("DEGENERATE SCAN OVER " + getTableRef().getTable().getName().getString())); } ResultIterator iterator = iterator(); ExplainPlan explainPlan = new ExplainPlan(getPlanSteps(iterator)); iterator.close(); return explainPlan; }
@Override public MutationState execute() throws SQLException { // We have a point lookup, so we know we have a simple set of fully qualified // keys for our ranges ScanRanges ranges = context.getScanRanges(); Iterator<KeyRange> iterator = ranges.getPointLookupKeyIterator(); MultiRowMutationState mutation = new MultiRowMutationState(ranges.getPointLookupCount()); while (iterator.hasNext()) { mutation.put(new ImmutableBytesPtr(iterator.next().getLowerRange()), new RowMutationState(PRow.DELETE_MARKER, 0, statement.getConnection().getStatementExecutionCounter(), NULL_ROWTIMESTAMP_INFO, null)); } return new MutationState(dataPlan.getTableRef(), mutation, 0, maxSize, maxSizeBytes, connection); }
@Test public void testOrPKRanges() throws SQLException { Connection conn = DriverManager.getConnection(getUrl()); ensureTableCreated(getUrl(), TestUtil.BTABLE_NAME); Statement stmt = conn.createStatement(); // BTABLE has 5 PK columns String query = "select * from " + BTABLE_NAME + " where (a_string > '1' and a_string < '5') or (a_string > '6' and a_string < '9')"; StatementContext context = compileStatement(query); Filter filter = context.getScan().getFilter(); assertNotNull(filter); assertTrue(filter instanceof SkipScanFilter); ScanRanges scanRanges = context.getScanRanges(); assertNotNull(scanRanges); List<List<KeyRange>> ranges = scanRanges.getRanges(); assertEquals(1, ranges.size()); List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList( KeyRange.getKeyRange(Bytes.toBytes("1"), false, Bytes.toBytes("5"), false), KeyRange.getKeyRange(Bytes.toBytes("6"), false, Bytes.toBytes("9"), false))); assertEquals(expectedRanges, ranges); stmt.close(); conn.close(); }
assertEquals(3 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount()); plan = stmt.compileQuery("select * from my_table_mt_view where (pkcol3, pkcol4) > ('0', '0') and pkcol1 = '000000000000000'"); assertEquals(2 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount()); plan = stmt.compileQuery("select * from my_table_mt_view where (pkcol1, pkcol2, pkcol3) < ('0', '0', '0')"); assertEquals(4 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount()); plan = stmt.compileQuery("select * from my_table_mt_view where (pkcol1, pkcol2, pkcol3) < ('9', '9', '9') and (pkcol1, pkcol2) > ('0', '0')"); assertEquals(4 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount()); plan = stmt.compileQuery("select * from my_table_mt_view where pkcol1 = 'a' and pkcol2 = 'b' and pkcol3 = 'c' and (pkcol1, pkcol2) < ('z', 'z')"); assertEquals(4 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount()); plan = stmt.compileQuery("select * from my_table_mt_view where (pkcol2, pkcol3) > ('0', '0') and pkcol1 = '000000000000000'"); assertEquals(4 + offset, plan.getContext().getScanRanges().getBoundPkColumnCount());
assertTrue(filterList.getFilters().get(1) instanceof SingleKeyValueComparisonFilter); ScanRanges scanRanges = context.getScanRanges(); assertNotNull(scanRanges); assertEquals(3,scanRanges.getRanges().size());
ScanRanges ranges=plan.getContext().getScanRanges();
@Test public void testOrDiffColExpression() throws SQLException { String tenantId1 = "000000000000001"; String entityId1 = "002333333333331"; String query = "select * from atable where organization_id = ? or entity_id = ?"; List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertNotNull(filter); assertTrue(filter instanceof RowKeyComparisonFilter); ScanRanges scanRanges = context.getScanRanges(); assertEquals(ScanRanges.EVERYTHING,scanRanges); assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow()); assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow()); }
@Test public void testAndOrExpression() throws SQLException { String tenantId1 = "000000000000001"; String tenantId2 = "000000000000003"; String entityId1 = "002333333333331"; String entityId2 = "002333333333333"; String query = "select * from atable where (organization_id = ? and entity_id = ?) or (organization_id = ? and entity_id = ?)"; List<Object> binds = Arrays.<Object>asList(tenantId1,entityId1,tenantId2,entityId2); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertNotNull(filter); assertTrue(filter instanceof RowKeyComparisonFilter); ScanRanges scanRanges = context.getScanRanges(); assertEquals(ScanRanges.EVERYTHING,scanRanges); assertArrayEquals(HConstants.EMPTY_START_ROW, scan.getStartRow()); assertArrayEquals(HConstants.EMPTY_END_ROW, scan.getStopRow()); }
assertArrayEquals(expectedEndKey, skipScanFilter.getSlots().get(0).get(1).getLowerRange()); StatementContext context = plan.getContext(); ScanRanges scanRanges = context.getScanRanges(); List<List<KeyRange>> ranges = scanRanges.getRanges(); assertEquals(expectedRanges, ranges);
@Test public void testOrSameColRangeExpression() throws SQLException { String query = "select * from atable where substr(organization_id,1,3) = ? or organization_id LIKE 'foo%'"; List<Object> binds = Arrays.<Object>asList("00D"); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertNotNull(filter); assertTrue(filter instanceof SkipScanFilter); ScanRanges scanRanges = context.getScanRanges(); assertNotNull(scanRanges); List<List<KeyRange>> ranges = scanRanges.getRanges(); assertEquals(1,ranges.size()); List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList( PChar.INSTANCE.getKeyRange( StringUtil.padChar(PChar.INSTANCE.toBytes("00D"),15), true, StringUtil.padChar(ByteUtil.nextKey(PChar.INSTANCE.toBytes("00D")),15), false), PChar.INSTANCE.getKeyRange( StringUtil.padChar(PChar.INSTANCE.toBytes("foo"),15), true, StringUtil.padChar(ByteUtil.nextKey(PChar.INSTANCE.toBytes("foo")),15), false))); assertEquals(expectedRanges, ranges); }
@Test public void testOrSameColExpression() throws SQLException { String tenantId1 = "000000000000001"; String tenantId2 = "000000000000003"; String query = "select * from atable where organization_id = ? or organization_id = ?"; List<Object> binds = Arrays.<Object>asList(tenantId1,tenantId2); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertNotNull(filter); assertTrue(filter instanceof SkipScanFilter); ScanRanges scanRanges = context.getScanRanges(); assertNotNull(scanRanges); List<List<KeyRange>> ranges = scanRanges.getRanges(); assertEquals(1,ranges.size()); List<List<KeyRange>> expectedRanges = Collections.singletonList(Arrays.asList( PChar.INSTANCE.getKeyRange(PChar.INSTANCE.toBytes(tenantId1), true, PChar.INSTANCE.toBytes(tenantId1), true), PChar.INSTANCE.getKeyRange(PChar.INSTANCE.toBytes(tenantId2), true, PChar.INSTANCE.toBytes(tenantId2), true))); assertEquals(expectedRanges, ranges); byte[] startRow = PVarchar.INSTANCE.toBytes(tenantId1); assertArrayEquals(startRow, scan.getStartRow()); assertArrayEquals(ByteUtil.nextKey(PVarchar.INSTANCE.toBytes(tenantId2)), scan.getStopRow()); }
@Test public void testUsingRVCFullyQualifiedInClause() throws Exception { String firstOrgId = "000000000000001"; String secondOrgId = "000000000000009"; String firstParentId = "000000000000011"; String secondParentId = "000000000000021"; String query = "select * from atable where (organization_id, entity_id) IN ((?, ?), (?, ?))"; List<Object> binds = Arrays.<Object>asList(firstOrgId, firstParentId, secondOrgId, secondParentId); StatementContext context = compileStatement(query, binds); Scan scan = context.getScan(); Filter filter = scan.getFilter(); assertTrue(filter instanceof SkipScanFilter); List<List<KeyRange>> skipScanRanges = Collections.singletonList(Arrays.asList( KeyRange.getKeyRange(ByteUtil.concat(PChar.INSTANCE.toBytes(firstOrgId), PChar.INSTANCE.toBytes(firstParentId))), KeyRange.getKeyRange(ByteUtil.concat(PChar.INSTANCE.toBytes(secondOrgId), PChar.INSTANCE.toBytes(secondParentId))))); assertEquals(skipScanRanges, context.getScanRanges().getRanges()); assertArrayEquals(ByteUtil.concat(PChar.INSTANCE.toBytes(firstOrgId), PChar.INSTANCE.toBytes(firstParentId)), scan.getStartRow()); assertArrayEquals(ByteUtil.concat(PChar.INSTANCE.toBytes(secondOrgId), PChar.INSTANCE.toBytes(secondParentId), QueryConstants.SEPARATOR_BYTE_ARRAY), scan.getStopRow()); }