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 @@ - + <application>libpq</application> - C Library @@ -2869,12 +2869,11 @@ typedef struct { - Retrieving Result Information for Other Commands + Retrieving Other Result Information - These functions are used to extract information from - PGresult objects that are not - SELECT results. + These functions are used to extract other information from + PGresult objects. @@ -2925,12 +2924,12 @@ typedef struct { This function returns a string containing the number of rows affected by the SQL statement that generated the PGresult. This function can only be used following - the execution of an INSERT, UPDATE, - DELETE, MOVE, FETCH, or - COPY statement, or an EXECUTE of a - prepared query that contains an INSERT, - UPDATE, or DELETE statement. If the - command that generated the PGresult was anything + the execution of a SELECT, CREATE TABLE AS, + INSERT, UPDATE, DELETE, + MOVE, FETCH, or COPY statement, + or an EXECUTE of a prepared query that contains an + INSERT, UPDATE, or DELETE statement. + If the command that generated the PGresult was anything else, PQcmdTuples returns an empty string. The caller should not free the return value directly. It will be freed when the associated 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 @@ - + Frontend/Backend Protocol @@ -2221,6 +2221,12 @@ CommandComplete (B) rows is the number of rows updated. + + For a SELECT or CREATE TABLE AS + command, the tag is SELECT rows + where rows is the number of rows retrieved. + + For a MOVE command, the tag is MOVE rows where 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)