com.impossibl.postgres.protocol.RequestExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pgjdbc-ng Show documentation
Show all versions of pgjdbc-ng Show documentation
PostgreSQL JDBC - NG - Driver
The newest version!
/**
* Copyright (c) 2013, impossibl.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of impossibl.com nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.impossibl.postgres.protocol;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import io.netty.buffer.ByteBuf;
public interface RequestExecutor {
/**
* Base type handler for all requests.
*/
interface ErrorHandler {
void handleError(Throwable cause, List notices) throws IOException;
}
/**
* Base type handler for requests that may receive a ready callback
* containing a transaction status.
*/
interface SynchronizedHandler extends ErrorHandler {
void handleReady(TransactionStatus transactionStatus) throws IOException;
}
/**
* Issues an isolated synchronization message. Useful to
* determine connection status without side effects.
*
* @param handler Simple handler to receive status.
* @throws IOException If an error occurs submitting the request.
*/
void sync(SynchronizedHandler handler) throws IOException;
/*****
* Query requests. Directly execute unparsed SQL text.
*/
/**
* Request handler interface for the {@link #query(String, QueryHandler)} request.
*/
interface QueryHandler extends SynchronizedHandler {
void handleComplete(String command, Long rowsAffected, Long insertedOid, TypeRef[] parameterTypes, ResultField[] resultFields, RowDataSet rows, List notices) throws IOException;
}
/**
* Uses the "simple" query protocol to execute the given query.
*
* The SQL provided may contain multiple queries concatenated with
* a semi-colon. Each separate query will produce a single
* {@link QueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)}`
* or
* {@link QueryHandler#handleError(Throwable, List)}
* callback in the provided handler. After all
* queries have been completed a
* {@link QueryHandler#handleReady(TransactionStatus)} is issued.
*
* @param sql SQL query or queries to execute.
* @param handler Query handler to process results. Can produce multiple
* {@link QueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)}
* or
* {@link QueryHandler#handleError(Throwable, List)}
* callbacks. Followed by a final
* {@link QueryHandler#handleReady(TransactionStatus)}
* callback when all requests are complete.
* @throws IOException If an error occurs submitting the request.
*/
void query(String sql, QueryHandler handler) throws IOException;
/**
* Request handler interface for the
* {@link #query(String, String, FieldFormatRef[], ByteBuf[], FieldFormatRef[], int, ExtendedQueryHandler)}
* request.
*/
interface ExtendedQueryHandler extends QueryHandler {
void handleSuspend(TypeRef[] parameterTypes, ResultField[] resultFields, RowDataSet rows, List notices) throws IOException;
}
/**
* Uses the "extended" query protocol to execute the given query. The
* requests can pass parameters and result formats.
*
* The SQL can only contain a single SQL query and thus the will only
* produce a single
* {@link ExtendedQueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)},
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* or
* {@link ExtendedQueryHandler#handleError(Throwable, List)}
* callback, followed by a final
* {@link ExtendedQueryHandler#handleReady(TransactionStatus)}.
*
* Setting {@code maxRows} to anything greater than zero enables suspend/resume
* functionality via portals. Results are delivered in groups of {@code maxRows} via the
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* callback.
* After the first group is received the
* {@link #resume(String, int, ResumeHandler)}
* request can be used to receive the next group of rows.
*
* A unique {@code portalName} is required if you wish to have multiple portals
* open simultaneously. If not, you can pass {@code null} and an unnamed portal will
* be used; it will destroy any current use of that portal.
* Anytime a named portal is used it must be finalized with a
* {@link #close(ServerObjectType, String)} or {@link #finish(String, SynchronizedHandler)}
* request.
*
* @param sql SQL query to execute.
* @param portalName Name of the portal to instantiate or {@code null} to use the unnamed portal.
* @param parameterFormats Formats (text or binary) of parameters in `parameterBuffers`. Must match the number of
* `parameterBuffers` provided.
* @param parameterBuffers Buffer of encoded parameter values.
* @param resultFieldFormats Desired formats of the result fields. Passing an empty array will request all binary
* format parameters. Passing any number of formats less than the number of result
* fields will cause the last format provided to be repeated.
* @param maxRows The number of results to receive at a time, or zero to receive all results at once. Anything
* other than zero instantiates a portal.
* @param handler Query handler to process results. Will produce a single
* {@link ExtendedQueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)},
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* or
* {@link ExtendedQueryHandler#handleError(Throwable, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void query(String sql, String portalName,
FieldFormatRef[] parameterFormats, ByteBuf[] parameterBuffers,
FieldFormatRef[] resultFieldFormats, int maxRows, ExtendedQueryHandler handler) throws IOException;
/**
* Uses the "extended" query protocol to query the rows associated with a portal that was prepared by the server
* and returned as the result of a previous query or call.
*
* The execution will only produce a single
* {@link ExtendedQueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)},
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* or
* {@link ExtendedQueryHandler#handleError(Throwable, List)}
* callback, followed by a final
* {@link ExtendedQueryHandler#handleReady(TransactionStatus)}.
*
* Setting {@code maxRows} to anything greater than zero enables suspend/resume
* functionality via portals. Results are delivered in groups of {@code maxRows} via the
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* callback.
* After the first group is received the
* {@link #resume(String, int, ResumeHandler)}
* request can be used to receive the next group of rows.
*
* @param portalName Name of the portal to query.
* @param maxRows The number of results to receive at a time, or zero to receive all results at once. Anything
* other than zero instantiates a portal.
* @param handler Query handler to process results. Will produce a single
* {@link ExtendedQueryHandler#handleComplete(String, Long, Long, TypeRef[], ResultField[], RowDataSet, List)},
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* or
* {@link ExtendedQueryHandler#handleError(Throwable, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void query(String portalName, int maxRows, ExtendedQueryHandler handler) throws IOException;
/*****
* Prepare. Prepares a named query for execution.
*****/
/**
* Request handler interface for th `prepare(sql,statementName,parameterTypes,PrepareHandler)` request.
*/
interface PrepareHandler extends ErrorHandler {
void handleComplete(TypeRef[] parameterTypes, ResultField[] resultFields, List notices) throws IOException;
}
/**
* Prepares a query for later, possibly repeated, execution via the
* {@link #execute(String, String, FieldFormatRef[], ByteBuf[], FieldFormatRef[], int, ExecuteHandler)}
* request.
*
* The SQL can only contain a single SQL query. Any text that contains multiple
* queries will be rejected with an error.
*
* If {@code statementName} is provided the query will be saved with that name and can be executed
* repeatedly until it is closed. If {@code null} is provided as the statement name it will save it
* under the "unnamed" statement and can be used until another prepare request is made using
* the "unnamed" statement. All named statements should be closed via a
* {@link #close(ServerObjectType, String)}
* request when they are no longer in use.
*
* {@code parameterTypes} directs the server on what types of parameters are intended to correspond to
* parameter placeholders in the SQL text. One or all parameter types can be omitted by passing
* less than the number of parameters in the query or passing {@code null} as the parameter type. The server
* will attempt to infer the proper type for any parameters without provided types.
*
* @param sqlText SQL text to parse; containing a maximum of one query.
* @param statementName Name of the to-be-parsed sql or {@code null} to use the unnamed statement. All named
* statements should be closed when no longer in use.
* @param parameterTypes Parameter types corresponding to parameters placeholders in the query string.
* @param handler Handler to process results of the request. Will produce a single
* {@link PrepareHandler#handleComplete(TypeRef[], ResultField[], List)}
* or
* {@link PrepareHandler#handleError(Throwable, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void prepare(String statementName, String sqlText, TypeRef[] parameterTypes, PrepareHandler handler) throws IOException;
/*****
* Execute. Execute a previously prepared query & allows resuming suspended queries.
*****/
/**
* Request handler interface for the
* {@link #execute(String, String, FieldFormatRef[], ByteBuf[], FieldFormatRef[], int, ExecuteHandler)}
* request.
*/
interface ExecuteHandler extends ResumeHandler, SynchronizedHandler {
}
/**
* Uses the "extended" query protocol to execute a previously prepared query. The
* requests can pass parameters and result formats.
*
* Setting {@code maxRows} to anything greater than zero enables suspend/resume
* functionality via portals. Results are delivered in groups of {@code maxRows} via the
* {@link ExtendedQueryHandler#handleSuspend(TypeRef[], ResultField[], RowDataSet, List)}
* callback.
* After the first group is received the
* {@link #resume(String, int, ResumeHandler)}
* request can be used to receive the next group of rows.
*
* A unique {@code portalName} is required if you wish to have multiple portals
* open and suspended simultaneously. If not, you can pass {@code null} and an
* unnamed portal will be used; it will destroy any current use of that portal.
* Anytime a named portal is used it must be finalized with a
* {@link #close(ServerObjectType, String)} or {@link #finish(String, SynchronizedHandler)}
* request.
*
* @param portalName Name of the portal to instantiate or {@code null} to use the unnamed portal.
* @param statementName Name of the statement to execute or {@code null} to execute the unnamed statement.
* @param parameterFormats Formats (text or binary) of parameters in `parameterBuffers`. Must match the number of
* `parameterBuffers` provided.
* @param parameterBuffers Buffer of encoded parameter values.
* @param resultFieldFormats Desired formats of the result fields. Passing an empty array will request all binary
* format parameters. Passing any number of formats less than the number of result
* fields will cause the last format provided to be repeated.
* @param maxRows The number of results to receive at a time, or zero to receive all results at once. Anything
* other than zero instantiates a portal.
* @param handler Execute handler to process results. Will produce a single
* {@link ExecuteHandler#handleComplete(String, Long, Long, RowDataSet, List)},
* {@link ExecuteHandler#handleError(Throwable, List)}
* callback, followed by a final
* {@link ExecuteHandler#handleReady(TransactionStatus)}
* for completed queries.
* Alternatively, for suspended queries, you will receive a single
* {@link ExecuteHandler#handleSuspend(RowDataSet, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void execute(String portalName, String statementName,
FieldFormatRef[] parameterFormats, ByteBuf[] parameterBuffers,
FieldFormatRef[] resultFieldFormats, int maxRows,
ExecuteHandler handler) throws IOException;
/**
* Request handler interface for the
* {@link #resume(String, int, ResumeHandler)}
* request.
*/
interface ResumeHandler extends ErrorHandler {
void handleComplete(String command, Long rowsAffected, Long insertedOid, RowDataSet rows, List notices) throws IOException;
void handleSuspend(RowDataSet rows, List notices) throws IOException;
}
/**
* Resumes a portal previously instantiated via an
* {@link #execute(String, String, FieldFormatRef[], ByteBuf[], FieldFormatRef[], int, ExecuteHandler)}
* or
* {@link #query(String, String, FieldFormatRef[], ByteBuf[], FieldFormatRef[], int, ExtendedQueryHandler)}
* request.
*
* A portal can be resumed until no more rows are available. As long as more rows are available
* the request will complete with a
* {@link ResumeHandler#handleSuspend(RowDataSet, List)}
* callback. When no more rows are available the request will complete with a
* {@link ResumeHandler#handleComplete(String, Long, Long, RowDataSet, List)}
* callback.
*
* Of particular note is that this request is not synchronized. Its
* handler does not extend {@link SynchronizedHandler}), thus will not receive a
* ready callback.
*
* @param portalName Name of the portal to resume or {@code null} to resume the unnamed portal.
* @param maxRows Max number of rows to return from this request.
* @param handler Execute handler to process results. Will produce a single
* {@link ExecuteHandler#handleComplete(String, Long, Long, RowDataSet, List)},
* {@link ExecuteHandler#handleSuspend(RowDataSet, List)} or
* {@link ExecuteHandler#handleError(Throwable, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void resume(String portalName, int maxRows, ResumeHandler handler) throws IOException;
/**
* Closes a portal that was previously suspended and synchronizes the
* transaction state.
*
* This can be used in place of a {@link #close(ServerObjectType, String)}
* request to allow waiting for the requests completion and synchronization.
*
* @param portalName Name of a previously executed, and suspended, portal.
* @param handler Handler to process synchronization callback.
* @throws IOException If an error occurs submitting the request.
*/
void finish(String portalName, SynchronizedHandler handler) throws IOException;
/*****
* Function Call
*****/
/**
* Request handler interface for the
* {@link #call(int, FieldFormatRef[], ByteBuf[], FunctionCallHandler)}
* request.
*/
interface FunctionCallHandler extends ErrorHandler {
void handleComplete(ByteBuf result, List notices);
}
/**
* Invokes the function specified by {@code functionId} and returns its
* results.
*
* This request is essentially deprecated by PostgreSQL and included here
* for completeness.
*
* @param functionId Function to invoke; specified by its OID.
* @param parameterFormats Formats (text or binary) of parameters in `parameterBuffers`. Must match the number of
* `parameterBuffers` provided.
* @param parameterBuffers Buffer of encoded parameter values.
* @param handler Function call handler to process results. Will produce a single
* {@link FunctionCallHandler#handleComplete(ByteBuf, List)}
* or
* {@link FunctionCallHandler#handleError(Throwable, List)}
* callback.
* @throws IOException If an error occurs submitting the request.
*/
void call(int functionId,
FieldFormatRef[] parameterFormats, ByteBuf[] parameterBuffers,
FunctionCallHandler handler) throws IOException;
/*****
* Utility requests. Generally these are "fire and forget" with no completion handlers.
*/
/**
* Closes a previously prepared statement for the connection.
*
* @param objectName Name of the object to close.
* @throws IOException If an error occurs submitting the request.
*/
void close(ServerObjectType serverObjectType, String objectName) throws IOException;
/**
* Executes a statement at the earliest convenience. The submitter has no
* ability to wait for or monitor the status of the request. All notices and
* errors are reported to whatever request handler is submitted after it.
*
* The best example of using this is beginning a transaction. The request can be
* sent and will be reported on the following request; including errors that would
* stop the following request from executing.
*
* Although it uses bind/execute, it currently doesn't support passing parameters
* to the bind, nor receiving any results from a response.
*
* @param statementName Name of statement to execute.
* @throws IOException If an error occurs submitting the request.
*/
void lazyExecute(String statementName) throws IOException;
/*****
* Asynchronous Notification
*/
interface NotificationHandler {
void handleNotification(int processId, String channelName, String payload) throws IOException;
}
/*****
* Copy In & Out
*/
interface CopyFromHandler extends SynchronizedHandler {
void handleComplete() throws IOException;
}
void copyFrom(String sql, InputStream stream, CopyFromHandler handler) throws IOException;
interface CopyToHandler extends SynchronizedHandler {
void handleComplete() throws IOException;
}
void copyTo(String sql, OutputStream stream, CopyToHandler handler) throws IOException;
}