11/*-------------------------------------------------------------------------
22 *
33 * copy.c
4+ *COPY command.
5+ *
46 *
57 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
68 * Portions Copyright (c) 1994, Regents of the University of California
79 *
810 *
911 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.183 2002/11/26 03:01:57 tgl Exp $
12+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.184 2002/12/01 18:14:22 tgl Exp $
1113 *
1214 *-------------------------------------------------------------------------
1315 */
@@ -532,6 +534,8 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
532534char * string ;
533535Snapshot mySnapshot ;
534536List * cur ;
537+ MemoryContext oldcontext ;
538+ MemoryContext mycontext ;
535539
536540tupDesc = rel -> rd_att ;
537541attr = tupDesc -> attrs ;
@@ -561,6 +565,18 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
561565elog (ERROR ,"COPY BINARY: cstring not supported" );
562566}
563567
568+ /*
569+ * Create a temporary memory context that we can reset once per row
570+ * to recover palloc'd memory. This avoids any problems with leaks
571+ * inside datatype output routines, and should be faster than retail
572+ * pfree's anyway. (We don't need a whole econtext as CopyFrom does.)
573+ */
574+ mycontext = AllocSetContextCreate (CurrentMemoryContext ,
575+ "COPY TO" ,
576+ ALLOCSET_DEFAULT_MINSIZE ,
577+ ALLOCSET_DEFAULT_INITSIZE ,
578+ ALLOCSET_DEFAULT_MAXSIZE );
579+
564580if (binary )
565581{
566582/* Generate header for a binary copy */
@@ -591,6 +607,9 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
591607
592608CHECK_FOR_INTERRUPTS ();
593609
610+ MemoryContextReset (mycontext );
611+ oldcontext = MemoryContextSwitchTo (mycontext );
612+
594613if (binary )
595614{
596615/* Binary per-tuple header */
@@ -615,19 +634,17 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
615634string = DatumGetCString (DirectFunctionCall1 (oidout ,
616635ObjectIdGetDatum (HeapTupleGetOid (tuple ))));
617636CopySendString (string ,fp );
618- pfree (string );
619637need_delim = true;
620638}
621639}
622640
623641foreach (cur ,attnumlist )
624642{
625643int attnum = lfirsti (cur );
626- Datum origvalue ,
627- value ;
644+ Datum value ;
628645bool isnull ;
629646
630- origvalue = heap_getattr (tuple ,attnum ,tupDesc ,& isnull );
647+ value = heap_getattr (tuple ,attnum ,tupDesc ,& isnull );
631648
632649if (!binary )
633650{
@@ -650,25 +667,13 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
650667}
651668else
652669{
653- /*
654- * If we have a toasted datum, forcibly detoast it to
655- * avoid memory leakage inside the type's output routine
656- * (or for binary case, becase we must output untoasted
657- * value).
658- */
659- if (isvarlena [attnum - 1 ])
660- value = PointerGetDatum (PG_DETOAST_DATUM (origvalue ));
661- else
662- value = origvalue ;
663-
664670if (!binary )
665671{
666672string = DatumGetCString (FunctionCall3 (& out_functions [attnum - 1 ],
667673value ,
668674ObjectIdGetDatum (elements [attnum - 1 ]),
669675Int32GetDatum (attr [attnum - 1 ]-> atttypmod )));
670676CopyAttributeOut (fp ,string ,delim );
671- pfree (string );
672677}
673678else
674679{
@@ -678,6 +683,10 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
678683{
679684/* varlena */
680685Assert (fld_size == -1 );
686+
687+ /* If we have a toasted datum, detoast it */
688+ value = PointerGetDatum (PG_DETOAST_DATUM (value ));
689+
681690CopySendData (DatumGetPointer (value ),
682691VARSIZE (value ),
683692fp );
@@ -706,15 +715,13 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
706715fp );
707716}
708717}
709-
710- /* Clean up detoasted copy, if any */
711- if (value != origvalue )
712- pfree (DatumGetPointer (value ));
713718}
714719}
715720
716721if (!binary )
717722CopySendChar ('\n' ,fp );
723+
724+ MemoryContextSwitchTo (oldcontext );
718725}
719726
720727heap_endscan (scandesc );
@@ -727,6 +734,8 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
727734CopySendData (& fld_count ,sizeof (int16 ),fp );
728735}
729736
737+ MemoryContextDelete (mycontext );
738+
730739pfree (out_functions );
731740pfree (elements );
732741pfree (isvarlena );
@@ -1235,13 +1244,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
12351244 */
12361245copy_lineno = 0 ;
12371246
1247+ MemoryContextSwitchTo (oldcontext );
1248+
12381249/*
12391250 * Execute AFTER STATEMENT insertion triggers
12401251 */
12411252ExecASInsertTriggers (estate ,resultRelInfo );
12421253
1243- MemoryContextSwitchTo (oldcontext );
1244-
12451254pfree (values );
12461255pfree (nulls );
12471256
@@ -1463,7 +1472,6 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
14631472attribute_buf .len = 0 ;
14641473attribute_buf .data [0 ]= '\0' ;
14651474appendBinaryStringInfo (& attribute_buf ,cvt ,strlen (cvt ));
1466- pfree (cvt );
14671475}
14681476}
14691477
@@ -1476,24 +1484,16 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
14761484char * string ;
14771485char c ;
14781486char delimc = delim [0 ];
1479-
14801487bool same_encoding ;
1481- char * string_start ;
14821488int mblen ;
14831489int i ;
14841490
14851491same_encoding = (server_encoding == client_encoding );
14861492if (!same_encoding )
1487- {
14881493string = (char * )pg_server_to_client ((unsignedchar * )server_string ,
14891494strlen (server_string ));
1490- string_start = string ;
1491- }
14921495else
1493- {
14941496string = server_string ;
1495- string_start = NULL ;
1496- }
14971497
14981498for (; (c = * string )!= '\0' ;string += mblen )
14991499{
@@ -1527,7 +1527,11 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
15271527CopySendChar ('\\' ,fp );
15281528CopySendChar (c ,fp );
15291529
1530- /* XXX shouldn't this be done even when encoding is same? */
1530+ /*
1531+ * We can skip pg_encoding_mblen() overhead when encoding
1532+ * is same, because in valid backend encodings, extra
1533+ * bytes of a multibyte character never look like ASCII.
1534+ */
15311535if (!same_encoding )
15321536{
15331537/* send additional bytes of the char, if any */
@@ -1538,9 +1542,6 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
15381542break ;
15391543}
15401544}
1541-
1542- if (string_start )
1543- pfree (string_start );/* pfree pg_server_to_client result */
15441545}
15451546
15461547/*