Search in sources :

Example 11 with ErrorCollector

use of org.apache.drill.common.expression.ErrorCollector in project drill by apache.

the class JoinUtils method addLeastRestrictiveCasts.

/**
   * Utility method used by joins to add implicit casts on one of the sides of the join condition in case the two
   * expressions have different types.
   * @param leftExpressions array of expressions from left input into the join
   * @param leftBatch left input record batch
   * @param rightExpressions array of expressions from right input into the join
   * @param rightBatch right input record batch
   * @param context fragment context
   */
public static void addLeastRestrictiveCasts(LogicalExpression[] leftExpressions, VectorAccessible leftBatch, LogicalExpression[] rightExpressions, VectorAccessible rightBatch, FragmentContext context) {
    assert rightExpressions.length == leftExpressions.length;
    for (int i = 0; i < rightExpressions.length; i++) {
        LogicalExpression rightExpression = rightExpressions[i];
        LogicalExpression leftExpression = leftExpressions[i];
        TypeProtos.MinorType rightType = rightExpression.getMajorType().getMinorType();
        TypeProtos.MinorType leftType = leftExpression.getMajorType().getMinorType();
        if (rightType == TypeProtos.MinorType.UNION || leftType == TypeProtos.MinorType.UNION) {
            continue;
        }
        if (rightType != leftType) {
            // currently we only support implicit casts if the input types are numeric or varchar/varbinary
            if (!allowImplicitCast(rightType, leftType)) {
                throw new DrillRuntimeException(String.format("Join only supports implicit casts between " + "1. Numeric data\n 2. Varchar, Varbinary data 3. Date, Timestamp data " + "Left type: %s, Right type: %s. Add explicit casts to avoid this error", leftType, rightType));
            }
            // We need to add a cast to one of the expressions
            List<TypeProtos.MinorType> types = new LinkedList<>();
            types.add(rightType);
            types.add(leftType);
            TypeProtos.MinorType result = TypeCastRules.getLeastRestrictiveType(types);
            ErrorCollector errorCollector = new ErrorCollectorImpl();
            if (result == null) {
                throw new DrillRuntimeException(String.format("Join conditions cannot be compared failing left " + "expression:" + " %s failing right expression: %s", leftExpression.getMajorType().toString(), rightExpression.getMajorType().toString()));
            } else if (result != rightType) {
                // Add a cast expression on top of the right expression
                LogicalExpression castExpr = ExpressionTreeMaterializer.addCastExpression(rightExpression, leftExpression.getMajorType(), context.getFunctionRegistry(), errorCollector);
                // Store the newly casted expression
                rightExpressions[i] = ExpressionTreeMaterializer.materialize(castExpr, rightBatch, errorCollector, context.getFunctionRegistry());
            } else if (result != leftType) {
                // Add a cast expression on top of the left expression
                LogicalExpression castExpr = ExpressionTreeMaterializer.addCastExpression(leftExpression, rightExpression.getMajorType(), context.getFunctionRegistry(), errorCollector);
                // store the newly casted expression
                leftExpressions[i] = ExpressionTreeMaterializer.materialize(castExpr, leftBatch, errorCollector, context.getFunctionRegistry());
            }
        }
    }
}
Also used : ErrorCollectorImpl(org.apache.drill.common.expression.ErrorCollectorImpl) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) ErrorCollector(org.apache.drill.common.expression.ErrorCollector) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) TypeProtos(org.apache.drill.common.types.TypeProtos) LinkedList(java.util.LinkedList)

Example 12 with ErrorCollector

use of org.apache.drill.common.expression.ErrorCollector in project drill by apache.

the class MergeJoinBatch method generateNewWorker.

