Search in sources :

Example 1 with LogicalSchema

use of io.confluent.ksql.schema.ksql.LogicalSchema in project ksql by confluentinc.

the class FinalProjectNode method throwOnEmptyValueOrUnknownColumns.

private void throwOnEmptyValueOrUnknownColumns() {
    final LogicalSchema schema = getSchema();
    if (schema.value().isEmpty()) {
        throw new KsqlException("The projection contains no value columns.");
    }
    validateProjection();
}
Also used : LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) KsqlException(io.confluent.ksql.util.KsqlException)

Example 2 with LogicalSchema

use of io.confluent.ksql.schema.ksql.LogicalSchema 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);
}
Also used : DataSource(io.confluent.ksql.metastore.model.DataSource) ColumnName(io.confluent.ksql.name.ColumnName) SourceName(io.confluent.ksql.name.SourceName) GrammaticalJoiner(io.confluent.ksql.util.GrammaticalJoiner) UnqualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp) Name(io.confluent.ksql.name.Name) HashMap(java.util.HashMap) SelectItem(io.confluent.ksql.parser.tree.SelectItem) HashSet(java.util.HashSet) AsValue(io.confluent.ksql.function.udf.AsValue) Pair(io.confluent.ksql.util.Pair) ImmutableList(com.google.common.collect.ImmutableList) Analysis(io.confluent.ksql.analyzer.Analysis) Map(java.util.Map) MetaStore(io.confluent.ksql.metastore.MetaStore) Projection(io.confluent.ksql.planner.Projection) ColumnReferenceExp(io.confluent.ksql.execution.expression.tree.ColumnReferenceExp) RequiredColumns(io.confluent.ksql.planner.RequiredColumns) SystemColumns(io.confluent.ksql.schema.ksql.SystemColumns) Set(java.util.Set) KsqlConfig(io.confluent.ksql.util.KsqlConfig) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) Collectors(java.util.stream.Collectors) SelectExpression(io.confluent.ksql.execution.plan.SelectExpression) Builder(io.confluent.ksql.schema.ksql.LogicalSchema.Builder) NodeLocation(io.confluent.ksql.parser.NodeLocation) List(java.util.List) Entry(java.util.Map.Entry) KsqlException(io.confluent.ksql.util.KsqlException) Optional(java.util.Optional) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Builder(io.confluent.ksql.schema.ksql.LogicalSchema.Builder) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) SelectExpression(io.confluent.ksql.execution.plan.SelectExpression) KsqlException(io.confluent.ksql.util.KsqlException) UnqualifiedColumnReferenceExp(io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp) ColumnName(io.confluent.ksql.name.ColumnName) SourceName(io.confluent.ksql.name.SourceName) Name(io.confluent.ksql.name.Name) ColumnName(io.confluent.ksql.name.ColumnName) HashSet(java.util.HashSet)

Example 3 with LogicalSchema

use of io.confluent.ksql.schema.ksql.LogicalSchema in project ksql by confluentinc.

the class LogicalPlanner method buildInternalRepartitionNode.

private PreJoinRepartitionNode buildInternalRepartitionNode(final PlanNode source, final String side, final Expression joinExpression, final BiFunction<Expression, Context<Void>, Optional<Expression>> plugin) {
    final Expression rewrittenPartitionBy = ExpressionTreeRewriter.rewriteWith(plugin, joinExpression);
    final LogicalSchema schema = buildRepartitionedSchema(source, Collections.singletonList(rewrittenPartitionBy));
    return new PreJoinRepartitionNode(new PlanNodeId(side + "SourceKeyed"), source, schema, rewrittenPartitionBy);
}
Also used : PlanNodeId(io.confluent.ksql.planner.plan.PlanNodeId) 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) PreJoinRepartitionNode(io.confluent.ksql.planner.plan.PreJoinRepartitionNode) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema)

Example 4 with LogicalSchema

use of io.confluent.ksql.schema.ksql.LogicalSchema in project ksql by confluentinc.

the class PushRouting method connectToHosts.

/**
 * Connects to all of the hosts provided.
 * @return A future for a PushConnectionsHandle, which can be used to terminate connections.
 */
