Search in sources :

Example 26 with DrillParseContext

use of org.apache.drill.exec.planner.logical.DrillParseContext in project drill by apache.

the class IndexPlanUtils method queryCoveredByIndex.

/**
 * This method is called only when the index has at least one functional indexed field. If there is no function field,
 * we don't need to worry whether there could be paths not found in Scan.
 * In functional case, we have to check all available (if needed) operators to find out if the query is covered or not.
 * E.g. cast(a.b as INT) in project, a.b in Scan's rowType or columns, and cast(a.b as INT)
 * is an indexed field named '$0'. In this case, by looking at Scan, we see only 'a.b' which is not in index. We have to
 * look into Project, and if we see 'a.b' is only used in functional index expression cast(a.b as INT), then we know
 * this Project+Scan is covered.
 * @param indexContext the index call context
 * @param functionInfo functional index information that may impact rewrite
 * @return false if the query could not be covered by the index (should not create covering index plan)
 */
private static boolean queryCoveredByIndex(IndexCallContext indexContext, FunctionalIndexInfo functionInfo) {
    if (indexContext.getFilter() != null && indexContext.getUpperProject() == null) {
        if (!isFullQuery(indexContext)) {
            return false;
        }
    }
    DrillParseContext parserContext = new DrillParseContext(PrelUtil.getPlannerSettings(indexContext.getCall().rel(0).getCluster()));
    Set<LogicalExpression> exprs = Sets.newHashSet();
    if (indexContext.getUpperProject() != null) {
        if (indexContext.getLowerProject() == null) {
            for (RexNode rex : indexContext.getUpperProject().getProjects()) {
                LogicalExpression expr = RexToExpression.toDrill(parserContext, null, indexContext.getScan(), rex);
                exprs.add(expr);
            }
            // now collect paths in filter since upperProject may drop some paths in filter
            IndexableExprMarker filterMarker = new IndexableExprMarker(indexContext.getScan());
            indexContext.getFilterCondition().accept(filterMarker);
            for (RexNode rex : filterMarker.getIndexableExpression().keySet()) {
                LogicalExpression expr = RexToExpression.toDrill(parserContext, null, indexContext.getScan(), rex);
                exprs.add(expr);
            }
        } else {
            // we have underneath project, so we have to do more to convert expressions
            for (RexNode rex : indexContext.getUpperProject().getProjects()) {
                LogicalExpression expr = RexToExpression.toDrill(parserContext, indexContext.getLowerProject(), indexContext.getScan(), rex);
                exprs.add(expr);
            }
            // Now collect paths in filter since upperProject may drop some paths in filter.
            // Since this is (upper)Proj+Filter+(lower)Proj+Scan case, and IndexableExprMarker works
            // only with expressions that referencing directly to Scan, it has to use indexContext.origPushedCondition
            IndexableExprMarker filterMarker = new IndexableExprMarker(indexContext.getScan());
            indexContext.getOrigCondition().accept(filterMarker);
            for (RexNode rex : filterMarker.getIndexableExpression().keySet()) {
                // Since rex represents the filter expression directly referencing the scan row type,
                // (the condition has been pushed down of lowerProject), set the lowerProject as null.
                LogicalExpression expr = RexToExpression.toDrill(parserContext, null, indexContext.getScan(), rex);
                exprs.add(expr);
            }
        }
    } else if (indexContext.getLowerProject() != null) {
        for (RexNode rex : indexContext.getLowerProject().getProjects()) {
            LogicalExpression expr = DrillOptiq.toDrill(parserContext, indexContext.getScan(), rex);
            exprs.add(expr);
        }
    } else {
        // upperProject and lowerProject both are null, the only place to find columns being used in query is scan
        exprs.addAll(indexContext.getScanColumns());
    }
    Map<LogicalExpression, Set<SchemaPath>> exprPathMap = functionInfo.getPathsInFunctionExpr();
    PathInExpr exprSearch = new PathInExpr(exprPathMap);
    for (LogicalExpression expr : exprs) {
        if (expr.accept(exprSearch, null) == false) {
            return false;
        }
    }
    // if we come to here, paths in indexed function expressions are covered in capProject.
    // now we check other paths.
    // check the leftout paths (appear in capProject other than functional index expression) are covered by other index fields or not
    List<LogicalExpression> leftPaths = Lists.newArrayList(exprSearch.getRemainderPaths());
    indexContext.setLeftOutPathsInFunctions(exprSearch.getRemainderPathsInFunctions());
    return functionInfo.getIndexDesc().isCoveringIndex(leftPaths);
}
Also used : LogicalExpression(org.apache.drill.common.expression.LogicalExpression) RelTraitSet(org.apache.calcite.plan.RelTraitSet) Set(java.util.Set) DrillParseContext(org.apache.drill.exec.planner.logical.DrillParseContext) RexNode(org.apache.calcite.rex.RexNode)

