Make the COPY command return a command tag that includes the number of
rows copied. Backend side of Volkan Yazici's recent patch, with corrections and documentation.
This commit is contained in:
parent
4e086f7cb5
commit
023570f5e3
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/protocol.sgml,v 1.63 2006/01/18 06:49:25 neilc Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/protocol.sgml,v 1.64 2006/03/03 19:54:09 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="protocol">
|
<chapter id="protocol">
|
||||||
<title>Frontend/Backend Protocol</title>
|
<title>Frontend/Backend Protocol</title>
|
||||||
|
@ -2069,7 +2069,7 @@ CommandComplete (B)
|
||||||
String
|
String
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The command tag. This is usually a single
|
The command tag. This is usually a single
|
||||||
word that identifies which SQL command was completed.
|
word that identifies which SQL command was completed.
|
||||||
</para>
|
</para>
|
||||||
|
@ -2109,7 +2109,16 @@ CommandComplete (B)
|
||||||
<literal>FETCH <replaceable>rows</replaceable></literal> where
|
<literal>FETCH <replaceable>rows</replaceable></literal> where
|
||||||
<replaceable>rows</replaceable> is the number of rows that
|
<replaceable>rows</replaceable> is the number of rows that
|
||||||
have been retrieved from the cursor.
|
have been retrieved from the cursor.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For a <command>COPY</command> command, the tag is
|
||||||
|
<literal>COPY <replaceable>rows</replaceable></literal> where
|
||||||
|
<replaceable>rows</replaceable> is the number of rows copied.
|
||||||
|
(Note: the row count appears only in
|
||||||
|
<productname>PostgreSQL</productname> 8.2 and later.)
|
||||||
|
</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.72 2005/12/28 14:38:32 momjian Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.73 2006/03/03 19:54:10 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -253,6 +253,20 @@ COPY <replaceable class="parameter">tablename</replaceable> [ ( <replaceable cla
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Outputs</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
On successful completion, a <command>COPY</> command returns a command
|
||||||
|
tag of the form
|
||||||
|
<screen>
|
||||||
|
COPY <replaceable class="parameter">count</replaceable>
|
||||||
|
</screen>
|
||||||
|
The <replaceable class="parameter">count</replaceable> is the number
|
||||||
|
of rows inserted into or copied from the table.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Notes</title>
|
<title>Notes</title>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
int client_encoding; /* remote side's character encoding */
|
||||||
bool need_transcoding; /* client encoding diff from server? */
|
bool need_transcoding; /* client encoding diff from server? */
|
||||||
bool encoding_embeds_ascii; /* ASCII can be non-first byte? */
|
bool encoding_embeds_ascii; /* ASCII can be non-first byte? */
|
||||||
|
uint64 processed; /* # of tuples processed */
|
||||||
|
|
||||||
/* parameters from the COPY command */
|
/* parameters from the COPY command */
|
||||||
Relation rel; /* relation to copy to or from */
|
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
|
* Do not allow the copy if user doesn't have proper permission to access
|
||||||
* the table.
|
* the table.
|
||||||
*/
|
*/
|
||||||
void
|
uint64
|
||||||
DoCopy(const CopyStmt *stmt)
|
DoCopy(const CopyStmt *stmt)
|
||||||
{
|
{
|
||||||
CopyState cstate;
|
CopyState cstate;
|
||||||
|
@ -724,6 +725,7 @@ DoCopy(const CopyStmt *stmt)
|
||||||
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
|
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
|
||||||
AclResult aclresult;
|
AclResult aclresult;
|
||||||
ListCell *option;
|
ListCell *option;
|
||||||
|
uint64 processed;
|
||||||
|
|
||||||
/* Allocate workspace and zero all fields */
|
/* Allocate workspace and zero all fields */
|
||||||
cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
|
cstate = (CopyStateData *) palloc0(sizeof(CopyStateData));
|
||||||
|
@ -1019,6 +1021,7 @@ DoCopy(const CopyStmt *stmt)
|
||||||
cstate->line_buf_converted = false;
|
cstate->line_buf_converted = false;
|
||||||
cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
|
cstate->raw_buf = (char *) palloc(RAW_BUF_SIZE + 1);
|
||||||
cstate->raw_buf_index = cstate->raw_buf_len = 0;
|
cstate->raw_buf_index = cstate->raw_buf_len = 0;
|
||||||
|
cstate->processed = 0;
|
||||||
|
|
||||||
/* Set up encoding conversion info */
|
/* Set up encoding conversion info */
|
||||||
cstate->client_encoding = pg_get_client_encoding();
|
cstate->client_encoding = pg_get_client_encoding();
|
||||||
|
@ -1161,10 +1164,14 @@ DoCopy(const CopyStmt *stmt)
|
||||||
heap_close(cstate->rel, (is_from ? NoLock : AccessShareLock));
|
heap_close(cstate->rel, (is_from ? NoLock : AccessShareLock));
|
||||||
|
|
||||||
/* Clean up storage (probably not really necessary) */
|
/* Clean up storage (probably not really necessary) */
|
||||||
|
processed = cstate->processed;
|
||||||
|
|
||||||
pfree(cstate->attribute_buf.data);
|
pfree(cstate->attribute_buf.data);
|
||||||
pfree(cstate->line_buf.data);
|
pfree(cstate->line_buf.data);
|
||||||
pfree(cstate->raw_buf);
|
pfree(cstate->raw_buf);
|
||||||
pfree(cstate);
|
pfree(cstate);
|
||||||
|
|
||||||
|
return processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1401,6 +1408,8 @@ CopyTo(CopyState cstate)
|
||||||
CopySendEndOfRow(cstate);
|
CopySendEndOfRow(cstate);
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
|
||||||
|
cstate->processed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_endscan(scandesc);
|
heap_endscan(scandesc);
|
||||||
|
@ -2002,6 +2011,13 @@ CopyFrom(CopyState cstate)
|
||||||
|
|
||||||
/* AFTER ROW INSERT Triggers */
|
/* AFTER ROW INSERT Triggers */
|
||||||
ExecARInsertTriggers(estate, resultRelInfo, tuple);
|
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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
break;
|
||||||
|
|
||||||
case T_CopyStmt:
|
case T_CopyStmt:
|
||||||
DoCopy((CopyStmt *) parsetree);
|
{
|
||||||
|
uint64 processed = DoCopy((CopyStmt *) parsetree);
|
||||||
|
|
||||||
|
if (completionTag)
|
||||||
|
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
|
||||||
|
"COPY " UINT64_FORMAT, processed);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_PrepareStmt:
|
case T_PrepareStmt:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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"
|
#include "nodes/parsenodes.h"
|
||||||
|
|
||||||
|
|
||||||
extern void DoCopy(const CopyStmt *stmt);
|
extern uint64 DoCopy(const CopyStmt *stmt);
|
||||||
|
|
||||||
#endif /* COPY_H */
|
#endif /* COPY_H */
|
||||||
|
|
Loading…
Reference in New Issue