Search in sources :

Example 1 with PGTypes

use of io.crate.protocols.postgres.types.PGTypes in project crate by crate.

the class PostgresWireProtocol method handleExecute.

/**
 * Execute Message
 * Header:
 * | 'E' | int32 len
 * <p>
 * Body:
 * | string portalName
 * | int32 maxRows (0 = unlimited)
 */
private void handleExecute(ByteBuf buffer, DelayableWriteChannel channel) {
    String portalName = readCString(buffer);
    int maxRows = buffer.readInt();
    String query = session.getQuery(portalName);
    if (query.isEmpty()) {
        // remove portal so that it doesn't stick around and no attempt to batch it with follow up statement is made
        session.close((byte) 'P', portalName);
        Messages.sendEmptyQueryResponse(channel);
        return;
    }
    List<? extends DataType> outputTypes = session.getOutputTypes(portalName);
    ResultReceiver resultReceiver;
    if (outputTypes == null) {
        // this is a DML query
        maxRows = 0;
        resultReceiver = new RowCountReceiver(query, channel.bypassDelay(), getAccessControl.apply(session.sessionContext()));
    } else {
        // query with resultSet
        resultReceiver = new ResultSetReceiver(query, channel.bypassDelay(), session.transactionState(), getAccessControl.apply(session.sessionContext()), Lists2.map(outputTypes, PGTypes::get), session.getResultFormatCodes(portalName));
    }
    // .execute is going async and may execute the query in another thread-pool.
    // The results are later sent to the clients via the `ResultReceiver` created
    // above, The `channel.write` calls - which the `ResultReceiver` makes - may
    // happen in a thread which is *not* a netty thread.
    // If that is the case, netty schedules the writes intead of running them
    // immediately. A consequence of that is that *this* thread can continue
    // processing other messages from the client, and if this thread then sends messages to the
    // client, these are sent immediately, overtaking the result messages of the
    // execute that is triggered here.
    // 
    // This would lead to out-of-order messages. For example, we could send a
    // `parseComplete` before the `commandComplete` of the previous statement has
    // been transmitted.
    // 
    // To ensure clients receive messages in the correct order we delay all writes
    // on the channel until the future below is finished.
    CompletableFuture<?> execute = session.execute(portalName, maxRows, resultReceiver);
    if (execute != null) {
        channel.delayWritesUntil(execute);
    }
}
Also used : PGTypes(io.crate.protocols.postgres.types.PGTypes) ResultReceiver(io.crate.action.sql.ResultReceiver)

Aggregations

ResultReceiver (io.crate.action.sql.ResultReceiver)1 PGTypes (io.crate.protocols.postgres.types.PGTypes)1