Example 27 with DrillParseContext

use of org.apache.drill.exec.planner.logical.DrillParseContext in project drill by apache.

the class IndexPlanUtils method updateSortExpression.

/**
 * generate logical expressions for sort rexNodes in SortRel, the result is store to IndexPlanCallContext
 * @param indexContext the index call context
 * @param coll list of field collations
 */
public static void updateSortExpression(IndexCallContext indexContext, List<RelFieldCollation> coll) {
    if (coll == null) {
        return;
    }
    DrillParseContext parserContext = new DrillParseContext(PrelUtil.getPlannerSettings(indexContext.getCall().rel(0).getCluster()));
    indexContext.createSortExprs();
    for (RelFieldCollation collation : coll) {
        int idx = collation.getFieldIndex();
        DrillProjectRelBase oneProject;
        if (indexContext.getUpperProject() != null && indexContext.getLowerProject() != null) {
            LogicalExpression expr = RexToExpression.toDrill(parserContext, indexContext.getLowerProject(), indexContext.getScan(), indexContext.getUpperProject().getProjects().get(idx));
            indexContext.getSortExprs().add(expr);
        } else {
            // one project is null now
            oneProject = (indexContext.getUpperProject() != null) ? indexContext.getUpperProject() : indexContext.getLowerProject();
            if (oneProject != null) {
                LogicalExpression expr = RexToExpression.toDrill(parserContext, null, indexContext.getScan(), getProjects(oneProject).get(idx));
                indexContext.getSortExprs().add(expr);
            } else {
                // two projects are null
                SchemaPath path;
                RelDataTypeField f = indexContext.getScan().getRowType().getFieldList().get(idx);
                String pathSeg = f.getName().replaceAll("`", "");
                final String[] segs = pathSeg.split("\\.");
                path = SchemaPath.getCompoundPath(segs);
                indexContext.getSortExprs().add(path);
            }
        }
    }
}
Also used : LogicalExpression(org.apache.drill.common.expression.LogicalExpression) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SchemaPath(org.apache.drill.common.expression.SchemaPath) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) DrillParseContext(org.apache.drill.exec.planner.logical.DrillParseContext) DrillProjectRelBase(org.apache.drill.exec.planner.common.DrillProjectRelBase)

Example 28 with DrillParseContext

use of org.apache.drill.exec.planner.logical.DrillParseContext in project drill by apache.

the class IndexPlanUtils method getProjectExprs.

public static Map<LogicalExpression, Integer> getProjectExprs(List<RexNode> projectRexs, DrillProjectRelBase project, RelNode input) {
    Map<LogicalExpression, Integer> projectExprs = Maps.newLinkedHashMap();
    DrillParseContext parserContext = new DrillParseContext(PrelUtil.getPlannerSettings(input.getCluster()));
    int idx = 0;
    for (RexNode rex : projectRexs) {
        LogicalExpression expr;
        expr = RexToExpression.toDrill(parserContext, project, input, rex);
        projectExprs.put(expr, idx);
        idx++;
    }
    return projectExprs;
}
Also used : LogicalExpression(org.apache.drill.common.expression.LogicalExpression) DrillParseContext(org.apache.drill.exec.planner.logical.DrillParseContext) RexNode(org.apache.calcite.rex.RexNode)