private JoinWorker generateNewWorker() throws ClassTransformationException, IOException, SchemaChangeException {
    final ClassGenerator<JoinWorker> cg = CodeGenerator.getRoot(JoinWorker.TEMPLATE_DEFINITION, context.getFunctionRegistry(), context.getOptions());
    cg.getCodeGenerator().plainJavaCapable(true);
    // Uncomment out this line to debug the generated code.
    //    cg.getCodeGenerator().saveCodeForDebugging(true);
    final ErrorCollector collector = new ErrorCollectorImpl();
    // Generate members and initialization code
    /////////////////////////////////////////
    // declare and assign JoinStatus member
    cg.setMappingSet(setupMapping);
    JClass joinStatusClass = cg.getModel().ref(JoinStatus.class);
    JVar joinStatus = cg.clazz.field(JMod.NONE, joinStatusClass, "status");
    cg.getSetupBlock().assign(JExpr._this().ref(joinStatus), JExpr.direct("status"));
    // declare and assign outgoing VectorContainer member
    JClass vectorContainerClass = cg.getModel().ref(VectorContainer.class);
    JVar outgoingVectorContainer = cg.clazz.field(JMod.NONE, vectorContainerClass, "outgoing");
    cg.getSetupBlock().assign(JExpr._this().ref(outgoingVectorContainer), JExpr.direct("outgoing"));
    // declare and assign incoming left RecordBatch member
    JClass recordBatchClass = cg.getModel().ref(RecordIterator.class);
    JVar incomingLeftRecordBatch = cg.clazz.field(JMod.NONE, recordBatchClass, "incomingLeft");
    cg.getSetupBlock().assign(JExpr._this().ref(incomingLeftRecordBatch), joinStatus.ref("left"));
    // declare and assign incoming right RecordBatch member
    JVar incomingRightRecordBatch = cg.clazz.field(JMod.NONE, recordBatchClass, "incomingRight");
    cg.getSetupBlock().assign(JExpr._this().ref(incomingRightRecordBatch), joinStatus.ref("right"));
    // declare 'incoming' member so VVReadExpr generated code can point to the left or right batch
    JVar incomingRecordBatch = cg.clazz.field(JMod.NONE, recordBatchClass, "incoming");
    /*
     * Materialize expressions on both sides of the join condition. Check if both the sides
     * have the same return type, if not then inject casts so that comparison function will work as
     * expected
     */
    LogicalExpression[] leftExpr = new LogicalExpression[conditions.size()];
    LogicalExpression[] rightExpr = new LogicalExpression[conditions.size()];
    IterOutcome lastLeftStatus = status.getLeftStatus();
    IterOutcome lastRightStatus = status.getRightStatus();
    for (int i = 0; i < conditions.size(); i++) {
        JoinCondition condition = conditions.get(i);
        leftExpr[i] = materializeExpression(condition.getLeft(), lastLeftStatus, leftIterator, collector);
        rightExpr[i] = materializeExpression(condition.getRight(), lastRightStatus, rightIterator, collector);
    }
    // call to throw an exception. In this case we can safely skip adding the casts
    if (lastRightStatus != IterOutcome.NONE) {
        JoinUtils.addLeastRestrictiveCasts(leftExpr, leftIterator, rightExpr, rightIterator, context);
    }
    //generate doCompare() method
    /////////////////////////////////////////
    generateDoCompare(cg, incomingRecordBatch, leftExpr, incomingLeftRecordBatch, rightExpr, incomingRightRecordBatch, collector);
    // generate copyLeft()
    //////////////////////
    cg.setMappingSet(copyLeftMapping);
    int vectorId = 0;
    if (worker == null || !status.left.finished()) {
        for (VectorWrapper<?> vw : leftIterator) {
            MajorType inputType = vw.getField().getType();
            MajorType outputType;
            if (joinType == JoinRelType.RIGHT && inputType.getMode() == DataMode.REQUIRED) {
                outputType = Types.overrideMode(inputType, DataMode.OPTIONAL);
            } else {
                outputType = inputType;
            }
            // TODO (DRILL-4011): Factor out CopyUtil and use it here.
            JVar vvIn = cg.declareVectorValueSetupAndMember("incomingLeft", new TypedFieldId(inputType, vectorId));
            JVar vvOut = cg.declareVectorValueSetupAndMember("outgoing", new TypedFieldId(outputType, vectorId));
            // todo: check result of copyFromSafe and grow allocation
            cg.getEvalBlock().add(vvOut.invoke("copyFromSafe").arg(copyLeftMapping.getValueReadIndex()).arg(copyLeftMapping.getValueWriteIndex()).arg(vvIn));
            cg.rotateBlock();
            ++vectorId;
        }
    }
    // generate copyRight()
    ///////////////////////
    cg.setMappingSet(copyRightMappping);
    int rightVectorBase = vectorId;
    if (status.getRightStatus() != IterOutcome.NONE && (worker == null || !status.right.finished())) {
        for (VectorWrapper<?> vw : rightIterator) {
            MajorType inputType = vw.getField().getType();
            MajorType outputType;
            if (joinType == JoinRelType.LEFT && inputType.getMode() == DataMode.REQUIRED) {
                outputType = Types.overrideMode(inputType, DataMode.OPTIONAL);
            } else {
                outputType = inputType;
            }
            // TODO (DRILL-4011): Factor out CopyUtil and use it here.
            JVar vvIn = cg.declareVectorValueSetupAndMember("incomingRight", new TypedFieldId(inputType, vectorId - rightVectorBase));
            JVar vvOut = cg.declareVectorValueSetupAndMember("outgoing", new TypedFieldId(outputType, vectorId));
            // todo: check result of copyFromSafe and grow allocation
            cg.getEvalBlock().add(vvOut.invoke("copyFromSafe").arg(copyRightMappping.getValueReadIndex()).arg(copyRightMappping.getValueWriteIndex()).arg(vvIn));
            cg.rotateBlock();
            ++vectorId;
        }
    }
    JoinWorker w = context.getImplementationClass(cg);
    w.setupJoin(context, status, this.container);
    return w;
}
Also used : JClass(com.sun.codemodel.JClass) MajorType(org.apache.drill.common.types.TypeProtos.MajorType) ErrorCollector(org.apache.drill.common.expression.ErrorCollector) JoinCondition(org.apache.drill.common.logical.data.JoinCondition) ErrorCollectorImpl(org.apache.drill.common.expression.ErrorCollectorImpl) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) TypedFieldId(org.apache.drill.exec.record.TypedFieldId) JVar(com.sun.codemodel.JVar)

