use of io.confluent.ksql.execution.expression.tree.Expression 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.execution.expression.tree.Expression in project ksql by confluentinc.
the class QueryFilterNode method extractLookupConstraints.
/**
* The WHERE clause is in DNF and this method extracts key constraints from each disjunct.
* In order to do that successfully, a given disjunct must have equality conditions on the keys.
* For example, for "KEY = 1 AND WINDOWSTART > 0 OR COUNT > 5 AND WINDOWEND < 10", the disjunct
* "KEY = 1 AND WINDOWSTART > 0" has a key equality constraint for value 1. The second
* disjunct "COUNT > 5 AND WINDOWEND < 10" does not and so has an unbound key constraint.
* seenKeys is used to make sure that all columns of a multi-column
* key are constrained via an equality condition.
* keyContents has the key values for each columns of a key.
* @return the constraints on the key values used to to do keyed lookup.
*/
private ImmutableList<LookupConstraint> extractLookupConstraints() {
if (requiresTableScan) {
LOG.debug("Skipping extracting key value extraction. Already requires table scan");
return ImmutableList.of(new NonKeyConstraint());
}
final ImmutableList.Builder<LookupConstraint> constraintPerDisjunct = ImmutableList.builder();
for (Expression disjunct : disjuncts) {
final KeyValueExtractor keyValueExtractor = new KeyValueExtractor();
keyValueExtractor.process(disjunct, null);
// Validation and extractions of window bounds
final Optional<WindowBounds> optionalWindowBounds;
if (isWindowed) {
final WindowBounds windowBounds = new WindowBounds();
new WindowBoundsExtractor().process(disjunct, windowBounds);
optionalWindowBounds = Optional.of(windowBounds);
} else {
optionalWindowBounds = Optional.empty();
}
final LookupConstraint constraint = keyValueExtractor.getLookupConstraint(optionalWindowBounds);
constraintPerDisjunct.add(constraint);
}
return constraintPerDisjunct.build();
}
use of io.confluent.ksql.execution.expression.tree.Expression 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)));
}
use of io.confluent.ksql.execution.expression.tree.Expression 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.execution.expression.tree.Expression in project ksql by confluentinc.
the class LogicRewriter method extractDisjuncts.
public static List<Expression> extractDisjuncts(final Expression expression) {
final Expression dnf = rewriteDNF(expression);
final DisjunctExtractor disjunctExtractor = new DisjunctExtractor();
disjunctExtractor.process(dnf, null);
return disjunctExtractor.getDisjuncts();
}
Aggregations