예제 #1
0
 /** Creates a DrillScan. */
 public DrillScanRel(
     final RelOptCluster cluster, final RelTraitSet traits, final RelOptTable table) {
   // By default, scan does not support project pushdown.
   // Decision whether push projects into scan will be made solely in DrillPushProjIntoScanRule.
   this(cluster, traits, table, table.getRowType(), GroupScan.ALL_COLUMNS);
   this.settings = PrelUtil.getPlannerSettings(cluster.getPlanner());
 }
예제 #2
0
 /** Creates a DrillScanRel for a particular GroupScan */
 public DrillScanRel(
     final RelOptCluster cluster,
     final RelTraitSet traits,
     final RelOptTable table,
     final GroupScan groupScan,
     final RelDataType rowType,
     final List<SchemaPath> columns) {
   super(DRILL_LOGICAL, cluster, traits, table);
   this.rowType = rowType;
   this.columns = columns;
   this.groupScan = groupScan;
   this.settings = PrelUtil.getPlannerSettings(cluster.getPlanner());
 }
예제 #3
0
  /// TODO: this method is same as the one for ScanPrel...eventually we should consolidate
  /// this and few other methods in a common base class which would be extended
  /// by both logical and physical rels.
  @Override
  public RelOptCost computeSelfCost(final RelOptPlanner planner) {
    final ScanStats stats = groupScan.getScanStats(settings);
    int columnCount = getRowType().getFieldCount();
    double ioCost = 0;
    boolean isStarQuery =
        Iterables.tryFind(
                getRowType().getFieldNames(),
                new Predicate<String>() {
                  @Override
                  public boolean apply(String input) {
                    return Preconditions.checkNotNull(input).equals("*");
                  }
                })
            .isPresent();

    if (isStarQuery) {
      columnCount = STAR_COLUMN_COST;
    }

    // double rowCount = RelMetadataQuery.getRowCount(this);
    double rowCount = stats.getRecordCount();
    if (rowCount < 1) {
      rowCount = 1;
    }

    if (PrelUtil.getSettings(getCluster()).useDefaultCosting()) {
      return planner
          .getCostFactory()
          .makeCost(rowCount * columnCount, stats.getCpuCost(), stats.getDiskCost());
    }

    double cpuCost =
        rowCount * columnCount; // for now, assume cpu cost is proportional to row count.
    // Even though scan is reading from disk, in the currently generated plans all plans will
    // need to read the same amount of data, so keeping the disk io cost 0 is ok for now.
    // In the future we might consider alternative scans that go against projections or
    // different compression schemes etc that affect the amount of data read. Such alternatives
    // would affect both cpu and io cost.

    DrillCostFactory costFactory = (DrillCostFactory) planner.getCostFactory();
    return costFactory.makeCost(rowCount, cpuCost, ioCost, 0);
  }
