private GroupScan getGroupScanWithLimit(GroupScan groupScan, LimitPrel limit) { final int offset = limit.getOffset() != null ? Math.max(0, RexLiteral.intValue(limit.getOffset())) : 0; final int fetch = Math.max(0, RexLiteral.intValue(limit.getFetch())); // Scan Limit uses conservative approach: use offset 0 and fetch = parent limit offset + parent limit fetch. if (groupScan instanceof JsonTableGroupScan) { JsonTableGroupScan jsonTableGroupScan = (JsonTableGroupScan) groupScan; return (jsonTableGroupScan.clone(jsonTableGroupScan.getScanSpec()).applyLimit(offset + fetch)); } else if (groupScan instanceof BinaryTableGroupScan) { BinaryTableGroupScan binaryTableGroupScan = (BinaryTableGroupScan) groupScan; final HBaseScanSpec oldScanSpec = binaryTableGroupScan.getHBaseScanSpec(); final HBaseScanSpec newScanSpec = new HBaseScanSpec(oldScanSpec.getTableName(), oldScanSpec.getStartRow(), oldScanSpec.getStopRow(), oldScanSpec.getFilter()); return new BinaryTableGroupScan(binaryTableGroupScan.getUserName(), binaryTableGroupScan.getStoragePlugin(), binaryTableGroupScan.getFormatPlugin(), newScanSpec, binaryTableGroupScan.getColumns(), binaryTableGroupScan.getTableStats()).applyLimit(offset + fetch); } return null; }
@Override public void onMatch(RelOptRuleCall call) { final ProjectPrel project = call.rel(1); final LimitPrel limit = call.rel(0); RelNode child = project.getInput(); final RelNode limitUnderProject = new LimitPrel(child.getCluster(), child.getTraitSet(), child, limit.getOffset(), limit.getFetch()); final RelNode newProject = new ProjectPrel(project.getCluster(), project.getTraitSet(), limitUnderProject, project.getProjects(), project.getRowType()); if (DrillRelOptUtil.isProjectFlatten(project)) { //Preserve limit above the project since Flatten can produce more rows. Also mark it so we do not fire the rule again. child = newProject; final RelNode limitAboveProject = new LimitPrel(child.getCluster(), child.getTraitSet(), child, limit.getOffset(), limit.getFetch(), true); call.transformTo(limitAboveProject); } else { call.transformTo(newProject); } }
protected void doPushLimitIntoRowKeyJoin(RelOptRuleCall call, LimitPrel limit, final ProjectPrel project, RowKeyJoinPrel join) { final RelNode newChild; try { RelNode left = join.getLeft(); RelNode right = join.getRight(); final RelNode limitOnLeft = new LimitPrel(left.getCluster(), left.getTraitSet(), left, limit.getOffset(), limit.getFetch()); RowKeyJoinPrel newJoin = new RowKeyJoinPrel(join.getCluster(), join.getTraitSet(), limitOnLeft, right, join.getCondition(), join.getJoinType()); if (project != null) { final ProjectPrel newProject = new ProjectPrel(project.getCluster(), project.getTraitSet(), newJoin, project.getProjects(), project.getRowType()); newChild = newProject; } else { newChild = newJoin; } call.transformTo(newChild); logger.debug("pushLimitIntoRowKeyJoin: Pushed limit on left side of Join " + join.toString()); } catch (Exception e) { logger.warn("pushLimitIntoRowKeyJoin: Exception while trying limit pushdown!", e); } } }
@Override public Prel prepareForLateralUnnestPipeline(List<RelNode> children) { return new LimitPrel(this.getCluster(), this.traitSet, children.get(0), getOffset(), getFetch(), isPushDown(), true); } }
@Override public void onMatch(RelOptRuleCall call) { final LimitPrel limit = (LimitPrel) call.rel(0); final ExchangePrel exchangePrel = (ExchangePrel) call.rel(1); RelNode child = exchangePrel.getInput(); final int offset = limit.getOffset() != null ? Math.max(0, RexLiteral.intValue(limit.getOffset())) : 0; final int fetch = Math.max(0, RexLiteral.intValue(limit.getFetch())); // child Limit uses conservative approach: use offset 0 and fetch = parent limit offset + parent limit fetch. final RexNode childFetch = limit.getCluster().getRexBuilder().makeExactLiteral(BigDecimal.valueOf(offset + fetch)); final RelNode limitUnderExchange = new LimitPrel(child.getCluster(), child.getTraitSet(), child, null, childFetch); final RelNode newExch = exchangePrel.copy(exchangePrel.getTraitSet(), ImmutableList.of(limitUnderExchange)); final RelNode limitAboveExchange = new LimitPrel(limit.getCluster(), limit.getTraitSet(), newExch, limit.getOffset(), limit.getFetch(), true); call.transformTo(limitAboveExchange); }
@Override public void onMatch(RelOptRuleCall call) { final LimitPrel limit = call.rel(0); final SingleMergeExchangePrel smex = call.rel(1); final SortPrel sort = call.rel(2); // First offset to include into results (inclusive). Null implies it is starting from offset 0 int offset = limit.getOffset() != null ? Math.max(0, RexLiteral.intValue(limit.getOffset())) : 0; int fetch = Math.max(0, RexLiteral.intValue(limit.getFetch())); final TopNPrel topN = new TopNPrel(limit.getCluster(), sort.getTraitSet(), sort.getInput(), offset + fetch, sort.getCollation()); final LimitPrel newLimit = new LimitPrel(limit.getCluster(), limit.getTraitSet(), new SingleMergeExchangePrel(smex.getCluster(), smex.getTraitSet(), topN, sort.getCollation()), limit.getOffset(), limit.getFetch()); call.transformTo(newLimit); }
private GroupScan getGroupScanWithLimit(GroupScan groupScan, LimitPrel limit) { final int offset = limit.getOffset() != null ? Math.max(0, RexLiteral.intValue(limit.getOffset())) : 0; final int fetch = Math.max(0, RexLiteral.intValue(limit.getFetch())); // Scan Limit uses conservative approach: use offset 0 and fetch = parent limit offset + parent limit fetch. if (groupScan instanceof JsonTableGroupScan) { JsonTableGroupScan jsonTableGroupScan = (JsonTableGroupScan) groupScan; return (jsonTableGroupScan.clone(jsonTableGroupScan.getScanSpec()).applyLimit(offset + fetch)); } else if (groupScan instanceof BinaryTableGroupScan) { BinaryTableGroupScan binaryTableGroupScan = (BinaryTableGroupScan) groupScan; final HBaseScanSpec oldScanSpec = binaryTableGroupScan.getHBaseScanSpec(); final HBaseScanSpec newScanSpec = new HBaseScanSpec(oldScanSpec.getTableName(), oldScanSpec.getStartRow(), oldScanSpec.getStopRow(), oldScanSpec.getFilter()); return new BinaryTableGroupScan(binaryTableGroupScan.getUserName(), binaryTableGroupScan.getStoragePlugin(), binaryTableGroupScan.getFormatPlugin(), newScanSpec, binaryTableGroupScan.getColumns(), binaryTableGroupScan.getTableStats()).applyLimit(offset + fetch); } return null; }
@Override public void onMatch(RelOptRuleCall call) { final ProjectPrel project = call.rel(1); final LimitPrel limit = call.rel(0); RelNode child = project.getInput(); final RelNode limitUnderProject = new LimitPrel(child.getCluster(), child.getTraitSet(), child, limit.getOffset(), limit.getFetch()); final RelNode newProject = new ProjectPrel(project.getCluster(), project.getTraitSet(), limitUnderProject, project.getProjects(), project.getRowType()); if (DrillRelOptUtil.isProjectFlatten(project)) { //Preserve limit above the project since Flatten can produce more rows. Also mark it so we do not fire the rule again. child = newProject; final RelNode limitAboveProject = new LimitPrel(child.getCluster(), child.getTraitSet(), child, limit.getOffset(), limit.getFetch(), true); call.transformTo(limitAboveProject); } else { call.transformTo(newProject); } }
protected void doPushLimitIntoRowKeyJoin(RelOptRuleCall call, LimitPrel limit, final ProjectPrel project, RowKeyJoinPrel join) { final RelNode newChild; try { RelNode left = join.getLeft(); RelNode right = join.getRight(); final RelNode limitOnLeft = new LimitPrel(left.getCluster(), left.getTraitSet(), left, limit.getOffset(), limit.getFetch()); RowKeyJoinPrel newJoin = new RowKeyJoinPrel(join.getCluster(), join.getTraitSet(), limitOnLeft, right, join.getCondition(), join.getJoinType()); if (project != null) { final ProjectPrel newProject = new ProjectPrel(project.getCluster(), project.getTraitSet(), newJoin, project.getProjects(), project.getRowType()); newChild = newProject; } else { newChild = newJoin; } call.transformTo(newChild); logger.debug("pushLimitIntoRowKeyJoin: Pushed limit on left side of Join " + join.toString()); } catch (Exception e) { logger.warn("pushLimitIntoRowKeyJoin: Exception while trying limit pushdown!", e); } } }