Search in sources :

Example 1 with DataSourceNode

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

the class PullPhysicalPlanBuilder method buildPullPhysicalPlan.

/**
 * Visits the logical plan top-down to build the physical plan.
 * @param logicalPlanNode the logical plan root node
 * @return the root node of the tree of physical operators
 */
// CHECKSTYLE_RULES.OFF: CyclomaticComplexity
public PullPhysicalPlan buildPullPhysicalPlan(final LogicalPlanNode logicalPlanNode) {
    // CHECKSTYLE_RULES.ON: CyclomaticComplexity
    DataSourceOperator dataSourceOperator = null;
    final OutputNode outputNode = logicalPlanNode.getNode().orElseThrow(() -> new IllegalArgumentException("Need an output node to build a plan"));
    if (!(outputNode instanceof KsqlBareOutputNode)) {
        throw new KsqlException("Pull queries expect the root of the logical plan to be a " + "KsqlBareOutputNode.");
    }
    // We skip KsqlBareOutputNode in the translation since it only applies the LIMIT
    PlanNode currentLogicalNode = outputNode.getSource();
    AbstractPhysicalOperator prevPhysicalOp = null;
    AbstractPhysicalOperator rootPhysicalOp = null;
    while (true) {
        AbstractPhysicalOperator currentPhysicalOp = null;
        if (currentLogicalNode instanceof QueryProjectNode) {
            currentPhysicalOp = translateProjectNode((QueryProjectNode) currentLogicalNode);
        } else if (currentLogicalNode instanceof QueryFilterNode) {
            currentPhysicalOp = translateFilterNode((QueryFilterNode) currentLogicalNode);
            seenSelectOperator = true;
        } else if (currentLogicalNode instanceof QueryLimitNode) {
            currentPhysicalOp = new LimitOperator((QueryLimitNode) currentLogicalNode);
        } else if (currentLogicalNode instanceof DataSourceNode) {
            currentPhysicalOp = translateDataSourceNode((DataSourceNode) currentLogicalNode);
            dataSourceOperator = (DataSourceOperator) currentPhysicalOp;
        } else {
            throw new KsqlException(String.format("Error in translating logical to physical plan for pull queries: unrecognized logical" + " node %s.", currentLogicalNode));
        }
        if (prevPhysicalOp == null) {
            rootPhysicalOp = currentPhysicalOp;
        } else {
            prevPhysicalOp.addChild(currentPhysicalOp);
        }
        prevPhysicalOp = currentPhysicalOp;
        // Exit the loop when a leaf node is reached
        if (currentLogicalNode.getSources().isEmpty()) {
            break;
        }
        if (currentLogicalNode.getSources().size() > 1) {
            throw new KsqlException("Pull queries do not support joins or nested sub-queries yet.");
        }
        currentLogicalNode = currentLogicalNode.getSources().get(0);
    }
    if (dataSourceOperator == null) {
        throw new IllegalStateException("DataSourceOperator cannot be null in Pull physical plan");
    }
    return new PullPhysicalPlan(rootPhysicalOp, (rootPhysicalOp).getLogicalNode().getSchema(), queryId, lookupConstraints, pullPhysicalPlanType, querySourceType, mat, dataSourceOperator);
}
Also used : KsqlBareOutputNode(io.confluent.ksql.planner.plan.KsqlBareOutputNode) OutputNode(io.confluent.ksql.planner.plan.OutputNode) DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) AbstractPhysicalOperator(io.confluent.ksql.physical.common.operators.AbstractPhysicalOperator) KsqlException(io.confluent.ksql.util.KsqlException) DataSourceOperator(io.confluent.ksql.physical.pull.operators.DataSourceOperator) QueryFilterNode(io.confluent.ksql.planner.plan.QueryFilterNode) QueryLimitNode(io.confluent.ksql.planner.plan.QueryLimitNode) QueryProjectNode(io.confluent.ksql.planner.plan.QueryProjectNode) KsqlBareOutputNode(io.confluent.ksql.planner.plan.KsqlBareOutputNode) PlanNode(io.confluent.ksql.planner.plan.PlanNode) LogicalPlanNode(io.confluent.ksql.planner.LogicalPlanNode) LimitOperator(io.confluent.ksql.physical.pull.operators.LimitOperator)

Example 2 with DataSourceNode

use of io.confluent.ksql.planner.plan.DataSourceNode 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 3 with DataSourceNode

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

the class LogicalPlanner method buildJoin.

/**
 * @param root    the root of the Join Tree
 * @param prefix  the prefix to uniquely identify the plan node
 * @return the PlanNode representing this Join Tree
 */