@SuppressWarnings("checkstyle:ParameterNumber")
private CompletableFuture<PushConnectionsHandle> connectToHosts(final ServiceContext serviceContext, final PushPhysicalPlanManager pushPhysicalPlanManager, final ConfiguredStatement<Query> statement, final Collection<KsqlNode> hosts, final LogicalSchema outputSchema, final TransientQueryQueue transientQueryQueue, final PushConnectionsHandle pushConnectionsHandle, final boolean dynamicallyAddedNode, final Optional<ScalablePushQueryMetrics> scalablePushQueryMetrics, final Set<KsqlNode> catchupHosts, final PushRoutingOptions pushRoutingOptions, final String thisHostName) {
    final Map<KsqlNode, CompletableFuture<RoutingResult>> futureMap = new LinkedHashMap<>();
    for (final KsqlNode node : hosts) {
        pushConnectionsHandle.add(node, new RoutingResult(RoutingResultStatus.IN_PROGRESS, () -> {
        }));
        final CompletableFuture<Void> callback = new CompletableFuture<>();
        callback.handle((v, t) -> {
            if (t == null) {
                pushConnectionsHandle.get(node).ifPresent(result -> {
                    result.close();
                    result.updateStatus(RoutingResultStatus.COMPLETE);
                });
                LOG.info("Host {} completed request {}.", node, pushPhysicalPlanManager.getQueryId());
            } else if (t instanceof GapFoundException) {
                pushConnectionsHandle.get(node).ifPresent(result -> {
                    result.close();
                    result.updateStatus(RoutingResultStatus.OFFSET_GAP_FOUND);
                });
            } else {
                pushConnectionsHandle.completeExceptionally(t);
            }
            return null;
        });
        futureMap.put(node, executeOrRouteQuery(node, statement, serviceContext, pushPhysicalPlanManager, outputSchema, transientQueryQueue, callback, scalablePushQueryMetrics, pushConnectionsHandle.getOffsetsTracker(), catchupHosts.contains(node), pushRoutingOptions, thisHostName));
    }
    return CompletableFuture.allOf(futureMap.values().toArray(new CompletableFuture[0])).thenApply(v -> {
        for (final KsqlNode node : hosts) {
            final CompletableFuture<RoutingResult> future = futureMap.get(node);
            final RoutingResult routingResult = future.join();
            pushConnectionsHandle.add(node, routingResult);
        }
        return pushConnectionsHandle;
    }).exceptionally(t -> {
        final KsqlNode node = futureMap.entrySet().stream().filter(e -> e.getValue().isCompletedExceptionally()).map(Entry::getKey).findFirst().orElse(null);
        for (KsqlNode n : hosts) {
            final CompletableFuture<RoutingResult> future = futureMap.get(n);
            // Take whatever completed exceptionally and mark it as failed
            if (future.isCompletedExceptionally()) {
                pushConnectionsHandle.get(n).ifPresent(result -> result.updateStatus(RoutingResultStatus.FAILED));
            } else {
                final RoutingResult routingResult = future.join();
                pushConnectionsHandle.add(node, routingResult);
            }
        }
        LOG.warn("Error routing query {} id {} to host {} at timestamp {} with exception {}", statement.getStatementText(), pushPhysicalPlanManager.getQueryId(), node, System.currentTimeMillis(), t.getCause());
        // retries in that case and don't fail the original request.
        if (!dynamicallyAddedNode) {
            pushConnectionsHandle.completeExceptionally(new KsqlException(String.format("Unable to execute push query \"%s\". %s", statement.getStatementText(), t.getCause().getMessage())));
        }
        return pushConnectionsHandle;
    }).exceptionally(t -> {
        LOG.error("Unexpected error handing exception", t);
        return pushConnectionsHandle;
    });
}
Also used : Query(io.confluent.ksql.parser.tree.Query) LoadingCache(com.google.common.cache.LoadingCache) KeyValue(io.confluent.ksql.util.KeyValue) ServiceContext(io.confluent.ksql.services.ServiceContext) LoggerFactory(org.slf4j.LoggerFactory) RowMetadata(io.confluent.ksql.util.RowMetadata) DataRow(io.confluent.ksql.rest.entity.StreamedRow.DataRow) RestResponse(io.confluent.ksql.rest.client.RestResponse) Context(io.vertx.core.Context) KsqlErrorMessage(io.confluent.ksql.rest.entity.KsqlErrorMessage) PushContinuationToken(io.confluent.ksql.rest.entity.PushContinuationToken) QueryRow(io.confluent.ksql.physical.common.QueryRow) Map(java.util.Map) QueryId(io.confluent.ksql.query.QueryId) KsqlRequestConfig(io.confluent.ksql.util.KsqlRequestConfig) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) ScalablePushQueryMetrics(io.confluent.ksql.internal.ScalablePushQueryMetrics) ConfiguredStatement(io.confluent.ksql.statement.ConfiguredStatement) BufferedPublisher(io.confluent.ksql.reactive.BufferedPublisher) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) CacheLoader(com.google.common.cache.CacheLoader) KsqlNode(io.confluent.ksql.physical.scalablepush.locator.PushLocator.KsqlNode) BaseSubscriber(io.confluent.ksql.reactive.BaseSubscriber) List(java.util.List) VertxUtils(io.confluent.ksql.util.VertxUtils) Entry(java.util.Map.Entry) KsqlException(io.confluent.ksql.util.KsqlException) Optional(java.util.Optional) TransientQueryQueue(io.confluent.ksql.query.TransientQueryQueue) CacheBuilder(com.google.common.cache.CacheBuilder) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) StreamedRow(io.confluent.ksql.rest.entity.StreamedRow) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) KeyValueMetadata(io.confluent.ksql.util.KeyValueMetadata) PushOffsetRange(io.confluent.ksql.util.PushOffsetRange) OffsetVector(io.confluent.ksql.util.OffsetVector) BiConsumer(java.util.function.BiConsumer) Logger(org.slf4j.Logger) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) GenericRow(io.confluent.ksql.GenericRow) Subscription(org.reactivestreams.Subscription) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) PushOffsetVector(io.confluent.ksql.util.PushOffsetVector) Collections(java.util.Collections) CompletableFuture(java.util.concurrent.CompletableFuture) KsqlNode(io.confluent.ksql.physical.scalablepush.locator.PushLocator.KsqlNode) KsqlException(io.confluent.ksql.util.KsqlException) LinkedHashMap(java.util.LinkedHashMap)

