Robert Haas írta: > On Mon, Feb 8, 2010 at 5:53 AM, Boszormenyi Zoltan <z...@cybertec.at> wrote: > >> New patch is attached with the discussed changes. >> > > This looks OK to me now, but it lacks docs. > > I'll set it to Waiting on Author. > > ...Robert >
I added a small change to protocol.sgml for the "CommandComplete" message describing the change. Is it enough? Best regards, Zoltán Böszörményi -- Bible has answers for everything. Proof: "But let your communication be, Yea, yea; Nay, nay: for whatsoever is more than these cometh of evil." (Matthew 5:37) - basics of digital technology. "May your kingdom come" - superficial description of plate tectonics ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH http://www.postgresql.at/
diff -dcrpN pgsql.orig/doc/src/sgml/protocol.sgml pgsql/doc/src/sgml/protocol.sgml *** pgsql.orig/doc/src/sgml/protocol.sgml 2010-02-03 11:12:23.000000000 +0100 --- pgsql/doc/src/sgml/protocol.sgml 2010-02-12 16:44:18.000000000 +0100 *************** CommandComplete (B) *** 2222,2227 **** --- 2222,2234 ---- </para> <para> + For a <command>SELECT [INTO]</command> and + <command>CREATE TABLE ... AS query</command> commands, + 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 -dcrpN pgsql.orig/src/backend/tcop/pquery.c pgsql/src/backend/tcop/pquery.c *** pgsql.orig/src/backend/tcop/pquery.c 2010-01-03 12:54:25.000000000 +0100 --- pgsql/src/backend/tcop/pquery.c 2010-02-08 11:46:33.000000000 +0100 *************** ProcessQuery(PlannedStmt *plan, *** 205,211 **** switch (queryDesc->operation) { case CMD_SELECT: ! strcpy(completionTag, "SELECT"); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) --- 205,212 ---- switch (queryDesc->operation) { case CMD_SELECT: ! snprintf(completionTag, COMPLETION_TAG_BUFSIZE, ! "SELECT %u", queryDesc->estate->es_processed); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) *************** PortalRun(Portal portal, long count, boo *** 714,719 **** --- 715,721 ---- char *completionTag) { bool result; + uint32 nprocessed; ResourceOwner saveTopTransactionResourceOwner; MemoryContext saveTopTransactionContext; Portal saveActivePortal; *************** PortalRun(Portal portal, long count, boo *** 776,814 **** 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. */ ! if (!portal->holdStore) FillPortalStore(portal, isTopLevel); /* * Now fetch desired portion of results. */ ! (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; --- 778,812 ---- switch (portal->strategy) { case PORTAL_ONE_SELECT: 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. Do this only for the ! * PORTAL_ONE_RETURNING and PORTAL_UTIL_SELECT cases. */ ! if ((portal->strategy != PORTAL_ONE_SELECT) && (!portal->holdStore)) FillPortalStore(portal, isTopLevel); /* * Now fetch desired portion of results. */ ! nprocessed = PortalRunSelect(portal, true, count, dest); ! /* ! * 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 (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; *************** PortalRunMulti(Portal portal, bool isTop *** 1318,1337 **** * If a command completion tag was supplied, use it. Otherwise use the * portal's commandTag as the default completion tag. * ! * Exception: clients will expect INSERT/UPDATE/DELETE tags to have ! * counts, so fake something up if necessary. (This could happen if the * original query was replaced by a DO INSTEAD rule.) */ if (completionTag && completionTag[0] == '\0') { if (portal->commandTag) strcpy(completionTag, portal->commandTag); if (strcmp(completionTag, "INSERT") == 0) ! strcpy(completionTag, "INSERT 0 0"); else if (strcmp(completionTag, "UPDATE") == 0) ! strcpy(completionTag, "UPDATE 0"); else if (strcmp(completionTag, "DELETE") == 0) ! strcpy(completionTag, "DELETE 0"); } } --- 1316,1346 ---- * If a command completion tag was supplied, use it. Otherwise use the * portal's commandTag as the default completion tag. * ! * Exception: clients will expect SELECT/INSERT/UPDATE/DELETE tags to have ! * counts, so try to provide the proper info. (This could happen if the * original query was replaced by a DO INSTEAD rule.) */ if (completionTag && completionTag[0] == '\0') { + Oid lastOid = InvalidOid; + uint32 processed = 0; + + if (portal->queryDesc && portal->queryDesc->estate) + { + lastOid = portal->queryDesc->estate->es_lastoid; + processed = portal->queryDesc->estate->es_processed; + } + if (portal->commandTag) strcpy(completionTag, portal->commandTag); if (strcmp(completionTag, "INSERT") == 0) ! sprintf(completionTag, "INSERT %u %u", lastOid, processed); else if (strcmp(completionTag, "UPDATE") == 0) ! sprintf(completionTag, "UPDATE %u", processed); else if (strcmp(completionTag, "DELETE") == 0) ! sprintf(completionTag, "DELETE %u", processed); ! else if (strcmp(completionTag, "SELECT") == 0) ! sprintf(completionTag, "SELECT %u", processed); } } diff -dcrpN pgsql.orig/src/interfaces/libpq/fe-exec.c pgsql/src/interfaces/libpq/fe-exec.c *** pgsql.orig/src/interfaces/libpq/fe-exec.c 2010-01-21 20:45:39.000000000 +0100 --- pgsql/src/interfaces/libpq/fe-exec.c 2010-02-08 10:32:25.000000000 +0100 *************** PQcmdTuples(PGresult *res) *** 2753,2758 **** --- 2753,2759 ---- p++; } else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 || + strncmp(res->cmdStatus, "SELECT ", 7) == 0 || strncmp(res->cmdStatus, "UPDATE ", 7) == 0) p = res->cmdStatus + 7; else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers