Thread: ToDo: allow to get a number of processed rows by COPY statement
Hello There is not possible to get a number of processed rows when COPY is evaluated via SPI. Client can use a tag, but SPI doesn't use a tag. I propose a small change a ProcessUtility to return a processed rows. Note: I found a small inconsistency between SPI and Utility interface. SPI still use a 4 byte unsign int for storing a number of processed rows. Utility use a 8bytes unsign int. Motivation: postgres=# \sf fx CREATE OR REPLACE FUNCTION public.fx(tablename text, filename text) RETURNS integer LANGUAGE plpgsql AS $function$ declare r int; begin execute format('COPY %s FROM %s', quote_ident(tablename), quote_literal(filename)); get diagnostics r = row_count; return r; end; $function$ Regards Pavel Stehule
Attachment
Pavel Stehule <pavel.stehule@gmail.com> wrote: > There is not possible to get a number of processed rows when COPY > is evaluated via SPI. Client can use a tag, but SPI doesn't use a > tag. > > I propose a small change a ProcessUtility to return a processed > rows. Please add this to the open CommitFest: https://commitfest.postgresql.org/action/commitfest_view/open -Kevin
What ever happened to this patch? I don't see it on any of the commit-fests, though someone was asked for it to be added: http://archives.postgresql.org/pgsql-hackers/2011-10/msg00381.php --------------------------------------------------------------------------- On Tue, Oct 4, 2011 at 12:22:19PM +0200, Pavel Stehule wrote: > Hello > > There is not possible to get a number of processed rows when COPY is > evaluated via SPI. Client can use a tag, but SPI doesn't use a tag. > > I propose a small change a ProcessUtility to return a processed rows. > > Note: I found a small inconsistency between SPI and Utility interface. > SPI still use a 4 byte unsign int for storing a number of processed > rows. Utility use a 8bytes unsign int. > > Motivation: > > postgres=# \sf fx > CREATE OR REPLACE FUNCTION public.fx(tablename text, filename text) > RETURNS integer > LANGUAGE plpgsql > AS $function$ > declare r int; > begin > execute format('COPY %s FROM %s', quote_ident(tablename), > quote_literal(filename)); > get diagnostics r = row_count; > return r; > end; > $function$ > > Regards > > Pavel Stehule > diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c > index 398bc40..a7c2b8f 100644 > --- a/src/backend/executor/functions.c > +++ b/src/backend/executor/functions.c > @@ -600,6 +600,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) > es->qd->params, > false, /* not top level */ > es->qd->dest, > + NULL, > NULL); > result = true; /* never stops early */ > } > diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c > index 688279c..21cabcc 100644 > --- a/src/backend/executor/spi.c > +++ b/src/backend/executor/spi.c > @@ -1838,6 +1838,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, > { > Node *stmt = (Node *) lfirst(lc2); > bool canSetTag; > + bool isCopyStmt = false; > DestReceiver *dest; > > _SPI_current->processed = 0; > @@ -1857,6 +1858,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, > { > CopyStmt *cstmt = (CopyStmt *) stmt; > > + isCopyStmt = true; > if (cstmt->filename == NULL) > { > my_res = SPI_ERROR_COPY; > @@ -1911,16 +1913,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, > } > else > { > + uint32 processed; > + > ProcessUtility(stmt, > plansource->query_string, > paramLI, > false, /* not top level */ > dest, > - NULL); > + NULL, > + &processed); > /* Update "processed" if stmt returned tuples */ > + > if (_SPI_current->tuptable) > _SPI_current->processed = _SPI_current->tuptable->alloced - > _SPI_current->tuptable->free; > + else if (canSetTag && isCopyStmt) > + _SPI_current->processed = processed; > + > res = SPI_OK_UTILITY; > } > > diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c > index 466727b..1a861ee 100644 > --- a/src/backend/tcop/pquery.c > +++ b/src/backend/tcop/pquery.c > @@ -1184,7 +1184,8 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, > portal->portalParams, > isTopLevel, > dest, > - completionTag); > + completionTag, > + NULL); > > /* Some utility statements may change context on us */ > MemoryContextSwitchTo(PortalGetHeapMemory(portal)); > diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c > index 0749227..35db28c 100644 > --- a/src/backend/tcop/utility.c > +++ b/src/backend/tcop/utility.c > @@ -319,6 +319,9 @@ CheckRestrictedOperation(const char *cmdname) > * completionTag is only set nonempty if we want to return a nondefault status. > * > * completionTag may be NULL if caller doesn't want a status string. > + * > + * processed may be NULL if caller doesn't want a number of processed rows > + * by COPY statement > */ > void > ProcessUtility(Node *parsetree, > @@ -326,7 +329,8 @@ ProcessUtility(Node *parsetree, > ParamListInfo params, > bool isTopLevel, > DestReceiver *dest, > - char *completionTag) > + char *completionTag, > + uint32 *processed) > { > Assert(queryString != NULL); /* required as of 8.4 */ > > @@ -337,10 +341,10 @@ ProcessUtility(Node *parsetree, > */ > if (ProcessUtility_hook) > (*ProcessUtility_hook) (parsetree, queryString, params, > - isTopLevel, dest, completionTag); > + isTopLevel, dest, completionTag, processed); > else > standard_ProcessUtility(parsetree, queryString, params, > - isTopLevel, dest, completionTag); > + isTopLevel, dest, completionTag, processed); > } > > void > @@ -349,7 +353,8 @@ standard_ProcessUtility(Node *parsetree, > ParamListInfo params, > bool isTopLevel, > DestReceiver *dest, > - char *completionTag) > + char *completionTag, > + uint32 *processed) > { > check_xact_readonly(parsetree); > > @@ -571,6 +576,7 @@ standard_ProcessUtility(Node *parsetree, > params, > false, > None_Receiver, > + NULL, > NULL); > } > > @@ -716,12 +722,14 @@ standard_ProcessUtility(Node *parsetree, > > case T_CopyStmt: > { > - uint64 processed; > + uint64 _processed; > > - processed = DoCopy((CopyStmt *) parsetree, queryString); > + _processed = DoCopy((CopyStmt *) parsetree, queryString); > if (completionTag) > snprintf(completionTag, COMPLETION_TAG_BUFSIZE, > - "COPY " UINT64_FORMAT, processed); > + "COPY " UINT64_FORMAT, _processed); > + if (processed != NULL) > + *processed = (uint32) _processed; > } > break; > > @@ -782,6 +790,7 @@ standard_ProcessUtility(Node *parsetree, > params, > false, > None_Receiver, > + NULL, > NULL); > } > > diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h > index c21857a..86fad4b 100644 > --- a/src/include/tcop/utility.h > +++ b/src/include/tcop/utility.h > @@ -20,15 +20,16 @@ > /* Hook for plugins to get control in ProcessUtility() */ > typedef void (*ProcessUtility_hook_type) (Node *parsetree, > const char *queryString, ParamListInfo params, bool isTopLevel, > - DestReceiver *dest, char *completionTag); > + DestReceiver *dest, char *completionTag, > + uint32 *processed); > extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook; > > extern void ProcessUtility(Node *parsetree, const char *queryString, > ParamListInfo params, bool isTopLevel, > - DestReceiver *dest, char *completionTag); > + DestReceiver *dest, char *completionTag, uint32 *processed); > extern void standard_ProcessUtility(Node *parsetree, const char *queryString, > ParamListInfo params, bool isTopLevel, > - DestReceiver *dest, char *completionTag); > + DestReceiver *dest, char *completionTag, uint32 *processed); > > extern bool UtilityReturnsTuples(Node *parsetree); > > > -- > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-hackers -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
Hello I can reassign it again Regards Pavel 2012/8/16 Bruce Momjian <bruce@momjian.us>: > > What ever happened to this patch? I don't see it on any of the > commit-fests, though someone was asked for it to be added: > > http://archives.postgresql.org/pgsql-hackers/2011-10/msg00381.php > > --------------------------------------------------------------------------- > > On Tue, Oct 4, 2011 at 12:22:19PM +0200, Pavel Stehule wrote: >> Hello >> >> There is not possible to get a number of processed rows when COPY is >> evaluated via SPI. Client can use a tag, but SPI doesn't use a tag. >> >> I propose a small change a ProcessUtility to return a processed rows. >> >> Note: I found a small inconsistency between SPI and Utility interface. >> SPI still use a 4 byte unsign int for storing a number of processed >> rows. Utility use a 8bytes unsign int. >> >> Motivation: >> >> postgres=# \sf fx >> CREATE OR REPLACE FUNCTION public.fx(tablename text, filename text) >> RETURNS integer >> LANGUAGE plpgsql >> AS $function$ >> declare r int; >> begin >> execute format('COPY %s FROM %s', quote_ident(tablename), >> quote_literal(filename)); >> get diagnostics r = row_count; >> return r; >> end; >> $function$ >> >> Regards >> >> Pavel Stehule > >> diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c >> index 398bc40..a7c2b8f 100644 >> --- a/src/backend/executor/functions.c >> +++ b/src/backend/executor/functions.c >> @@ -600,6 +600,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) >> es->qd->params, >> false, /* not top level */ >> es->qd->dest, >> + NULL, >> NULL); >> result = true; /* never stops early */ >> } >> diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c >> index 688279c..21cabcc 100644 >> --- a/src/backend/executor/spi.c >> +++ b/src/backend/executor/spi.c >> @@ -1838,6 +1838,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> { >> Node *stmt = (Node *) lfirst(lc2); >> bool canSetTag; >> + bool isCopyStmt = false; >> DestReceiver *dest; >> >> _SPI_current->processed = 0; >> @@ -1857,6 +1858,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> { >> CopyStmt *cstmt = (CopyStmt *) stmt; >> >> + isCopyStmt = true; >> if (cstmt->filename == NULL) >> { >> my_res = SPI_ERROR_COPY; >> @@ -1911,16 +1913,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> } >> else >> { >> + uint32 processed; >> + >> ProcessUtility(stmt, >> plansource->query_string, >> paramLI, >> false, /* not top level */ >> dest, >> - NULL); >> + NULL, >> + &processed); >> /* Update "processed" if stmt returned tuples */ >> + >> if (_SPI_current->tuptable) >> _SPI_current->processed = _SPI_current->tuptable->alloced - >> _SPI_current->tuptable->free; >> + else if (canSetTag && isCopyStmt) >> + _SPI_current->processed = processed; >> + >> res = SPI_OK_UTILITY; >> } >> >> diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c >> index 466727b..1a861ee 100644 >> --- a/src/backend/tcop/pquery.c >> +++ b/src/backend/tcop/pquery.c >> @@ -1184,7 +1184,8 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, >> portal->portalParams, >> isTopLevel, >> dest, >> - completionTag); >> + completionTag, >> + NULL); >> >> /* Some utility statements may change context on us */ >> MemoryContextSwitchTo(PortalGetHeapMemory(portal)); >> diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c >> index 0749227..35db28c 100644 >> --- a/src/backend/tcop/utility.c >> +++ b/src/backend/tcop/utility.c >> @@ -319,6 +319,9 @@ CheckRestrictedOperation(const char *cmdname) >> * completionTag is only set nonempty if we want to return a nondefault status. >> * >> * completionTag may be NULL if caller doesn't want a status string. >> + * >> + * processed may be NULL if caller doesn't want a number of processed rows >> + * by COPY statement >> */ >> void >> ProcessUtility(Node *parsetree, >> @@ -326,7 +329,8 @@ ProcessUtility(Node *parsetree, >> ParamListInfo params, >> bool isTopLevel, >> DestReceiver *dest, >> - char *completionTag) >> + char *completionTag, >> + uint32 *processed) >> { >> Assert(queryString != NULL); /* required as of 8.4 */ >> >> @@ -337,10 +341,10 @@ ProcessUtility(Node *parsetree, >> */ >> if (ProcessUtility_hook) >> (*ProcessUtility_hook) (parsetree, queryString, params, >> - isTopLevel, dest, completionTag); >> + isTopLevel, dest, completionTag, processed); >> else >> standard_ProcessUtility(parsetree, queryString, params, >> - isTopLevel, dest, completionTag); >> + isTopLevel, dest, completionTag, processed); >> } >> >> void >> @@ -349,7 +353,8 @@ standard_ProcessUtility(Node *parsetree, >> ParamListInfo params, >> bool isTopLevel, >> DestReceiver *dest, >> - char *completionTag) >> + char *completionTag, >> + uint32 *processed) >> { >> check_xact_readonly(parsetree); >> >> @@ -571,6 +576,7 @@ standard_ProcessUtility(Node *parsetree, >> params, >> false, >> None_Receiver, >> + NULL, >> NULL); >> } >> >> @@ -716,12 +722,14 @@ standard_ProcessUtility(Node *parsetree, >> >> case T_CopyStmt: >> { >> - uint64 processed; >> + uint64 _processed; >> >> - processed = DoCopy((CopyStmt *) parsetree, queryString); >> + _processed = DoCopy((CopyStmt *) parsetree, queryString); >> if (completionTag) >> snprintf(completionTag, COMPLETION_TAG_BUFSIZE, >> - "COPY " UINT64_FORMAT, processed); >> + "COPY " UINT64_FORMAT, _processed); >> + if (processed != NULL) >> + *processed = (uint32) _processed; >> } >> break; >> >> @@ -782,6 +790,7 @@ standard_ProcessUtility(Node *parsetree, >> params, >> false, >> None_Receiver, >> + NULL, >> NULL); >> } >> >> diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h >> index c21857a..86fad4b 100644 >> --- a/src/include/tcop/utility.h >> +++ b/src/include/tcop/utility.h >> @@ -20,15 +20,16 @@ >> /* Hook for plugins to get control in ProcessUtility() */ >> typedef void (*ProcessUtility_hook_type) (Node *parsetree, >> const char *queryString, ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, >> + uint32 *processed); >> extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook; >> >> extern void ProcessUtility(Node *parsetree, const char *queryString, >> ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, uint32 *processed); >> extern void standard_ProcessUtility(Node *parsetree, const char *queryString, >> ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, uint32 *processed); >> >> extern bool UtilityReturnsTuples(Node *parsetree); >> > >> >> -- >> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) >> To make changes to your subscription: >> http://www.postgresql.org/mailpref/pgsql-hackers > > > -- > Bruce Momjian <bruce@momjian.us> http://momjian.us > EnterpriseDB http://enterprisedb.com > > + It's impossible for everything to be true. +
Hello here is updated patch postgres=# copy omega to '/tmp/xxx'; COPY 60 postgres=# do $$ declare r int; begin copy omega from '/tmp/xxx'; get diagnostics r = row_count; raise notice '>>> %', r; end; $$ language plpgsql; NOTICE: >>> 60 DO Regards Pavel 2012/8/16 Bruce Momjian <bruce@momjian.us>: > > What ever happened to this patch? I don't see it on any of the > commit-fests, though someone was asked for it to be added: > > http://archives.postgresql.org/pgsql-hackers/2011-10/msg00381.php > > --------------------------------------------------------------------------- > > On Tue, Oct 4, 2011 at 12:22:19PM +0200, Pavel Stehule wrote: >> Hello >> >> There is not possible to get a number of processed rows when COPY is >> evaluated via SPI. Client can use a tag, but SPI doesn't use a tag. >> >> I propose a small change a ProcessUtility to return a processed rows. >> >> Note: I found a small inconsistency between SPI and Utility interface. >> SPI still use a 4 byte unsign int for storing a number of processed >> rows. Utility use a 8bytes unsign int. >> >> Motivation: >> >> postgres=# \sf fx >> CREATE OR REPLACE FUNCTION public.fx(tablename text, filename text) >> RETURNS integer >> LANGUAGE plpgsql >> AS $function$ >> declare r int; >> begin >> execute format('COPY %s FROM %s', quote_ident(tablename), >> quote_literal(filename)); >> get diagnostics r = row_count; >> return r; >> end; >> $function$ >> >> Regards >> >> Pavel Stehule > >> diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c >> index 398bc40..a7c2b8f 100644 >> --- a/src/backend/executor/functions.c >> +++ b/src/backend/executor/functions.c >> @@ -600,6 +600,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) >> es->qd->params, >> false, /* not top level */ >> es->qd->dest, >> + NULL, >> NULL); >> result = true; /* never stops early */ >> } >> diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c >> index 688279c..21cabcc 100644 >> --- a/src/backend/executor/spi.c >> +++ b/src/backend/executor/spi.c >> @@ -1838,6 +1838,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> { >> Node *stmt = (Node *) lfirst(lc2); >> bool canSetTag; >> + bool isCopyStmt = false; >> DestReceiver *dest; >> >> _SPI_current->processed = 0; >> @@ -1857,6 +1858,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> { >> CopyStmt *cstmt = (CopyStmt *) stmt; >> >> + isCopyStmt = true; >> if (cstmt->filename == NULL) >> { >> my_res = SPI_ERROR_COPY; >> @@ -1911,16 +1913,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, >> } >> else >> { >> + uint32 processed; >> + >> ProcessUtility(stmt, >> plansource->query_string, >> paramLI, >> false, /* not top level */ >> dest, >> - NULL); >> + NULL, >> + &processed); >> /* Update "processed" if stmt returned tuples */ >> + >> if (_SPI_current->tuptable) >> _SPI_current->processed = _SPI_current->tuptable->alloced - >> _SPI_current->tuptable->free; >> + else if (canSetTag && isCopyStmt) >> + _SPI_current->processed = processed; >> + >> res = SPI_OK_UTILITY; >> } >> >> diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c >> index 466727b..1a861ee 100644 >> --- a/src/backend/tcop/pquery.c >> +++ b/src/backend/tcop/pquery.c >> @@ -1184,7 +1184,8 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, >> portal->portalParams, >> isTopLevel, >> dest, >> - completionTag); >> + completionTag, >> + NULL); >> >> /* Some utility statements may change context on us */ >> MemoryContextSwitchTo(PortalGetHeapMemory(portal)); >> diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c >> index 0749227..35db28c 100644 >> --- a/src/backend/tcop/utility.c >> +++ b/src/backend/tcop/utility.c >> @@ -319,6 +319,9 @@ CheckRestrictedOperation(const char *cmdname) >> * completionTag is only set nonempty if we want to return a nondefault status. >> * >> * completionTag may be NULL if caller doesn't want a status string. >> + * >> + * processed may be NULL if caller doesn't want a number of processed rows >> + * by COPY statement >> */ >> void >> ProcessUtility(Node *parsetree, >> @@ -326,7 +329,8 @@ ProcessUtility(Node *parsetree, >> ParamListInfo params, >> bool isTopLevel, >> DestReceiver *dest, >> - char *completionTag) >> + char *completionTag, >> + uint32 *processed) >> { >> Assert(queryString != NULL); /* required as of 8.4 */ >> >> @@ -337,10 +341,10 @@ ProcessUtility(Node *parsetree, >> */ >> if (ProcessUtility_hook) >> (*ProcessUtility_hook) (parsetree, queryString, params, >> - isTopLevel, dest, completionTag); >> + isTopLevel, dest, completionTag, processed); >> else >> standard_ProcessUtility(parsetree, queryString, params, >> - isTopLevel, dest, completionTag); >> + isTopLevel, dest, completionTag, processed); >> } >> >> void >> @@ -349,7 +353,8 @@ standard_ProcessUtility(Node *parsetree, >> ParamListInfo params, >> bool isTopLevel, >> DestReceiver *dest, >> - char *completionTag) >> + char *completionTag, >> + uint32 *processed) >> { >> check_xact_readonly(parsetree); >> >> @@ -571,6 +576,7 @@ standard_ProcessUtility(Node *parsetree, >> params, >> false, >> None_Receiver, >> + NULL, >> NULL); >> } >> >> @@ -716,12 +722,14 @@ standard_ProcessUtility(Node *parsetree, >> >> case T_CopyStmt: >> { >> - uint64 processed; >> + uint64 _processed; >> >> - processed = DoCopy((CopyStmt *) parsetree, queryString); >> + _processed = DoCopy((CopyStmt *) parsetree, queryString); >> if (completionTag) >> snprintf(completionTag, COMPLETION_TAG_BUFSIZE, >> - "COPY " UINT64_FORMAT, processed); >> + "COPY " UINT64_FORMAT, _processed); >> + if (processed != NULL) >> + *processed = (uint32) _processed; >> } >> break; >> >> @@ -782,6 +790,7 @@ standard_ProcessUtility(Node *parsetree, >> params, >> false, >> None_Receiver, >> + NULL, >> NULL); >> } >> >> diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h >> index c21857a..86fad4b 100644 >> --- a/src/include/tcop/utility.h >> +++ b/src/include/tcop/utility.h >> @@ -20,15 +20,16 @@ >> /* Hook for plugins to get control in ProcessUtility() */ >> typedef void (*ProcessUtility_hook_type) (Node *parsetree, >> const char *queryString, ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, >> + uint32 *processed); >> extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook; >> >> extern void ProcessUtility(Node *parsetree, const char *queryString, >> ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, uint32 *processed); >> extern void standard_ProcessUtility(Node *parsetree, const char *queryString, >> ParamListInfo params, bool isTopLevel, >> - DestReceiver *dest, char *completionTag); >> + DestReceiver *dest, char *completionTag, uint32 *processed); >> >> extern bool UtilityReturnsTuples(Node *parsetree); >> > >> >> -- >> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) >> To make changes to your subscription: >> http://www.postgresql.org/mailpref/pgsql-hackers > > > -- > Bruce Momjian <bruce@momjian.us> http://momjian.us > EnterpriseDB http://enterprisedb.com > > + It's impossible for everything to be true. +
Attachment
On 16.08.2012 14:43, Pavel Stehule wrote: > Hello > > here is updated patch The patch seems to be truncated, it ends with: *** a/src/test/regress/input/copy.source --- b/src/test/regress/input/copy.source *************** *** 106,108 **** this is just a line full of junk that would error out if parsed --- 106,112 ---- \. copy copytest3 to stdout csv header; + + -- copy should to return processed rows + do $$ + I believe the code changes are OK, but regression test changes are missing. Can you resend the full patch, please? - Heikki