private void appendScanRow(StringBuilder buf, Bound bound) {
   ScanRanges scanRanges = context.getScanRanges();
   KeyRange minMaxRange = context.getMinMaxRange();
   Iterator<byte[]> minMaxIterator = Iterators.emptyIterator();
   if (minMaxRange != null) {
     RowKeySchema schema = tableRef.getTable().getRowKeySchema();
     if (!minMaxRange.isUnbound(bound)) {
       minMaxIterator = new RowKeyValueIterator(schema, minMaxRange.getRange(bound));
     }
   }
   int nRanges = scanRanges.getRanges().size();
   for (int i = 0, minPos = 0; minPos < nRanges || minMaxIterator.hasNext(); i++) {
     List<KeyRange> ranges = minPos >= nRanges ? EVERYTHING : scanRanges.getRanges().get(minPos++);
     KeyRange range = bound == Bound.LOWER ? ranges.get(0) : ranges.get(ranges.size() - 1);
     byte[] b = range.getRange(bound);
     Boolean isNull =
         KeyRange.IS_NULL_RANGE == range
             ? Boolean.TRUE
             : KeyRange.IS_NOT_NULL_RANGE == range ? Boolean.FALSE : null;
     if (minMaxIterator.hasNext()) {
       byte[] bMinMax = minMaxIterator.next();
       int cmp = Bytes.compareTo(bMinMax, b) * (bound == Bound.LOWER ? 1 : -1);
       if (cmp > 0) {
         minPos = nRanges;
         b = bMinMax;
         isNull = null;
       } else if (cmp < 0) {
         minMaxIterator = Iterators.emptyIterator();
       }
     }
     appendPKColumnValue(buf, b, isNull, i);
     buf.append(',');
   }
 }
示例#2
0
 public static boolean forceRowKeyOrder(StatementContext context) {
   return context
       .getConnection()
       .getQueryServices()
       .getProps()
       .getBoolean(
           QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB,
           QueryServicesOptions.DEFAULT_FORCE_ROW_KEY_ORDER);
 }
 private void appendKeyRanges(StringBuilder buf) {
   ScanRanges scanRanges = context.getScanRanges();
   KeyRange minMaxRange = context.getMinMaxRange();
   if (minMaxRange == null
       && (scanRanges == ScanRanges.EVERYTHING || scanRanges == ScanRanges.NOTHING)) {
     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, ']');
 }