Example 29 with DrillParseContext

use of org.apache.drill.exec.planner.logical.DrillParseContext in project drill by apache.

the class IndexPlanUtils method updateSortExpression.

/**
 * generate logical expressions for sort rexNodes in SortRel, the result is store to IndexPlanCallContext
 * @param indexContext the index call context
 * @param coll list of field collations
 */
public static void updateSortExpression(IndexPhysicalPlanCallContext indexContext, List<RelFieldCollation> coll) {
    if (coll == null) {
        return;
    }
    DrillParseContext parserContext = new DrillParseContext(PrelUtil.getPlannerSettings(indexContext.call.rel(0).getCluster()));
    indexContext.sortExprs = Lists.newArrayList();
    for (RelFieldCollation collation : coll) {
        int idx = collation.getFieldIndex();
        ProjectPrel oneProject;
        if (indexContext.upperProject != null && indexContext.lowerProject != null) {
            LogicalExpression expr = RexToExpression.toDrill(parserContext, indexContext.lowerProject, indexContext.scan, indexContext.upperProject.getProjects().get(idx));
            indexContext.sortExprs.add(expr);
        } else {
            // one project is null now
            oneProject = (indexContext.upperProject != null) ? indexContext.upperProject : indexContext.lowerProject;
            if (oneProject != null) {
                LogicalExpression expr = RexToExpression.toDrill(parserContext, null, indexContext.scan, oneProject.getProjects().get(idx));
                indexContext.sortExprs.add(expr);
            } else {
                // two projects are null
                SchemaPath path;
                RelDataTypeField f = indexContext.scan.getRowType().getFieldList().get(idx);
                String pathSeg = f.getName().replaceAll("`", "");
                final String[] segs = pathSeg.split("\\.");
                path = SchemaPath.getCompoundPath(segs);
                indexContext.sortExprs.add(path);
            }
        }
    }
}
Also used : ProjectPrel(org.apache.drill.exec.planner.physical.ProjectPrel) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SchemaPath(org.apache.drill.common.expression.SchemaPath) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) DrillParseContext(org.apache.drill.exec.planner.logical.DrillParseContext)

Example 30 with DrillParseContext

use of org.apache.drill.exec.planner.logical.DrillParseContext in project drill by apache.

the class CoveringIndexPlanGenerator method convertChild.

