From 81f6db4803082f89b86a2d4701bf6237e6988db5 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Wed, 19 Feb 2003 03:59:02 +0000
Subject: [PATCH] Allow PQcmdTuples to return row counts for MOVE and FETCH.

Neil Conway
---
 doc/src/sgml/libpq.sgml        | 70 ++++++++++++++++++----------------
 doc/src/sgml/protocol.sgml     | 16 +++++++-
 src/backend/tcop/utility.c     |  4 +-
 src/interfaces/libpq/fe-exec.c | 69 ++++++++++++++++-----------------
 4 files changed, 90 insertions(+), 69 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 1ce38c37951..087f40e2380 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.110 2003/02/14 02:21:25 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.111 2003/02/19 03:59:02 momjian Exp $
 -->
 
  <chapter id="libpq">
@@ -702,12 +702,11 @@ char *PQerrorMessage(const PGconn* conn);
 int PQbackendPID(const PGconn *conn);
        </synopsis>
        The backend <acronym>PID</acronym> is useful for debugging
-       purposes and for comparison
-       to NOTIFY messages (which include the <acronym>PID</acronym> of
-       the notifying backend).
-       Note that the <acronym>PID</acronym> belongs to a process
-       executing on the database
-       server host, not the local host!
+       purposes and for comparison to <command>NOTIFY</command>
+       messages (which include the <acronym>PID</acronym> of the
+       notifying backend).  Note that the <acronym>PID</acronym>
+       belongs to a process executing on the database server host, not
+       the local host!
       </para>
      </listitem>
 
@@ -818,13 +817,14 @@ ExecStatusType PQresultStatus(const PGresult *res)
  </listitem>
 </itemizedlist>
 
