Skip to content

Commit 4644fc8

Browse files
committed
Eliminate query length limitation imposed by pg_client_to_server
and pg_server_to_client. Eliminate copy.c's restriction on the length of a single attribute.
1 parent b65ab31 commit 4644fc8

File tree

4 files changed

+137
-162
lines changed

4 files changed

+137
-162
lines changed

src/backend/commands/copy.c

Lines changed: 65 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.86 1999/07/22 02:40:06 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.87 1999/09/11 22:28:11 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -26,6 +26,7 @@
2626
#include "commands/copy.h"
2727
#include "commands/trigger.h"
2828
#include "executor/executor.h"
29+
#include "lib/stringinfo.h"
2930
#include "libpq/libpq.h"
3031
#include "miscadmin.h"
3132
#include "utils/acl.h"
@@ -51,14 +52,10 @@ static void GetIndexRelations(Oid main_relation_oid,
5152
int *n_indices,
5253
Relation **index_rels);
5354

54-
#ifdef COPY_PATCH
5555
static void CopyReadNewline(FILE *fp, int *newline);
5656
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline);
57-
#else
58-
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
59-
#endif
6057

61-
static void CopyAttributeOut(FILE *fp, char *string, char *delim, int is_array);
58+
static void CopyAttributeOut(FILE *fp, char *string, char *delim);
6259
static int CountTuples(Relation relation);
6360

6461
/*
@@ -431,7 +428,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
431428
{
432429
string = (char *) (*fmgr_faddr(&out_functions[i]))
433430
(value, elements[i], typmod[i]);
434-
CopyAttributeOut(fp, string, delim, attr[i]->attnelems);
431+
CopyAttributeOut(fp, string, delim);
435432
pfree(string);
436433
}
437434
else
@@ -691,38 +688,31 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
691688
{
692689
if (!binary)
693690
{
694-
#ifdef COPY_PATCH
695691
int newline = 0;
696692

697-
#endif
698693
lineno++;
699694
if (oids)
700695
{
701-
#ifdef COPY_PATCH
702696
string = CopyReadAttribute(fp, &isnull, delim, &newline);
703-
#else
704-
string = CopyReadAttribute(fp, &isnull, delim);
705-
#endif
706697
if (string == NULL)
707698
done = 1;
708699
else
709700
{
710701
loaded_oid = oidin(string);
711702
if (loaded_oid < BootstrapObjectIdData)
712703
elog(ERROR, "COPY TEXT: Invalid Oid. line: %d", lineno);
704+
pfree(string);
713705
}
714706
}
715707
for (i = 0; i < attr_count && !done; i++)
716708
{
717-
#ifdef COPY_PATCH
718709
string = CopyReadAttribute(fp, &isnull, delim, &newline);
719-
#else
720-
string = CopyReadAttribute(fp, &isnull, delim);
721-
#endif
722710
if (isnull)
723711
{
724712
values[i] = PointerGetDatum(NULL);
725713
nulls[i] = 'n';
714+
if (string)
715+
pfree(string);
726716
}
727717
else if (string == NULL)
728718
done = 1;
@@ -739,12 +729,11 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
739729
if (!PointerIsValid(values[i]) &&
740730
!(rel->rd_att->attrs[i]->attbyval))
741731
elog(ERROR, "copy from line %d: Bad file format", lineno);
732+
pfree(string);
742733
}
743734
}
744-
#ifdef COPY_PATCH
745735
if (!done)
746736
CopyReadNewline(fp, &newline);
747-
#endif
748737
}
749738
else
750739
{ /* binary */
@@ -812,11 +801,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
812801
if (done)
813802
continue;
814803

815-
/*
816-
* Does it have any sence ? - vadim 12/14/96
817-
*
818-
* tupDesc = CreateTupleDesc(attr_count, attr);
819-
*/
820804
tuple = heap_formtuple(tupDesc, values, nulls);
821805
if (oids)
822806
tuple->t_data->t_oid = loaded_oid;
@@ -1086,30 +1070,18 @@ GetIndexRelations(Oid main_relation_oid,
10861070
}
10871071
}
10881072

1089-
#define EXT_ATTLEN (5 * BLCKSZ)
10901073

