Search in sources :

Example 1 with Portal

use of io.crate.protocols.postgres.Portal in project crate by crate.

the class Session method singleExec.

@VisibleForTesting
CompletableFuture<?> singleExec(Portal portal, ResultReceiver<?> resultReceiver, int maxRows) {
    var activeConsumer = portal.activeConsumer();
    if (activeConsumer != null && activeConsumer.suspended()) {
        activeConsumer.replaceResultReceiver(resultReceiver, maxRows);
        activeConsumer.resume();
        return resultReceiver.completionFuture();
    }
    var jobId = UUIDs.dirtyUUID();
    var routingProvider = new RoutingProvider(Randomness.get().nextInt(), planner.getAwarenessAttributes());
    var clusterState = executor.clusterService().state();
    var txnCtx = new CoordinatorTxnCtx(sessionContext);
    var nodeCtx = executor.nodeContext();
    var params = new RowN(portal.params().toArray());
    var plannerContext = new PlannerContext(clusterState, routingProvider, jobId, txnCtx, nodeCtx, maxRows, params);
    var analyzedStmt = portal.analyzedStatement();
    String rawStatement = portal.preparedStmt().rawStatement();
    if (analyzedStmt == null) {
        String errorMsg = "Statement must have been analyzed: " + rawStatement;
        jobsLogs.logPreExecutionFailure(jobId, rawStatement, errorMsg, sessionContext.sessionUser());
        throw new IllegalStateException(errorMsg);
    }
    Plan plan;
    try {
        plan = planner.plan(analyzedStmt, plannerContext);
    } catch (Throwable t) {
        jobsLogs.logPreExecutionFailure(jobId, rawStatement, SQLExceptions.messageOf(t), sessionContext.sessionUser());
        throw t;
    }
    if (!analyzedStmt.isWriteOperation()) {
        resultReceiver = new RetryOnFailureResultReceiver(executor.clusterService(), clusterState, indexName -> executor.clusterService().state().metadata().hasIndex(indexName), resultReceiver, jobId, (newJobId, resultRec) -> retryQuery(newJobId, analyzedStmt, routingProvider, new RowConsumerToResultReceiver(resultRec, maxRows, new JobsLogsUpdateListener(newJobId, jobsLogs)), params, txnCtx, nodeCtx));
    }
    jobsLogs.logExecutionStart(jobId, rawStatement, sessionContext.sessionUser(), StatementClassifier.classify(plan));
    RowConsumerToResultReceiver consumer = new RowConsumerToResultReceiver(resultReceiver, maxRows, new JobsLogsUpdateListener(jobId, jobsLogs));
    portal.setActiveConsumer(consumer);
    plan.execute(executor, plannerContext, consumer, params, SubQueryResults.EMPTY);
    return resultReceiver.completionFuture();
}
Also used : ParamTypeHints(io.crate.analyze.ParamTypeHints) RetryOnFailureResultReceiver(io.crate.protocols.postgres.RetryOnFailureResultReceiver) Analyzer(io.crate.analyze.Analyzer) DependencyCarrier(io.crate.planner.DependencyCarrier) ClusterState(org.elasticsearch.cluster.ClusterState) Relations(io.crate.analyze.Relations) RowN(io.crate.data.RowN) TransactionState(io.crate.protocols.postgres.TransactionState) Map(java.util.Map) JobsLogsUpdateListener(io.crate.protocols.postgres.JobsLogsUpdateListener) TableInfo(io.crate.metadata.table.TableInfo) NodeContext(io.crate.metadata.NodeContext) AnalyzedStatement(io.crate.analyze.AnalyzedStatement) UUIDs(org.elasticsearch.common.UUIDs) UUID(java.util.UUID) Lists2(io.crate.common.collections.Lists2) List(java.util.List) Logger(org.apache.logging.log4j.Logger) AnalyzedDiscard(io.crate.analyze.AnalyzedDiscard) Row(io.crate.data.Row) Symbol(io.crate.expression.symbol.Symbol) AnalyzedBegin(io.crate.analyze.AnalyzedBegin) SubQueryResults(io.crate.planner.operators.SubQueryResults) Statement(io.crate.sql.tree.Statement) VisibleForTesting(io.crate.common.annotations.VisibleForTesting) Row1(io.crate.data.Row1) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) AnalyzedCommit(io.crate.analyze.AnalyzedCommit) AccessControl(io.crate.auth.AccessControl) QueriedSelectRelation(io.crate.analyze.QueriedSelectRelation) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) JobsLogs(io.crate.execution.engine.collect.stats.JobsLogs) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Portal(io.crate.protocols.postgres.Portal) Symbols(io.crate.expression.symbol.Symbols) FormatCodes(io.crate.protocols.postgres.FormatCodes) SqlParser(io.crate.sql.parser.SqlParser) Nullable(javax.annotation.Nullable) Iterator(java.util.Iterator) RelationInfo(io.crate.metadata.RelationInfo) Target(io.crate.sql.tree.DiscardStatement.Target) DataType(io.crate.types.DataType) Planner(io.crate.planner.Planner) RoutingProvider(io.crate.metadata.RoutingProvider) RowConsumer(io.crate.data.RowConsumer) StatementClassifier(io.crate.planner.operators.StatementClassifier) AbstractTableRelation(io.crate.analyze.relations.AbstractTableRelation) PlannerContext(io.crate.planner.PlannerContext) Plan(io.crate.planner.Plan) AnalyzedRelation(io.crate.analyze.relations.AnalyzedRelation) ReadOnlyException(io.crate.exceptions.ReadOnlyException) SQLExceptions(io.crate.exceptions.SQLExceptions) LogManager(org.apache.logging.log4j.LogManager) Randomness(org.elasticsearch.common.Randomness) AnalyzedDeallocate(io.crate.analyze.AnalyzedDeallocate) RoutingProvider(io.crate.metadata.RoutingProvider) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) Plan(io.crate.planner.Plan) RowN(io.crate.data.RowN) PlannerContext(io.crate.planner.PlannerContext) JobsLogsUpdateListener(io.crate.protocols.postgres.JobsLogsUpdateListener) RetryOnFailureResultReceiver(io.crate.protocols.postgres.RetryOnFailureResultReceiver) VisibleForTesting(io.crate.common.annotations.VisibleForTesting)

Example 2 with Portal

use of io.crate.protocols.postgres.Portal in project crate by crate.

the class Session method execute.

@Nullable
public CompletableFuture<?> execute(String portalName, int maxRows, ResultReceiver<?> resultReceiver) {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("method=execute portalName={} maxRows={}", portalName, maxRows);
    }
    Portal portal = getSafePortal(portalName);
    var analyzedStmt = portal.analyzedStatement();
    if (isReadOnly && analyzedStmt.isWriteOperation()) {
        throw new ReadOnlyException(portal.preparedStmt().rawStatement());
    }
    if (analyzedStmt instanceof AnalyzedBegin) {
        currentTransactionState = TransactionState.IN_TRANSACTION;
        resultReceiver.allFinished(false);
    } else if (analyzedStmt instanceof AnalyzedCommit) {
        currentTransactionState = TransactionState.IDLE;
        resultReceiver.allFinished(false);
        return resultReceiver.completionFuture();
    } else if (analyzedStmt instanceof AnalyzedDeallocate) {
        String stmtToDeallocate = ((AnalyzedDeallocate) analyzedStmt).preparedStmtName();
        if (stmtToDeallocate != null) {
            close((byte) 'S', stmtToDeallocate);
        } else {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("deallocating all prepared statements");
            }
            preparedStatements.clear();
        }
        resultReceiver.allFinished(false);
    } else if (analyzedStmt instanceof AnalyzedDiscard) {
        AnalyzedDiscard discard = (AnalyzedDiscard) analyzedStmt;
        // See https://www.postgresql.org/docs/current/sql-discard.html
        if (discard.target() == Target.ALL) {
            close();
        }
        resultReceiver.allFinished(false);
    } else if (analyzedStmt.isWriteOperation()) {
        /* We defer the execution for any other statements to `sync` messages so that we can efficiently process
             * bulk operations. E.g. If we receive `INSERT INTO (x) VALUES (?)` bindings/execute multiple times
             * We want to create bulk requests internally:                                                          /
             * - To reduce network overhead
             * - To have 1 disk flush per shard instead of 1 disk flush per item
             *
             * Many clients support this by doing something like this:
             *
             *      var preparedStatement = conn.prepareStatement("...")
             *      for (var args in manyArgs):
             *          preparedStatement.execute(args)
             *      conn.commit()
             */
        deferredExecutionsByStmt.compute(portal.preparedStmt().parsedStatement(), (key, oldValue) -> {
            DeferredExecution deferredExecution = new DeferredExecution(portal, maxRows, resultReceiver);
            if (oldValue == null) {
                ArrayList<DeferredExecution> deferredExecutions = new ArrayList<>();
                deferredExecutions.add(deferredExecution);
                return deferredExecutions;
            } else {
                oldValue.add(deferredExecution);
                return oldValue;
            }
        });
        return resultReceiver.completionFuture();
    } else {
        if (!deferredExecutionsByStmt.isEmpty()) {
            throw new UnsupportedOperationException("Only write operations are allowed in Batch statements");
        }
        if (activeExecution == null) {
            activeExecution = singleExec(portal, resultReceiver, maxRows);
        } else {
            activeExecution = activeExecution.thenCompose(ignored -> singleExec(portal, resultReceiver, maxRows));
        }
        return activeExecution;
    }
    return null;
}
Also used : ParamTypeHints(io.crate.analyze.ParamTypeHints) RetryOnFailureResultReceiver(io.crate.protocols.postgres.RetryOnFailureResultReceiver) Analyzer(io.crate.analyze.Analyzer) DependencyCarrier(io.crate.planner.DependencyCarrier) ClusterState(org.elasticsearch.cluster.ClusterState) Relations(io.crate.analyze.Relations) RowN(io.crate.data.RowN) TransactionState(io.crate.protocols.postgres.TransactionState) Map(java.util.Map) JobsLogsUpdateListener(io.crate.protocols.postgres.JobsLogsUpdateListener) TableInfo(io.crate.metadata.table.TableInfo) NodeContext(io.crate.metadata.NodeContext) AnalyzedStatement(io.crate.analyze.AnalyzedStatement) UUIDs(org.elasticsearch.common.UUIDs) UUID(java.util.UUID) Lists2(io.crate.common.collections.Lists2) List(java.util.List) Logger(org.apache.logging.log4j.Logger) AnalyzedDiscard(io.crate.analyze.AnalyzedDiscard) Row(io.crate.data.Row) Symbol(io.crate.expression.symbol.Symbol) AnalyzedBegin(io.crate.analyze.AnalyzedBegin) SubQueryResults(io.crate.planner.operators.SubQueryResults) Statement(io.crate.sql.tree.Statement) VisibleForTesting(io.crate.common.annotations.VisibleForTesting) Row1(io.crate.data.Row1) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) AnalyzedCommit(io.crate.analyze.AnalyzedCommit) AccessControl(io.crate.auth.AccessControl) QueriedSelectRelation(io.crate.analyze.QueriedSelectRelation) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) JobsLogs(io.crate.execution.engine.collect.stats.JobsLogs) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Portal(io.crate.protocols.postgres.Portal) Symbols(io.crate.expression.symbol.Symbols) FormatCodes(io.crate.protocols.postgres.FormatCodes) SqlParser(io.crate.sql.parser.SqlParser) Nullable(javax.annotation.Nullable) Iterator(java.util.Iterator) RelationInfo(io.crate.metadata.RelationInfo) Target(io.crate.sql.tree.DiscardStatement.Target) DataType(io.crate.types.DataType) Planner(io.crate.planner.Planner) RoutingProvider(io.crate.metadata.RoutingProvider) RowConsumer(io.crate.data.RowConsumer) StatementClassifier(io.crate.planner.operators.StatementClassifier) AbstractTableRelation(io.crate.analyze.relations.AbstractTableRelation) PlannerContext(io.crate.planner.PlannerContext) Plan(io.crate.planner.Plan) AnalyzedRelation(io.crate.analyze.relations.AnalyzedRelation) ReadOnlyException(io.crate.exceptions.ReadOnlyException) SQLExceptions(io.crate.exceptions.SQLExceptions) LogManager(org.apache.logging.log4j.LogManager) Randomness(org.elasticsearch.common.Randomness) AnalyzedDeallocate(io.crate.analyze.AnalyzedDeallocate) AnalyzedBegin(io.crate.analyze.AnalyzedBegin) ArrayList(java.util.ArrayList) AnalyzedCommit(io.crate.analyze.AnalyzedCommit) AnalyzedDeallocate(io.crate.analyze.AnalyzedDeallocate) Portal(io.crate.protocols.postgres.Portal) AnalyzedDiscard(io.crate.analyze.AnalyzedDiscard) ReadOnlyException(io.crate.exceptions.ReadOnlyException) Nullable(javax.annotation.Nullable)

Example 3 with Portal

use of io.crate.protocols.postgres.Portal in project crate by crate.

the class Session method getOutputTypes.

@Nullable
public List<? extends DataType> getOutputTypes(String portalName) {
    Portal portal = getSafePortal(portalName);
    var analyzedStatement = portal.analyzedStatement();
    List<Symbol> fields = analyzedStatement.outputs();
    if (fields != null) {
        return Symbols.typeView(fields);
    }
    return null;
}
Also used : Symbol(io.crate.expression.symbol.Symbol) Portal(io.crate.protocols.postgres.Portal) Nullable(javax.annotation.Nullable)

Example 4 with Portal

use of io.crate.protocols.postgres.Portal in project crate by crate.

the class Session method bind.

public void bind(String portalName, String statementName, List<Object> params, @Nullable FormatCodes.FormatCode[] resultFormatCodes) {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("method=bind portalName={} statementName={} params={}", portalName, statementName, params);
    }
    PreparedStmt preparedStmt;
    try {
        preparedStmt = getSafeStmt(statementName);
    } catch (Throwable t) {
        jobsLogs.logPreExecutionFailure(UUIDs.dirtyUUID(), null, SQLExceptions.messageOf(t), sessionContext.sessionUser());
        throw t;
    }
    Portal portal = new Portal(portalName, preparedStmt, params, preparedStmt.analyzedStatement(), resultFormatCodes);
    Portal oldPortal = portals.put(portalName, portal);
    if (oldPortal != null) {
        // According to the wire protocol spec named portals should be removed explicitly and only
        // unnamed portals are implicitly closed/overridden.
        // We don't comply with the spec because we allow batching of statements, see #execute
        oldPortal.closeActiveConsumer();
    }
}
Also used : Portal(io.crate.protocols.postgres.Portal)

