summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2010-02-16 20:58:14 +0000
committerBruce Momjian <bruce@momjian.us>2010-02-16 20:58:14 +0000
commitaa7e7ae9a6adfd5553ed05144cf765fbf7c8f5af (patch)
treefc46bf6e0d1c1a278c30c8e41a5e19547786d55b
parent346a721eed4c0bcfb07039633807b67443f21bbf (diff)
downloadpostgresql-aa7e7ae9a6adfd5553ed05144cf765fbf7c8f5af.tar.gz
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
-rw-r--r--doc/src/sgml/libpq.sgml21
-rw-r--r--doc/src/sgml/protocol.sgml8
-rw-r--r--src/backend/tcop/pquery.c46
-rw-r--r--src/interfaces/libpq/fe-exec.c5
4 files changed, 43 insertions, 37 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index c7131fea4c..4972a8c259 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -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">
<title><application>libpq</application> - C Library</title>
@@ -2869,12 +2869,11 @@ typedef struct {
</sect2>
<sect2 id="libpq-exec-nonselect">
- <title>Retrieving Result Information for Other Commands</title>
+ <title>Retrieving Other Result Information</title>
<para>
- These functions are used to extract information from
- <structname>PGresult</structname> objects that are not
- <command>SELECT</> results.
+ These functions are used to extract other information from
+ <structname>PGresult</structname> objects.
</para>
<variablelist>
@@ -2925,12 +2924,12 @@ typedef struct {
This function returns a string containing the number of rows
affected by the <acronym>SQL</> statement that generated the
<structname>PGresult</>. This function can only be used following
- the execution of an <command>INSERT</>, <command>UPDATE</>,
- <command>DELETE</>, <command>MOVE</>, <command>FETCH</>, or
- <command>COPY</> statement, or an <command>EXECUTE</> of a
- prepared query that contains an <command>INSERT</>,
- <command>UPDATE</>, or <command>DELETE</> statement. If the
- command that generated the <structname>PGresult</> was anything
+ the execution of a <command>SELECT</>, <command>CREATE TABLE AS</>,
+ <command>INSERT</>, <command>UPDATE</>, <command>DELETE</>,
+ <command>MOVE</>, <command>FETCH</>, or <command>COPY</> statement,
+ or an <command>EXECUTE</> of a prepared query that contains an
+ <command>INSERT</>, <command>UPDATE</>, or <command>DELETE</> statement.
+ If the command that generated the <structname>PGresult</> was anything
else, <function>PQcmdTuples</> returns an empty string. The caller
should not free the return value directly. It will be freed when
the associated <structname>PGresult</> handle is passed to
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 5b69f37324..e4364ec305 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -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">
<title>Frontend/Backend Protocol</title>
@@ -2222,6 +2222,12 @@ CommandComplete (B)
</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>
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
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 42960b8225..8beb82385a 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -8,7 +8,7 @@
*
*
* 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)
{
case CMD_SELECT:
- strcpy(completionTag, "SELECT");
+ snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
+ "SELECT %u", queryDesc->estate->es_processed);
break;
case CMD_INSERT:
if (queryDesc->estate->es_processed == 1)
@@ -714,6 +715,7 @@ PortalRun(Portal portal, long count, bool isTopLevel,
char *completionTag)
{
bool result;
+ uint32 nprocessed;
ResourceOwner saveTopTransactionResourceOwner;
MemoryContext saveTopTransactionContext;
Portal saveActivePortal;
@@ -776,39 +778,35 @@ PortalRun(Portal portal, long count, bool isTopLevel,
switch (portal->strategy)
{
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_UTIL_SELECT:
/*
* 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);
/*
* 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)
- 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 */
portal->status = PORTAL_READY;
@@ -1331,7 +1329,9 @@ PortalRunMulti(Portal portal, bool isTopLevel,
{
if (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");
else if (strcmp(completionTag, "UPDATE") == 0)
strcpy(completionTag, "UPDATE 0");
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 2e5551d31e..df4e8879c8 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
*
*
* 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? */
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)
p = res->cmdStatus + 7;
else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)