Allow PQcmdTuples to return row counts for MOVE and FETCH.

Neil Conway
This commit is contained in:
Bruce Momjian 2003-02-19 03:59:02 +00:00
parent 1eb9fd49d1
commit 81f6db4803
4 changed files with 92 additions and 71 deletions

View File

@ -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"> <chapter id="libpq">
@ -702,12 +702,11 @@ char *PQerrorMessage(const PGconn* conn);
int PQbackendPID(const PGconn *conn); int PQbackendPID(const PGconn *conn);
</synopsis> </synopsis>
The backend <acronym>PID</acronym> is useful for debugging The backend <acronym>PID</acronym> is useful for debugging
purposes and for comparison purposes and for comparison to <command>NOTIFY</command>
to NOTIFY messages (which include the <acronym>PID</acronym> of messages (which include the <acronym>PID</acronym> of the
the notifying backend). notifying backend). Note that the <acronym>PID</acronym>
Note that the <acronym>PID</acronym> belongs to a process belongs to a process executing on the database server host, not
executing on the database the local host!
server host, not the local host!
</para> </para>
</listitem> </listitem>
@ -818,13 +817,14 @@ ExecStatusType PQresultStatus(const PGresult *res)
</listitem> </listitem>
</itemizedlist> </itemizedlist>
If the result status is <literal>PGRES_TUPLES_OK</literal>, then the If the result status is <literal>PGRES_TUPLES_OK</literal>, then the
routines described below can be used to retrieve the routines described below can be used to retrieve the rows returned by
rows returned by the query. Note that a SELECT command that the query. Note that a <command>SELECT</command> command that happens
happens to retrieve zero rows still shows <literal>PGRES_TUPLES_OK</literal>. to retrieve zero rows still shows <literal>PGRES_TUPLES_OK</literal>.
<literal>PGRES_COMMAND_OK</literal> is for commands that can never return rows <literal>PGRES_COMMAND_OK</literal> is for commands that can never
(INSERT, UPDATE, etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often return rows (<command>INSERT</command>, <command>UPDATE</command>,
exposes a bug in the client software. etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often
indicates a bug in the client software.
</para> </para>
</listitem> </listitem>
@ -1243,36 +1243,41 @@ char * PQcmdStatus(PGresult *res);
char * PQcmdTuples(PGresult *res); char * PQcmdTuples(PGresult *res);
</synopsis> </synopsis>
If the <acronym>SQL</acronym> command that generated the If the <acronym>SQL</acronym> command that generated the
<structname>PGresult</structname> was INSERT, UPDATE or DELETE, this returns a <structname>PGresult</structname> was <command>INSERT</command>,
string containing the number of rows affected. If the <command>UPDATE</command>, <command>DELETE</command>,
command was anything else, it returns the empty string. <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> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>PQoidValue</function> <function>PQoidValue</function>
Returns the object ID of the inserted row, if the Returns the object ID of the inserted row, if the
<acronym>SQL</acronym> command was an INSERT <acronym>SQL</acronym> command was an <command>INSERT</command>
that inserted exactly one row into a table that has OIDs. that inserted exactly one row into a table that has OIDs.
Otherwise, returns <literal>InvalidOid</literal>. Otherwise, returns <literal>InvalidOid</literal>.
<synopsis> <synopsis>
Oid PQoidValue(const PGresult *res); Oid PQoidValue(const PGresult *res);
</synopsis> </synopsis>
The type <type>Oid</type> and the constant <literal>InvalidOid</literal> The type <type>Oid</type> and the constant
will be defined if you include the <application>libpq</application> <literal>InvalidOid</literal> will be defined if you include the
header file. They will both be some integer type. <application>libpq</application> header file. They will both be
some integer type.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>PQoidStatus</function> <function>PQoidStatus</function>
Returns a string with the object ID of the inserted row, if the Returns a string with the object ID
<acronym>SQL</acronym> command was an INSERT. of the inserted row, if the <acronym>SQL</acronym> command
(The string will be <literal>0</> if the INSERT did not insert exactly one was an <command>INSERT</command>. (The string will be
row, or if the target table does not have OIDs.) If the command <literal>0</> if the <command>INSERT</command> did not
was not an INSERT, returns an empty string. 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> <synopsis>
char * PQoidStatus(const PGresult *res); char * PQoidStatus(const PGresult *res);
</synopsis> </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>PQconsumeInput</function> to read the input. It can then call
<function>PQisBusy</function>, followed by <function>PQgetResult</function> <function>PQisBusy</function>, followed by <function>PQgetResult</function>
if <function>PQisBusy</function> returns false (0). It can also call 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>
<para> <para>
@ -1700,13 +1706,13 @@ of asynchronous notification.
<function>PQnotifies()</function> does not actually read backend data; it just <function>PQnotifies()</function> does not actually read backend data; it just
returns messages previously absorbed by another <application>libpq</application> returns messages previously absorbed by another <application>libpq</application>
function. In prior releases of <application>libpq</application>, the only way 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 even empty ones, and then check <function>PQnotifies()</function> after each
<function>PQexec()</function>. While this still works, it is <function>PQexec()</function>. While this still works, it is
deprecated as a waste of processing power. deprecated as a waste of processing power.
</para> </para>
<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 messages when you have no useful queries to make is to call
<function>PQconsumeInput()</function>, then check <function>PQconsumeInput()</function>, then check
<function>PQnotifies()</function>. <function>PQnotifies()</function>.

View File

@ -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"> <chapter id="protocol">
<title>Frontend/Backend Protocol</title> <title>Frontend/Backend Protocol</title>
@ -1335,6 +1335,20 @@ CompletedResponse (B)
<literal>UPDATE <Replaceable>rows</Replaceable></literal> where <literal>UPDATE <Replaceable>rows</Replaceable></literal> where
<Replaceable>rows</Replaceable> is the number of rows updated. <Replaceable>rows</Replaceable> is the number of rows updated.
</Para> </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> </ListItem>
</VarListEntry> </VarListEntry>
</VariableList> </VariableList>

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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)) switch (nodeTag(parsetree))
{ {
/* /*
* ******************************** transactions ******************************** * ******************** transactions ********************
*/ */
case T_TransactionStmt: case T_TransactionStmt:
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 - PQoidValue -
a perhaps preferable form of the above which just returns a perhaps preferable form of the above which just returns
an Oid type an Oid type
*/ */
Oid Oid
@ -2300,53 +2300,54 @@ PQoidValue(const PGresult *res)
/* /*
PQcmdTuples - PQcmdTuples -
if the last command was an INSERT/UPDATE/DELETE, return number If the last command was an INSERT/UPDATE/DELETE/MOVE/FETCH, return a
of inserted/affected tuples, if not, return "" string containing the number of inserted/affected tuples. If not,
return "".
XXX: this should probably return an int
*/ */
char * char *
PQcmdTuples(PGresult *res) PQcmdTuples(PGresult *res)
{ {
char noticeBuf[128]; char noticeBuf[128];
char *p;
if (!res) if (!res)
return ""; return "";
if (strncmp(res->cmdStatus, "INSERT", 6) == 0 || if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
strncmp(res->cmdStatus, "DELETE", 6) == 0 ||
strncmp(res->cmdStatus, "UPDATE", 6) == 0)
{ {
char *p = res->cmdStatus + 6; 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++; p++;
if (*(res->cmdStatus) != 'I') /* UPDATE/DELETE */ /* INSERT: skip oid */
return p;
while (*p != ' ' && *p) while (*p != ' ' && *p)
p++; /* INSERT: skip oid */ p++;
if (*p == 0)
{
if (res->noticeHook)
{
snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("no row count available\n"));
DONOTICE(res, noticeBuf);
}
return "";
}
p++;
return p;
} }
return ""; 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)
{
snprintf(noticeBuf, sizeof(noticeBuf),
libpq_gettext("could not interpret result from server: %s\n"),
res->cmdStatus);
DONOTICE(res, noticeBuf);
}
return "";
}
return p;
} }
/* /*