use of io.confluent.ksql.name.ColumnName in project ksql by confluentinc.
the class AggregateExpressionRewriter method visitFunctionCall.
@Override
public Optional<Expression> visitFunctionCall(final FunctionCall node, final ExpressionTreeRewriter.Context<Void> context) {
final FunctionName functionName = node.getName();
if (functionRegistry.isAggregate(functionName)) {
final ColumnName aggVarName = ColumnNames.aggregateColumn(aggVariableIndex);
aggVariableIndex++;
return Optional.of(new UnqualifiedColumnReferenceExp(node.getLocation(), aggVarName));
} else {
final List<Expression> arguments = new ArrayList<>();
for (final Expression argExpression : node.getArguments()) {
arguments.add(context.process(argExpression));
}
return Optional.of(new FunctionCall(node.getLocation(), node.getName(), arguments));
}
}
use of io.confluent.ksql.name.ColumnName in project ksql by confluentinc.
the class FinalProjectNode method build.
private Pair<LogicalSchema, List<SelectExpression>> build(final MetaStore metaStore, final KsqlConfig ksqlConfig) {
final LogicalSchema parentSchema = getSource().getSchema();
final Optional<LogicalSchema> targetSchema = getTargetSchema(metaStore);
final List<SelectExpression> selectExpressions = SelectionUtil.buildSelectExpressions(getSource(), projection.selectItems(), targetSchema);
final LogicalSchema schema = SelectionUtil.buildProjectionSchema(parentSchema, selectExpressions, metaStore);
if (into.isPresent()) {
// Persistent queries have key columns as value columns - final projection can exclude them:
final Map<ColumnName, Set<ColumnName>> seenKeyColumns = new HashMap<>();
selectExpressions.removeIf(se -> {
if (se.getExpression() instanceof UnqualifiedColumnReferenceExp) {
final ColumnName columnName = ((UnqualifiedColumnReferenceExp) se.getExpression()).getColumnName();
// Window bounds columns are currently removed if not aliased:
if (SystemColumns.isWindowBound(columnName) && se.getAlias().equals(columnName)) {
return true;
}
if (parentSchema.isKeyColumn(columnName)) {
seenKeyColumns.computeIfAbsent(columnName, k -> new HashSet<>()).add(se.getAlias());
return true;
}
}
return false;
});
for (final Entry<ColumnName, Set<ColumnName>> seenKey : seenKeyColumns.entrySet()) {
if (seenKey.getValue().size() > 1) {
final String keys = GrammaticalJoiner.and().join(seenKey.getValue().stream().map(Name::text).sorted());
throw new KsqlException("The projection contains a key column (" + seenKey.getKey() + ") more than once, aliased as: " + 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 LogicalSchema nodeSchema;
if (into.isPresent()) {
nodeSchema = schema.withoutPseudoAndKeyColsInValue(ksqlConfig);
} else {
// Transient queries return key columns in the value, so the projection includes them, and
// the schema needs to include them too:
final Builder builder = LogicalSchema.builder();
builder.keyColumns(parentSchema.key());
schema.columns().forEach(builder::valueColumn);
nodeSchema = builder.build();
}
return Pair.of(nodeSchema, selectExpressions);
}
use of io.confluent.ksql.name.ColumnName in project ksql by confluentinc.
the class LogicalPlanner method getTimestampColumn.
private Optional<TimestampColumn> getTimestampColumn(final LogicalSchema inputSchema, final ImmutableAnalysis analysis) {
final Optional<ColumnName> timestampColumnName = analysis.getProperties().getTimestampColumnName();
final Optional<TimestampColumn> timestampColumn = timestampColumnName.map(n -> new TimestampColumn(n, analysis.getProperties().getTimestampFormat()));
TimestampExtractionPolicyFactory.validateTimestampColumn(ksqlConfig, inputSchema, timestampColumn);
return timestampColumn;
}
use of io.confluent.ksql.name.ColumnName in project ksql by confluentinc.
the class QueryFilterNode method validateWhereClauseAndCheckTableScan.
private boolean validateWhereClauseAndCheckTableScan() {
for (Expression disjunct : disjuncts) {
final Validator validator = new Validator();
validator.process(disjunct, null);
if (validator.requiresTableScan) {
return true;
}
if (!validator.isKeyedQuery) {
if (queryPlannerOptions.getTableScansEnabled()) {
return true;
} else {
throw invalidWhereClauseException("WHERE clause missing key column for disjunct: " + disjunct.toString(), isWindowed);
}
}
if (!validator.seenKeys.isEmpty() && validator.seenKeys.cardinality() != schema.key().size()) {
if (queryPlannerOptions.getTableScansEnabled()) {
return true;
} else {
final List<ColumnName> seenKeyNames = validator.seenKeys.stream().boxed().map(i -> schema.key().get(i)).map(Column::name).collect(Collectors.toList());
throw invalidWhereClauseException("Multi-column sources must specify every key in the WHERE clause. Specified: " + seenKeyNames + " Expected: " + schema.key(), isWindowed);
}
}
}
return false;
}
use of io.confluent.ksql.name.ColumnName in project ksql by confluentinc.
the class SelectionUtil method resolveSingleColumn.
private static Stream<SelectExpression> resolveSingleColumn(final int idx, final PlanNode parentNode, final SingleColumn column, final Optional<Column> targetColumn) {
final Expression expression = parentNode.resolveSelect(idx, column.getExpression());
final ColumnName alias = column.getAlias().orElseThrow(() -> new IllegalStateException("Alias should be present by this point"));
return Stream.of(SelectExpression.of(alias, targetColumn.map(col -> ImplicitlyCastResolver.resolve(expression, col.type())).orElse(expression)));
}
Aggregations