Make the COPY command return a command tag that includes the number of
authorTom Lane
Fri, 3 Mar 2006 19:54:10 +0000 (19:54 +0000)
committerTom Lane
Fri, 3 Mar 2006 19:54:10 +0000 (19:54 +0000)
rows copied.  Backend side of Volkan Yazici's recent patch, with
corrections and documentation.

doc/src/sgml/protocol.sgml
doc/src/sgml/ref/copy.sgml
src/backend/commands/copy.c
src/backend/tcop/utility.c
src/include/commands/copy.h

index 689460ed92fd4bb76146a45f28d2dfb2b50fdeee..73eef92fff121cd3a624bb5001caf15ff40b11cd 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  Frontend/Backend Protocol
@@ -2069,7 +2069,7 @@ CommandComplete (B)
         String
 
 
-
+       
         The command tag.  This is usually a single
         word that identifies which SQL command was completed.
        
@@ -2109,7 +2109,16 @@ CommandComplete (B)
         FETCH rows where
         rows is the number of rows that
         have been retrieved from the cursor.
-
+       
+
+       
+        For a COPY command, the tag is
+        COPY rows where
+        rows is the number of rows copied.
+        (Note: the row count appears only in
+        PostgreSQL 8.2 and later.)
+       
+
 
 
 
index bf6b1f1c3fc3ac9c7c3e8f51324b0bfa46cba293..e748cc2e8e97f9be26d83c7eb32e836338fedb71 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -253,6 +253,20 @@ COPY tablename [ ( 
   
  
 
+  Outputs
+
+  
+   On successful completion, a COPY command returns a command
+   tag of the form
+
+COPY count
+
+   The count is the number
+   of rows inserted into or copied from the table.
+  
+
  
   Notes
 
index af3df4a689987810528e6753a4ffae9ced61448f..858815e56e1cdf351983f379b4e401cd7ce06e85 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.258 2006/02/03 12:41:07 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.259 2006/03/03 19:54:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,6 +102,7 @@ typedef struct CopyStateData
    int         client_encoding;    /* remote side's character encoding */
    bool        need_transcoding;       /* client encoding diff from server? */
    bool        encoding_embeds_ascii;  /* ASCII can be non-first byte? */
+   uint64      processed;      /* # of tuples processed */
 
    /* parameters from the COPY command */
    Relation    rel;            /* relation to copy to or from */
@@ -710,7 +711,7 @@ CopyLoadRawBuf(CopyState cstate)
  * Do not allow the copy if user doesn't have proper permission to access
  * the table.
  */
-void
+uint64
 DoCopy(const CopyStmt *stmt)
 {
    CopyState   cstate;
@@ -724,6 +725,7 @@ DoCopy(const CopyStmt *stmt)
    AclMode     required_access = (is_from ? ACL_INSERT : ACL_SELECT);
    AclResult   aclresult;
    ListCell   *option;
+   uint64      processed;
 
    /* Allocate workspace and zero all fields */
    cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
@@ -1019,6 +1021,7 @@ DoCopy(const CopyStmt *stmt)
    cstate->line_buf_converted = false;
    cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
    cstate->raw_buf_index = cstate->raw_buf_len = 0;
+   cstate->processed = 0;
 
    /* Set up encoding conversion info */
    cstate->client_encoding = pg_get_client_encoding();
@@ -1161,10 +1164,14 @@ DoCopy(const CopyStmt *stmt)
    heap_close(cstate->rel, (is_from ? NoLock : AccessShareLock));
 
    /* Clean up storage (probably not really necessary) */
+   processed = cstate->processed;
+
    pfree(cstate->attribute_buf.data);
    pfree(cstate->line_buf.data);
    pfree(cstate->raw_buf);
    pfree(cstate);
+
+   return processed;
 }
 
 
@@ -1401,6 +1408,8 @@ CopyTo(CopyState cstate)
        CopySendEndOfRow(cstate);
 
        MemoryContextSwitchTo(oldcontext);
+       
+       cstate->processed++;
    }
 
    heap_endscan(scandesc);
@@ -2002,6 +2011,13 @@ CopyFrom(CopyState cstate)
 
            /* AFTER ROW INSERT Triggers */
            ExecARInsertTriggers(estate, resultRelInfo, tuple);
+
+           /*
+            * We count only tuples not suppressed by a BEFORE INSERT trigger;
+            * this is the same definition used by execMain.c for counting
+            * tuples inserted by an INSERT command.
+            */
+           cstate->processed++;
        }
    }
 
index 9a9d138032b7abb52df686aad64a44a4a6ec58cd..36c6e45393a7e872027b28b1bcc101078ff1dc30 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.253 2006/03/03 03:30:53 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.254 2006/03/03 19:54:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -636,7 +636,13 @@ ProcessUtility(Node *parsetree,
            break;
 
        case T_CopyStmt:
-           DoCopy((CopyStmt *) parsetree);
+           {
+               uint64  processed = DoCopy((CopyStmt *) parsetree);
+
+               if (completionTag)
+                   snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
+                            "COPY " UINT64_FORMAT, processed);
+           }
            break;
 
        case T_PrepareStmt:
index 7a22c5bd8d011309b83a7c6c77c247ee839b8cdb..bd4e7812d96e86550d87b7613544d96a14c8536f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/copy.h,v 1.25 2004/12/31 22:03:28 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/commands/copy.h,v 1.26 2006/03/03 19:54:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,6 @@
 #include "nodes/parsenodes.h"
 
 
-extern void DoCopy(const CopyStmt *stmt);
+extern uint64 DoCopy(const CopyStmt *stmt);
 
 #endif   /* COPY_H */