10911074
/*
1092-
returns 1 is c is in s
1075+
returns 1 if c is in s
10931076
*/
10941077
static bool
10951078
inString(char c, char *s)
10961079
{
1097-
int i;
1098-
1099-
if (s)
1100-
{
1101-
i = 0;
1102-
while (s[i] != '\0')
1103-
{
1104-
if (s[i] == c)
1105-
return 1;
1106-
i++;
1107-
}
1108-
}
1080+
if (s && c)
1081+
return strchr(s, c) != NULL;
11091082
return 0;
11101083
}
11111084

1112-
#ifdef COPY_PATCH
11131085
/*
11141086
* Reads input from fp until an end of line is seen.
11151087
*/
@@ -1125,64 +1097,57 @@ CopyReadNewline(FILE *fp, int *newline)
11251097
*newline = 0;
11261098
}
11271099

1128-
#endif
1129-
11301100
/*
1131-
* Reads input from fp until eof is seen. If we are reading from standard
1132-
* input, AND we see a dot on a line by itself (a dot followed immediately
1133-
* by a newline), we exit as if we saw eof. This is so that copy pipelines
1134-
* can be used as standard input.
1101+
* Read the value of a single attribute.
1102+
*
1103+
* Result is either a palloc'd string, or NULL (if EOF or a null attribute).
1104+
* *isnull is set true if a null attribute, else false.
1105+
*
1106+
* delim is the string of acceptable delimiter characters(s).
1107+
* *newline remembers whether we've seen a newline ending this tuple.
11351108
*/
11361109

11371110
static char *
1138-
#ifdef COPY_PATCH
11391111
CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
1140-
#else
1141-
CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
1142-
#endif
11431112
{
1144-
static char attribute[EXT_ATTLEN];
1113+
StringInfoData attribute_buf;
11451114
char c;
1146-
int done = 0;
1147-
int i = 0;
1148-
11491115
#ifdef MULTIBYTE
11501116
int mblen;
11511117
int encoding;
11521118
unsigned char s[2];
1119+
char *cvt;
11531120
int j;
11541121

1155-
#endif
1156-
1157-
#ifdef MULTIBYTE
11581122
encoding = pg_get_client_encoding();
11591123
s[1] = 0;
11601124
#endif
11611125

1162-
#ifdef COPY_PATCH
11631126
/* if last delimiter was a newline return a NULL attribute */
11641127
if (*newline)
11651128
{
11661129
*isnull = (bool) true;
11671130
return NULL;
11681131
}
1169-
#endif
11701132

11711133
*isnull = (bool) false; /* set default */
1134+
1135+
initStringInfo(&attribute_buf);
1136+
11721137
if (CopyGetEof(fp))
1173-
return NULL;
1138+
goto endOfFile;
11741139

1175-
while (!done)
1140+
for (;;)
11761141
{
11771142
c = CopyGetChar(fp);
1178-
11791143
if (CopyGetEof(fp))
1180-
return NULL;
1181-
else if (c == '\\')
1144+
goto endOfFile;
1145+
1146+
if (c == '\\')
11821147
{
11831148
c = CopyGetChar(fp);
11841149
if (CopyGetEof(fp))
1185-
return NULL;
1150+
goto endOfFile;
11861151
switch (c)
11871152
{
11881153
case '0':
@@ -1212,14 +1177,14 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
12121177
else
12131178
{
12141179
if (CopyGetEof(fp))
1215-
return NULL;
1180+
goto endOfFile;
12161181
CopyDonePeek(fp, c, 0); /* Return to stream! */
12171182
}
12181183
}
12191184
else
12201185
{
12211186
if (CopyGetEof(fp))
1222-
return NULL;
1187+
goto endOfFile;
12231188
CopyDonePeek(fp, c, 0); /* Return to stream! */
12241189
}
12251190
c = val & 0377;
@@ -1244,66 +1209,70 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
12441209
c = '\v';
12451210
break;
12461211
case 'N':
1247-
attribute[0] = '\0'; /* just to be safe */
12481212
*isnull = (bool) true;
12491213
break;
12501214
case '.':
12511215
c = CopyGetChar(fp);
12521216
if (c != '\n')
12531217
elog(ERROR, "CopyReadAttribute - end of record marker corrupted. line: %d", lineno);
1254-
return NULL;
1218+
goto endOfFile;
12551219
break;
12561220
}
12571221
}
1258-
else if (inString(c, delim) || c == '\n')
1222+
else if (c == '\n' || inString(c, delim))
12591223
{
1260-
#ifdef COPY_PATCH
12611224
if (c == '\n')
12621225
*newline = 1;
1263-
#endif
1264-
done = 1;
1226+
break;
12651227
}
1266-
if (!done)
1267-
attribute[i++] = c;
1228+
appendStringInfoChar(&attribute_buf, c);
12681229
#ifdef MULTIBYTE
1230+
/* get additional bytes of the char, if any */
12691231
s[0] = c;
12701232
mblen = pg_encoding_mblen(encoding, s);
1271-
mblen--;
1272-
for (j = 0; j < mblen; j++)
1233+
for (j = 1; j < mblen; j++)
12731234
{
12741235
c = CopyGetChar(fp);
12751236
if (CopyGetEof(fp))
1276-
return NULL;
1277-
attribute[i++] = c;
1237+
goto endOfFile;
1238+
appendStringInfoChar(&attribute_buf, c);
12781239
}
12791240
#endif
1280-
if (i == EXT_ATTLEN - 1)
1281-
elog(ERROR, "CopyReadAttribute - attribute length too long. line: %d", lineno);
12821241
}
1283-
attribute[i] = '\0';
1242+
12841243
#ifdef MULTIBYTE
1285-
return (pg_client_to_server((unsigned char *) attribute, strlen(attribute)));
1286-
#else
1287-
return &attribute[0];
1244+
cvt = (char *) pg_client_to_server((unsigned char *) attribute_buf.data,
1245+
attribute_buf.len);
1246+
if (cvt != attribute_buf.data)
1247+
{
1248+
pfree(attribute_buf.data);
1249+
return cvt;
1250+
}
12881251
#endif
1252+
return attribute_buf.data;
1253+
1254+
endOfFile:
1255+
pfree(attribute_buf.data);
1256+
return NULL;
12891257
}
12901258

