Search in sources :

Example 1 with JoinType

use of io.confluent.ksql.planner.plan.JoinNode.JoinType 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 JoinType

use of io.confluent.ksql.planner.plan.JoinNode.JoinType in project ksql by confluentinc.

the class LogicalPlanner method verifyJoin.

/**
 * @return the foreign key column if this is a foreign key join
 */
private Optional<Expression> verifyJoin(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 (leftNode.getNodeOutputType() == DataSourceType.KSTREAM) {
        if (rightNode.getNodeOutputType() == DataSourceType.KTABLE) {
            verifyStreamTableJoin(joinInfo, rightNode);
        }
    // stream-stream join detected: nothing to verify
    } else {
        if (rightNode.getNodeOutputType() == DataSourceType.KSTREAM) {
            throw new KsqlException(String.format("Invalid join order:" + " table-stream joins are not supported; only stream-table joins. Got %s %s %s.", joinInfo.getLeftSource().getDataSource().getName().text(), joinType, joinInfo.getRightSource().getDataSource().getName().text()));
        }
        if (joinOnNonKeyAttribute(rightExpression, rightNode, joinInfo.getRightSource())) {
            throw new KsqlException(String.format("Invalid join condition:" + " table-table joins require to join on the primary key of the right input" + " table. Got %s = %s.", joinInfo.getFlippedLeftJoinExpression(), joinInfo.getFlippedRightJoinExpression()));
        }
        if (joinOnNonKeyAttribute(leftExpression, leftNode, joinInfo.getLeftSource())) {
            return verifyForeignKeyJoin(joinInfo, leftNode, rightNode);
        } else {
            // primary key join detected
            final SqlType leftKeyType = Iterables.getOnlyElement(leftNode.getSchema().key()).type();
            final SqlType rightKeyType = Iterables.getOnlyElement(rightNode.getSchema().key()).type();
            verifyJoinConditionTypes(leftKeyType, rightKeyType, leftExpression, rightExpression, joinInfo.hasFlippedJoinCondition());
        }
    }
    return Optional.empty();
}
Also used : 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) JoinType(io.confluent.ksql.planner.plan.JoinNode.JoinType) SqlType(io.confluent.ksql.schema.ksql.types.SqlType) KsqlException(io.confluent.ksql.util.KsqlException)

Example 3 with JoinType

use of io.confluent.ksql.planner.plan.JoinNode.JoinType in project ksql by confluentinc.

the class LogicalPlanner method verifyStreamTableJoin.

private static void verifyStreamTableJoin(final JoinInfo joinInfo, final PlanNode rightNode) {
    final JoinType joinType = joinInfo.getType();
    final Expression rightExpression = joinInfo.getRightJoinExpression();
    if (joinType.equals(JoinType.OUTER)) {
        throw new KsqlException(String.format("Invalid join type: " + "full-outer join not supported for stream-table join. Got %s %s %s.", joinInfo.getLeftSource().getDataSource().getName().text(), joinType, joinInfo.getRightSource().getDataSource().getName().text()));
    }
    if (joinOnNonKeyAttribute(rightExpression, rightNode, joinInfo.getRightSource())) {
        throw new KsqlException(String.format("Invalid join condition:" + " stream-table joins require to join on the table's primary key." + " Got %s = %s.", joinInfo.getFlippedLeftJoinExpression(), joinInfo.getFlippedRightJoinExpression()));
    }
}
Also used : 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) JoinType(io.confluent.ksql.planner.plan.JoinNode.JoinType) KsqlException(io.confluent.ksql.util.KsqlException)

Aggregations

Expression (io.confluent.ksql.execution.expression.tree.Expression)3 SelectExpression (io.confluent.ksql.execution.plan.SelectExpression)3 KsqlWindowExpression (io.confluent.ksql.execution.windows.KsqlWindowExpression)3 WindowExpression (io.confluent.ksql.parser.tree.WindowExpression)3 JoinType (io.confluent.ksql.planner.plan.JoinNode.JoinType)3 KsqlException (io.confluent.ksql.util.KsqlException)3 SqlType (io.confluent.ksql.schema.ksql.types.SqlType)2 Context (io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter.Context)1 CodeGenRunner (io.confluent.ksql.execution.codegen.CodeGenRunner)1 QualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.QualifiedColumnReferenceExp)1 UnqualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp)1 VisitParentExpressionVisitor (io.confluent.ksql.execution.expression.tree.VisitParentExpressionVisitor)1 ExpressionEvaluator (io.confluent.ksql.execution.transform.ExpressionEvaluator)1 DataSourceNode (io.confluent.ksql.planner.plan.DataSourceNode)1 Optional (java.util.Optional)1