private JoinNode buildJoin(final Join root, final String prefix, final boolean isWindowed) {
    final PlanNode preRepartitionLeft;
    if (root.getLeft() instanceof JoinTree.Join) {
        preRepartitionLeft = buildJoin((Join) root.getLeft(), prefix + "L_", isWindowed);
    } else {
        final JoinTree.Leaf leaf = (Leaf) root.getLeft();
        preRepartitionLeft = new DataSourceNode(new PlanNodeId("KafkaTopic_" + prefix + "Left"), leaf.getSource().getDataSource(), leaf.getSource().getAlias(), isWindowed, ksqlConfig);
    }
    final PlanNode preRepartitionRight;
    if (root.getRight() instanceof JoinTree.Join) {
        preRepartitionRight = buildJoin((Join) root.getRight(), prefix + "R_", isWindowed);
    } else {
        final JoinTree.Leaf leaf = (Leaf) root.getRight();
        preRepartitionRight = new DataSourceNode(new PlanNodeId("KafkaTopic_" + prefix + "Right"), leaf.getSource().getDataSource(), leaf.getSource().getAlias(), isWindowed, ksqlConfig);
    }
    final Optional<Expression> fkExpression = verifyJoin(root.getInfo(), preRepartitionLeft, preRepartitionRight);
    final JoinKey joinKey = fkExpression.map(columnReferenceExp -> buildForeignJoinKey(root, fkExpression.get())).orElseGet(() -> buildJoinKey(root));
    final PlanNode left = prepareSourceForJoin(root.getLeft(), preRepartitionLeft, prefix + "Left", root.getInfo().getLeftJoinExpression(), fkExpression.isPresent());
    final PlanNode right = prepareSourceForJoin(root.getRight(), preRepartitionRight, prefix + "Right", root.getInfo().getRightJoinExpression(), fkExpression.isPresent());
    return new JoinNode(new PlanNodeId(prefix + "Join"), root.getInfo().getType(), joinKey.rewriteWith(refRewriter::process), prefix.isEmpty(), left, right, root.getInfo().getWithinExpression(), ksqlConfig.getString(KsqlConfig.KSQL_DEFAULT_KEY_FORMAT_CONFIG));
}
Also used : PlanNodeId(io.confluent.ksql.planner.plan.PlanNodeId) JoinInfo(io.confluent.ksql.analyzer.Analysis.JoinInfo) DataSource(io.confluent.ksql.metastore.model.DataSource) Leaf(io.confluent.ksql.planner.JoinTree.Leaf) AggregateAnalysisResult(io.confluent.ksql.analyzer.AggregateAnalysisResult) Into(io.confluent.ksql.analyzer.Analysis.Into) ColumnName(io.confluent.ksql.name.ColumnName) SourceName(io.confluent.ksql.name.SourceName) BiFunction(java.util.function.BiFunction) AggregateAnalyzer(io.confluent.ksql.analyzer.AggregateAnalyzer) FilterNode(io.confluent.ksql.planner.plan.FilterNode) SerdeFeaturesFactory(io.confluent.ksql.serde.SerdeFeaturesFactory) JoinKey(io.confluent.ksql.planner.plan.JoinNode.JoinKey) CodeGenRunner(io.confluent.ksql.execution.codegen.CodeGenRunner) WindowInfo(io.confluent.ksql.serde.WindowInfo) RewrittenAnalysis(io.confluent.ksql.analyzer.RewrittenAnalysis) QueryLimitNode(io.confluent.ksql.planner.plan.QueryLimitNode) AggregateNode(io.confluent.ksql.planner.plan.AggregateNode) AliasedDataSource(io.confluent.ksql.analyzer.Analysis.AliasedDataSource) TimestampExtractionPolicyFactory(io.confluent.ksql.execution.streams.timestamp.TimestampExtractionPolicyFactory) ExpressionTypeManager(io.confluent.ksql.execution.util.ExpressionTypeManager) KsqlBareOutputNode(io.confluent.ksql.planner.plan.KsqlBareOutputNode) SelectionUtil(io.confluent.ksql.planner.plan.SelectionUtil) PartitionBy(io.confluent.ksql.parser.tree.PartitionBy) ColumnReferenceExp(io.confluent.ksql.execution.expression.tree.ColumnReferenceExp) PreJoinProjectNode(io.confluent.ksql.planner.plan.PreJoinProjectNode) VisitParentExpressionVisitor(io.confluent.ksql.execution.expression.tree.VisitParentExpressionVisitor) FinalProjectNode(io.confluent.ksql.planner.plan.FinalProjectNode) ColumnNames(io.confluent.ksql.schema.ksql.ColumnNames) RefinementInfo(io.confluent.ksql.serde.RefinementInfo) ImmutableAnalysis(io.confluent.ksql.analyzer.ImmutableAnalysis) ExpressionEvaluator(io.confluent.ksql.execution.transform.ExpressionEvaluator) Expression(io.confluent.ksql.execution.expression.tree.Expression) JoinType(io.confluent.ksql.planner.plan.JoinNode.JoinType) Set(java.util.Set) QueryFilterNode(io.confluent.ksql.planner.plan.QueryFilterNode) KsqlConfig(io.confluent.ksql.util.KsqlConfig) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) Collectors(java.util.stream.Collectors) TimestampColumn(io.confluent.ksql.execution.timestamp.TimestampColumn) PlanNodeId(io.confluent.ksql.planner.plan.PlanNodeId) SingleSourcePlanNode(io.confluent.ksql.planner.plan.SingleSourcePlanNode) Builder(io.confluent.ksql.schema.ksql.LogicalSchema.Builder) Objects(java.util.Objects) Join(io.confluent.ksql.planner.JoinTree.Join) List(java.util.List) KsqlException(io.confluent.ksql.util.KsqlException) Optional(java.util.Optional) QueryProjectNode(io.confluent.ksql.planner.plan.QueryProjectNode) Column(io.confluent.ksql.schema.ksql.Column) FormatInfo(io.confluent.ksql.serde.FormatInfo) ProjectNode(io.confluent.ksql.planner.plan.ProjectNode) Iterables(com.google.common.collect.Iterables) FormatFactory(io.confluent.ksql.serde.FormatFactory) GrammaticalJoiner(io.confluent.ksql.util.GrammaticalJoiner) KeyFormat(io.confluent.ksql.serde.KeyFormat) JoinNode(io.confluent.ksql.planner.plan.JoinNode) SuppressNode(io.confluent.ksql.planner.plan.SuppressNode) UnqualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp) PartitionByParamsFactory(io.confluent.ksql.execution.streams.PartitionByParamsFactory) DataSourceType(io.confluent.ksql.metastore.model.DataSource.DataSourceType) Function(java.util.function.Function) NoneFormat(io.confluent.ksql.serde.none.NoneFormat) AsValue(io.confluent.ksql.function.udf.AsValue) QualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.QualifiedColumnReferenceExp) MetaStore(io.confluent.ksql.metastore.MetaStore) GroupBy(io.confluent.ksql.parser.tree.GroupBy) KsqlStructuredDataOutputNode(io.confluent.ksql.planner.plan.KsqlStructuredDataOutputNode) UserRepartitionNode(io.confluent.ksql.planner.plan.UserRepartitionNode) WindowExpression(io.confluent.ksql.parser.tree.WindowExpression) SqlType(io.confluent.ksql.schema.ksql.types.SqlType) SerdeFeatures(io.confluent.ksql.serde.SerdeFeatures) DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) NewTopic(io.confluent.ksql.analyzer.Analysis.Into.NewTopic) KsqlWindowExpression(io.confluent.ksql.execution.windows.KsqlWindowExpression) OutputNode(io.confluent.ksql.planner.plan.OutputNode) FilterTypeValidator(io.confluent.ksql.analyzer.FilterTypeValidator) FlatMapNode(io.confluent.ksql.planner.plan.FlatMapNode) ValueFormat(io.confluent.ksql.serde.ValueFormat) SelectExpression(io.confluent.ksql.execution.plan.SelectExpression) NodeLocation(io.confluent.ksql.parser.NodeLocation) PreJoinRepartitionNode(io.confluent.ksql.planner.plan.PreJoinRepartitionNode) FunctionCall(io.confluent.ksql.execution.expression.tree.FunctionCall) KsqlTopic(io.confluent.ksql.execution.ddl.commands.KsqlTopic) PlanNode(io.confluent.ksql.planner.plan.PlanNode) Context(io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter.Context) ExpressionTreeRewriter(io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter) OutputRefinement(io.confluent.ksql.parser.OutputRefinement) FilterType(io.confluent.ksql.analyzer.FilterTypeValidator.FilterType) Collections(java.util.Collections) DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) SingleSourcePlanNode(io.confluent.ksql.planner.plan.SingleSourcePlanNode) PlanNode(io.confluent.ksql.planner.plan.PlanNode) JoinKey(io.confluent.ksql.planner.plan.JoinNode.JoinKey) 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) JoinNode(io.confluent.ksql.planner.plan.JoinNode) Join(io.confluent.ksql.planner.JoinTree.Join) Leaf(io.confluent.ksql.planner.JoinTree.Leaf) Leaf(io.confluent.ksql.planner.JoinTree.Leaf)

