diff options
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 223 |
1 files changed, 161 insertions, 62 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 350561d7267..0e2cd6a8a76 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.143 2003/08/04 02:40:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.144 2003/08/13 16:29:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,6 +44,15 @@ char *const pgresStatus[] = { static bool PQsendQueryStart(PGconn *conn); +static int PQsendQueryGuts(PGconn *conn, + const char *command, + const char *stmtName, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); static void parseInput(PGconn *conn); static bool PQexecStart(PGconn *conn); static PGresult *PQexecFinish(PGconn *conn); @@ -668,58 +677,160 @@ PQsendQueryParams(PGconn *conn, const int *paramFormats, int resultFormat) { - int i; + if (!PQsendQueryStart(conn)) + return 0; + + if (!command) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("command string is a null pointer\n")); + return 0; + } + + return PQsendQueryGuts(conn, + command, + "", /* use unnamed statement */ + nParams, + paramTypes, + paramValues, + paramLengths, + paramFormats, + resultFormat); +} +/* + * PQsendQueryPrepared + * Like PQsendQuery, but execute a previously prepared statement, + * using 3.0 protocol so we can pass parameters + */ +int +PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ if (!PQsendQueryStart(conn)) return 0; - /* This isn't gonna work on a 2.0 server */ - if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) + if (!stmtName) { printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("function requires at least 3.0 protocol\n")); + libpq_gettext("statement name is a null pointer\n")); return 0; } - if (!command) + return PQsendQueryGuts(conn, + NULL, /* no command to parse */ + stmtName, + nParams, + NULL, /* no param types */ + paramValues, + paramLengths, + paramFormats, + resultFormat); +} + +/* + * Common startup code for PQsendQuery and sibling routines + */ +static bool +PQsendQueryStart(PGconn *conn) +{ + if (!conn) + return false; + + /* clear the error string */ + resetPQExpBuffer(&conn->errorMessage); + + /* Don't try to send if we know there's no live connection. */ + if (conn->status != CONNECTION_OK) { printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("command string is a null pointer\n")); + libpq_gettext("no connection to the server\n")); + return false; + } + /* Can't send while already busy, either. */ + if (conn->asyncStatus != PGASYNC_IDLE) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("another command is already in progress\n")); + return false; + } + + /* initialize async result-accumulation state */ + conn->result = NULL; + conn->curTuple = NULL; + + /* ready to send command message */ + return true; +} + +/* + * PQsendQueryGuts + * Common code for 3.0-protocol query sending + * PQsendQueryStart should be done already + * + * command may be NULL to indicate we use an already-prepared statement + */ +static int +PQsendQueryGuts(PGconn *conn, + const char *command, + const char *stmtName, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + int i; + + /* This isn't gonna work on a 2.0 server */ + if (PG_PROTOCOL_MAJOR(conn->pversion) < 3) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("function requires at least 3.0 protocol\n")); return 0; } /* - * We will send Parse, Bind, Describe Portal, Execute, Sync, using - * unnamed statement and portal. + * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync, + * using specified statement name and the unnamed portal. */ - /* construct the Parse message */ - if (pqPutMsgStart('P', false, conn) < 0 || - pqPuts("", conn) < 0 || - pqPuts(command, conn) < 0) - goto sendFailed; - if (nParams > 0 && paramTypes) + if (command) { - if (pqPutInt(nParams, 2, conn) < 0) + /* construct the Parse message */ + if (pqPutMsgStart('P', false, conn) < 0 || + pqPuts(stmtName, conn) < 0 || + pqPuts(command, conn) < 0) goto sendFailed; - for (i = 0; i < nParams; i++) + if (nParams > 0 && paramTypes) { - if (pqPutInt(paramTypes[i], 4, conn) < 0) + 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) + else + { + if (pqPutInt(0, 2, conn) < 0) + goto sendFailed; + } + if (pqPutMsgEnd(conn) < 0) goto sendFailed; } - if (pqPutMsgEnd(conn) < 0) - goto sendFailed; /* construct the Bind message */ if (pqPutMsgStart('B', false, conn) < 0 || pqPuts("", conn) < 0 || - pqPuts("", conn) < 0) + pqPuts(stmtName, conn) < 0) goto sendFailed; if (nParams > 0 && paramFormats) { @@ -808,41 +919,6 @@ sendFailed: } /* - * Common startup code for PQsendQuery and PQsendQueryParams - */ -static bool -PQsendQueryStart(PGconn *conn) -{ - if (!conn) - return false; - - /* clear the error string */ - resetPQExpBuffer(&conn->errorMessage); - - /* Don't try to send if we know there's no live connection. */ - if (conn->status != CONNECTION_OK) - { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("no connection to the server\n")); - return false; - } - /* Can't send while already busy, either. */ - if (conn->asyncStatus != PGASYNC_IDLE) - { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("another command is already in progress\n")); - return false; - } - - /* initialize async result-accumulation state */ - conn->result = NULL; - conn->curTuple = NULL; - - /* ready to send command message */ - return true; -} - -/* * pqHandleSendFailure: try to clean up after failure to send command. * * Primarily, what we want to accomplish here is to process an async @@ -1071,7 +1147,30 @@ PQexecParams(PGconn *conn, } /* - * Common code for PQexec and PQexecParams: prepare to send command + * PQexecPrepared + * Like PQexec, but execute a previously prepared statement, + * using 3.0 protocol so we can pass parameters + */ +PGresult * +PQexecPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendQueryPrepared(conn, stmtName, + nParams, paramValues, paramLengths, + paramFormats, resultFormat)) + return NULL; + return PQexecFinish(conn); +} + +/* + * Common code for PQexec and sibling routines: prepare to send command */ static bool PQexecStart(PGconn *conn) @@ -1139,7 +1238,7 @@ PQexecStart(PGconn *conn) } /* - * Common code for PQexec and PQexecParams: wait for command result + * Common code for PQexec and sibling routines: wait for command result */ static PGresult * PQexecFinish(PGconn *conn) |