Example 5 with LogicalSchema

use of io.confluent.ksql.schema.ksql.LogicalSchema in project ksql by confluentinc.

the class PushRouting method checkForNewHosts.

private void checkForNewHosts(final ServiceContext serviceContext, final PushPhysicalPlanManager pushPhysicalPlanManager, final ConfiguredStatement<Query> statement, final LogicalSchema outputSchema, final TransientQueryQueue transientQueryQueue, final PushConnectionsHandle pushConnectionsHandle, final Optional<ScalablePushQueryMetrics> scalablePushQueryMetrics, final PushRoutingOptions pushRoutingOptions, final String thisHostName) {
    VertxUtils.checkContext(pushPhysicalPlanManager.getContext());
    if (pushConnectionsHandle.isClosed()) {
        return;
    }
    final Set<KsqlNode> updatedHosts = registryToNodes.apply(pushPhysicalPlanManager.getScalablePushRegistry());
    final Set<KsqlNode> hosts = pushConnectionsHandle.getActiveHosts();
    final Set<KsqlNode> newHosts = Sets.difference(updatedHosts, hosts).stream().filter(node -> pushConnectionsHandle.get(node).map(routingResult -> routingResult.getStatus() != RoutingResultStatus.IN_PROGRESS).orElse(true)).collect(Collectors.toSet());
    final Set<KsqlNode> removedHosts = Sets.difference(hosts, updatedHosts);
    if (newHosts.size() > 0) {
        LOG.info("Dynamically adding new hosts {} for {}", newHosts, pushPhysicalPlanManager.getQueryId());
        final Set<KsqlNode> catchupHosts = newHosts.stream().filter(node -> pushConnectionsHandle.get(node).map(routingResult -> routingResult.getStatus() == RoutingResultStatus.OFFSET_GAP_FOUND).orElse(false)).collect(Collectors.toSet());
        connectToHosts(serviceContext, pushPhysicalPlanManager, statement, newHosts, outputSchema, transientQueryQueue, pushConnectionsHandle, true, scalablePushQueryMetrics, catchupHosts, pushRoutingOptions, thisHostName);
    }
    if (removedHosts.size() > 0) {
        LOG.info("Dynamically removing hosts {} for {}", removedHosts, pushPhysicalPlanManager.getQueryId());
        for (final KsqlNode node : removedHosts) {
            final RoutingResult result = pushConnectionsHandle.remove(node);
            result.close();
            result.updateStatus(RoutingResultStatus.REMOVED);
        }
    }
    pushPhysicalPlanManager.getContext().owner().setTimer(clusterCheckInterval, timerId -> checkForNewHosts(serviceContext, pushPhysicalPlanManager, statement, outputSchema, transientQueryQueue, pushConnectionsHandle, scalablePushQueryMetrics, pushRoutingOptions, thisHostName));
}
Also used : Query(io.confluent.ksql.parser.tree.Query) LoadingCache(com.google.common.cache.LoadingCache) KeyValue(io.confluent.ksql.util.KeyValue) ServiceContext(io.confluent.ksql.services.ServiceContext) LoggerFactory(org.slf4j.LoggerFactory) RowMetadata(io.confluent.ksql.util.RowMetadata) DataRow(io.confluent.ksql.rest.entity.StreamedRow.DataRow) RestResponse(io.confluent.ksql.rest.client.RestResponse) Context(io.vertx.core.Context) KsqlErrorMessage(io.confluent.ksql.rest.entity.KsqlErrorMessage) PushContinuationToken(io.confluent.ksql.rest.entity.PushContinuationToken) QueryRow(io.confluent.ksql.physical.common.QueryRow) Map(java.util.Map) QueryId(io.confluent.ksql.query.QueryId) KsqlRequestConfig(io.confluent.ksql.util.KsqlRequestConfig) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) ScalablePushQueryMetrics(io.confluent.ksql.internal.ScalablePushQueryMetrics) ConfiguredStatement(io.confluent.ksql.statement.ConfiguredStatement) BufferedPublisher(io.confluent.ksql.reactive.BufferedPublisher) LogicalSchema(io.confluent.ksql.schema.ksql.LogicalSchema) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) CacheLoader(com.google.common.cache.CacheLoader) KsqlNode(io.confluent.ksql.physical.scalablepush.locator.PushLocator.KsqlNode) BaseSubscriber(io.confluent.ksql.reactive.BaseSubscriber) List(java.util.List) VertxUtils(io.confluent.ksql.util.VertxUtils) Entry(java.util.Map.Entry) KsqlException(io.confluent.ksql.util.KsqlException) Optional(java.util.Optional) TransientQueryQueue(io.confluent.ksql.query.TransientQueryQueue) CacheBuilder(com.google.common.cache.CacheBuilder) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) StreamedRow(io.confluent.ksql.rest.entity.StreamedRow) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) KeyValueMetadata(io.confluent.ksql.util.KeyValueMetadata) PushOffsetRange(io.confluent.ksql.util.PushOffsetRange) OffsetVector(io.confluent.ksql.util.OffsetVector) BiConsumer(java.util.function.BiConsumer) Logger(org.slf4j.Logger) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) GenericRow(io.confluent.ksql.GenericRow) Subscription(org.reactivestreams.Subscription) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) PushOffsetVector(io.confluent.ksql.util.PushOffsetVector) Collections(java.util.Collections) KsqlNode(io.confluent.ksql.physical.scalablepush.locator.PushLocator.KsqlNode)

