summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r--src/interfaces/libpq/fe-exec.c124
1 files changed, 103 insertions, 21 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 14d706efd57..01f8efabbef 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -77,8 +77,8 @@ static void parseInput(PGconn *conn);
static PGresult *getCopyResult(PGconn *conn, ExecStatusType copytype);
static bool PQexecStart(PGconn *conn);
static PGresult *PQexecFinish(PGconn *conn);
-static int PQsendDescribe(PGconn *conn, char desc_type,
- const char *desc_target);
+static int PQsendTypedCommand(PGconn *conn, char command, char type,
+ const char *target);
static int check_field_number(const PGresult *res, int field_num);
static void pqPipelineProcessQueue(PGconn *conn);
static int pqPipelineFlush(PGconn *conn);
@@ -2422,7 +2422,7 @@ PQdescribePrepared(PGconn *conn, const char *stmt)
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendDescribe(conn, 'S', stmt))
+ if (!PQsendTypedCommand(conn, 'D', 'S', stmt))
return NULL;
return PQexecFinish(conn);
}
@@ -2441,7 +2441,7 @@ PQdescribePortal(PGconn *conn, const char *portal)
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendDescribe(conn, 'P', portal))
+ if (!PQsendTypedCommand(conn, 'D', 'P', portal))
return NULL;
return PQexecFinish(conn);
}
@@ -2456,7 +2456,7 @@ PQdescribePortal(PGconn *conn, const char *portal)
int
PQsendDescribePrepared(PGconn *conn, const char *stmt)
{
- return PQsendDescribe(conn, 'S', stmt);
+ return PQsendTypedCommand(conn, 'D', 'S', stmt);
}
/*
@@ -2469,26 +2469,96 @@ PQsendDescribePrepared(PGconn *conn, const char *stmt)
int
PQsendDescribePortal(PGconn *conn, const char *portal)
{
- return PQsendDescribe(conn, 'P', portal);
+ return PQsendTypedCommand(conn, 'D', 'P', portal);
}
/*
- * PQsendDescribe
- * Common code to send a Describe command
+ * PQclosePrepared
+ * Close a previously prepared statement
+ *
+ * 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). On success, the PGresult contains status
+ * PGRES_COMMAND_OK. The user is responsible for freeing the PGresult via
+ * PQclear() when done with it.
+ */
+PGresult *
+PQclosePrepared(PGconn *conn, const char *stmt)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendTypedCommand(conn, 'C', 'S', stmt))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQclosePortal
+ * Close a previously created portal
+ *
+ * This is exactly like PQclosePrepared, but for portals. Note that at the
+ * moment, libpq doesn't really expose portals to the client; but this can be
+ * used with a portal created by a SQL DECLARE CURSOR command.
+ */
+PGresult *
+PQclosePortal(PGconn *conn, const char *portal)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendTypedCommand(conn, 'C', 'P', portal))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQsendClosePrepared
+ * Submit a Close Statement command, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ */
+int
+PQsendClosePrepared(PGconn *conn, const char *stmt)
+{
+ return PQsendTypedCommand(conn, 'C', 'S', stmt);
+}
+
+/*
+ * PQsendClosePortal
+ * Submit a Close Portal command, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ */
+int
+PQsendClosePortal(PGconn *conn, const char *portal)
+{
+ return PQsendTypedCommand(conn, 'C', 'P', portal);
+}
+
+/*
+ * PQsendTypedCommand
+ * Common code to send a Describe or Close command
+ *
+ * Available options for "command" are
+ * 'C' for Close; or
+ * 'D' for Describe.
+ *
+ * Available options for "type" are
+ * 'S' to run a command on a prepared statement; or
+ * 'P' to run a command on a portal.
*
- * Available options for desc_type are
- * 'S' to describe a prepared statement; or
- * 'P' to describe a portal.
* Returns 1 on success and 0 on failure.
*/
static int
-PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
+PQsendTypedCommand(PGconn *conn, char command, char type, const char *target)
{
PGcmdQueueEntry *entry = NULL;
- /* Treat null desc_target as empty string */
- if (!desc_target)
- desc_target = "";
+ /* Treat null target as empty string */
+ if (!target)
+ target = "";
if (!PQsendQueryStart(conn, true))
return 0;
@@ -2497,10 +2567,10 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
if (entry == NULL)
return 0; /* error msg already set */
- /* construct the Describe message */
- if (pqPutMsgStart('D', conn) < 0 ||
- pqPutc(desc_type, conn) < 0 ||
- pqPuts(desc_target, conn) < 0 ||
+ /* construct the Close message */
+ if (pqPutMsgStart(command, conn) < 0 ||
+ pqPutc(type, conn) < 0 ||
+ pqPuts(target, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
@@ -2512,8 +2582,20 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
goto sendFailed;
}
- /* remember we are doing a Describe */
- entry->queryclass = PGQUERY_DESCRIBE;
+ /* remember if we are doing a Close or a Describe */
+ if (command == 'C')
+ {
+ entry->queryclass = PGQUERY_CLOSE;
+ }
+ else if (command == 'D')
+ {
+ entry->queryclass = PGQUERY_DESCRIBE;
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "unknown command type provided");
+ goto sendFailed;
+ }
/*
* Give the data a push (in pipeline mode, only if we're past the size