/*-------------------------------------------------------------------------
*
* copy.c
+ * COPY command.
+ *
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.183 2002/11/26 03:01:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.184 2002/12/01 18:14:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
char *string;
Snapshot mySnapshot;
List *cur;
+ MemoryContext oldcontext;
+ MemoryContext mycontext;
tupDesc = rel->rd_att;
attr = tupDesc->attrs;
elog(ERROR, "COPY BINARY: cstring not supported");
}
+ /*
+ * Create a temporary memory context that we can reset once per row
+ * to recover palloc'd memory. This avoids any problems with leaks
+ * inside datatype output routines, and should be faster than retail
+ * pfree's anyway. (We don't need a whole econtext as CopyFrom does.)
+ */
+ mycontext = AllocSetContextCreate(CurrentMemoryContext,
+ "COPY TO",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+
if (binary)
{
/* Generate header for a binary copy */
CHECK_FOR_INTERRUPTS();
+ MemoryContextReset(mycontext);
+ oldcontext = MemoryContextSwitchTo(mycontext);
+
if (binary)
{
/* Binary per-tuple header */
string = DatumGetCString(DirectFunctionCall1(oidout,
ObjectIdGetDatum(HeapTupleGetOid(tuple))));
CopySendString(string, fp);
- pfree(string);
need_delim = true;
}
}
foreach(cur, attnumlist)
{
int attnum = lfirsti(cur);
- Datum origvalue,
- value;
+ Datum value;
bool isnull;
- origvalue = heap_getattr(tuple, attnum, tupDesc, &isnull);
+ value = heap_getattr(tuple, attnum, tupDesc, &isnull);
if (!binary)
{
}
else
{
- /*
- * If we have a toasted datum, forcibly detoast it to
- * avoid memory leakage inside the type's output routine
- * (or for binary case, becase we must output untoasted
- * value).
- */
- if (isvarlena[attnum - 1])
- value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
- else
- value = origvalue;
-
if (!binary)
{
string = DatumGetCString(FunctionCall3(&out_functions[attnum - 1],
ObjectIdGetDatum(elements[attnum - 1]),
Int32GetDatum(attr[attnum - 1]->atttypmod)));
CopyAttributeOut(fp, string, delim);
- pfree(string);
}
else
{
{
/* varlena */
Assert(fld_size == -1);
+
+ /* If we have a toasted datum, detoast it */
+ value = PointerGetDatum(PG_DETOAST_DATUM(value));
+
CopySendData(DatumGetPointer(value),
VARSIZE(value),
fp);
fp);
}
}
-
- /* Clean up detoasted copy, if any */
- if (value != origvalue)
- pfree(DatumGetPointer(value));
}
}
if (!binary)
CopySendChar('\n', fp);
+
+ MemoryContextSwitchTo(oldcontext);
}
heap_endscan(scandesc);
CopySendData(&fld_count, sizeof(int16), fp);
}
+ MemoryContextDelete(mycontext);
+
pfree(out_functions);
pfree(elements);
pfree(isvarlena);
*/
copy_lineno = 0;
+ MemoryContextSwitchTo(oldcontext);
+
/*
* Execute AFTER STATEMENT insertion triggers
*/
ExecASInsertTriggers(estate, resultRelInfo);
- MemoryContextSwitchTo(oldcontext);
-
pfree(values);
pfree(nulls);
attribute_buf.len = 0;
attribute_buf.data[0] = '\0';
appendBinaryStringInfo(&attribute_buf, cvt, strlen(cvt));
- pfree(cvt);
}
}
char *string;
char c;
char delimc = delim[0];
-
bool same_encoding;
- char *string_start;
int mblen;
int i;
same_encoding = (server_encoding == client_encoding);
if (!same_encoding)
- {
string = (char *) pg_server_to_client((unsigned char *) server_string,
strlen(server_string));
- string_start = string;
- }
else
- {
string = server_string;
- string_start = NULL;
- }
for (; (c = *string) != '\0'; string += mblen)
{
CopySendChar('\\', fp);
CopySendChar(c, fp);
- /* XXX shouldn't this be done even when encoding is same? */
+ /*
+ * We can skip pg_encoding_mblen() overhead when encoding
+ * is same, because in valid backend encodings, extra
+ * bytes of a multibyte character never look like ASCII.
+ */
if (!same_encoding)
{
/* send additional bytes of the char, if any */
break;
}
}
-
- if (string_start)
- pfree(string_start); /* pfree pg_server_to_client result */
}
/*