-If  the result status is <literal>PGRES_TUPLES_OK</literal>, then the
-routines described below can be  used  to  retrieve  the
-rows returned by the query.  Note that a SELECT command that
-happens to retrieve zero rows still shows <literal>PGRES_TUPLES_OK</literal>.
-<literal>PGRES_COMMAND_OK</literal> is for commands that can never return rows
-(INSERT, UPDATE, etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often
-exposes a bug in the client software.
+If the result status is <literal>PGRES_TUPLES_OK</literal>, then the
+routines described below can be used to retrieve the rows returned by
+the query.  Note that a <command>SELECT</command> command that happens
+to retrieve zero rows still shows <literal>PGRES_TUPLES_OK</literal>.
+<literal>PGRES_COMMAND_OK</literal> is for commands that can never
+return rows (<command>INSERT</command>, <command>UPDATE</command>,
+etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often
+indicates a bug in the client software.
 </para>
 </listitem>
 
@@ -1243,36 +1243,41 @@ char * PQcmdStatus(PGresult *res);
 char * PQcmdTuples(PGresult *res);
 </synopsis>
           If the <acronym>SQL</acronym> command that generated the
-	  <structname>PGresult</structname> was INSERT, UPDATE or DELETE, this returns a
-	  string containing the number of rows affected.  If the
-          command was anything else, it returns the empty string.
+	  <structname>PGresult</structname> was <command>INSERT</command>,
+	  <command>UPDATE</command>, <command>DELETE</command>,
+	  <command>MOVE</command>, or <command>FETCH</command> this
+	  returns a string containing the number of rows affected.  If the
+	  command was anything else, it returns the empty string.
 </para>
 </listitem>
 
 <listitem>
 <para>
 <function>PQoidValue</function>
-          Returns the object ID of the inserted row, if the
-	  <acronym>SQL</acronym> command was an INSERT
-	  that inserted exactly one row into a table that has OIDs.
-          Otherwise, returns <literal>InvalidOid</literal>.
+      Returns the object ID of the inserted row, if the
+      <acronym>SQL</acronym> command was an <command>INSERT</command>
+      that inserted exactly one row into a table that has OIDs.
+      Otherwise, returns <literal>InvalidOid</literal>.
 <synopsis>
 Oid PQoidValue(const PGresult *res);
 </synopsis>
-          The type <type>Oid</type> and the constant <literal>InvalidOid</literal>
-          will be defined if you include the <application>libpq</application>
-          header file. They will both be some integer type.
+          The type <type>Oid</type> and the constant
+      <literal>InvalidOid</literal> will be defined if you include the
+      <application>libpq</application> header file. They will both be
+      some integer type.
 </para>
 </listitem>
 
 <listitem>
 <para>
 <function>PQoidStatus</function>
-          Returns a string with the object ID of the inserted row, if the
-	  <acronym>SQL</acronym> command was an INSERT.
-	  (The string will be <literal>0</> if the INSERT did not insert exactly one
-	  row, or if the target table does not have OIDs.)  If the command
-	  was not an INSERT, returns an empty string.
+      Returns a string with the object ID
+      of the inserted row, if the <acronym>SQL</acronym> command
+      was an <command>INSERT</command>.  (The string will be
+      <literal>0</> if the <command>INSERT</command> did not
+      insert exactly one row, or if the target table does not have
+      OIDs.)  If the command was not an <command>INSERT</command>,
+      returns an empty string.
 <synopsis>
 char * PQoidStatus(const PGresult *res);
 </synopsis>
@@ -1530,7 +1535,8 @@ When the main loop detects input ready, it should call
 <function>PQconsumeInput</function> to read the input.  It can then call
 <function>PQisBusy</function>, followed by <function>PQgetResult</function>
 if <function>PQisBusy</function> returns false (0).  It can also call
-<function>PQnotifies</function> to detect NOTIFY messages (see <xref linkend="libpq-notify">).
+<function>PQnotifies</function> to detect <command>NOTIFY</command>
+messages (see <xref linkend="libpq-notify">).
 </para>
 
 <para>
@@ -1700,13 +1706,13 @@ of asynchronous notification.
 <function>PQnotifies()</function> does not actually read backend data; it just
 returns messages previously absorbed by another <application>libpq</application>
 function.  In prior releases of <application>libpq</application>, the only way
-to ensure timely receipt of NOTIFY messages was to constantly submit queries,
+to ensure timely receipt of <command>NOTIFY</command> messages was to constantly submit queries,
 even empty ones, and then check <function>PQnotifies()</function> after each
 <function>PQexec()</function>.  While this still works, it is
 deprecated as a waste of processing power.
 </para>
 <para>
-A better way to check for NOTIFY
+A better way to check for <command>NOTIFY</command>
 messages when you have no useful queries to make is to call
 <function>PQconsumeInput()</function>, then check
 <function>PQnotifies()</function>.
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 06901a8e335..f6507387287 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.24 2002/03/22 19:20:21 petere Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.25 2003/02/19 03:59:02 momjian Exp $ -->
 
 <chapter id="protocol">
  <title>Frontend/Backend Protocol</title>
@@ -1335,6 +1335,20 @@ CompletedResponse (B)
 	<literal>UPDATE <Replaceable>rows</Replaceable></literal> where
         <Replaceable>rows</Replaceable> is the number of rows updated.
 </Para>
+
+       <para>
+        For a <command>MOVE</command> command, the tag is
+        <literal>MOVE <replaceable>rows</replaceable></literal> where
+        <replaceable>rows</replaceable> is the number of rows the
+        cursor's position has been changed by.
+       </para>
+
+       <para>
+        For a <command>FETCH</command> command, the tag is
+        <literal>FETCH <replaceable>rows</replaceable></literal> where
+        <replaceable>rows</replaceable> is the number of rows that
+        have been retrieved from the cursor.
+       </para>
 </ListItem>
 </VarListEntry>
 </VariableList>
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index b48550428f6..db7dc0945cd 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.192 2003/02/13 05:20:01 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.193 2003/02/19 03:59:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -254,7 +254,7 @@ ProcessUtility(Node *parsetree,
 	switch (nodeTag(parsetree))
 	{
 			/*
-			 * ******************************** transactions ********************************
+			 * ******************** transactions ********************
 			 */
 		case T_TransactionStmt:
 			{
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 858c4339c46..bc18aeaf087 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.124 2003/01/07 22:23:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.125 2003/02/19 03:59:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2272,7 +2272,7 @@ PQoidStatus(const PGresult *res)
 
 /*
   PQoidValue -
-		a perhaps preferable form of the above which just returns
+	a perhaps preferable form of the above which just returns
 	an Oid type
 */
 Oid
@@ -2300,53 +2300,54 @@ PQoidValue(const PGresult *res)
 
 /*
    PQcmdTuples -
-	if the last command was an INSERT/UPDATE/DELETE, return number
-	of inserted/affected tuples, if not, return ""
+	If the last command was an INSERT/UPDATE/DELETE/MOVE/FETCH, return a
+	string containing the number of inserted/affected tuples. If not,
+	return "".
+
+	XXX: this should probably return an int
 */
 char *
 PQcmdTuples(PGresult *res)
 {
 	char		noticeBuf[128];
+	char		*p;
 
 	if (!res)
 		return "";
 
-	if (strncmp(res->cmdStatus, "INSERT", 6) == 0 ||
-		strncmp(res->cmdStatus, "DELETE", 6) == 0 ||
-		strncmp(res->cmdStatus, "UPDATE", 6) == 0)
+	if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
 	{
-		char	   *p = res->cmdStatus + 6;
-
-		if (*p == 0)
-		{
-			if (res->noticeHook)
-			{
-				snprintf(noticeBuf, sizeof(noticeBuf),
-						 libpq_gettext("could not interpret result from server: %s\n"),
-						 res->cmdStatus);
-				DONOTICE(res, noticeBuf);
-			}
-			return "";
-		}
+		p = res->cmdStatus + 6;
 		p++;
-		if (*(res->cmdStatus) != 'I')	/* UPDATE/DELETE */
-			return p;
+		/* INSERT: skip oid */
 		while (*p != ' ' && *p)
-			p++;				/* INSERT: skip oid */
-		if (*p == 0)
+			p++;
+	}
+	else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
+			 strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
+		p = res->cmdStatus + 6;
+	else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
+		p = res->cmdStatus + 5;
+	else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0)
+		p = res->cmdStatus + 4;
+	else
+		return "";
+
+	p++;
+
+	if (*p == 0)
+	{
+		if (res->noticeHook)
 		{
-			if (res->noticeHook)
-			{
-				snprintf(noticeBuf, sizeof(noticeBuf),
-						 libpq_gettext("no row count available\n"));
-				DONOTICE(res, noticeBuf);
-			}
-			return "";
+			snprintf(noticeBuf, sizeof(noticeBuf),
+					 libpq_gettext("could not interpret result from server: %s\n"),
+					 res->cmdStatus);
+			DONOTICE(res, noticeBuf);
 		}
-		p++;
-		return p;
+		return "";
 	}
-	return "";
+
+	return p;
 }
 
 /*
-- 
GitLab