Robert Haas írta:
> ...
> OK, please change it.
>   

New patch is attached with the discussed changes.

>>> Someone who knows the overall structure of the code better than I do
>>> will have to comment on whether there are any code paths to worry
>>> about that do not go through PortalRun().
>>>
>>> A general concern I have is that this what we're basically doing here
>>> is handling the most common case in ProcessQuery() and then installing
>>> fallback mechanisms to pick up any stragglers: but the fallback
>>> mechanisms only guarantee that we'll add a number to the command tag,
>>> not that it will be meaningful.  Unfortunately, my limited imagination
>>> can't quite figure out in what cases we'll get a SELECT command tag
>>> back other than (1) plain old SELECT, (2) SELECT INTO, and (3) CTAS,
>>> so I'm not sure what to go test.
>>>       
>
> Any thoughts on these issues, anyone?
>
> ...Robert
>   

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/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

Reply via email to