aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-exec.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-10-18 22:00:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-10-18 22:00:42 +0000
commit9d9cfb1ad75b60f4e9258078d7f483ea123dc7b2 (patch)
tree9d908c4439d2025f1e424dfe599c7eb53dc74a41 /src/interfaces/libpq/fe-exec.c
parentb3fe6bcafe8f54ca354495a01eeff1b0a5353892 (diff)
downloadpostgresql-9d9cfb1ad75b60f4e9258078d7f483ea123dc7b2.tar.gz
postgresql-9d9cfb1ad75b60f4e9258078d7f483ea123dc7b2.zip
Add PQprepare/PQsendPrepared functions to libpq to support preparing
statements without necessarily specifying the datatypes of their parameters. Abhijit Menon-Sen with some help from Tom Lane.
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r--src/interfaces/libpq/fe-exec.c120
1 files changed, 115 insertions, 5 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 5e19d78b37a..fff9746e33b 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.163 2004/10/16 22:52:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.164 2004/10/18 22:00:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -664,7 +664,7 @@ PQsendQuery(PGconn *conn, const char *query)
}
/* remember we are using simple query protocol */
- conn->ext_query = false;
+ conn->queryclass = PGQUERY_SIMPLE;
/*
* Give the data a push. In nonblock mode, don't complain if we're
@@ -718,6 +718,94 @@ PQsendQueryParams(PGconn *conn,
}
/*
+ * 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 (!PQsendQueryStart(conn))
+ return 0;
+
+ if (!stmtName)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("statement name is a null pointer\n"));
+ return 0;
+ }
+
+ if (!query)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("command string is a null pointer\n"));
+ return 0;
+ }
+
+ /* 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 protocol version 3.0\n"));
+ return 0;
+ }
+
+ /* construct the Parse message */
+ 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;
+
+ /* construct the Sync message */
+ if (pqPutMsgStart('S', false, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* remember we are doing just a Parse */
+ conn->queryclass = PGQUERY_PREPARE;
+
+ /*
+ * Give the data a push. In nonblock mode, don't complain if we're
+ * unable to send it all; PQgetResult() will do any additional
+ * flushing needed.
+ */
+ if (pqFlush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ conn->asyncStatus = PGASYNC_BUSY;
+ return 1;
+
+sendFailed:
+ pqHandleSendFailure(conn);
+ return 0;
+}
+
+/*
* PQsendQueryPrepared
* Like PQsendQuery, but execute a previously prepared statement,
* using protocol 3.0 so we can pass parameters
@@ -921,7 +1009,7 @@ PQsendQueryGuts(PGconn *conn,
goto sendFailed;
/* remember we are using extended query protocol */
- conn->ext_query = true;
+ conn->queryclass = PGQUERY_EXTENDED;
/*
* Give the data a push. In nonblock mode, don't complain if we're
@@ -1134,7 +1222,6 @@ PQgetResult(PGconn *conn)
* The user is responsible for freeing the PGresult via PQclear()
* when done with it.
*/
-
PGresult *
PQexec(PGconn *conn, const char *query)
{
@@ -1169,6 +1256,29 @@ PQexecParams(PGconn *conn,
}
/*
+ * PQprepare
+ * Creates a prepared statement by issuing a v3.0 parse message.
+ *
+ * If the query was not even sent, return NULL; conn->errorMessage is set to
+ * a relevant message.
+ * If the query was sent, a new PGresult is returned (which could indicate
+ * either success or failure).
+ * The user is responsible for freeing the PGresult via PQclear()
+ * when done with it.
+ */
+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);
+}
+
+/*
* PQexecPrepared
* Like PQexec, but execute a previously prepared statement,
* using protocol 3.0 so we can pass parameters
@@ -1451,7 +1561,7 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
* If we sent the COPY command in extended-query mode, we must
* issue a Sync as well.
*/
- if (conn->ext_query)
+ if (conn->queryclass != PGQUERY_SIMPLE)
{
if (pqPutMsgStart('S', false, conn) < 0 ||
pqPutMsgEnd(conn) < 0)