Example 13 with ErrorCollector

use of org.apache.drill.common.expression.ErrorCollector in project drill by apache.

the class OrderedPartitionRecordBatch method setupNewSchema.

/**
   * Sets up projection that will transfer all of the columns in batch, and also populate the partition column based on
   * which partition a record falls into in the partition table
   *
   * @param batch
   * @throws SchemaChangeException
   */
protected void setupNewSchema(VectorAccessible batch) throws SchemaChangeException {
    container.clear();
    final ErrorCollector collector = new ErrorCollectorImpl();
    final List<TransferPair> transfers = Lists.newArrayList();
    final ClassGenerator<OrderedPartitionProjector> cg = CodeGenerator.getRoot(OrderedPartitionProjector.TEMPLATE_DEFINITION, context.getFunctionRegistry(), context.getOptions());
    for (VectorWrapper<?> vw : batch) {
        TransferPair tp = vw.getValueVector().getTransferPair(oContext.getAllocator());
        transfers.add(tp);
        container.add(tp.getTo());
    }
    cg.setMappingSet(mainMapping);
    int count = 0;
    for (Ordering od : popConfig.getOrderings()) {
        final LogicalExpression expr = ExpressionTreeMaterializer.materialize(od.getExpr(), batch, collector, context.getFunctionRegistry());
        if (collector.hasErrors()) {
            throw new SchemaChangeException("Failure while materializing expression. " + collector.toErrorString());
        }
        cg.setMappingSet(incomingMapping);
        ClassGenerator.HoldingContainer left = cg.addExpr(expr, ClassGenerator.BlkCreateMode.FALSE);
        cg.setMappingSet(partitionMapping);
        ClassGenerator.HoldingContainer right = cg.addExpr(new ValueVectorReadExpression(new TypedFieldId(expr.getMajorType(), count++)), ClassGenerator.BlkCreateMode.FALSE);
        cg.setMappingSet(mainMapping);
        // next we wrap the two comparison sides and add the expression block for the comparison.
        LogicalExpression fh = FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right, context.getFunctionRegistry());
        ClassGenerator.HoldingContainer out = cg.addExpr(fh, ClassGenerator.BlkCreateMode.FALSE);
        JConditional jc = cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
        if (od.getDirection() == Direction.ASCENDING) {
            jc._then()._return(out.getValue());
        } else {
            jc._then()._return(out.getValue().minus());
        }
    }
    cg.getEvalBlock()._return(JExpr.lit(0));
    container.add(this.partitionKeyVector);
    container.buildSchema(batch.getSchema().getSelectionVectorMode());
    try {
        this.projector = context.getImplementationClass(cg);
        projector.setup(context, batch, this, transfers, partitionVectors, partitions, popConfig.getRef());
    } catch (ClassTransformationException | IOException e) {
        throw new SchemaChangeException("Failure while attempting to load generated class", e);
    }
}
Also used : TransferPair(org.apache.drill.exec.record.TransferPair) ClassTransformationException(org.apache.drill.exec.exception.ClassTransformationException) ErrorCollector(org.apache.drill.common.expression.ErrorCollector) IOException(java.io.IOException) ErrorCollectorImpl(org.apache.drill.common.expression.ErrorCollectorImpl) ValueVectorReadExpression(org.apache.drill.exec.expr.ValueVectorReadExpression) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) SchemaChangeException(org.apache.drill.exec.exception.SchemaChangeException) ClassGenerator(org.apache.drill.exec.expr.ClassGenerator) TypedFieldId(org.apache.drill.exec.record.TypedFieldId) Ordering(org.apache.drill.common.logical.data.Order.Ordering) HoldingContainer(org.apache.drill.exec.expr.ClassGenerator.HoldingContainer) JConditional(com.sun.codemodel.JConditional)

Example 14 with ErrorCollector

use of org.apache.drill.common.expression.ErrorCollector in project drill by apache.

the class SortBatch method createNewSorter.

public static Sorter createNewSorter(FragmentContext context, List<Ordering> orderings, VectorAccessible batch, MappingSet mainMapping, MappingSet leftMapping, MappingSet rightMapping) throws ClassTransformationException, IOException, SchemaChangeException {
    CodeGenerator<Sorter> cg = CodeGenerator.get(Sorter.TEMPLATE_DEFINITION, context.getFunctionRegistry(), context.getOptions());
    // This operator may be deprecated. No tests exercise it.
    // There is no way, at present, to verify if the generated code
    // works with Plain-old Java.
    //    cg.plainOldJavaCapable(true);
    // Uncomment out this line to debug the generated code.
    //    cg.saveCodeForDebugging(true);
    ClassGenerator<Sorter> g = cg.getRoot();
    g.setMappingSet(mainMapping);
    for (Ordering od : orderings) {
        // first, we rewrite the evaluation stack for each side of the comparison.
        ErrorCollector collector = new ErrorCollectorImpl();
        final LogicalExpression expr = ExpressionTreeMaterializer.materialize(od.getExpr(), batch, collector, context.getFunctionRegistry());
        if (collector.hasErrors()) {
            throw new SchemaChangeException("Failure while materializing expression. " + collector.toErrorString());
        }
        g.setMappingSet(leftMapping);
        HoldingContainer left = g.addExpr(expr, ClassGenerator.BlkCreateMode.FALSE);
        g.setMappingSet(rightMapping);
        HoldingContainer right = g.addExpr(expr, ClassGenerator.BlkCreateMode.FALSE);
        g.setMappingSet(mainMapping);
        // next we wrap the two comparison sides and add the expression block for the comparison.
        LogicalExpression fh = FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right, context.getFunctionRegistry());
        HoldingContainer out = g.addExpr(fh, ClassGenerator.BlkCreateMode.FALSE);
        JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
        if (od.getDirection() == Direction.ASCENDING) {
            jc._then()._return(out.getValue());
        } else {
            jc._then()._return(out.getValue().minus());
        }
    }
    g.getEvalBlock()._return(JExpr.lit(0));
    return context.getImplementationClass(cg);
}
Also used : ErrorCollectorImpl(org.apache.drill.common.expression.ErrorCollectorImpl) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) SchemaChangeException(org.apache.drill.exec.exception.SchemaChangeException) HoldingContainer(org.apache.drill.exec.expr.ClassGenerator.HoldingContainer) Ordering(org.apache.drill.common.logical.data.Order.Ordering) ErrorCollector(org.apache.drill.common.expression.ErrorCollector) JConditional(com.sun.codemodel.JConditional)