Example 4 with DataSourceNode

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

the class LogicalPlannerTest method shouldCreatePlanWithTableAsSource.

@Test
public void shouldCreatePlanWithTableAsSource() {
    final PlanNode planNode = buildLogicalPlan("select col0 from TEST2 EMIT CHANGES limit 5;");
    assertThat(planNode.getSources().size(), equalTo(1));
    final DataSource dataSource = ((DataSourceNode) planNode.getSources().get(0).getSources().get(0).getSources().get(0)).getDataSource();
    assertThat(dataSource.getDataSourceType(), equalTo(DataSourceType.KTABLE));
    assertThat(dataSource.getName(), equalTo(SourceName.of("TEST2")));
}
Also used : DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) PlanNode(io.confluent.ksql.planner.plan.PlanNode) DataSource(io.confluent.ksql.metastore.model.DataSource) Test(org.junit.Test)

Example 5 with DataSourceNode

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

the class LogicalPlannerTest method testLimitStreamPullQueryLogicalPlan.

@Test
public void testLimitStreamPullQueryLogicalPlan() {
    final String simpleQuery = "SELECT * FROM test1 LIMIT 3;";
    final PlanNode logicalPlan = buildLogicalPlan(simpleQuery);
    assertThat(logicalPlan, instanceOf(KsqlBareOutputNode.class));
    assertThat(logicalPlan.getNodeOutputType(), equalTo(DataSourceType.KSTREAM));
    final PlanNode finalProjectNode = logicalPlan.getSources().get(0);
    assertThat(finalProjectNode, instanceOf(FinalProjectNode.class));
    assertThat(finalProjectNode.getNodeOutputType(), equalTo(DataSourceType.KSTREAM));
    final PlanNode queryLimitNode = finalProjectNode.getSources().get(0);
    assertThat(queryLimitNode, instanceOf(QueryLimitNode.class));
    assertThat(((QueryLimitNode) queryLimitNode).getLimit(), equalTo(3));
    assertThat(queryLimitNode.getNodeOutputType(), equalTo(DataSourceType.KSTREAM));
    final PlanNode dataSourceNode = queryLimitNode.getSources().get(0);
    assertThat(dataSourceNode, instanceOf(DataSourceNode.class));
    assertThat(dataSourceNode.getNodeOutputType(), equalTo(DataSourceType.KSTREAM));
}
Also used : DataSourceNode(io.confluent.ksql.planner.plan.DataSourceNode) PlanNode(io.confluent.ksql.planner.plan.PlanNode) KsqlBareOutputNode(io.confluent.ksql.planner.plan.KsqlBareOutputNode) FinalProjectNode(io.confluent.ksql.planner.plan.FinalProjectNode) Matchers.containsString(org.hamcrest.Matchers.containsString) QueryLimitNode(io.confluent.ksql.planner.plan.QueryLimitNode) Test(org.junit.Test)