示例#4
0
 public static boolean isRoundRobinPossible(OrderBy orderBy, StatementContext context)
     throws SQLException {
   int fetchSize = context.getStatement().getFetchSize();
   /*
    * Selecting underlying scanners in a round-robin fashion is possible if there is no ordering of rows needed,
    * not even row key order. Also no point doing round robin of scanners if fetch size
    * is 1.
    */
   return fetchSize > 1
       && !shouldRowsBeInRowKeyOrder(orderBy, context)
       && orderBy.getOrderByExpressions().isEmpty();
 }
 private void appendPKColumnValue(StringBuilder buf, byte[] range, Boolean isNull, int slotIndex) {
   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();
   ColumnModifier modifier = tableRef.getTable().getPKColumns().get(slotIndex).getColumnModifier();
   if (modifier != null) {
     buf.append('~');
     range = modifier.apply(range, 0, new byte[range.length], 0, range.length);
   }
   Format formatter = context.getConnection().getFormatter(type);
   buf.append(type.toStringLiteral(range, formatter));
 }
 public DegenerateQueryPlan(
     StatementContext context, FilterableStatement statement, TableRef table) {
   super(
       context,
       statement,
       table,
       RowProjector.EMPTY_PROJECTOR,
       PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA,
       null,
       OrderBy.EMPTY_ORDER_BY,
       GroupBy.EMPTY_GROUP_BY,
       null);
   context.setScanRanges(ScanRanges.NOTHING);
 }
 public SortMergeJoinPlan(
     StatementContext context,
     FilterableStatement statement,
     TableRef table,
     JoinType type,
     QueryPlan lhsPlan,
     QueryPlan rhsPlan,
     List<Expression> lhsKeyExpressions,
     List<Expression> rhsKeyExpressions,
     PTable joinedTable,
     PTable lhsTable,
     PTable rhsTable,
     int rhsFieldPosition,
     boolean isSingleValueOnly) {
   if (type == JoinType.Right)
     throw new IllegalArgumentException("JoinType should not be " + type);
   this.context = context;
   this.statement = statement;
   this.table = table;
   this.type = type;
   this.lhsPlan = lhsPlan;
   this.rhsPlan = rhsPlan;
   this.lhsKeyExpressions = lhsKeyExpressions;
   this.rhsKeyExpressions = rhsKeyExpressions;
   this.joinedSchema = buildSchema(joinedTable);
   this.lhsSchema = buildSchema(lhsTable);
   this.rhsSchema = buildSchema(rhsTable);
   this.rhsFieldPosition = rhsFieldPosition;
   this.isSingleValueOnly = isSingleValueOnly;
   this.tableRefs =
       Sets.newHashSetWithExpectedSize(
           lhsPlan.getSourceRefs().size() + rhsPlan.getSourceRefs().size());
   this.tableRefs.addAll(lhsPlan.getSourceRefs());
   this.tableRefs.addAll(rhsPlan.getSourceRefs());
   this.thresholdBytes =
       context
           .getConnection()
           .getQueryServices()
           .getProps()
           .getInt(
               QueryServices.SPOOL_THRESHOLD_BYTES_ATTRIB,
               QueryServicesOptions.DEFAULT_SPOOL_THRESHOLD_BYTES);
 }
 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;
     for (List<KeyRange> ranges : scanRanges.getRanges()) {
       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();
 }
  protected void explain(String prefix, List<String> planSteps) {
    StringBuilder buf = new StringBuilder(prefix);
    ScanRanges scanRanges = context.getScanRanges();
    boolean hasSkipScanFilter = false;
    if (scanRanges.isEverything()) {
      buf.append("FULL SCAN ");
    } else {
      hasSkipScanFilter = explainSkipScan(buf);
    }
    buf.append("OVER " + tableRef.getTable().getName().getString());
    if (!scanRanges.isPointLookup()) {
      appendKeyRanges(buf);
    }
    planSteps.add(buf.toString());

    Scan scan = context.getScan();
    Filter filter = scan.getFilter();
    PageFilter pageFilter = null;
    if (filter != null) {
      int offset = 0;
      boolean hasFirstKeyOnlyFilter = false;
      String filterDesc = "";
      if (hasSkipScanFilter) {
        if (filter instanceof FilterList) {
          List<Filter> filterList = ((FilterList) filter).getFilters();
          if (filterList.get(0) instanceof FirstKeyOnlyFilter) {
            hasFirstKeyOnlyFilter = true;
            offset = 1;
          }
          if (filterList.size() > offset + 1) {
            filterDesc = filterList.get(offset + 1).toString();
            if (filterList.size() > offset + 2) {
              pageFilter = (PageFilter) filterList.get(offset + 2);
            }
          }
        }
      } else if (filter instanceof FilterList) {
        List<Filter> filterList = ((FilterList) filter).getFilters();
        if (filterList.get(0) instanceof FirstKeyOnlyFilter) {
          hasFirstKeyOnlyFilter = true;
          offset = 1;
        }
        if (filterList.size() > offset) {
          filterDesc = filterList.get(offset).toString();
          if (filterList.size() > offset + 1) {
            pageFilter = (PageFilter) filterList.get(offset + 1);
          }
        }
      } else {
        if (filter instanceof FirstKeyOnlyFilter) {
          hasFirstKeyOnlyFilter = true;
        } else {
          filterDesc = filter.toString();
        }
      }
      if (filterDesc.length() > 0) {
        planSteps.add(
            "    SERVER FILTER BY "
                + (hasFirstKeyOnlyFilter ? "FIRST KEY ONLY AND " : "")
                + filterDesc);
      } else if (hasFirstKeyOnlyFilter) {
        planSteps.add("    SERVER FILTER BY FIRST KEY ONLY");
      }
      if (pageFilter != null) {
        planSteps.add("    SERVER " + pageFilter.getPageSize() + " ROW LIMIT");
      }
    }
    groupBy.explain(planSteps);
  }
  private static List<KeyRange> getSplits(
      final TableRef tableRef,
      final Scan scan,
      final List<HRegionLocation> regions,
      final ScanRanges scanRanges)
      throws SQLException {
    final List<TableRef> tableRefs = Collections.singletonList(tableRef);
    ColumnResolver resolver =
        new ColumnResolver() {

          @Override
          public List<PFunction> getFunctions() {
            return Collections.emptyList();
          }

          @Override
          public List<TableRef> getTables() {
            return tableRefs;
          }

          @Override
          public TableRef resolveTable(String schemaName, String tableName) throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public ColumnRef resolveColumn(String schemaName, String tableName, String colName)
              throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public PFunction resolveFunction(String functionName) throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public boolean hasUDFs() {
            return false;
          }
        };
    PhoenixConnection connection =
        DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES))
            .unwrap(PhoenixConnection.class);
    final PhoenixStatement statement = new PhoenixStatement(connection);
    final StatementContext context =
        new StatementContext(statement, resolver, scan, new SequenceManager(statement));
    context.setScanRanges(scanRanges);
    ParallelIterators parallelIterators =
        new ParallelIterators(
            new QueryPlan() {

              @Override
              public StatementContext getContext() {
                return context;
              }

              @Override
              public ParameterMetaData getParameterMetaData() {
                return PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA;
              }

              @Override
              public ExplainPlan getExplainPlan() throws SQLException {
                return ExplainPlan.EMPTY_PLAN;
              }

              @Override
              public ResultIterator iterator(ParallelScanGrouper scanGrouper) throws SQLException {
                return ResultIterator.EMPTY_ITERATOR;
              }

              @Override
              public ResultIterator iterator() throws SQLException {
                return ResultIterator.EMPTY_ITERATOR;
              }

              @Override
              public long getEstimatedSize() {
                return 0;
              }

              @Override
              public TableRef getTableRef() {
                return tableRef;
              }

              @Override
              public RowProjector getProjector() {
                return RowProjector.EMPTY_PROJECTOR;
              }

              @Override
              public Integer getLimit() {
                return null;
              }

              @Override
              public OrderBy getOrderBy() {
                return OrderBy.EMPTY_ORDER_BY;
              }

              @Override
              public GroupBy getGroupBy() {
                return GroupBy.EMPTY_GROUP_BY;
              }

              @Override
              public List<KeyRange> getSplits() {
                return null;
              }

              @Override
              public FilterableStatement getStatement() {
                return SelectStatement.SELECT_ONE;
              }

              @Override
              public boolean isDegenerate() {
                return false;
              }

              @Override
              public boolean isRowKeyOrdered() {
                return true;
              }

              @Override
              public List<List<Scan>> getScans() {
                return null;
              }

              @Override
              public boolean useRoundRobinIterator() {
                return false;
              }
            },
            null,
            new SpoolingResultIterator.SpoolingResultIteratorFactory(
                context.getConnection().getQueryServices()));
    List<KeyRange> keyRanges = parallelIterators.getSplits();
    return keyRanges;
  }