Aggregations

LogicalSchema (io.confluent.ksql.schema.ksql.LogicalSchema)223 Test (org.junit.Test)152 Expression (io.confluent.ksql.execution.expression.tree.Expression)44 ColumnName (io.confluent.ksql.name.ColumnName)31 GenericRow (io.confluent.ksql.GenericRow)30 UnqualifiedColumnReferenceExp (io.confluent.ksql.execution.expression.tree.UnqualifiedColumnReferenceExp)29 KsqlException (io.confluent.ksql.util.KsqlException)27 GenericKey (io.confluent.ksql.GenericKey)20 StringLiteral (io.confluent.ksql.execution.expression.tree.StringLiteral)19 List (java.util.List)16 TimestampColumn (io.confluent.ksql.execution.timestamp.TimestampColumn)14 SqlType (io.confluent.ksql.schema.ksql.types.SqlType)14 Optional (java.util.Optional)14 Collectors (java.util.stream.Collectors)14 QueryContext (io.confluent.ksql.execution.context.QueryContext)13 ArithmeticBinaryExpression (io.confluent.ksql.execution.expression.tree.ArithmeticBinaryExpression)12 DereferenceExpression (io.confluent.ksql.execution.expression.tree.DereferenceExpression)12 SelectExpression (io.confluent.ksql.execution.plan.SelectExpression)12 Column (io.confluent.ksql.schema.ksql.Column)12 ComparisonExpression (io.confluent.ksql.execution.expression.tree.ComparisonExpression)11