Aggregations

DataSourceNode (io.confluent.ksql.planner.plan.DataSourceNode)8 PlanNode (io.confluent.ksql.planner.plan.PlanNode)7 KsqlBareOutputNode (io.confluent.ksql.planner.plan.KsqlBareOutputNode)6 QueryLimitNode (io.confluent.ksql.planner.plan.QueryLimitNode)5 KsqlException (io.confluent.ksql.util.KsqlException)5 OutputNode (io.confluent.ksql.planner.plan.OutputNode)4 QueryFilterNode (io.confluent.ksql.planner.plan.QueryFilterNode)4 QueryProjectNode (io.confluent.ksql.planner.plan.QueryProjectNode)4 Context (io.confluent.ksql.engine.rewrite.ExpressionTreeRewriter.Context)3 CodeGenRunner (io.confluent.ksql.execution.codegen.CodeGenRunner)3 Expression (io.confluent.ksql.execution.expression.tree.Expression)3 QualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.QualifiedColumnReferenceExp)3 UnqualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp)3 VisitParentExpressionVisitor (io.confluent.ksql.execution.expression.tree.VisitParentExpressionVisitor)3 SelectExpression (io.confluent.ksql.execution.plan.SelectExpression)3 ExpressionEvaluator (io.confluent.ksql.execution.transform.ExpressionEvaluator)3 KsqlWindowExpression (io.confluent.ksql.execution.windows.KsqlWindowExpression)3 FinalProjectNode (io.confluent.ksql.planner.plan.FinalProjectNode)3 Test (org.junit.Test)3 Iterables (com.google.common.collect.Iterables)2