Example 5 with Portal

use of io.crate.protocols.postgres.Portal in project crate by crate.

the class Session method describe.

public DescribeResult describe(char type, String portalOrStatement) {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("method=describe type={} portalOrStatement={}", type, portalOrStatement);
    }
    switch(type) {
        case 'P':
            Portal portal = getSafePortal(portalOrStatement);
            var analyzedStmt = portal.analyzedStatement();
            return new DescribeResult(portal.preparedStmt().parameterTypes(), analyzedStmt.outputs(), resolveTableFromSelect(analyzedStmt));
        case 'S':
            /*
                 * describe might be called without prior bind call.
                 *
                 * If the client uses server-side prepared statements this is usually the case.
                 *
                 * E.g. the statement is first prepared:
                 *
                 *      parse stmtName=S_1 query=insert into t (x) values ($1) paramTypes=[integer]
                 *      describe type=S portalOrStatement=S_1
                 *      sync
                 *
                 * and then used with different bind calls:
                 *
                 *      bind portalName= statementName=S_1 params=[0]
                 *      describe type=P portalOrStatement=
                 *      execute
                 *
                 *      bind portalName= statementName=S_1 params=[1]
                 *      describe type=P portalOrStatement=
                 *      execute
                 */
            PreparedStmt preparedStmt = preparedStatements.get(portalOrStatement);
            AnalyzedStatement analyzedStatement = preparedStmt.analyzedStatement();
            return new DescribeResult(preparedStmt.parameterTypes(), analyzedStatement.outputs(), resolveTableFromSelect(analyzedStatement));
        default:
            throw new AssertionError("Unsupported type: " + type);
    }
}
Also used : Portal(io.crate.protocols.postgres.Portal) AnalyzedStatement(io.crate.analyze.AnalyzedStatement)

Aggregations

Portal (io.crate.protocols.postgres.Portal)7 AnalyzedStatement (io.crate.analyze.AnalyzedStatement)4 Symbol (io.crate.expression.symbol.Symbol)4 AnalyzedBegin (io.crate.analyze.AnalyzedBegin)3 AnalyzedCommit (io.crate.analyze.AnalyzedCommit)3 AnalyzedDeallocate (io.crate.analyze.AnalyzedDeallocate)3 AnalyzedDiscard (io.crate.analyze.AnalyzedDiscard)3 Analyzer (io.crate.analyze.Analyzer)3 ParamTypeHints (io.crate.analyze.ParamTypeHints)3 QueriedSelectRelation (io.crate.analyze.QueriedSelectRelation)3 Relations (io.crate.analyze.Relations)3 AbstractTableRelation (io.crate.analyze.relations.AbstractTableRelation)3 AnalyzedRelation (io.crate.analyze.relations.AnalyzedRelation)3 AccessControl (io.crate.auth.AccessControl)3 VisibleForTesting (io.crate.common.annotations.VisibleForTesting)3 Lists2 (io.crate.common.collections.Lists2)3 Row (io.crate.data.Row)3 Row1 (io.crate.data.Row1)3 RowConsumer (io.crate.data.RowConsumer)3 RowN (io.crate.data.RowN)3