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 boolean matches(RelOptRuleCall call) { final LimitPrel limit = call.rel(0); // We do not fire this rule if fetch() is null (indicating we have to fetch all the // remaining rows starting from offset. return !limit.isPushDown() && limit.getFetch() != null; } };
protected void doPushLimitIntoGroupScan(RelOptRuleCall call, LimitPrel limit, final ProjectPrel project, ScanPrel scan, GroupScan groupScan) { try { final GroupScan newGroupScan = getGroupScanWithLimit(groupScan, limit); if (newGroupScan == null) { return; } final ScanPrel newScan = new ScanPrel(scan.getCluster(), scan.getTraitSet(), newGroupScan, scan.getRowType(), scan.getTable()); final RelNode newChild; if (project != null) { final ProjectPrel newProject = new ProjectPrel(project.getCluster(), project.getTraitSet(), newScan, project.getProjects(), project.getRowType()); newChild = newProject; } else { newChild = newScan; } call.transformTo(newChild); logger.debug("pushLimitIntoGroupScan: Converted to a new ScanPrel " + newScan.getGroupScan()); } catch (Exception e) { logger.warn("pushLimitIntoGroupScan: Exception while trying limit pushdown!", e); } }
protected void doPushFilterToScan(final RelOptRuleCall call, final FilterPrel filter, final ProjectPrel project, final ScanPrel scan, final HBaseGroupScan groupScan, final RexNode condition) { final LogicalExpression conditionExp = DrillOptiq.toDrill(new DrillParseContext(PrelUtil.getPlannerSettings(call.getPlanner())), scan, condition); final HBaseFilterBuilder hbaseFilterBuilder = new HBaseFilterBuilder(groupScan, conditionExp); final HBaseScanSpec newScanSpec = hbaseFilterBuilder.parseTree(); if (newScanSpec == null) { return; //no filter pushdown ==> No transformation. } final HBaseGroupScan newGroupsScan = new HBaseGroupScan(groupScan.getUserName(), groupScan.getStoragePlugin(), newScanSpec, groupScan.getColumns()); newGroupsScan.setFilterPushedDown(true); final ScanPrel newScanPrel = new ScanPrel(scan.getCluster(), filter.getTraitSet(), newGroupsScan, scan.getRowType(), scan.getTable()); // Depending on whether is a project in the middle, assign either scan or copy of project to childRel. final RelNode childRel = project == null ? newScanPrel : project.copy(project.getTraitSet(), ImmutableList.of(newScanPrel)); if (hbaseFilterBuilder.isAllExpressionsConverted()) { /* * Since we could convert the entire filter condition expression into an HBase filter, * we can eliminate the filter operator altogether. */ call.transformTo(childRel); } else { call.transformTo(filter.copy(filter.getTraitSet(), ImmutableList.of(childRel))); } }
@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); } }
@Override public void onMatch(RelOptRuleCall call) { final FilterPrel filter = call.rel(0); final ScanPrel scan = call.rel(1); final RexNode condition = filter.getCondition(); if (scan.getGroupScan() instanceof BinaryTableGroupScan) { BinaryTableGroupScan groupScan = (BinaryTableGroupScan)scan.getGroupScan(); doPushFilterIntoBinaryGroupScan(call, filter, null, scan, groupScan, condition); } else { assert(scan.getGroupScan() instanceof JsonTableGroupScan); JsonTableGroupScan groupScan = (JsonTableGroupScan)scan.getGroupScan(); doPushFilterIntoJsonGroupScan(call, filter, null, scan, groupScan, condition); } }
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(1); if (scan.getGroupScan() instanceof BinaryTableGroupScan || scan.getGroupScan() instanceof JsonTableGroupScan) { return super.matches(call); } return false; } };
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = call.rel(1); final LimitPrel limit = call.rel(0); // pushdown only apply limit but not offset, // so if getFetch() return null no need to run this rule. if (scan.getGroupScan().supportsLimitPushdown() && !limit.isPushDown() && limit.getFetch() != null) { if ((scan.getGroupScan() instanceof JsonTableGroupScan && ((JsonTableGroupScan) scan.getGroupScan()).isIndexScan()) || (scan.getGroupScan() instanceof RestrictedJsonTableGroupScan)) { return true; } } return false; } };
@Override public boolean matches(RelOptRuleCall call) { final DrillScanRel scan = (DrillScanRel) call.rel(1); GroupScan groupScan = scan.getGroupScan(); // this rule is applicable only for Hive based partition pruning if (PrelUtil.getPlannerSettings(scan.getCluster().getPlanner()).isHepPartitionPruningEnabled()) { return groupScan instanceof HiveScan && groupScan.supportsPartitionFilterPushdown() && !scan.partitionFilterPushdown(); } else { return groupScan instanceof HiveScan && groupScan.supportsPartitionFilterPushdown(); } }
@Override public PhysicalOperator getPhysicalOperator(PhysicalPlanCreator creator) throws IOException { JdbcGroupScan output = new JdbcGroupScan(sql, convention.getPlugin(), rows); return creator.addMetadata(this, output); }
@Override public void onMatch(RelOptRuleCall call) { final FilterPrel filter = call.rel(0); final ProjectPrel project = call.rel(1); final ScanPrel scan = call.rel(2); // convert the filter to one that references the child of the project final RexNode condition = RelOptUtil.pushPastProject(filter.getCondition(), project); if (scan.getGroupScan() instanceof BinaryTableGroupScan) { BinaryTableGroupScan groupScan = (BinaryTableGroupScan)scan.getGroupScan(); doPushFilterIntoBinaryGroupScan(call, filter, project, scan, groupScan, condition); } else { assert(scan.getGroupScan() instanceof JsonTableGroupScan); JsonTableGroupScan groupScan = (JsonTableGroupScan)scan.getGroupScan(); doPushFilterIntoJsonGroupScan(call, filter, project, scan, groupScan, condition); } }
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(2); if (scan.getGroupScan() instanceof BinaryTableGroupScan || scan.getGroupScan() instanceof JsonTableGroupScan) { return super.matches(call); } return false; } };
@Override public boolean matches(RelOptRuleCall call) { final DrillScanRel scan = (DrillScanRel) call.rel(2); GroupScan groupScan = scan.getGroupScan(); // this rule is applicable only for Hive based partition pruning if (PrelUtil.getPlannerSettings(scan.getCluster().getPlanner()).isHepPartitionPruningEnabled()) { return groupScan instanceof HiveScan && groupScan.supportsPartitionFilterPushdown() && !scan.partitionFilterPushdown(); } else { return groupScan instanceof HiveScan && groupScan.supportsPartitionFilterPushdown(); } }
@Override public void onMatch(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(1); final FilterPrel filter = (FilterPrel) call.rel(0); final RexNode condition = filter.getCondition(); HBaseGroupScan groupScan = (HBaseGroupScan)scan.getGroupScan(); if (groupScan.isFilterPushedDown()) { /* * The rule can get triggered again due to the transformed "scan => filter" sequence * created by the earlier execution of this rule when we could not do a complete * conversion of Optiq Filter's condition to HBase Filter. In such cases, we rely upon * this flag to not do a re-processing of the rule on the already transformed call. */ return; } doPushFilterToScan(call, filter, null, scan, groupScan, condition); }
@Override public void onMatch(RelOptRuleCall call) { final ProjectPrel project = call.rel(0); final ScanPrel scan = call.rel(1); if (scan.getGroupScan() instanceof JsonTableGroupScan) { JsonTableGroupScan groupScan = (JsonTableGroupScan) scan.getGroupScan(); doPushProjectIntoGroupScan(call, project, scan, groupScan); } }
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = call.rel(1); // See class level comments above for why only JsonGroupScan is considered if (scan.getGroupScan() instanceof JsonTableGroupScan) { return super.matches(call); } return false; } };
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(2); if (scan.getGroupScan() instanceof HBaseGroupScan) { return super.matches(call); } return false; } };
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(1); if (scan.getGroupScan() instanceof KafkaGroupScan) { return super.matches(call); } return false; } }
@Override public boolean matches(RelOptRuleCall call) { final ScanPrel scan = (ScanPrel) call.rel(1); if (scan.getGroupScan() instanceof HBaseGroupScan) { return super.matches(call); } return false; } };
@Override public void onMatch(RelOptRuleCall call) { final LimitPrel limit = call.rel(0); final ScanPrel scan = call.rel(1); doPushLimitIntoGroupScan(call, limit, null, scan, scan.getGroupScan()); }