mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Have SELECT and CREATE TABLE AS queries return a row count. While this
is invisible in psql, other interfaces, like libpq, make this value visible. Boszormenyi Zoltan
This commit is contained in:
parent
346a721eed
commit
aa7e7ae9a6
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.297 2010/02/05 03:09:04 joe Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.298 2010/02/16 20:58:13 momjian Exp $ -->
|
||||||
|
|
||||||
<chapter id="libpq">
|
<chapter id="libpq">
|
||||||
<title><application>libpq</application> - C Library</title>
|
<title><application>libpq</application> - C Library</title>
|
||||||
@ -2869,12 +2869,11 @@ typedef struct {
|
|||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="libpq-exec-nonselect">
|
<sect2 id="libpq-exec-nonselect">
|
||||||
<title>Retrieving Result Information for Other Commands</title>
|
<title>Retrieving Other Result Information</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
These functions are used to extract information from
|
These functions are used to extract other information from
|
||||||
<structname>PGresult</structname> objects that are not
|
<structname>PGresult</structname> objects.
|
||||||
<command>SELECT</> results.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@ -2925,12 +2924,12 @@ typedef struct {
|
|||||||
This function returns a string containing the number of rows
|
This function returns a string containing the number of rows
|
||||||
affected by the <acronym>SQL</> statement that generated the
|
affected by the <acronym>SQL</> statement that generated the
|
||||||
<structname>PGresult</>. This function can only be used following
|
<structname>PGresult</>. This function can only be used following
|
||||||
the execution of an <command>INSERT</>, <command>UPDATE</>,
|
the execution of a <command>SELECT</>, <command>CREATE TABLE AS</>,
|
||||||
<command>DELETE</>, <command>MOVE</>, <command>FETCH</>, or
|
<command>INSERT</>, <command>UPDATE</>, <command>DELETE</>,
|
||||||
<command>COPY</> statement, or an <command>EXECUTE</> of a
|
<command>MOVE</>, <command>FETCH</>, or <command>COPY</> statement,
|
||||||
prepared query that contains an <command>INSERT</>,
|
or an <command>EXECUTE</> of a prepared query that contains an
|
||||||
<command>UPDATE</>, or <command>DELETE</> statement. If the
|
<command>INSERT</>, <command>UPDATE</>, or <command>DELETE</> statement.
|
||||||
command that generated the <structname>PGresult</> was anything
|
If the command that generated the <structname>PGresult</> was anything
|
||||||
else, <function>PQcmdTuples</> returns an empty string. The caller
|
else, <function>PQcmdTuples</> returns an empty string. The caller
|
||||||
should not free the return value directly. It will be freed when
|
should not free the return value directly. It will be freed when
|
||||||
the associated <structname>PGresult</> handle is passed to
|
the associated <structname>PGresult</> handle is passed to
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/protocol.sgml,v 1.79 2010/02/16 20:15:14 momjian Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/protocol.sgml,v 1.80 2010/02/16 20:58:14 momjian Exp $ -->
|
||||||
|
|
||||||
<chapter id="protocol">
|
<chapter id="protocol">
|
||||||
<title>Frontend/Backend Protocol</title>
|
<title>Frontend/Backend Protocol</title>
|
||||||
@ -2221,6 +2221,12 @@ CommandComplete (B)
|
|||||||
<replaceable>rows</replaceable> is the number of rows updated.
|
<replaceable>rows</replaceable> is the number of rows updated.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For a <command>SELECT</command> or <command>CREATE TABLE AS</command>
|
||||||
|
command, the tag is <literal>SELECT <replaceable>rows</replaceable></literal>
|
||||||
|
where <replaceable>rows</replaceable> is the number of rows retrieved.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For a <command>MOVE</command> command, the tag is
|
For a <command>MOVE</command> command, the tag is
|
||||||
<literal>MOVE <replaceable>rows</replaceable></literal> where
|
<literal>MOVE <replaceable>rows</replaceable></literal> where
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.135 2010/02/13 22:45:41 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.136 2010/02/16 20:58:14 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -205,7 +205,8 @@ ProcessQuery(PlannedStmt *plan,
|
|||||||
switch (queryDesc->operation)
|
switch (queryDesc->operation)
|
||||||
{
|
{
|
||||||
case CMD_SELECT:
|
case CMD_SELECT:
|
||||||
strcpy(completionTag, "SELECT");
|
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
|
||||||
|
"SELECT %u", queryDesc->estate->es_processed);
|
||||||
break;
|
break;
|
||||||
case CMD_INSERT:
|
case CMD_INSERT:
|
||||||
if (queryDesc->estate->es_processed == 1)
|
if (queryDesc->estate->es_processed == 1)
|
||||||
@ -714,6 +715,7 @@ PortalRun(Portal portal, long count, bool isTopLevel,
|
|||||||
char *completionTag)
|
char *completionTag)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
uint32 nprocessed;
|
||||||
ResourceOwner saveTopTransactionResourceOwner;
|
ResourceOwner saveTopTransactionResourceOwner;
|
||||||
MemoryContext saveTopTransactionContext;
|
MemoryContext saveTopTransactionContext;
|
||||||
Portal saveActivePortal;
|
Portal saveActivePortal;
|
||||||
@ -776,39 +778,35 @@ PortalRun(Portal portal, long count, bool isTopLevel,
|
|||||||
switch (portal->strategy)
|
switch (portal->strategy)
|
||||||
{
|
{
|
||||||
case PORTAL_ONE_SELECT:
|
case PORTAL_ONE_SELECT:
|
||||||
(void) PortalRunSelect(portal, true, count, dest);
|
|
||||||
|
|
||||||
/* we know the query is supposed to set the tag */
|
|
||||||
if (completionTag && portal->commandTag)
|
|
||||||
strcpy(completionTag, portal->commandTag);
|
|
||||||
|
|
||||||
/* Mark portal not active */
|
|
||||||
portal->status = PORTAL_READY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since it's a forward fetch, say DONE iff atEnd is now true.
|
|
||||||
*/
|
|
||||||
result = portal->atEnd;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PORTAL_ONE_RETURNING:
|
case PORTAL_ONE_RETURNING:
|
||||||
case PORTAL_UTIL_SELECT:
|
case PORTAL_UTIL_SELECT:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have not yet run the command, do so, storing its
|
* If we have not yet run the command, do so, storing its
|
||||||
* results in the portal's tuplestore.
|
* results in the portal's tuplestore. Do this only for the
|
||||||
|
* PORTAL_ONE_RETURNING and PORTAL_UTIL_SELECT cases.
|
||||||
*/
|
*/
|
||||||
if (!portal->holdStore)
|
if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
|
||||||
FillPortalStore(portal, isTopLevel);
|
FillPortalStore(portal, isTopLevel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now fetch desired portion of results.
|
* Now fetch desired portion of results.
|
||||||
*/
|
*/
|
||||||
(void) PortalRunSelect(portal, true, count, dest);
|
nprocessed = PortalRunSelect(portal, true, count, dest);
|
||||||
|
|
||||||
/* we know the query is supposed to set the tag */
|
/*
|
||||||
|
* If the portal result contains a command tag and the caller
|
||||||
|
* gave us a pointer to store it, copy it. Patch the "SELECT"
|
||||||
|
* tag to also provide the rowcount.
|
||||||
|
*/
|
||||||
if (completionTag && portal->commandTag)
|
if (completionTag && portal->commandTag)
|
||||||
strcpy(completionTag, portal->commandTag);
|
{
|
||||||
|
if (strcmp(portal->commandTag, "SELECT") == 0)
|
||||||
|
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
|
||||||
|
"SELECT %u", nprocessed);
|
||||||
|
else
|
||||||
|
strcpy(completionTag, portal->commandTag);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark portal not active */
|
/* Mark portal not active */
|
||||||
portal->status = PORTAL_READY;
|
portal->status = PORTAL_READY;
|
||||||
@ -1331,7 +1329,9 @@ PortalRunMulti(Portal portal, bool isTopLevel,
|
|||||||
{
|
{
|
||||||
if (portal->commandTag)
|
if (portal->commandTag)
|
||||||
strcpy(completionTag, portal->commandTag);
|
strcpy(completionTag, portal->commandTag);
|
||||||
if (strcmp(completionTag, "INSERT") == 0)
|
if (strcmp(completionTag, "SELECT") == 0)
|
||||||
|
sprintf(completionTag, "SELECT 0 0");
|
||||||
|
else if (strcmp(completionTag, "INSERT") == 0)
|
||||||
strcpy(completionTag, "INSERT 0 0");
|
strcpy(completionTag, "INSERT 0 0");
|
||||||
else if (strcmp(completionTag, "UPDATE") == 0)
|
else if (strcmp(completionTag, "UPDATE") == 0)
|
||||||
strcpy(completionTag, "UPDATE 0");
|
strcpy(completionTag, "UPDATE 0");
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.208 2010/01/21 18:43:25 rhaas Exp $
|
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.209 2010/02/16 20:58:14 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2752,7 +2752,8 @@ PQcmdTuples(PGresult *res)
|
|||||||
goto interpret_error; /* no space? */
|
goto interpret_error; /* no space? */
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
|
else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
|
||||||
|
strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
|
||||||
strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
|
strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
|
||||||
p = res->cmdStatus + 7;
|
p = res->cmdStatus + 7;
|
||||||
else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
|
else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user