@Override
public RelNode convertChild(final RelNode filter, final RelNode input) throws InvalidRelException {
    if (indexGroupScan == null) {
        logger.error("Null indexgroupScan in CoveringIndexPlanGenerator.convertChild");
        return null;
    }
    RexNode coveringCondition;
    ScanPrel indexScanPrel = IndexPlanUtils.buildCoveringIndexScan(origScan, indexGroupScan, indexContext, indexDesc);
    // If remainder condition, then combine the index and remainder conditions. This is a covering plan so we can
    // pushed the entire condition into the index.
    coveringCondition = IndexPlanUtils.getTotalFilter(indexCondition, remainderCondition, indexScanPrel.getCluster().getRexBuilder());
    RexNode newIndexCondition = rewriteFunctionalCondition(coveringCondition, indexScanPrel.getRowType(), functionInfo);
    // build collation for filter
    RelTraitSet indexFilterTraitSet = indexScanPrel.getTraitSet();
    FilterPrel indexFilterPrel = new FilterPrel(indexScanPrel.getCluster(), indexFilterTraitSet, indexScanPrel, newIndexCondition);
    ProjectPrel indexProjectPrel = null;
    if (origProject != null) {
        RelCollation collation = IndexPlanUtils.buildCollationProject(IndexPlanUtils.getProjects(origProject), null, origScan, functionInfo, indexContext);
        indexProjectPrel = new ProjectPrel(origScan.getCluster(), indexFilterTraitSet.plus(collation), indexFilterPrel, IndexPlanUtils.getProjects(origProject), origProject.getRowType());
    }
    RelNode finalRel;
    if (indexProjectPrel != null) {
        finalRel = indexProjectPrel;
    } else {
        finalRel = indexFilterPrel;
    }
    if (upperProject != null) {
        RelCollation newCollation = IndexPlanUtils.buildCollationProject(IndexPlanUtils.getProjects(upperProject), origProject, origScan, functionInfo, indexContext);
        ProjectPrel cap = new ProjectPrel(upperProject.getCluster(), newCollation == null ? finalRel.getTraitSet() : finalRel.getTraitSet().plus(newCollation), finalRel, IndexPlanUtils.getProjects(upperProject), upperProject.getRowType());
        if (functionInfo.hasFunctional()) {
            // if there is functional index field, then a rewrite may be needed in upperProject/indexProject
            // merge upperProject with indexProjectPrel(from origProject) if both exist,
            ProjectPrel newProject = cap;
            if (indexProjectPrel != null) {
                newProject = (ProjectPrel) DrillMergeProjectRule.replace(newProject, indexProjectPrel);
            }
            // then rewrite functional expressions in new project.
            List<RexNode> newProjects = Lists.newArrayList();
            DrillParseContext parseContxt = new DrillParseContext(PrelUtil.getPlannerSettings(newProject.getCluster()));
            for (RexNode projectRex : newProject.getProjects()) {
                RexNode newRex = IndexPlanUtils.rewriteFunctionalRex(indexContext, parseContxt, null, origScan, projectRex, indexScanPrel.getRowType(), functionInfo);
                newProjects.add(newRex);
            }
            ProjectPrel rewrittenProject = new ProjectPrel(newProject.getCluster(), newCollation == null ? newProject.getTraitSet() : newProject.getTraitSet().plus(newCollation), indexFilterPrel, newProjects, newProject.getRowType());
            cap = rewrittenProject;
        }
        finalRel = cap;
    }
    if (indexContext.getSort() != null) {
        finalRel = getSortNode(indexContext, finalRel, false, true, true);
        Preconditions.checkArgument(finalRel != null);
    }
    finalRel = Prule.convert(finalRel, finalRel.getTraitSet().plus(Prel.DRILL_PHYSICAL));
    logger.debug("CoveringIndexPlanGenerator got finalRel {} from origScan {}, original digest {}, new digest {}.", finalRel.toString(), origScan.toString(), upperProject == null ? indexContext.getFilter().getDigest() : upperProject.getDigest(), finalRel.getDigest());
    return finalRel;
}
Also used : ProjectPrel(org.apache.drill.exec.planner.physical.ProjectPrel) ScanPrel(org.apache.drill.exec.planner.physical.ScanPrel) RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) DrillParseContext(org.apache.drill.exec.planner.logical.DrillParseContext) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RexNode(org.apache.calcite.rex.RexNode) FilterPrel(org.apache.drill.exec.planner.physical.FilterPrel)

Aggregations

DrillParseContext (org.apache.drill.exec.planner.logical.DrillParseContext)41 LogicalExpression (org.apache.drill.common.expression.LogicalExpression)31 RexNode (org.apache.calcite.rex.RexNode)17 ScanPrel (org.apache.drill.exec.planner.physical.ScanPrel)16 RelNode (org.apache.calcite.rel.RelNode)14 PhysicalOperator (org.apache.drill.exec.physical.base.PhysicalOperator)10 GroupScan (org.apache.drill.exec.physical.base.GroupScan)5 FilterPrel (org.apache.drill.exec.planner.physical.FilterPrel)5 IOException (java.io.IOException)3 RelTraitSet (org.apache.calcite.plan.RelTraitSet)3 RelFieldCollation (org.apache.calcite.rel.RelFieldCollation)3 Project (org.apache.calcite.rel.core.Project)3 RexLiteral (org.apache.calcite.rex.RexLiteral)3 SchemaPath (org.apache.drill.common.expression.SchemaPath)3 ProjectPrel (org.apache.drill.exec.planner.physical.ProjectPrel)3 Stopwatch (com.google.common.base.Stopwatch)2 RelCollation (org.apache.calcite.rel.RelCollation)2 Filter (org.apache.calcite.rel.core.Filter)2 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)2 DrillRuntimeException (org.apache.drill.common.exceptions.DrillRuntimeException)2