use of io.confluent.ksql.name.SourceName in project ksql by confluentinc.
the class LogicalPlanner method buildForeignJoinKey.
private JoinKey buildForeignJoinKey(final Join join, final Expression foreignKeyExpression) {
final AliasedDataSource leftSource = join.getInfo().getLeftSource();
final SourceName alias = leftSource.getAlias();
final List<QualifiedColumnReferenceExp> leftSourceKeys = leftSource.getDataSource().getSchema().key().stream().map(c -> new QualifiedColumnReferenceExp(alias, c.name())).collect(Collectors.toList());
final VisitParentExpressionVisitor<Optional<Expression>, Context<Void>> aliasRewritter = 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(ColumnNames.generatedJoinColumnAlias(node.getQualifier(), node.getColumnName())));
}
};
final Expression aliasedForeignKeyExpression = ExpressionTreeRewriter.rewriteWith(aliasRewritter::process, foreignKeyExpression);
return JoinKey.foreignKey(aliasedForeignKeyExpression, leftSourceKeys);
}
use of io.confluent.ksql.name.SourceName in project ksql by confluentinc.
the class JoinNode method validateKeyPresent.
@Override
void validateKeyPresent(final SourceName sinkName, final Projection projection) {
if (joinKey.isForeignKey()) {
final DataSourceNode leftInputTable = getLeftmostSourceNode();
final SourceName leftInputTableName = leftInputTable.getAlias();
final List<Column> leftInputTableKeys = leftInputTable.getDataSource().getSchema().key();
final List<Column> missingKeys = leftInputTableKeys.stream().filter(k -> !projection.containsExpression(new QualifiedColumnReferenceExp(leftInputTableName, k.name())) && !projection.containsExpression(new UnqualifiedColumnReferenceExp(ColumnNames.generatedJoinColumnAlias(leftInputTableName, k.name())))).collect(Collectors.toList());
if (!missingKeys.isEmpty()) {
throwMissingKeyColumnForFkJoinException(missingKeys, leftInputTableName);
}
} else {
final boolean atLeastOneKey = joinKey.getAllViableKeys(schema).stream().anyMatch(projection::containsExpression);
if (!atLeastOneKey) {
final boolean synthetic = joinKey.isSynthetic();
final List<? extends Expression> viable = joinKey.getOriginalViableKeys(schema);
throwKeysNotIncludedError(sinkName, "join expression", viable, false, synthetic);
}
}
}
use of io.confluent.ksql.name.SourceName in project ksql by confluentinc.
the class KsqlStructuredDataOutputNode method validate.
private static void validate(final PlanNode source, final SourceName sinkName) {
if (!(source instanceof VerifiableNode)) {
throw new IllegalArgumentException("VerifiableNode required");
}
((VerifiableNode) source).validateKeyPresent(sinkName);
final LogicalSchema schema = source.getSchema();
final String duplicates = schema.columns().stream().map(Column::name).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream().filter(e -> e.getValue() > 1).map(Entry::getKey).map(ColumnName::toString).collect(Collectors.joining(", "));
if (!duplicates.isEmpty()) {
throw new IllegalArgumentException("Value columns clash with key columns: " + duplicates);
}
}
use of io.confluent.ksql.name.SourceName in project ksql by confluentinc.
the class EngineExecutor method maybeCreateSinkDdl.
private Optional<DdlCommand> maybeCreateSinkDdl(final ConfiguredStatement<?> cfgStatement, final KsqlStructuredDataOutputNode outputNode) {
if (!outputNode.createInto()) {
validateExistingSink(outputNode);
return Optional.empty();
}
final Statement statement = cfgStatement.getStatement();
final SourceName intoSource = outputNode.getSinkName().get();
final boolean orReplace = statement instanceof CreateAsSelect && ((CreateAsSelect) statement).isOrReplace();
final boolean ifNotExists = statement instanceof CreateAsSelect && ((CreateAsSelect) statement).isNotExists();
final DataSource dataSource = engineContext.getMetaStore().getSource(intoSource);
if (dataSource != null && !ifNotExists && !orReplace) {
final String failedSourceType = outputNode.getNodeOutputType().getKsqlType();
final String foundSourceType = dataSource.getDataSourceType().getKsqlType();
throw new KsqlException(String.format("Cannot add %s '%s': A %s with the same name already exists", failedSourceType.toLowerCase(), intoSource.text(), foundSourceType.toLowerCase()));
}
return Optional.of(engineContext.createDdlCommand(outputNode));
}
use of io.confluent.ksql.name.SourceName in project ksql by confluentinc.
the class EngineExecutor method getSources.
private Set<DataSource> getSources(final QueryPlan queryPlan) {
final ImmutableSet.Builder<DataSource> sources = ImmutableSet.builder();
for (final SourceName name : queryPlan.getSources()) {
final DataSource dataSource = engineContext.getMetaStore().getSource(name);
if (dataSource == null) {
throw new KsqlException("Unknown source: " + name.toString(FormatOptions.noEscape()));
}
sources.add(dataSource);
}
return sources.build();
}
Aggregations