Search in sources :

Example 1 with ExpressionEvaluator

use of io.confluent.ksql.execution.transform.ExpressionEvaluator in project ksql by confluentinc.

the class LogicalPlanner method verifyForeignKeyJoin.

private Optional<Expression> verifyForeignKeyJoin(final JoinInfo joinInfo, final PlanNode leftNode, final PlanNode rightNode) {
    final JoinType joinType = joinInfo.getType();
    final Expression leftExpression = joinInfo.getLeftJoinExpression();
    final Expression rightExpression = joinInfo.getRightJoinExpression();
    if (joinInfo.getType().equals(JoinType.OUTER)) {
        throw new KsqlException(String.format("Invalid join type:" + " full-outer join not supported for foreign-key table-table join." + " Got %s %s %s.", joinInfo.getLeftSource().getDataSource().getName().text(), joinType, joinInfo.getRightSource().getDataSource().getName().text()));
    }
    // because a FK-join output table has the same PK as its left input table
    if (!(leftNode instanceof DataSourceNode) || !(rightNode instanceof DataSourceNode)) {
        throw new KsqlException(String.format("Invalid join condition:" + " foreign-key table-table joins are not supported as part of n-way joins." + " Got %s = %s.", joinInfo.getFlippedLeftJoinExpression(), joinInfo.getFlippedRightJoinExpression()));
    }
    final CodeGenRunner codeGenRunner = new CodeGenRunner(leftNode.getSchema(), ksqlConfig, metaStore);
    final VisitParentExpressionVisitor<Optional<Expression>, Context<Void>> unqualifiedRewritter = new VisitParentExpressionVisitor<Optional<Expression>, Context<Void>>(Optional.empty()) {

        @Override
        public Optional<Expression> visitQualifiedColumnReference(final QualifiedColumnReferenceExp node, final Context<Void> ctx) {
            return Optional.of(new UnqualifiedColumnReferenceExp(node.getColumnName()));
        }
    };
    final Expression leftExpressionUnqualified = ExpressionTreeRewriter.rewriteWith(unqualifiedRewritter::process, leftExpression);
    final ExpressionEvaluator expressionEvaluator = codeGenRunner.buildCodeGenFromParseTree(leftExpressionUnqualified, "Left Join Expression");
    final SqlType fkType = expressionEvaluator.getExpressionType();
    final SqlType rightKeyType = Iterables.getOnlyElement(rightNode.getSchema().key()).type();
    verifyJoinConditionTypes(fkType, rightKeyType, leftExpression, rightExpression, joinInfo.hasFlippedJoinCondition());
    if (((DataSourceNode) rightNode).isWindowed()) {
        throw new KsqlException("Foreign-key table-table joins are not supported on windowed tables.");
    }
    return Optional.of(leftExpression);
}
Also used : Context(io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter.Context) DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) CodeGenRunner(io.confluent.ksql.execution.codegen.CodeGenRunner) Optional(java.util.Optional) QualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.QualifiedColumnReferenceExp) JoinType(io.confluent.ksql.planner.plan.JoinNode.JoinType) KsqlException(io.confluent.ksql.util.KsqlException) VisitParentExpressionVisitor(io.confluent.ksql.execution.expression.tree.VisitParentExpressionVisitor) UnqualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp) ExpressionEvaluator(io.confluent.ksql.execution.transform.ExpressionEvaluator) Expression(io.confluent.ksql.execution.expression.tree.Expression) WindowExpression(io.confluent.ksql.parser.tree.WindowExpression) KsqlWindowExpression(io.confluent.ksql.execution.windows.KsqlWindowExpression) SelectExpression(io.confluent.ksql.execution.plan.SelectExpression) SqlType(io.confluent.ksql.schema.ksql.types.SqlType)

Example 2 with ExpressionEvaluator

use of io.confluent.ksql.execution.transform.ExpressionEvaluator in project ksql by confluentinc.

the class ExpressionEvaluatorParityTest method runEvaluator.

private void runEvaluator(final GenericRow row, Callable<ExpressionEvaluator> compile, final Object expectedResult, final Optional<EvaluatorError> error) throws Exception {
    ExpressionEvaluator expressionEvaluator = null;
    try {
        expressionEvaluator = compile.call();
    } catch (Exception e) {
        if (error.isPresent() && error.get().getErrorTime() == ErrorTime.COMPILE_TIME) {
            assertThat(e.getMessage(), containsString(error.get().getMessage()));
            return;
        } else {
            throw e;
        }
    }
    Object result = null;
    try {
        result = expressionEvaluator.evaluate(row, null, processingLogger, () -> "ERROR!!!");
    } catch (Exception e) {
        if (error.isPresent() && error.get().getErrorTime() == ErrorTime.EVALUATION_TIME) {
            assertThat(e.getMessage(), containsString(error.get().getMessage()));
            return;
        } else {
            throw e;
        }
    }
    if (error.isPresent() && error.get().getErrorTime() == ErrorTime.EVALUATION_LOGGER) {
        verify(processingLogger, times(1)).error(errorMessageCaptor.capture());
        RecordProcessingError processingError = ((RecordProcessingError) errorMessageCaptor.getValue());
        if (error.get().getMessage() == null) {
            assertThat(processingError.getException().get().getMessage(), nullValue());
        } else {
            assertThat(processingError.getException().get().getMessage(), containsString(error.get().getMessage()));
        }
    } else {
        verify(processingLogger, never()).error(any());
    }
    reset(processingLogger);
    assertThat(result, is(expectedResult));
}
Also used : RecordProcessingError(io.confluent.ksql.logging.processing.RecordProcessingError) ExpressionEvaluator(io.confluent.ksql.execution.transform.ExpressionEvaluator)