12911259
static void
1292-
CopyAttributeOut(FILE *fp, char *server_string, char *delim, int is_array)
1260+
CopyAttributeOut(FILE *fp, char *server_string, char *delim)
12931261
{
12941262
char *string;
12951263
char c;
1296-
12971264
#ifdef MULTIBYTE
1298-
int mblen;
1265+
char *string_start;
12991266
int encoding;
1267+
int mblen;
13001268
int i;
1301-
13021269
#endif
13031270

13041271
#ifdef MULTIBYTE
1305-
string = pg_server_to_client(server_string, strlen(server_string));
13061272
encoding = pg_get_client_encoding();
1273+
string = (char *) pg_server_to_client((unsigned char *) server_string,
1274+
strlen(server_string));
1275+
string_start = string;
13071276
#else
13081277
string = server_string;
13091278
#endif
@@ -1315,33 +1284,20 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim, int is_array)
13151284
for (; (c = *string) != '\0'; string++)
13161285
#endif
13171286
{
1318-
if (c == delim[0] || c == '\n' ||
1319-
(c == '\\' && !is_array))
1287+
if (c == delim[0] || c == '\n' || c == '\\')
13201288
CopySendChar('\\', fp);
1321-
else if (c == '\\' && is_array)
1322-
{
1323-
if (*(string + 1) == '\\')
1324-
{
1325-
/* translate \\ to \\\\ */
1326-
CopySendChar('\\', fp);
1327-
CopySendChar('\\', fp);
1328-
CopySendChar('\\', fp);
1329-
string++;
1330-
}
1331-
else if (*(string + 1) == '"')
1332-
{
1333-
/* translate \" to \\\" */
1334-
CopySendChar('\\', fp);
1335-
CopySendChar('\\', fp);
1336-
}
1337-
}
13381289
#ifdef MULTIBYTE
13391290
for (i = 0; i < mblen; i++)
13401291
CopySendChar(*(string + i), fp);
13411292
#else
1342-
CopySendChar(*string, fp);
1293+
CopySendChar(c, fp);
13431294
#endif
13441295
}
1296+
1297+
#ifdef MULTIBYTE
1298+
if (string_start != server_string)
1299+
pfree(string_start); /* pfree pg_server_to_client result */
1300+
#endif
13451301
}
13461302

13471303
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy