(unnamed)

text/plain

Filename: (unnamed)
Type: text/plain
Part: 0
Message: Re: [PATCH] Provide rowcount for utility SELECTs
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v
retrieving revision 1.297
diff -c -c -r1.297 libpq.sgml
*** doc/src/sgml/libpq.sgml	5 Feb 2010 03:09:04 -0000	1.297
--- doc/src/sgml/libpq.sgml	14 Feb 2010 03:11:00 -0000
***************
*** 2869,2880 ****
    </sect2>
  
    <sect2 id="libpq-exec-nonselect">
!    <title>Retrieving Result Information for Other Commands</title>
  
     <para>
!     These functions are used to extract information from
!     <structname>PGresult</structname> objects that are not
!     <command>SELECT</> results.
     </para>
  
     <variablelist>
--- 2869,2879 ----
    </sect2>
  
    <sect2 id="libpq-exec-nonselect">
!    <title>Retrieving Other Result Information</title>
  
     <para>
!     These functions are used to extract other information from
!     <structname>PGresult</structname> objects.
     </para>
  
     <variablelist>
***************
*** 2925,2936 ****
         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
         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
--- 2924,2935 ----
         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 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
Index: doc/src/sgml/protocol.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v
retrieving revision 1.78
diff -c -c -r1.78 protocol.sgml
*** doc/src/sgml/protocol.sgml	3 Feb 2010 09:47:19 -0000	1.78
--- doc/src/sgml/protocol.sgml	14 Feb 2010 03:11:00 -0000
***************
*** 2222,2227 ****
--- 2222,2233 ----
         </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
Index: src/backend/tcop/pquery.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tcop/pquery.c,v
retrieving revision 1.135
diff -c -c -r1.135 pquery.c
*** src/backend/tcop/pquery.c	13 Feb 2010 22:45:41 -0000	1.135
--- src/backend/tcop/pquery.c	14 Feb 2010 03:11:04 -0000
***************
*** 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)
***************
*** 714,719 ****
--- 715,721 ----
  		  char *completionTag)
  {
  	bool		result;
+ 	uint32		nprocessed;
  	ResourceOwner saveTopTransactionResourceOwner;
  	MemoryContext saveTopTransactionContext;
  	Portal		saveActivePortal;
***************
*** 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;
***************
*** 1331,1337 ****
  	{
  		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");
--- 1329,1337 ----
  	{
  		if (portal->commandTag)
  			strcpy(completionTag, portal->commandTag);
! 		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");
Index: src/interfaces/libpq/fe-exec.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v
retrieving revision 1.208
diff -c -c -r1.208 fe-exec.c
*** src/interfaces/libpq/fe-exec.c	21 Jan 2010 18:43:25 -0000	1.208
--- src/interfaces/libpq/fe-exec.c	14 Feb 2010 03:11:04 -0000
***************
*** 2752,2758 ****
  			goto interpret_error;		/* no space? */
  		p++;
  	}
! 	else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
  			 strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
  		p = res->cmdStatus + 7;
  	else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
--- 2752,2759 ----
  			goto interpret_error;		/* no space? */
  		p++;
  	}
! 	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)