Example 3 with ExpressionEvaluator

use of io.confluent.ksql.execution.transform.ExpressionEvaluator in project ksql by confluentinc.

the class ForeignKeyTableTableJoinBuilder method build.

public static <KLeftT, KRightT> KTableHolder<KLeftT> build(final KTableHolder<KLeftT> left, final KTableHolder<KRightT> right, final ForeignKeyTableTableJoin<KLeftT, KRightT> join, final RuntimeBuildContext buildContext) {
    final LogicalSchema leftSchema = left.getSchema();
    final LogicalSchema rightSchema = right.getSchema();
    final ProcessingLogger logger = buildContext.getProcessingLogger(join.getProperties().getQueryContext());
    final ExpressionEvaluator expressionEvaluator;
    final CodeGenRunner codeGenRunner = new CodeGenRunner(leftSchema, buildContext.getKsqlConfig(), buildContext.getFunctionRegistry());
    final Optional<ColumnName> leftColumnName = join.getLeftJoinColumnName();
    final Optional<Expression> leftJoinExpression = join.getLeftJoinExpression();
    if (leftColumnName.isPresent()) {
        expressionEvaluator = codeGenRunner.buildCodeGenFromParseTree(new UnqualifiedColumnReferenceExp(leftColumnName.get()), "Left Join Expression");
    } else if (leftJoinExpression.isPresent()) {
        expressionEvaluator = codeGenRunner.buildCodeGenFromParseTree(leftJoinExpression.get(), "Left Join Expression");
    } else {
        throw new IllegalStateException("Both leftColumnName and leftJoinExpression are empty.");
    }
    final ForeignKeyJoinParams<KRightT> joinParams = ForeignKeyJoinParamsFactory.create(expressionEvaluator, leftSchema, rightSchema, logger);
    final Formats formats = join.getFormats();
    final PhysicalSchema physicalSchema = PhysicalSchema.from(joinParams.getSchema(), formats.getKeyFeatures(), formats.getValueFeatures());
    final Serde<KLeftT> keySerde = left.getExecutionKeyFactory().buildKeySerde(formats.getKeyFormat(), physicalSchema, join.getProperties().getQueryContext());
    final Serde<GenericRow> valSerde = buildContext.buildValueSerde(formats.getValueFormat(), physicalSchema, join.getProperties().getQueryContext());
    final KTable<KLeftT, GenericRow> result;
    switch(join.getJoinType()) {
        case INNER:
            result = left.getTable().join(right.getTable(), joinParams.getKeyExtractor(), joinParams.getJoiner(), Materialized.with(keySerde, valSerde));
            break;
        case LEFT:
            result = left.getTable().leftJoin(right.getTable(), joinParams.getKeyExtractor(), joinParams.getJoiner(), Materialized.with(keySerde, valSerde));
            break;
        default:
            throw new IllegalStateException("invalid join type: " + join.getJoinType());
    }
    return KTableHolder.unmaterialized(result, joinParams.getSchema(), left.getExecutionKeyFactory());
}
Also used : ProcessingLogger(io.confluent.ksql.logging.processing.ProcessingLogger) CodeGenRunner(io.confluent.ksql.execution.codegen.CodeGenRunner) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) Formats(io.confluent.ksql.execution.plan.Formats) ExpressionEvaluator(io.confluent.ksql.execution.transform.ExpressionEvaluator) UnqualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp) GenericRow(io.confluent.ksql.GenericRow) ColumnName(io.confluent.ksql.name.ColumnName) PhysicalSchema(io.confluent.ksql.schema.ksql.PhysicalSchema) Expression(io.confluent.ksql.execution.expression.tree.Expression)

Aggregations

ExpressionEvaluator (io.confluent.ksql.execution.transform.ExpressionEvaluator)3 CodeGenRunner (io.confluent.ksql.execution.codegen.CodeGenRunner)2 Expression (io.confluent.ksql.execution.expression.tree.Expression)2 UnqualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp)2 GenericRow (io.confluent.ksql.GenericRow)1 Context (io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter.Context)1 QualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.QualifiedColumnReferenceExp)1 VisitParentExpressionVisitor (io.confluent.ksql.execution.expression.tree.VisitParentExpressionVisitor)1 Formats (io.confluent.ksql.execution.plan.Formats)1 SelectExpression (io.confluent.ksql.execution.plan.SelectExpression)1 KsqlWindowExpression (io.confluent.ksql.execution.windows.KsqlWindowExpression)1 ProcessingLogger (io.confluent.ksql.logging.processing.ProcessingLogger)1 RecordProcessingError (io.confluent.ksql.logging.processing.RecordProcessingError)1 ColumnName (io.confluent.ksql.name.ColumnName)1 WindowExpression (io.confluent.ksql.parser.tree.WindowExpression)1 DataSourceNode (io.confluent.ksql.planner.plan.DataSourceNode)1 JoinType (io.confluent.ksql.planner.plan.JoinNode.JoinType)1 LogicalSchema (io.confluent.ksql.schema.ksql.LogicalSchema)1 PhysicalSchema (io.confluent.ksql.schema.ksql.PhysicalSchema)1 SqlType (io.confluent.ksql.schema.ksql.types.SqlType)1