Index: doc/src/sgml/libpq.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v retrieving revision 1.165 diff -c -c -r1.165 libpq.sgml *** doc/src/sgml/libpq.sgml 1 Oct 2004 17:34:17 -0000 1.165 --- doc/src/sgml/libpq.sgml 18 Oct 2004 18:13:09 -0000 *************** *** 1183,1194 **** ! Presently, prepared statements for use with PQexecPrepared ! must be set up by executing an SQL PREPARE command, ! which is typically sent with PQexec (though any of ! libpq's query-submission functions may be used). ! A lower-level interface for preparing statements may be offered in a ! future release. --- 1183,1238 ---- ! Prepared statements for use with PQexecPrepared can be ! created by executing an SQL PREPARE statement (which is ! sent with PQexec, or one of the other query-submission ! functions), or with PQprepare. The latter does not ! require parameter types to be pre-specified. ! ! ! ! ! ! PQpreparePQprepare ! ! ! Submits a request to create a prepared statement with the ! given parameters, and waits for completion. ! ! PGresult *PQprepare(PGconn *conn, ! const char *stmtName, ! const char *query, ! int nParams, ! const Oid *paramTypes); ! ! ! ! ! PQprepare creates a prepared statement for execution with ! PQexecPrepared. Unlike PREPARE, it allows the ! client to prepare a statement without pre-specifying the types of each ! parameter. This function is supported only in protocol 3.0 and later ! connections; it will fail when using protocol 2.0. ! ! ! ! The function creates a prepared statement named stmtName ! (which may be "", to refer to the unnamed statement) from ! the query. If any parameters are used, they are referred ! to in the query as $1, $2, etc. ! ! nParams is the number of parameters for which types are ! pre-specified in the array paramTypes[]. It may be zero, ! or up to the number of parameters used in the query. Each entry in the ! paramTypes[] array should contain the OID of the type of ! the corresponding parameter. If nParams is 0, the server ! assigns a data type to each parameter, as it would for untyped literal ! strings. Likewise, if any element in the type array is zero, its type ! is inferred. ! ! ! ! *************** *** 2353,2358 **** --- 2397,2423 ---- + PQsendPreparePQsendPrepare + + + Sends a request to create a prepared statement with the given + parameters, without waiting for completion. + + int PQsendPrepare(PGconn *conn, + const char *stmtName, + const char *query, + int nParams, + const Oid *paramTypes); + + + This is an asynchronous version of PQprepare, and + its parameters are handled identically. It will not work on 2.0 + protocol connections. + + + + + PQgetResultPQgetResult Index: src/interfaces/libpq/fe-exec.c =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v retrieving revision 1.163 diff -c -c -r1.163 fe-exec.c *** src/interfaces/libpq/fe-exec.c 16 Oct 2004 22:52:53 -0000 1.163 --- src/interfaces/libpq/fe-exec.c 18 Oct 2004 18:13:23 -0000 *************** *** 635,640 **** --- 635,704 ---- /* + * PQsendPrepare + * Submit a Parse message, but don't wait for it to finish. + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ + int + PQsendPrepare(PGconn *conn, + const char *stmtName, const char *query, + int nParams, const Oid *paramTypes) + { + if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("function requires at least protocol version 3.0\n")); + return 0; + } + + if (!PQsendQueryStart(conn)) + return 0; + + if (pqPutMsgStart('P', false, conn) < 0 || + pqPuts(stmtName, conn) < 0 || + pqPuts(query, conn) < 0) + goto sendFailed; + + if (nParams > 0 && paramTypes) + { + int i; + + if (pqPutInt(nParams, 2, conn) < 0) + goto sendFailed; + for (i = 0; i < nParams; i++) + { + if (pqPutInt(paramTypes[i], 4, conn) < 0) + goto sendFailed; + } + } + else + { + if (pqPutInt(0, 2, conn) < 0) + goto sendFailed; + } + if (pqPutMsgEnd(conn) < 0) + goto sendFailed; + + if (pqPutMsgStart('S', false, conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + + conn->ext_query = true; + conn->sent_prepare = true; + if (pqFlush(conn) < 0) + goto sendFailed; + conn->asyncStatus = PGASYNC_BUSY; + return 1; + + sendFailed: + pqHandleSendFailure(conn); + return 0; + } + + + /* * PQsendQuery * Submit a query, but don't wait for it to finish * *************** *** 1145,1150 **** --- 1209,1236 ---- return PQexecFinish(conn); } + + /* + * PQprepare + * Creates a prepared statement by issuing a v3.0 parse message. + * + * Returns NULL if the query failed, and a new PGresult otherwise. The + * user is responsible for calling PQclient() on the result. + */ + + PGresult * + PQprepare(PGconn *conn, + const char *stmtName, const char *query, + int nParams, const Oid *paramTypes) + { + if (!PQexecStart(conn)) + return NULL; + if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes)) + return NULL; + return PQexecFinish(conn); + } + + /* * PQexecParams * Like PQexec, but use protocol 3.0 so we can pass parameters Index: src/interfaces/libpq/fe-protocol3.c =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol3.c,v retrieving revision 1.18 diff -c -c -r1.18 fe-protocol3.c *** src/interfaces/libpq/fe-protocol3.c 16 Oct 2004 22:52:54 -0000 1.18 --- src/interfaces/libpq/fe-protocol3.c 18 Oct 2004 18:13:26 -0000 *************** *** 220,225 **** --- 220,233 ---- conn->asyncStatus = PGASYNC_READY; break; case '1': /* Parse Complete */ + if (conn->sent_prepare) { + if (!conn->result) + conn->result = PQmakeEmptyPGresult(conn, + PGRES_COMMAND_OK); + conn->asyncStatus = PGASYNC_READY; + conn->sent_prepare = false; + } + break; case '2': /* Bind Complete */ case '3': /* Close Complete */ /* Nothing to do for these message types */ Index: src/interfaces/libpq/libpq-fe.h =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/libpq/libpq-fe.h,v retrieving revision 1.111 diff -c -c -r1.111 libpq-fe.h *** src/interfaces/libpq/libpq-fe.h 16 Oct 2004 22:52:55 -0000 1.111 --- src/interfaces/libpq/libpq-fe.h 18 Oct 2004 18:13:28 -0000 *************** *** 296,301 **** --- 296,304 ---- /* Simple synchronous query */ extern PGresult *PQexec(PGconn *conn, const char *query); + extern PGresult *PQprepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); extern PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, *************** *** 313,318 **** --- 316,324 ---- int resultFormat); /* Interface for multiple-result or asynchronous queries */ + extern int PQsendPrepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); extern int PQsendQuery(PGconn *conn, const char *query); extern int PQsendQueryParams(PGconn *conn, const char *command, Index: src/interfaces/libpq/libpq-int.h =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/libpq/libpq-int.h,v retrieving revision 1.94 diff -c -c -r1.94 libpq-int.h *** src/interfaces/libpq/libpq-int.h 16 Oct 2004 22:52:55 -0000 1.94 --- src/interfaces/libpq/libpq-int.h 18 Oct 2004 18:13:29 -0000 *************** *** 268,273 **** --- 268,275 ---- * nonblock sending semantics */ bool ext_query; /* was our last query sent with extended * query protocol? */ + bool sent_prepare; /* was our last Parse message sent with + * PQprepare? */ char copy_is_binary; /* 1 = copy binary, 0 = copy text */ int copy_already_done; /* # bytes already returned in * COPY OUT */