Example 15 with ErrorCollector

use of org.apache.drill.common.expression.ErrorCollector in project drill by apache.

the class MergingRecordBatch method generateComparisons.

private void generateComparisons(final ClassGenerator<?> g, final VectorAccessible batch) throws SchemaChangeException {
    g.setMappingSet(MAIN_MAPPING);
    for (final Ordering od : popConfig.getOrderings()) {
        // first, we rewrite the evaluation stack for each side of the comparison.
        final ErrorCollector collector = new ErrorCollectorImpl();
        final LogicalExpression expr = ExpressionTreeMaterializer.materialize(od.getExpr(), batch, collector, context.getFunctionRegistry());
        if (collector.hasErrors()) {
            throw new SchemaChangeException("Failure while materializing expression. " + collector.toErrorString());
        }
        g.setMappingSet(LEFT_MAPPING);
        final HoldingContainer left = g.addExpr(expr, ClassGenerator.BlkCreateMode.FALSE);
        g.setMappingSet(RIGHT_MAPPING);
        final HoldingContainer right = g.addExpr(expr, ClassGenerator.BlkCreateMode.FALSE);
        g.setMappingSet(MAIN_MAPPING);
        // next we wrap the two comparison sides and add the expression block for the comparison.
        final LogicalExpression fh = FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right, context.getFunctionRegistry());
        final HoldingContainer out = g.addExpr(fh, ClassGenerator.BlkCreateMode.FALSE);
        final JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
        if (od.getDirection() == Direction.ASCENDING) {
            jc._then()._return(out.getValue());
        } else {
            jc._then()._return(out.getValue().minus());
        }
    }
    g.getEvalBlock()._return(JExpr.lit(0));
}
Also used : ErrorCollectorImpl(org.apache.drill.common.expression.ErrorCollectorImpl) LogicalExpression(org.apache.drill.common.expression.LogicalExpression) SchemaChangeException(org.apache.drill.exec.exception.SchemaChangeException) HoldingContainer(org.apache.drill.exec.expr.ClassGenerator.HoldingContainer) Ordering(org.apache.drill.common.logical.data.Order.Ordering) ErrorCollector(org.apache.drill.common.expression.ErrorCollector) JConditional(com.sun.codemodel.JConditional)

Aggregations

ErrorCollector (org.apache.drill.common.expression.ErrorCollector)31 LogicalExpression (org.apache.drill.common.expression.LogicalExpression)31 ErrorCollectorImpl (org.apache.drill.common.expression.ErrorCollectorImpl)30 SchemaChangeException (org.apache.drill.exec.exception.SchemaChangeException)18 HoldingContainer (org.apache.drill.exec.expr.ClassGenerator.HoldingContainer)10 TypedFieldId (org.apache.drill.exec.record.TypedFieldId)10 Ordering (org.apache.drill.common.logical.data.Order.Ordering)9 MaterializedField (org.apache.drill.exec.record.MaterializedField)9 ValueVector (org.apache.drill.exec.vector.ValueVector)9 JConditional (com.sun.codemodel.JConditional)8 IOException (java.io.IOException)8 ClassTransformationException (org.apache.drill.exec.exception.ClassTransformationException)7 SchemaPath (org.apache.drill.common.expression.SchemaPath)6 ValueVectorWriteExpression (org.apache.drill.exec.expr.ValueVectorWriteExpression)6 TransferPair (org.apache.drill.exec.record.TransferPair)6 FieldReference (org.apache.drill.common.expression.FieldReference)5 NamedExpression (org.apache.drill.common.logical.data.NamedExpression)5 ExecTest (org.apache.drill.exec.ExecTest)4 NonStrictExpectations (mockit.NonStrictExpectations)3 IfExpression (org.apache.drill.common.expression.IfExpression)3