6
6
*
7
7
*
8
8
* IDENTIFICATION
9
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.95 2000/01/14 22:11:33 petere Exp $
9
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.96 2000/01/16 21:37:50 tgl Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -66,6 +66,21 @@ static int CountTuples(Relation relation);
66
66
static int lineno ;
67
67
static bool fe_eof ;
68
68
69
+ /*
70
+ * These static variables are used to avoid incurring overhead for each
71
+ * attribute processed. attribute_buf is reused on each CopyReadAttribute
72
+ * call to hold the string being read in. Under normal use it will soon
73
+ * grow to a suitable size, and then we will avoid palloc/pfree overhead
74
+ * for subsequent attributes. Note that CopyReadAttribute returns a pointer
75
+ * to attribute_buf's data buffer!
76
+ * encoding, if needed, can be set once at the start of the copy operation.
77
+ */
78
+ static StringInfoData attribute_buf ;
79
+ #ifdef MULTIBYTE
80
+ static int encoding ;
81
+ #endif
82
+
83
+
69
84
/*
70
85
* Internal communications functions
71
86
*/
@@ -276,78 +291,88 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
276
291
"directly to or from a file. Anyone can COPY to stdout or "
277
292
"from stdin. Psql's \\copy command also works for anyone." );
278
293
279
- if (from )
280
- { /* copy from file to database */
281
- if (rel -> rd_rel -> relkind == RELKIND_SEQUENCE )
282
- elog (ERROR , "You can't change sequence relation %s" , relname );
283
- if (pipe )
294
+ /*
295
+ * Set up variables to avoid per-attribute overhead.
296
+ */
297
+ initStringInfo (& attribute_buf );
298
+ #ifdef MULTIBYTE
299
+ encoding = pg_get_client_encoding ();
300
+ #endif
301
+
302
+ if (from )
303
+ { /* copy from file to database */
304
+ if (rel -> rd_rel -> relkind == RELKIND_SEQUENCE )
305
+ elog (ERROR , "You can't change sequence relation %s" , relname );
306
+ if (pipe )
307
+ {
308
+ if (IsUnderPostmaster )
284
309
{
285
- if (IsUnderPostmaster )
286
- {
287
- ReceiveCopyBegin ();
288
- fp = NULL ;
289
- }
290
- else
291
- fp = stdin ;
310
+ ReceiveCopyBegin ();
311
+ fp = NULL ;
292
312
}
293
313
else
294
- {
314
+ fp = stdin ;
315
+ }
316
+ else
317
+ {
295
318
#ifndef __CYGWIN32__
296
- fp = AllocateFile (filename , "r" );
319
+ fp = AllocateFile (filename , "r" );
297
320
#else
298
- fp = AllocateFile (filename , "rb" );
321
+ fp = AllocateFile (filename , "rb" );
299
322
#endif
300
- if (fp == NULL )
301
- elog (ERROR , "COPY command, running in backend with "
302
- "effective uid %d, could not open file '%s' for "
303
- "reading. Errno = %s (%d)." ,
304
- geteuid (), filename , strerror (errno ), errno );
305
- }
306
- CopyFrom (rel , binary , oids , fp , delim , null_print );
323
+ if (fp == NULL )
324
+ elog (ERROR , "COPY command, running in backend with "
325
+ "effective uid %d, could not open file '%s' for "
326
+ "reading. Errno = %s (%d)." ,
327
+ geteuid (), filename , strerror (errno ), errno );
307
328
}
308
- else
309
- { /* copy from database to file */
310
- if (pipe )
329
+ CopyFrom (rel , binary , oids , fp , delim , null_print );
330
+ }
331
+ else
332
+ { /* copy from database to file */
333
+ if (pipe )
334
+ {
335
+ if (IsUnderPostmaster )
311
336
{
312
- if (IsUnderPostmaster )
313
- {
314
- SendCopyBegin ();
315
- pq_startcopyout ();
316
- fp = NULL ;
317
- }
318
- else
319
- fp = stdout ;
337
+ SendCopyBegin ();
338
+ pq_startcopyout ();
339
+ fp = NULL ;
320
340
}
321
341
else
322
- {
323
- mode_t oumask ; /* Pre-existing umask value */
342
+ fp = stdout ;
343
+ }
344
+ else
345
+ {
346
+ mode_t oumask ; /* Pre-existing umask value */
324
347
325
348
oumask = umask ((mode_t ) 022 );
326
349
#ifndef __CYGWIN32__
327
- fp = AllocateFile (filename , "w" );
350
+ fp = AllocateFile (filename , "w" );
328
351
#else
329
- fp = AllocateFile (filename , "wb" );
352
+ fp = AllocateFile (filename , "wb" );
330
353
#endif
331
- umask (oumask );
332
- if (fp == NULL )
333
- elog (ERROR , "COPY command, running in backend with "
334
- "effective uid %d, could not open file '%s' for "
335
- "writing. Errno = %s (%d)." ,
336
- geteuid (), filename , strerror (errno ), errno );
337
- }
338
- CopyTo (rel , binary , oids , fp , delim , null_print );
339
- }
340
- if (!pipe )
341
- {
342
- FreeFile (fp );
343
- }
344
- else if (!from )
345
- {
346
- if (!binary )
347
- CopySendData ("\\.\n" , 3 , fp );
348
- if (IsUnderPostmaster )
349
- pq_endcopyout (false);
354
+ umask (oumask );
355
+ if (fp == NULL )
356
+ elog (ERROR , "COPY command, running in backend with "
357
+ "effective uid %d, could not open file '%s' for "
358
+ "writing. Errno = %s (%d)." ,
359
+ geteuid (), filename , strerror (errno ), errno );
350
360
}
361
+ CopyTo (rel , binary , oids , fp , delim , null_print );
362
+ }
363
+
364
+ if (!pipe )
365
+ {
366
+ FreeFile (fp );
367
+ }
368
+ else if (!from )
369
+ {
370
+ if (!binary )
371
+ CopySendData ("\\.\n" , 3 , fp );
372
+ if (IsUnderPostmaster )
373
+ pq_endcopyout (false);
374
+ }
375
+ pfree (attribute_buf .data );
351
376
352
377
/*
353
378
* Close the relation. If reading, we can release the AccessShareLock
@@ -717,7 +742,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
717
742
loaded_oid = oidin (string );
718
743
if (loaded_oid < BootstrapObjectIdData )
719
744
elog (ERROR , "COPY TEXT: Invalid Oid. line: %d" , lineno );
720
- pfree (string );
721
745
}
722
746
}
723
747
for (i = 0 ; i < attr_count && !done ; i ++ )
@@ -727,8 +751,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
727
751
{
728
752
values [i ] = PointerGetDatum (NULL );
729
753
nulls [i ] = 'n' ;
730
- if (string )
731
- pfree (string );
732
754
}
733
755
else if (string == NULL )
734
756
done = 1 ;
@@ -745,7 +767,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
745
767
if (!PointerIsValid (values [i ]) &&
746
768
!(rel -> rd_att -> attrs [i ]-> attbyval ))
747
769
elog (ERROR , "copy from line %d: Bad file format" , lineno );
748
- pfree (string );
749
770
}
750
771
}
751
772
if (!done )
@@ -1115,9 +1136,10 @@ CopyReadNewline(FILE *fp, int *newline)
1115
1136
/*
1116
1137
* Read the value of a single attribute.
1117
1138
*
1118
- * Result is either a palloc'd string, or NULL (if EOF or a null attribute).
1119
- * *isnull is set true if a null attribute, else false.
1139
+ * Result is either a string, or NULL (if EOF or a null attribute).
1140
+ * Note that the caller should not pfree the string!
1120
1141
*
1142
+ * *isnull is set true if a null attribute, else false.
1121
1143
* delim is the string of acceptable delimiter characters(s).
1122
1144
* *newline remembers whether we've seen a newline ending this tuple.
1123
1145
* null_print says how NULL values are represented
@@ -1126,19 +1148,20 @@ CopyReadNewline(FILE *fp, int *newline)
1126
1148
static char *
1127
1149
CopyReadAttribute (FILE * fp , bool * isnull , char * delim , int * newline , char * null_print )
1128
1150
{
1129
- StringInfoData attribute_buf ;
1130
1151
char c ;
1131
1152
#ifdef MULTIBYTE
1132
1153
int mblen ;
1133
- int encoding ;
1134
1154
unsigned char s [2 ];
1135
1155
char * cvt ;
1136
1156
int j ;
1137
1157
1138
- encoding = pg_get_client_encoding ();
1139
1158
s [1 ] = 0 ;
1140
1159
#endif
1141
1160
1161
+ /* reset attribute_buf to empty */
1162
+ attribute_buf .len = 0 ;
1163
+ attribute_buf .data [0 ] = '\0' ;
1164
+
1142
1165
/* if last delimiter was a newline return a NULL attribute */
1143
1166
if (* newline )
1144
1167
{
@@ -1148,8 +1171,6 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
1148
1171
1149
1172
* isnull = (bool ) false; /* set default */
1150
1173
1151
- initStringInfo (& attribute_buf );
1152
-
1153
1174
if (CopyGetEof (fp ))
1154
1175
goto endOfFile ;
1155
1176
@@ -1265,17 +1286,20 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
1265
1286
attribute_buf .len );
1266
1287
if (cvt != attribute_buf .data )
1267
1288
{
1268
- pfree (attribute_buf .data );
1269
- return cvt ;
1289
+ /* transfer converted data back to attribute_buf */
1290
+ attribute_buf .len = 0 ;
1291
+ attribute_buf .data [0 ] = '\0' ;
1292
+ appendBinaryStringInfo (& attribute_buf , cvt , strlen (cvt ));
1293
+ pfree (cvt );
1270
1294
}
1271
1295
#endif
1296
+
1272
1297
if (strcmp (attribute_buf .data , null_print )== 0 )
1273
1298
* isnull = true;
1274
1299
1275
1300
return attribute_buf .data ;
1276
1301
1277
1302
endOfFile :
1278
- pfree (attribute_buf .data );
1279
1303
return NULL ;
1280
1304
}
1281
1305
@@ -1286,13 +1310,11 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
1286
1310
char c ;
1287
1311
#ifdef MULTIBYTE
1288
1312
char * string_start ;
1289
- int encoding ;
1290
1313
int mblen ;
1291
1314
int i ;
1292
1315
#endif
1293
1316
1294
1317
#ifdef MULTIBYTE
1295
- encoding = pg_get_client_encoding ();
1296
1318
string = (char * ) pg_server_to_client ((unsigned char * ) server_string ,
1297
1319
strlen (server_string ));
1298
1320
string_start = string ;
0 commit comments