예제 #4
0
 /** Creates a DrillScan. */
 public DrillScanRel(
     final RelOptCluster cluster,
     final RelTraitSet traits,
     final RelOptTable table,
     final RelDataType rowType,
     final List<SchemaPath> columns) {
   super(DRILL_LOGICAL, cluster, traits, table);
   this.settings = PrelUtil.getPlannerSettings(cluster.getPlanner());
   this.rowType = rowType;
   if (columns == null) { // planner asks to scan all of the columns
     this.columns = ColumnList.all();
   } else if (columns.size() == 0) { // planner asks to skip all of the columns
     this.columns = ColumnList.none();
   } else { // planner asks to scan some columns
     this.columns = ColumnList.some(columns);
   }
   try {
     this.groupScan = drillTable.getGroupScan().clone(this.columns);
   } catch (final IOException e) {
     throw new DrillRuntimeException("Failure creating scan.", e);
   }
 }
  protected void doMatch(
      RelOptRuleCall call, ScanPrel scan, ProjectPrel project, FilterPrel filter) {
    final RexNode condition = filter.getCondition();

    InfoSchemaGroupScan groupScan = (InfoSchemaGroupScan) scan.getGroupScan();
    if (groupScan.isFilterPushedDown()) {
      return;
    }

    LogicalExpression conditionExp =
        DrillOptiq.toDrill(
            new DrillParseContext(PrelUtil.getPlannerSettings(call.getPlanner())),
            project != null ? project : scan,
            condition);
    InfoSchemaFilterBuilder filterBuilder = new InfoSchemaFilterBuilder(conditionExp);
    InfoSchemaFilter infoSchemaFilter = filterBuilder.build();
    if (infoSchemaFilter == null) {
      return; // no filter pushdown ==> No transformation.
    }

    final InfoSchemaGroupScan newGroupsScan =
        new InfoSchemaGroupScan(groupScan.getTable(), infoSchemaFilter);
    newGroupsScan.setFilterPushedDown(true);

    RelNode input = ScanPrel.create(scan, filter.getTraitSet(), newGroupsScan, scan.getRowType());
    if (project != null) {
      input =
          project.copy(project.getTraitSet(), input, project.getProjects(), filter.getRowType());
    }

    if (filterBuilder.isAllExpressionsConverted()) {
      // Filter can be removed as all expressions in the filter are converted and pushed to scan
      call.transformTo(input);
    } else {
      call.transformTo(filter.copy(filter.getTraitSet(), ImmutableList.of(input)));
    }
  }
  @Override
  public Prel visitProject(ProjectPrel project, Object unused) throws RelConversionException {

    // Apply the rule to the child
    RelNode originalInput = ((Prel) project.getInput(0)).accept(this, null);
    project = (ProjectPrel) project.copy(project.getTraitSet(), Lists.newArrayList(originalInput));

    List<RexNode> exprList = new ArrayList<>();

    List<RelDataTypeField> relDataTypes = new ArrayList();
    List<RelDataTypeField> origRelDataTypes = new ArrayList();
    int i = 0;
    final int lastColumnReferenced = PrelUtil.getLastUsedColumnReference(project.getProjects());

    if (lastColumnReferenced == -1) {
      return project;
    }

    final int lastRexInput = lastColumnReferenced + 1;
    RexVisitorComplexExprSplitter exprSplitter =
        new RexVisitorComplexExprSplitter(factory, funcReg, lastRexInput);

    for (RexNode rex : project.getChildExps()) {
      origRelDataTypes.add(project.getRowType().getFieldList().get(i));
      i++;
      exprList.add(rex.accept(exprSplitter));
    }
    List<RexNode> complexExprs = exprSplitter.getComplexExprs();

    if (complexExprs.size() == 1 && findTopComplexFunc(project.getChildExps()).size() == 1) {
      return project;
    }

    ProjectPrel childProject;

    List<RexNode> allExprs = new ArrayList();
    int exprIndex = 0;
    List<String> fieldNames = originalInput.getRowType().getFieldNames();
    for (int index = 0; index < lastRexInput; index++) {
      RexBuilder builder = new RexBuilder(factory);
      allExprs.add(
          builder.makeInputRef(new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index));

      if (fieldNames.get(index).contains(StarColumnHelper.STAR_COLUMN)) {
        relDataTypes.add(
            new RelDataTypeFieldImpl(
                fieldNames.get(index), allExprs.size(), factory.createSqlType(SqlTypeName.ANY)));
      } else {
        relDataTypes.add(
            new RelDataTypeFieldImpl(
                "EXPR$" + exprIndex, allExprs.size(), factory.createSqlType(SqlTypeName.ANY)));
        exprIndex++;
      }
    }
    RexNode currRexNode;
    int index = lastRexInput - 1;

    // if the projection expressions contained complex outputs, split them into their own individual
    // projects
    if (complexExprs.size() > 0) {
      while (complexExprs.size() > 0) {
        if (index >= lastRexInput) {
          allExprs.remove(allExprs.size() - 1);
          RexBuilder builder = new RexBuilder(factory);
          allExprs.add(
              builder.makeInputRef(
                  new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index));
        }
        index++;
        exprIndex++;

        currRexNode = complexExprs.remove(0);
        allExprs.add(currRexNode);
        relDataTypes.add(
            new RelDataTypeFieldImpl(
                "EXPR$" + exprIndex, allExprs.size(), factory.createSqlType(SqlTypeName.ANY)));
        childProject =
            new ProjectPrel(
                project.getCluster(),
                project.getTraitSet(),
                originalInput,
                ImmutableList.copyOf(allExprs),
                new RelRecordType(relDataTypes));
        originalInput = childProject;
      }
      // copied from above, find a better way to do this
      allExprs.remove(allExprs.size() - 1);
      RexBuilder builder = new RexBuilder(factory);
      allExprs.add(
          builder.makeInputRef(new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index));
      relDataTypes.add(
          new RelDataTypeFieldImpl(
              "EXPR$" + index, allExprs.size(), factory.createSqlType(SqlTypeName.ANY)));
    }
    return (Prel)
        project.copy(
            project.getTraitSet(), originalInput, exprList, new RelRecordType(origRelDataTypes));
  }