Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3a18f01

Browse files
committed
Run COPY OUT in a temporary memory context that's reset once per row,
and eliminate its manual pfree() calls. This solves the encoding-conversionbug recently reported, and should be faster and more robust than theoriginal coding anyway. For example, we are no longer at risk ifdatatype output routines leak memory or choose to return a constant string.
1 parent2b7ec40 commit3a18f01

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

‎src/backend/commands/copy.c

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
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,
532534
char*string;
533535
SnapshotmySnapshot;
534536
List*cur;
537+
MemoryContextoldcontext;
538+
MemoryContextmycontext;
535539

536540
tupDesc=rel->rd_att;
537541
attr=tupDesc->attrs;
@@ -561,6 +565,18 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
561565
elog(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+
564580
if (binary)
565581
{
566582
/* Generate header for a binary copy */
@@ -591,6 +607,9 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
591607

592608
CHECK_FOR_INTERRUPTS();
593609

610+
MemoryContextReset(mycontext);
611+
oldcontext=MemoryContextSwitchTo(mycontext);
612+
594613
if (binary)
595614
{
596615
/* Binary per-tuple header */
@@ -615,19 +634,17 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
615634
string=DatumGetCString(DirectFunctionCall1(oidout,
616635
ObjectIdGetDatum(HeapTupleGetOid(tuple))));
617636
CopySendString(string,fp);
618-
pfree(string);
619637
need_delim= true;
620638
}
621639
}
622640

623641
foreach(cur,attnumlist)
624642
{
625643
intattnum=lfirsti(cur);
626-
Datumorigvalue,
627-
value;
644+
Datumvalue;
628645
boolisnull;
629646

630-
origvalue=heap_getattr(tuple,attnum,tupDesc,&isnull);
647+
value=heap_getattr(tuple,attnum,tupDesc,&isnull);
631648

632649
if (!binary)
633650
{
@@ -650,25 +667,13 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
650667
}
651668
else
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-
664670
if (!binary)
665671
{
666672
string=DatumGetCString(FunctionCall3(&out_functions[attnum-1],
667673
value,
668674
ObjectIdGetDatum(elements[attnum-1]),
669675
Int32GetDatum(attr[attnum-1]->atttypmod)));
670676
CopyAttributeOut(fp,string,delim);
671-
pfree(string);
672677
}
673678
else
674679
{
@@ -678,6 +683,10 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
678683
{
679684
/* varlena */
680685
Assert(fld_size==-1);
686+
687+
/* If we have a toasted datum, detoast it */
688+
value=PointerGetDatum(PG_DETOAST_DATUM(value));
689+
681690
CopySendData(DatumGetPointer(value),
682691
VARSIZE(value),
683692
fp);
@@ -706,15 +715,13 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
706715
fp);
707716
}
708717
}
709-
710-
/* Clean up detoasted copy, if any */
711-
if (value!=origvalue)
712-
pfree(DatumGetPointer(value));
713718
}
714719
}
715720

716721
if (!binary)
717722
CopySendChar('\n',fp);
723+
724+
MemoryContextSwitchTo(oldcontext);
718725
}
719726

720727
heap_endscan(scandesc);
@@ -727,6 +734,8 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
727734
CopySendData(&fld_count,sizeof(int16),fp);
728735
}
729736

737+
MemoryContextDelete(mycontext);
738+
730739
pfree(out_functions);
731740
pfree(elements);
732741
pfree(isvarlena);
@@ -1235,13 +1244,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
12351244
*/
12361245
copy_lineno=0;
12371246

1247+
MemoryContextSwitchTo(oldcontext);
1248+
12381249
/*
12391250
* Execute AFTER STATEMENT insertion triggers
12401251
*/
12411252
ExecASInsertTriggers(estate,resultRelInfo);
12421253

1243-
MemoryContextSwitchTo(oldcontext);
1244-
12451254
pfree(values);
12461255
pfree(nulls);
12471256

@@ -1463,7 +1472,6 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
14631472
attribute_buf.len=0;
14641473
attribute_buf.data[0]='\0';
14651474
appendBinaryStringInfo(&attribute_buf,cvt,strlen(cvt));
1466-
pfree(cvt);
14671475
}
14681476
}
14691477

@@ -1476,24 +1484,16 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
14761484
char*string;
14771485
charc;
14781486
chardelimc=delim[0];
1479-
14801487
boolsame_encoding;
1481-
char*string_start;
14821488
intmblen;
14831489
inti;
14841490

14851491
same_encoding= (server_encoding==client_encoding);
14861492
if (!same_encoding)
1487-
{
14881493
string= (char*)pg_server_to_client((unsignedchar*)server_string,
14891494
strlen(server_string));
1490-
string_start=string;
1491-
}
14921495
else
1493-
{
14941496
string=server_string;
1495-
string_start=NULL;
1496-
}
14971497

14981498
for (; (c=*string)!='\0';string+=mblen)
14991499
{
@@ -1527,7 +1527,11 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
15271527
CopySendChar('\\',fp);
15281528
CopySendChar(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+
*/
15311535
if (!same_encoding)
15321536
{
15331537
/* send additional bytes of the char, if any */
@@ -1538,9 +1542,6 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
15381542
break;
15391543
}
15401544
}
1541-
1542-
if (string_start)
1543-
pfree(string_start);/* pfree pg_server_to_client result */
15441545
}
15451546

15461547
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp