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