use of io.confluent.ksql.analyzer.Analysis.Into in project ksql by confluentinc.
the class LogicalPlanner method buildOutputNode.
private OutputNode buildOutputNode(final PlanNode sourcePlanNode) {
final LogicalSchema inputSchema = sourcePlanNode.getSchema();
final Optional<TimestampColumn> timestampColumn = getTimestampColumn(inputSchema, analysis);
if (!analysis.getInto().isPresent()) {
return new KsqlBareOutputNode(new PlanNodeId("KSQL_STDOUT_NAME"), sourcePlanNode, inputSchema, analysis.getLimitClause(), timestampColumn, getWindowInfo());
}
final Into into = analysis.getInto().get();
final KsqlTopic existingTopic = getSinkTopic(into, sourcePlanNode.getSchema());
return new KsqlStructuredDataOutputNode(new PlanNodeId(into.getName().text()), sourcePlanNode, inputSchema, timestampColumn, existingTopic, analysis.getLimitClause(), into.isCreate(), into.getName(), analysis.getOrReplace());
}
use of io.confluent.ksql.analyzer.Analysis.Into in project ksql by confluentinc.
the class LogicalPlanner method buildAggregateSchema.
private LogicalSchema buildAggregateSchema(final PlanNode sourcePlanNode, final GroupBy groupBy, final List<SelectExpression> projectionExpressions) {
final LogicalSchema sourceSchema = sourcePlanNode.getSchema();
final LogicalSchema projectionSchema = SelectionUtil.buildProjectionSchema(sourceSchema.withPseudoAndKeyColsInValue(analysis.getWindowExpression().isPresent(), ksqlConfig), projectionExpressions, metaStore);
final List<Expression> groupByExps = groupBy.getGroupingExpressions();
final Function<Expression, Optional<ColumnName>> selectResolver = expression -> {
final List<ColumnName> foundInProjection = projectionExpressions.stream().filter(e -> e.getExpression().equals(expression)).map(SelectExpression::getAlias).collect(Collectors.toList());
switch(foundInProjection.size()) {
case 0:
return Optional.empty();
case 1:
return Optional.of(foundInProjection.get(0));
default:
final String keys = GrammaticalJoiner.and().join(foundInProjection);
throw new KsqlException("The projection contains a key column more than once: " + keys + "." + System.lineSeparator() + "Each key column must only be in the projection once. " + "If you intended to copy the key into the value, then consider using the " + AsValue.NAME + " function to indicate which key reference should be copied.");
}
};
final List<Column> valueColumns;
if (analysis.getInto().isPresent()) {
// Persistent query:
final Set<ColumnName> keyColumnNames = groupBy.getGroupingExpressions().stream().map(selectResolver).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toSet());
valueColumns = projectionSchema.value().stream().filter(col -> !keyColumnNames.contains(col.name())).collect(Collectors.toList());
if (valueColumns.isEmpty()) {
throw new KsqlException("The projection contains no value columns.");
}
} else {
// Transient query:
// Transient queries only return value columns, so must have key columns in the value:
valueColumns = projectionSchema.columns();
}
final Builder builder = LogicalSchema.builder();
final ExpressionTypeManager typeManager = new ExpressionTypeManager(sourceSchema, metaStore);
for (final Expression expression : groupByExps) {
final SqlType keyType = typeManager.getExpressionSqlType(expression);
final ColumnName keyName = selectResolver.apply(expression).orElseGet(() -> expression instanceof ColumnReferenceExp ? ((ColumnReferenceExp) expression).getColumnName() : ColumnNames.uniqueAliasFor(expression, sourceSchema));
builder.keyColumn(keyName, keyType);
}
return builder.valueColumns(valueColumns).build();
}
Aggregations