Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * copyfromparse.c
4 : : * Parse CSV/text/binary format for COPY FROM.
5 : : *
6 : : * This file contains routines to parse the text, CSV and binary input
7 : : * formats. The main entry point is NextCopyFrom(), which parses the
8 : : * next input line and returns it as Datums.
9 : : *
10 : : * In text/CSV mode, the parsing happens in multiple stages:
11 : : *
12 : : * [data source] --> raw_buf --> input_buf --> line_buf --> attribute_buf
13 : : * 1. 2. 3. 4.
14 : : *
15 : : * 1. CopyLoadRawBuf() reads raw data from the input file or client, and
16 : : * places it into 'raw_buf'.
17 : : *
18 : : * 2. CopyConvertBuf() calls the encoding conversion function to convert
19 : : * the data in 'raw_buf' from client to server encoding, placing the
20 : : * converted result in 'input_buf'.
21 : : *
22 : : * 3. CopyReadLine() parses the data in 'input_buf', one line at a time.
23 : : * It is responsible for finding the next newline marker, taking quote and
24 : : * escape characters into account according to the COPY options. The line
25 : : * is copied into 'line_buf', with quotes and escape characters still
26 : : * intact.
27 : : *
28 : : * 4. CopyReadAttributesText/CSV() function takes the input line from
29 : : * 'line_buf', and splits it into fields, unescaping the data as required.
30 : : * The fields are stored in 'attribute_buf', and 'raw_fields' array holds
31 : : * pointers to each field.
32 : : *
33 : : * If encoding conversion is not required, a shortcut is taken in step 2 to
34 : : * avoid copying the data unnecessarily. The 'input_buf' pointer is set to
35 : : * point directly to 'raw_buf', so that CopyLoadRawBuf() loads the raw data
36 : : * directly into 'input_buf'. CopyConvertBuf() then merely validates that
37 : : * the data is valid in the current encoding.
38 : : *
39 : : * In binary mode, the pipeline is much simpler. Input is loaded into
40 : : * 'raw_buf', and encoding conversion is done in the datatype-specific
41 : : * receive functions, if required. 'input_buf' and 'line_buf' are not used,
42 : : * but 'attribute_buf' is used as a temporary buffer to hold one attribute's
43 : : * data when it's passed the receive function.
44 : : *
45 : : * 'raw_buf' is always 64 kB in size (RAW_BUF_SIZE). 'input_buf' is also
46 : : * 64 kB (INPUT_BUF_SIZE), if encoding conversion is required. 'line_buf'
47 : : * and 'attribute_buf' are expanded on demand, to hold the longest line
48 : : * encountered so far.
49 : : *
50 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
51 : : * Portions Copyright (c) 1994, Regents of the University of California
52 : : *
53 : : *
54 : : * IDENTIFICATION
55 : : * src/backend/commands/copyfromparse.c
56 : : *
57 : : *-------------------------------------------------------------------------
58 : : */
59 : : #include "postgres.h"
60 : :
61 : : #include <ctype.h>
62 : : #include <unistd.h>
63 : : #include <sys/stat.h>
64 : :
65 : : #include "commands/copyapi.h"
66 : : #include "commands/copyfrom_internal.h"
67 : : #include "commands/progress.h"
68 : : #include "executor/executor.h"
69 : : #include "libpq/libpq.h"
70 : : #include "libpq/pqformat.h"
71 : : #include "mb/pg_wchar.h"
72 : : #include "miscadmin.h"
73 : : #include "pgstat.h"
74 : : #include "port/pg_bswap.h"
75 : : #include "utils/builtins.h"
76 : : #include "utils/rel.h"
77 : :
78 : : #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
79 : : #define OCTVALUE(c) ((c) - '0')
80 : :
81 : : /*
82 : : * These macros centralize code used to process line_buf and input_buf buffers.
83 : : * They are macros because they often do continue/break control and to avoid
84 : : * function call overhead in tight COPY loops.
85 : : *
86 : : * We must use "if (1)" because the usual "do {...} while(0)" wrapper would
87 : : * prevent the continue/break processing from working. We end the "if (1)"
88 : : * with "else ((void) 0)" to ensure the "if" does not unintentionally match
89 : : * any "else" in the calling code, and to avoid any compiler warnings about
90 : : * empty statements. See http://www.cit.gu.edu.au/~anthony/info/C/C.macros.
91 : : */
92 : :
93 : : /*
94 : : * This keeps the character read at the top of the loop in the buffer
95 : : * even if there is more than one read-ahead.
96 : : */
97 : : #define IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(extralen) \
98 : : if (1) \
99 : : { \
100 : : if (input_buf_ptr + (extralen) >= copy_buf_len && !hit_eof) \
101 : : { \
102 : : input_buf_ptr = prev_raw_ptr; /* undo fetch */ \
103 : : need_data = true; \
104 : : continue; \
105 : : } \
106 : : } else ((void) 0)
107 : :
108 : : /* This consumes the remainder of the buffer and breaks */
109 : : #define IF_NEED_REFILL_AND_EOF_BREAK(extralen) \
110 : : if (1) \
111 : : { \
112 : : if (input_buf_ptr + (extralen) >= copy_buf_len && hit_eof) \
113 : : { \
114 : : if (extralen) \
115 : : input_buf_ptr = copy_buf_len; /* consume the partial character */ \
116 : : /* backslash just before EOF, treat as data char */ \
117 : : result = true; \
118 : : break; \
119 : : } \
120 : : } else ((void) 0)
121 : :
122 : : /*
123 : : * Transfer any approved data to line_buf; must do this to be sure
124 : : * there is some room in input_buf.
125 : : */
126 : : #define REFILL_LINEBUF \
127 : : if (1) \
128 : : { \
129 : : if (input_buf_ptr > cstate->input_buf_index) \
130 : : { \
131 : : appendBinaryStringInfo(&cstate->line_buf, \
132 : : cstate->input_buf + cstate->input_buf_index, \
133 : : input_buf_ptr - cstate->input_buf_index); \
134 : : cstate->input_buf_index = input_buf_ptr; \
135 : : } \
136 : : } else ((void) 0)
137 : :
138 : : /* NOTE: there's a copy of this in copyto.c */
139 : : static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
140 : :
141 : :
142 : : /* non-export function prototypes */
143 : : static bool CopyReadLine(CopyFromState cstate, bool is_csv);
144 : : static bool CopyReadLineText(CopyFromState cstate, bool is_csv);
145 : : static int CopyReadAttributesText(CopyFromState cstate);
146 : : static int CopyReadAttributesCSV(CopyFromState cstate);
147 : : static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo,
148 : : Oid typioparam, int32 typmod,
149 : : bool *isnull);
150 : : static pg_attribute_always_inline bool CopyFromTextLikeOneRow(CopyFromState cstate,
151 : : ExprContext *econtext,
152 : : Datum *values,
153 : : bool *nulls,
154 : : bool is_csv);
155 : : static pg_attribute_always_inline bool NextCopyFromRawFieldsInternal(CopyFromState cstate,
156 : : char ***fields,
157 : : int *nfields,
158 : : bool is_csv);
159 : :
160 : :
161 : : /* Low-level communications functions */
162 : : static int CopyGetData(CopyFromState cstate, void *databuf,
163 : : int minread, int maxread);
164 : : static inline bool CopyGetInt32(CopyFromState cstate, int32 *val);
165 : : static inline bool CopyGetInt16(CopyFromState cstate, int16 *val);
166 : : static void CopyLoadInputBuf(CopyFromState cstate);
167 : : static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes);
168 : :
169 : : void
1748 heikki.linnakangas@i 170 :CBC 542 : ReceiveCopyBegin(CopyFromState cstate)
171 : : {
172 : : StringInfoData buf;
1647 173 : 542 : int natts = list_length(cstate->attnumlist);
174 : 542 : int16 format = (cstate->opts.binary ? 1 : 0);
175 : : int i;
176 : :
746 nathan@postgresql.or 177 : 542 : pq_beginmessage(&buf, PqMsg_CopyInResponse);
1647 heikki.linnakangas@i 178 : 542 : pq_sendbyte(&buf, format); /* overall format */
179 : 542 : pq_sendint16(&buf, natts);
180 [ + + ]: 1951 : for (i = 0; i < natts; i++)
181 : 1409 : pq_sendint16(&buf, format); /* per-column formats */
182 : 542 : pq_endmessage(&buf);
183 : 542 : cstate->copy_src = COPY_FRONTEND;
184 : 542 : cstate->fe_msgbuf = makeStringInfo();
185 : : /* We *must* flush here to ensure FE knows it can send. */
1748 186 : 542 : pq_flush();
187 : 542 : }
188 : :
189 : : void
190 : 7 : ReceiveCopyBinaryHeader(CopyFromState cstate)
191 : : {
192 : : char readSig[11];
193 : : int32 tmp;
194 : :
195 : : /* Signature */
196 [ + - ]: 7 : if (CopyReadBinaryData(cstate, readSig, 11) != 11 ||
197 [ - + ]: 7 : memcmp(readSig, BinarySignature, 11) != 0)
1748 heikki.linnakangas@i 198 [ # # ]:UBC 0 : ereport(ERROR,
199 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
200 : : errmsg("COPY file signature not recognized")));
201 : : /* Flags field */
1748 heikki.linnakangas@i 202 [ - + ]:CBC 7 : if (!CopyGetInt32(cstate, &tmp))
1748 heikki.linnakangas@i 203 [ # # ]:UBC 0 : ereport(ERROR,
204 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
205 : : errmsg("invalid COPY file header (missing flags)")));
1748 heikki.linnakangas@i 206 [ - + ]:CBC 7 : if ((tmp & (1 << 16)) != 0)
1748 heikki.linnakangas@i 207 [ # # ]:UBC 0 : ereport(ERROR,
208 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
209 : : errmsg("invalid COPY file header (WITH OIDS)")));
1748 heikki.linnakangas@i 210 :CBC 7 : tmp &= ~(1 << 16);
211 [ - + ]: 7 : if ((tmp >> 16) != 0)
1748 heikki.linnakangas@i 212 [ # # ]:UBC 0 : ereport(ERROR,
213 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
214 : : errmsg("unrecognized critical flags in COPY file header")));
215 : : /* Header extension length */
1748 heikki.linnakangas@i 216 [ + - ]:CBC 7 : if (!CopyGetInt32(cstate, &tmp) ||
217 [ - + ]: 7 : tmp < 0)
1748 heikki.linnakangas@i 218 [ # # ]:UBC 0 : ereport(ERROR,
219 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
220 : : errmsg("invalid COPY file header (missing length)")));
221 : : /* Skip extension header, if present */
1748 heikki.linnakangas@i 222 [ - + ]:CBC 7 : while (tmp-- > 0)
223 : : {
1748 heikki.linnakangas@i 224 [ # # ]:UBC 0 : if (CopyReadBinaryData(cstate, readSig, 1) != 1)
225 [ # # ]: 0 : ereport(ERROR,
226 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
227 : : errmsg("invalid COPY file header (wrong length)")));
228 : : }
1748 heikki.linnakangas@i 229 :CBC 7 : }
230 : :
231 : : /*
232 : : * CopyGetData reads data from the source (file or frontend)
233 : : *
234 : : * We attempt to read at least minread, and at most maxread, bytes from
235 : : * the source. The actual number of bytes read is returned; if this is
236 : : * less than minread, EOF was detected.
237 : : *
238 : : * Note: when copying from the frontend, we expect a proper EOF mark per
239 : : * protocol; if the frontend simply drops the connection, we raise error.
240 : : * It seems unwise to allow the COPY IN to complete normally in that case.
241 : : *
242 : : * NB: no data conversion is applied here.
243 : : */
244 : : static int
245 : 216022 : CopyGetData(CopyFromState cstate, void *databuf, int minread, int maxread)
246 : : {
247 : 216022 : int bytesread = 0;
248 : :
249 [ + + + - ]: 216022 : switch (cstate->copy_src)
250 : : {
251 : 544 : case COPY_FILE:
252 : 544 : bytesread = fread(databuf, 1, maxread, cstate->copy_file);
253 [ - + ]: 544 : if (ferror(cstate->copy_file))
1748 heikki.linnakangas@i 254 [ # # ]:UBC 0 : ereport(ERROR,
255 : : (errcode_for_file_access(),
256 : : errmsg("could not read from COPY file: %m")));
1748 heikki.linnakangas@i 257 [ + + ]:CBC 544 : if (bytesread == 0)
1619 258 : 213 : cstate->raw_reached_eof = true;
1748 259 : 544 : break;
1647 260 : 201494 : case COPY_FRONTEND:
1619 261 [ + - + + : 402183 : while (maxread > 0 && bytesread < minread && !cstate->raw_reached_eof)
+ + ]
262 : : {
263 : : int avail;
264 : :
1748 265 [ + + ]: 401817 : while (cstate->fe_msgbuf->cursor >= cstate->fe_msgbuf->len)
266 : : {
267 : : /* Try to receive another message */
268 : : int mtype;
269 : : int maxmsglen;
270 : :
271 : 201128 : readmessage:
272 : 201128 : HOLD_CANCEL_INTERRUPTS();
273 : 201128 : pq_startmsgread();
274 : 201128 : mtype = pq_getbyte();
275 [ - + ]: 201128 : if (mtype == EOF)
1748 heikki.linnakangas@i 276 [ # # ]:UBC 0 : ereport(ERROR,
277 : : (errcode(ERRCODE_CONNECTION_FAILURE),
278 : : errmsg("unexpected EOF on client connection with an open transaction")));
279 : : /* Validate message type and set packet size limit */
1592 tgl@sss.pgh.pa.us 280 [ + + + ]:CBC 201128 : switch (mtype)
281 : : {
746 nathan@postgresql.or 282 : 200689 : case PqMsg_CopyData:
1592 tgl@sss.pgh.pa.us 283 : 200689 : maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
284 : 200689 : break;
746 nathan@postgresql.or 285 : 437 : case PqMsg_CopyDone:
286 : : case PqMsg_CopyFail:
287 : : case PqMsg_Flush:
288 : : case PqMsg_Sync:
1592 tgl@sss.pgh.pa.us 289 : 437 : maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
290 : 437 : break;
291 : 2 : default:
292 [ + - ]: 2 : ereport(ERROR,
293 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
294 : : errmsg("unexpected message type 0x%02X during COPY from stdin",
295 : : mtype)));
296 : : maxmsglen = 0; /* keep compiler quiet */
297 : : break;
298 : : }
299 : : /* Now collect the message body */
300 [ - + ]: 201126 : if (pq_getmessage(cstate->fe_msgbuf, maxmsglen))
1748 heikki.linnakangas@i 301 [ # # ]:UBC 0 : ereport(ERROR,
302 : : (errcode(ERRCODE_CONNECTION_FAILURE),
303 : : errmsg("unexpected EOF on client connection with an open transaction")));
1748 heikki.linnakangas@i 304 [ - + ]:CBC 201126 : RESUME_CANCEL_INTERRUPTS();
305 : : /* ... and process it */
306 [ + + - - : 201126 : switch (mtype)
- ]
307 : : {
746 nathan@postgresql.or 308 : 200689 : case PqMsg_CopyData:
1748 heikki.linnakangas@i 309 : 200689 : break;
746 nathan@postgresql.or 310 : 437 : case PqMsg_CopyDone:
311 : : /* COPY IN correctly terminated by frontend */
1619 heikki.linnakangas@i 312 : 437 : cstate->raw_reached_eof = true;
1748 313 : 437 : return bytesread;
746 nathan@postgresql.or 314 :UBC 0 : case PqMsg_CopyFail:
1748 heikki.linnakangas@i 315 [ # # ]: 0 : ereport(ERROR,
316 : : (errcode(ERRCODE_QUERY_CANCELED),
317 : : errmsg("COPY from stdin failed: %s",
318 : : pq_getmsgstring(cstate->fe_msgbuf))));
319 : : break;
746 nathan@postgresql.or 320 : 0 : case PqMsg_Flush:
321 : : case PqMsg_Sync:
322 : :
323 : : /*
324 : : * Ignore Flush/Sync for the convenience of client
325 : : * libraries (such as libpq) that may send those
326 : : * without noticing that the command they just
327 : : * sent was COPY.
328 : : */
1748 heikki.linnakangas@i 329 : 0 : goto readmessage;
330 : 0 : default:
1592 tgl@sss.pgh.pa.us 331 : 0 : Assert(false); /* NOT REACHED */
332 : : }
333 : : }
1748 heikki.linnakangas@i 334 :CBC 200689 : avail = cstate->fe_msgbuf->len - cstate->fe_msgbuf->cursor;
335 [ - + ]: 200689 : if (avail > maxread)
1748 heikki.linnakangas@i 336 :UBC 0 : avail = maxread;
1748 heikki.linnakangas@i 337 :CBC 200689 : pq_copymsgbytes(cstate->fe_msgbuf, databuf, avail);
338 : 200689 : databuf = (void *) ((char *) databuf + avail);
339 : 200689 : maxread -= avail;
340 : 200689 : bytesread += avail;
341 : : }
342 : 201055 : break;
343 : 13984 : case COPY_CALLBACK:
344 : 13984 : bytesread = cstate->data_source_cb(databuf, minread, maxread);
345 : 13984 : break;
346 : : }
347 : :
348 : 215583 : return bytesread;
349 : : }
350 : :
351 : :
352 : : /*
353 : : * These functions do apply some data conversion
354 : : */
355 : :
356 : : /*
357 : : * CopyGetInt32 reads an int32 that appears in network byte order
358 : : *
359 : : * Returns true if OK, false if EOF
360 : : */
361 : : static inline bool
362 : 93 : CopyGetInt32(CopyFromState cstate, int32 *val)
363 : : {
364 : : uint32 buf;
365 : :
366 [ - + ]: 93 : if (CopyReadBinaryData(cstate, (char *) &buf, sizeof(buf)) != sizeof(buf))
367 : : {
1748 heikki.linnakangas@i 368 :UBC 0 : *val = 0; /* suppress compiler warning */
369 : 0 : return false;
370 : : }
1748 heikki.linnakangas@i 371 :CBC 93 : *val = (int32) pg_ntoh32(buf);
372 : 93 : return true;
373 : : }
374 : :
375 : : /*
376 : : * CopyGetInt16 reads an int16 that appears in network byte order
377 : : */
378 : : static inline bool
379 : 21 : CopyGetInt16(CopyFromState cstate, int16 *val)
380 : : {
381 : : uint16 buf;
382 : :
383 [ - + ]: 21 : if (CopyReadBinaryData(cstate, (char *) &buf, sizeof(buf)) != sizeof(buf))
384 : : {
1748 heikki.linnakangas@i 385 :UBC 0 : *val = 0; /* suppress compiler warning */
386 : 0 : return false;
387 : : }
1748 heikki.linnakangas@i 388 :CBC 21 : *val = (int16) pg_ntoh16(buf);
389 : 21 : return true;
390 : : }
391 : :
392 : :
393 : : /*
394 : : * Perform encoding conversion on data in 'raw_buf', writing the converted
395 : : * data into 'input_buf'.
396 : : *
397 : : * On entry, there must be some data to convert in 'raw_buf'.
398 : : */
399 : : static void
1619 400 : 431126 : CopyConvertBuf(CopyFromState cstate)
401 : : {
402 : : /*
403 : : * If the file and server encoding are the same, no encoding conversion is
404 : : * required. However, we still need to verify that the input is valid for
405 : : * the encoding.
406 : : */
407 [ + + ]: 431126 : if (!cstate->need_transcoding)
408 : : {
409 : : /*
410 : : * When conversion is not required, input_buf and raw_buf are the
411 : : * same. raw_buf_len is the total number of bytes in the buffer, and
412 : : * input_buf_len tracks how many of those bytes have already been
413 : : * verified.
414 : : */
415 : 431084 : int preverifiedlen = cstate->input_buf_len;
416 : 431084 : int unverifiedlen = cstate->raw_buf_len - cstate->input_buf_len;
417 : : int nverified;
418 : :
419 [ + + ]: 431084 : if (unverifiedlen == 0)
420 : : {
421 : : /*
422 : : * If no more raw data is coming, report the EOF to the caller.
423 : : */
424 [ + + ]: 216294 : if (cstate->raw_reached_eof)
425 : 751 : cstate->input_reached_eof = true;
426 : 216294 : return;
427 : : }
428 : :
429 : : /*
430 : : * Verify the new data, including any residual unverified bytes from
431 : : * previous round.
432 : : */
433 : 214790 : nverified = pg_encoding_verifymbstr(cstate->file_encoding,
434 : 214790 : cstate->raw_buf + preverifiedlen,
435 : : unverifiedlen);
436 [ - + ]: 214790 : if (nverified == 0)
437 : : {
438 : : /*
439 : : * Could not verify anything.
440 : : *
441 : : * If there is no more raw input data coming, it means that there
442 : : * was an incomplete multi-byte sequence at the end. Also, if
443 : : * there's "enough" input left, we should be able to verify at
444 : : * least one character, and a failure to do so means that we've
445 : : * hit an invalid byte sequence.
446 : : */
1196 heikki.linnakangas@i 447 [ # # # # ]:UBC 0 : if (cstate->raw_reached_eof || unverifiedlen >= pg_encoding_max_length(cstate->file_encoding))
1619 448 : 0 : cstate->input_reached_error = true;
449 : 0 : return;
450 : : }
1619 heikki.linnakangas@i 451 :CBC 214790 : cstate->input_buf_len += nverified;
452 : : }
453 : : else
454 : : {
455 : : /*
456 : : * Encoding conversion is needed.
457 : : */
458 : : int nbytes;
459 : : unsigned char *src;
460 : : int srclen;
461 : : unsigned char *dst;
462 : : int dstlen;
463 : : int convertedlen;
464 : :
465 [ + + ]: 42 : if (RAW_BUF_BYTES(cstate) == 0)
466 : : {
467 : : /*
468 : : * If no more raw data is coming, report the EOF to the caller.
469 : : */
470 [ + + ]: 24 : if (cstate->raw_reached_eof)
471 : 6 : cstate->input_reached_eof = true;
472 : 24 : return;
473 : : }
474 : :
475 : : /*
476 : : * First, copy down any unprocessed data.
477 : : */
478 : 18 : nbytes = INPUT_BUF_BYTES(cstate);
479 [ - + - - ]: 18 : if (nbytes > 0 && cstate->input_buf_index > 0)
1619 heikki.linnakangas@i 480 :UBC 0 : memmove(cstate->input_buf, cstate->input_buf + cstate->input_buf_index,
481 : : nbytes);
1619 heikki.linnakangas@i 482 :CBC 18 : cstate->input_buf_index = 0;
483 : 18 : cstate->input_buf_len = nbytes;
484 : 18 : cstate->input_buf[nbytes] = '\0';
485 : :
486 : 18 : src = (unsigned char *) cstate->raw_buf + cstate->raw_buf_index;
487 : 18 : srclen = cstate->raw_buf_len - cstate->raw_buf_index;
488 : 18 : dst = (unsigned char *) cstate->input_buf + cstate->input_buf_len;
489 : 18 : dstlen = INPUT_BUF_SIZE - cstate->input_buf_len + 1;
490 : :
491 : : /*
492 : : * Do the conversion. This might stop short, if there is an invalid
493 : : * byte sequence in the input. We'll convert as much as we can in
494 : : * that case.
495 : : *
496 : : * Note: Even if we hit an invalid byte sequence, we don't report the
497 : : * error until all the valid bytes have been consumed. The input
498 : : * might contain an end-of-input marker (\.), and we don't want to
499 : : * report an error if the invalid byte sequence is after the
500 : : * end-of-input marker. We might unnecessarily convert some data
501 : : * after the end-of-input marker as long as it's valid for the
502 : : * encoding, but that's harmless.
503 : : */
504 : 18 : convertedlen = pg_do_encoding_conversion_buf(cstate->conversion_proc,
505 : : cstate->file_encoding,
506 : : GetDatabaseEncoding(),
507 : : src, srclen,
508 : : dst, dstlen,
509 : : true);
510 [ + + ]: 18 : if (convertedlen == 0)
511 : : {
512 : : /*
513 : : * Could not convert anything. If there is no more raw input data
514 : : * coming, it means that there was an incomplete multi-byte
515 : : * sequence at the end. Also, if there is plenty of input left,
516 : : * we should be able to convert at least one character, so a
517 : : * failure to do so must mean that we've hit a byte sequence
518 : : * that's invalid.
519 : : */
520 [ + + - + ]: 12 : if (cstate->raw_reached_eof || srclen >= MAX_CONVERSION_INPUT_LENGTH)
521 : 6 : cstate->input_reached_error = true;
522 : 12 : return;
523 : : }
524 : 6 : cstate->raw_buf_index += convertedlen;
525 : 6 : cstate->input_buf_len += strlen((char *) dst);
526 : : }
527 : : }
528 : :
529 : : /*
530 : : * Report an encoding or conversion error.
531 : : */
532 : : static void
533 : 6 : CopyConversionError(CopyFromState cstate)
534 : : {
535 [ - + ]: 6 : Assert(cstate->raw_buf_len > 0);
536 [ - + ]: 6 : Assert(cstate->input_reached_error);
537 : :
538 [ - + ]: 6 : if (!cstate->need_transcoding)
539 : : {
540 : : /*
541 : : * Everything up to input_buf_len was successfully verified, and
542 : : * input_buf_len points to the invalid or incomplete character.
543 : : */
1619 heikki.linnakangas@i 544 :UBC 0 : report_invalid_encoding(cstate->file_encoding,
545 : 0 : cstate->raw_buf + cstate->input_buf_len,
546 : 0 : cstate->raw_buf_len - cstate->input_buf_len);
547 : : }
548 : : else
549 : : {
550 : : /*
551 : : * raw_buf_index points to the invalid or untranslatable character. We
552 : : * let the conversion routine report the error, because it can provide
553 : : * a more specific error message than we could here. An earlier call
554 : : * to the conversion routine in CopyConvertBuf() detected that there
555 : : * is an error, now we call the conversion routine again with
556 : : * noError=false, to have it throw the error.
557 : : */
558 : : unsigned char *src;
559 : : int srclen;
560 : : unsigned char *dst;
561 : : int dstlen;
562 : :
1619 heikki.linnakangas@i 563 :CBC 6 : src = (unsigned char *) cstate->raw_buf + cstate->raw_buf_index;
564 : 6 : srclen = cstate->raw_buf_len - cstate->raw_buf_index;
565 : 6 : dst = (unsigned char *) cstate->input_buf + cstate->input_buf_len;
566 : 6 : dstlen = INPUT_BUF_SIZE - cstate->input_buf_len + 1;
567 : :
568 : 6 : (void) pg_do_encoding_conversion_buf(cstate->conversion_proc,
569 : : cstate->file_encoding,
570 : : GetDatabaseEncoding(),
571 : : src, srclen,
572 : : dst, dstlen,
573 : : false);
574 : :
575 : : /*
576 : : * The conversion routine should have reported an error, so this
577 : : * should not be reached.
578 : : */
1619 heikki.linnakangas@i 579 [ # # ]:UBC 0 : elog(ERROR, "encoding conversion failed without error");
580 : : }
581 : : }
582 : :
583 : : /*
584 : : * Load more data from data source to raw_buf.
585 : : *
586 : : * If RAW_BUF_BYTES(cstate) > 0, the unprocessed bytes are moved to the
587 : : * beginning of the buffer, and we load new data after that.
588 : : */
589 : : static void
1748 heikki.linnakangas@i 590 :CBC 215585 : CopyLoadRawBuf(CopyFromState cstate)
591 : : {
592 : : int nbytes;
593 : : int inbytes;
594 : :
595 : : /*
596 : : * In text mode, if encoding conversion is not required, raw_buf and
597 : : * input_buf point to the same buffer. Their len/index better agree, too.
598 : : */
1619 599 [ + + ]: 215585 : if (cstate->raw_buf == cstate->input_buf)
600 : : {
601 [ - + ]: 215543 : Assert(!cstate->need_transcoding);
602 [ - + ]: 215543 : Assert(cstate->raw_buf_index == cstate->input_buf_index);
603 [ - + ]: 215543 : Assert(cstate->input_buf_len <= cstate->raw_buf_len);
604 : : }
605 : :
606 : : /*
607 : : * Copy down the unprocessed data if any.
608 : : */
609 : 215585 : nbytes = RAW_BUF_BYTES(cstate);
610 [ + + - + ]: 215585 : if (nbytes > 0 && cstate->raw_buf_index > 0)
1748 heikki.linnakangas@i 611 :UBC 0 : memmove(cstate->raw_buf, cstate->raw_buf + cstate->raw_buf_index,
612 : : nbytes);
1619 heikki.linnakangas@i 613 :CBC 215585 : cstate->raw_buf_len -= cstate->raw_buf_index;
614 : 215585 : cstate->raw_buf_index = 0;
615 : :
616 : : /*
617 : : * If raw_buf and input_buf are in fact the same buffer, adjust the
618 : : * input_buf variables, too.
619 : : */
620 [ + + ]: 215585 : if (cstate->raw_buf == cstate->input_buf)
621 : : {
622 : 215543 : cstate->input_buf_len -= cstate->input_buf_index;
623 : 215543 : cstate->input_buf_index = 0;
624 : : }
625 : :
626 : : /* Load more data */
627 : 215585 : inbytes = CopyGetData(cstate, cstate->raw_buf + cstate->raw_buf_len,
628 : 215585 : 1, RAW_BUF_SIZE - cstate->raw_buf_len);
1748 629 : 215583 : nbytes += inbytes;
630 : 215583 : cstate->raw_buf[nbytes] = '\0';
631 : 215583 : cstate->raw_buf_len = nbytes;
632 : :
1675 633 : 215583 : cstate->bytes_processed += inbytes;
1704 tomas.vondra@postgre 634 : 215583 : pgstat_progress_update_param(PROGRESS_COPY_BYTES_PROCESSED, cstate->bytes_processed);
635 : :
1619 heikki.linnakangas@i 636 [ + + ]: 215583 : if (inbytes == 0)
637 : 769 : cstate->raw_reached_eof = true;
638 : 215583 : }
639 : :
640 : : /*
641 : : * CopyLoadInputBuf loads some more data into input_buf
642 : : *
643 : : * On return, at least one more input character is loaded into
644 : : * input_buf, or input_reached_eof is set.
645 : : *
646 : : * If INPUT_BUF_BYTES(cstate) > 0, the unprocessed bytes are moved to the start
647 : : * of the buffer and then we load more data after that.
648 : : */
649 : : static void
650 : 215561 : CopyLoadInputBuf(CopyFromState cstate)
651 : : {
652 : 215561 : int nbytes = INPUT_BUF_BYTES(cstate);
653 : :
654 : : /*
655 : : * The caller has updated input_buf_index to indicate how much of the
656 : : * input has been consumed and isn't needed anymore. If input_buf is the
657 : : * same physical area as raw_buf, update raw_buf_index accordingly.
658 : : */
659 [ + + ]: 215561 : if (cstate->raw_buf == cstate->input_buf)
660 : : {
661 [ - + ]: 215543 : Assert(!cstate->need_transcoding);
662 [ - + ]: 215543 : Assert(cstate->input_buf_index >= cstate->raw_buf_index);
663 : 215543 : cstate->raw_buf_index = cstate->input_buf_index;
664 : : }
665 : :
666 : : for (;;)
667 : : {
668 : : /* If we now have some unconverted data, try to convert it */
669 : 431126 : CopyConvertBuf(cstate);
670 : :
671 : : /* If we now have some more input bytes ready, return them */
672 [ + + ]: 431126 : if (INPUT_BUF_BYTES(cstate) > nbytes)
673 : 214796 : return;
674 : :
675 : : /*
676 : : * If we reached an invalid byte sequence, or we're at an incomplete
677 : : * multi-byte character but there is no more raw input data, report
678 : : * conversion error.
679 : : */
680 [ + + ]: 216330 : if (cstate->input_reached_error)
681 : 6 : CopyConversionError(cstate);
682 : :
683 : : /* no more input, and everything has been converted */
684 [ + + ]: 216324 : if (cstate->input_reached_eof)
685 : 757 : break;
686 : :
687 : : /* Try to load more raw data */
688 [ - + ]: 215567 : Assert(!cstate->raw_reached_eof);
689 : 215567 : CopyLoadRawBuf(cstate);
690 : : }
691 : : }
692 : :
693 : : /*
694 : : * CopyReadBinaryData
695 : : *
696 : : * Reads up to 'nbytes' bytes from cstate->copy_file via cstate->raw_buf
697 : : * and writes them to 'dest'. Returns the number of bytes read (which
698 : : * would be less than 'nbytes' only if we reach EOF).
699 : : */
700 : : static int
1748 701 : 191 : CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes)
702 : : {
703 : 191 : int copied_bytes = 0;
704 : :
705 [ + + ]: 191 : if (RAW_BUF_BYTES(cstate) >= nbytes)
706 : : {
707 : : /* Enough bytes are present in the buffer. */
708 : 173 : memcpy(dest, cstate->raw_buf + cstate->raw_buf_index, nbytes);
709 : 173 : cstate->raw_buf_index += nbytes;
710 : 173 : copied_bytes = nbytes;
711 : : }
712 : : else
713 : : {
714 : : /*
715 : : * Not enough bytes in the buffer, so must read from the file. Need
716 : : * to loop since 'nbytes' could be larger than the buffer size.
717 : : */
718 : : do
719 : : {
720 : : int copy_bytes;
721 : :
722 : : /* Load more data if buffer is empty. */
723 [ + - ]: 18 : if (RAW_BUF_BYTES(cstate) == 0)
724 : : {
1619 725 : 18 : CopyLoadRawBuf(cstate);
726 [ + + ]: 18 : if (cstate->raw_reached_eof)
1748 727 : 6 : break; /* EOF */
728 : : }
729 : :
730 : : /* Transfer some bytes. */
731 : 12 : copy_bytes = Min(nbytes - copied_bytes, RAW_BUF_BYTES(cstate));
732 : 12 : memcpy(dest, cstate->raw_buf + cstate->raw_buf_index, copy_bytes);
733 : 12 : cstate->raw_buf_index += copy_bytes;
734 : 12 : dest += copy_bytes;
735 : 12 : copied_bytes += copy_bytes;
736 [ - + ]: 12 : } while (copied_bytes < nbytes);
737 : : }
738 : :
739 : 191 : return copied_bytes;
740 : : }
741 : :
742 : : /*
743 : : * This function is exposed for use by extensions that read raw fields in the
744 : : * next line. See NextCopyFromRawFieldsInternal() for details.
745 : : */
746 : : bool
190 msawada@postgresql.o 747 :UBC 0 : NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
748 : : {
749 : 0 : return NextCopyFromRawFieldsInternal(cstate, fields, nfields,
750 : 0 : cstate->opts.csv_mode);
751 : : }
752 : :
753 : : /*
754 : : * Workhorse for NextCopyFromRawFields().
755 : : *
756 : : * Read raw fields in the next line for COPY FROM in text or csv mode. Return
757 : : * false if no more lines.
758 : : *
759 : : * An internal temporary buffer is returned via 'fields'. It is valid until
760 : : * the next call of the function. Since the function returns all raw fields
761 : : * in the input file, 'nfields' could be different from the number of columns
762 : : * in the relation.
763 : : *
764 : : * NOTE: force_not_null option are not applied to the returned fields.
765 : : *
766 : : * We use pg_attribute_always_inline to reduce function call overhead
767 : : * and to help compilers to optimize away the 'is_csv' condition when called
768 : : * by internal functions such as CopyFromTextLikeOneRow().
769 : : */
770 : : static pg_attribute_always_inline bool
190 msawada@postgresql.o 771 :CBC 732878 : NextCopyFromRawFieldsInternal(CopyFromState cstate, char ***fields, int *nfields, bool is_csv)
772 : : {
773 : : int fldct;
65 fujii@postgresql.org 774 :GNC 732878 : bool done = false;
775 : :
776 : : /* only available for text or csv input */
1748 heikki.linnakangas@i 777 [ - + ]:CBC 732878 : Assert(!cstate->opts.binary);
778 : :
779 : : /* on input check that the header line is correct if needed */
65 fujii@postgresql.org 780 [ + + + + ]:GNC 732878 : if (cstate->cur_lineno == 0 && cstate->opts.header_line != COPY_HEADER_FALSE)
781 : : {
782 : : ListCell *cur;
783 : : TupleDesc tupDesc;
784 : 69 : int lines_to_skip = cstate->opts.header_line;
785 : :
786 : : /* If set to "match", one header line is skipped */
787 [ + + ]: 69 : if (cstate->opts.header_line == COPY_HEADER_MATCH)
788 : 38 : lines_to_skip = 1;
789 : :
1256 peter@eisentraut.org 790 :CBC 69 : tupDesc = RelationGetDescr(cstate->rel);
791 : :
65 fujii@postgresql.org 792 [ + + ]:GNC 159 : for (int i = 0; i < lines_to_skip; i++)
793 : : {
794 : 93 : cstate->cur_lineno++;
795 [ + + ]: 93 : if ((done = CopyReadLine(cstate, is_csv)))
796 : 3 : break;
797 : : }
798 : :
1256 peter@eisentraut.org 799 [ + + ]:CBC 69 : if (cstate->opts.header_line == COPY_HEADER_MATCH)
800 : : {
801 : : int fldnum;
802 : :
190 msawada@postgresql.o 803 [ + + ]: 38 : if (is_csv)
570 michael@paquier.xyz 804 : 5 : fldct = CopyReadAttributesCSV(cstate);
805 : : else
806 : 33 : fldct = CopyReadAttributesText(cstate);
807 : :
1256 peter@eisentraut.org 808 [ + + ]: 38 : if (fldct != list_length(cstate->attnumlist))
809 [ + - ]: 12 : ereport(ERROR,
810 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
811 : : errmsg("wrong number of fields in header line: got %d, expected %d",
812 : : fldct, list_length(cstate->attnumlist))));
813 : :
814 : 26 : fldnum = 0;
815 [ + - + + : 79 : foreach(cur, cstate->attnumlist)
+ + ]
816 : : {
817 : 63 : int attnum = lfirst_int(cur);
818 : : char *colName;
819 : 63 : Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1);
820 : :
1171 michael@paquier.xyz 821 [ - + ]: 63 : Assert(fldnum < cstate->max_fields);
822 : :
823 : 63 : colName = cstate->raw_fields[fldnum++];
1256 peter@eisentraut.org 824 [ + + ]: 63 : if (colName == NULL)
825 [ + - ]: 3 : ereport(ERROR,
826 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
827 : : errmsg("column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"",
828 : : fldnum, cstate->opts.null_print, NameStr(attr->attname))));
829 : :
1213 tgl@sss.pgh.pa.us 830 [ + + ]: 60 : if (namestrcmp(&attr->attname, colName) != 0)
831 : : {
1256 peter@eisentraut.org 832 [ + - ]: 7 : ereport(ERROR,
833 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
834 : : errmsg("column name mismatch in header line field %d: got \"%s\", expected \"%s\"",
835 : : fldnum, colName, NameStr(attr->attname))));
836 : : }
837 : : }
838 : : }
839 : :
840 [ + + ]: 47 : if (done)
1256 peter@eisentraut.org 841 :GBC 3 : return false;
842 : : }
843 : :
1748 heikki.linnakangas@i 844 :CBC 732853 : cstate->cur_lineno++;
845 : :
846 : : /* Actually read the line into memory here */
190 msawada@postgresql.o 847 : 732853 : done = CopyReadLine(cstate, is_csv);
848 : :
849 : : /*
850 : : * EOF at start of line means we're done. If we see EOF after some
851 : : * characters, we act as though it was newline followed by EOF, ie,
852 : : * process the line and then exit loop on next iteration.
853 : : */
1748 heikki.linnakangas@i 854 [ + + + - ]: 732839 : if (done && cstate->line_buf.len == 0)
855 : 825 : return false;
856 : :
857 : : /* Parse the line into de-escaped field values */
190 msawada@postgresql.o 858 [ + + ]: 732014 : if (is_csv)
570 michael@paquier.xyz 859 : 238 : fldct = CopyReadAttributesCSV(cstate);
860 : : else
861 : 731776 : fldct = CopyReadAttributesText(cstate);
862 : :
1748 heikki.linnakangas@i 863 : 732008 : *fields = cstate->raw_fields;
864 : 732008 : *nfields = fldct;
865 : 732008 : return true;
866 : : }
867 : :
868 : : /*
869 : : * Read next tuple from file for COPY FROM. Return false if no more tuples.
870 : : *
871 : : * 'econtext' is used to evaluate default expression for each column that is
872 : : * either not read from the file or is using the DEFAULT option of COPY FROM.
873 : : * It can be NULL when no default values are used, i.e. when all columns are
874 : : * read from the file, and DEFAULT option is unset.
875 : : *
876 : : * 'values' and 'nulls' arrays must be the same length as columns of the
877 : : * relation passed to BeginCopyFrom. This function fills the arrays.
878 : : */
879 : : bool
880 : 732899 : NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
881 : : Datum *values, bool *nulls)
882 : : {
883 : : TupleDesc tupDesc;
884 : : AttrNumber num_phys_attrs,
885 : 732899 : num_defaults = cstate->num_defaults;
886 : : int i;
887 : 732899 : int *defmap = cstate->defmap;
888 : 732899 : ExprState **defexprs = cstate->defexprs;
889 : :
890 : 732899 : tupDesc = RelationGetDescr(cstate->rel);
891 : 732899 : num_phys_attrs = tupDesc->natts;
892 : :
893 : : /* Initialize all values for row to NULL */
894 [ + - + - : 3162304 : MemSet(values, 0, num_phys_attrs * sizeof(Datum));
+ - + - +
+ ]
895 [ + - + + : 732899 : MemSet(nulls, true, num_phys_attrs * sizeof(bool));
- + - - -
- ]
772 drowley@postgresql.o 896 [ + - + + : 804953 : MemSet(cstate->defaults, false, num_phys_attrs * sizeof(bool));
+ - + - +
+ ]
897 : :
898 : : /* Get one row from source */
190 msawada@postgresql.o 899 [ + + ]: 732899 : if (!cstate->routine->CopyFromOneRow(cstate, econtext, values, nulls))
900 : 834 : return false;
901 : :
902 : : /*
903 : : * Now compute and insert any defaults available for the columns not
904 : : * provided by the input data. Anything not processed here or above will
905 : : * remain NULL.
906 : : */
907 [ + + ]: 762250 : for (i = 0; i < num_defaults; i++)
908 : : {
909 : : /*
910 : : * The caller must supply econtext and have switched into the
911 : : * per-tuple memory context in it.
912 : : */
913 [ - + ]: 30265 : Assert(econtext != NULL);
914 [ - + ]: 30265 : Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory);
915 : :
916 : 30265 : values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext,
917 : 30265 : &nulls[defmap[i]]);
918 : : }
919 : :
920 : 731985 : return true;
921 : : }
922 : :
923 : : /* Implementation of the per-row callback for text format */
924 : : bool
925 : 732526 : CopyFromTextOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values,
926 : : bool *nulls)
927 : : {
928 : 732526 : return CopyFromTextLikeOneRow(cstate, econtext, values, nulls, false);
929 : : }
930 : :
931 : : /* Implementation of the per-row callback for CSV format */
932 : : bool
933 : 352 : CopyFromCSVOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values,
934 : : bool *nulls)
935 : : {
936 : 352 : return CopyFromTextLikeOneRow(cstate, econtext, values, nulls, true);
937 : : }
938 : :
939 : : /*
940 : : * Workhorse for CopyFromTextOneRow() and CopyFromCSVOneRow().
941 : : *
942 : : * We use pg_attribute_always_inline to reduce function call overhead
943 : : * and to help compilers to optimize away the 'is_csv' condition.
944 : : */
945 : : static pg_attribute_always_inline bool
946 : 732878 : CopyFromTextLikeOneRow(CopyFromState cstate, ExprContext *econtext,
947 : : Datum *values, bool *nulls, bool is_csv)
948 : : {
949 : : TupleDesc tupDesc;
950 : : AttrNumber attr_count;
951 : 732878 : FmgrInfo *in_functions = cstate->in_functions;
952 : 732878 : Oid *typioparams = cstate->typioparams;
953 : 732878 : ExprState **defexprs = cstate->defexprs;
954 : : char **field_strings;
955 : : ListCell *cur;
956 : : int fldct;
957 : : int fieldno;
958 : : char *string;
959 : :
960 : 732878 : tupDesc = RelationGetDescr(cstate->rel);
961 : 732878 : attr_count = list_length(cstate->attnumlist);
962 : :
963 : : /* read raw fields in the next line */
964 [ + + ]: 732878 : if (!NextCopyFromRawFieldsInternal(cstate, &field_strings, &fldct, is_csv))
965 : 828 : return false;
966 : :
967 : : /* check for overflowing fields */
968 [ + + + + ]: 732008 : if (attr_count > 0 && fldct > attr_count)
969 [ + - ]: 9 : ereport(ERROR,
970 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
971 : : errmsg("extra data after last expected column")));
972 : :
973 : 731999 : fieldno = 0;
974 : :
975 : : /* Loop to read the user attributes on the line. */
976 [ + + + + : 3091660 : foreach(cur, cstate->attnumlist)
+ + ]
977 : : {
978 : 2359753 : int attnum = lfirst_int(cur);
979 : 2359753 : int m = attnum - 1;
980 : 2359753 : Form_pg_attribute att = TupleDescAttr(tupDesc, m);
981 : :
982 [ + + ]: 2359753 : if (fieldno >= fldct)
1748 heikki.linnakangas@i 983 [ + - ]: 9 : ereport(ERROR,
984 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
985 : : errmsg("missing data for column \"%s\"",
986 : : NameStr(att->attname))));
190 msawada@postgresql.o 987 : 2359744 : string = field_strings[fieldno++];
988 : :
989 [ + + ]: 2359744 : if (cstate->convert_select_flags &&
990 [ + + ]: 10 : !cstate->convert_select_flags[m])
991 : : {
992 : : /* ignore input field, leaving column as NULL */
993 : 5 : continue;
994 : : }
995 : :
996 [ + + ]: 2359739 : if (is_csv)
997 : : {
998 [ + + ]: 487 : if (string == NULL &&
999 [ + + ]: 22 : cstate->opts.force_notnull_flags[m])
1000 : : {
1001 : : /*
1002 : : * FORCE_NOT_NULL option is set and column is NULL - convert
1003 : : * it to the NULL string.
1004 : : */
1005 : 14 : string = cstate->opts.null_print;
1006 : : }
1007 [ + + + + ]: 473 : else if (string != NULL && cstate->opts.force_null_flags[m]
1008 [ + + ]: 25 : && strcmp(string, cstate->opts.null_print) == 0)
1009 : : {
1010 : : /*
1011 : : * FORCE_NULL option is set and column matches the NULL
1012 : : * string. It must have been quoted, or otherwise the string
1013 : : * would already have been set to NULL. Convert it to NULL as
1014 : : * specified.
1015 : : */
1016 : 13 : string = NULL;
1017 : : }
1018 : : }
1019 : :
1020 : 2359739 : cstate->cur_attname = NameStr(att->attname);
1021 : 2359739 : cstate->cur_attval = string;
1022 : :
1023 [ + + ]: 2359739 : if (string != NULL)
1024 : 2357314 : nulls[m] = false;
1025 : :
1026 [ + + ]: 2359739 : if (cstate->defaults[m])
1027 : : {
1028 : : /* We must have switched into the per-tuple memory context */
1029 [ - + ]: 30 : Assert(econtext != NULL);
1030 [ - + ]: 30 : Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory);
1031 : :
1032 : 30 : values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]);
1033 : : }
1034 : :
1035 : : /*
1036 : : * If ON_ERROR is specified with IGNORE, skip rows with soft errors
1037 : : */
1038 [ + + ]: 2359690 : else if (!InputFunctionCallSafe(&in_functions[m],
1039 : : string,
1040 : 2359709 : typioparams[m],
1041 : : att->atttypmod,
1042 : 2359709 : (Node *) cstate->escontext,
1043 : 2359709 : &values[m]))
1044 : : {
1045 [ - + ]: 64 : Assert(cstate->opts.on_error != COPY_ON_ERROR_STOP);
1046 : :
1047 : 64 : cstate->num_errors++;
1048 : :
1049 [ + + ]: 64 : if (cstate->opts.log_verbosity == COPY_LOG_VERBOSITY_VERBOSE)
1050 : : {
1051 : : /*
1052 : : * Since we emit line number and column info in the below
1053 : : * notice message, we suppress error context information other
1054 : : * than the relation name.
1055 : : */
1056 [ - + ]: 21 : Assert(!cstate->relname_only);
1057 : 21 : cstate->relname_only = true;
1058 : :
1059 [ + + ]: 21 : if (cstate->cur_attval)
1060 : : {
1061 : : char *attval;
1062 : :
1063 : 18 : attval = CopyLimitPrintoutLength(cstate->cur_attval);
1064 [ + - ]: 18 : ereport(NOTICE,
1065 : : errmsg("skipping row due to data type incompatibility at line %" PRIu64 " for column \"%s\": \"%s\"",
1066 : : cstate->cur_lineno,
1067 : : cstate->cur_attname,
1068 : : attval));
1069 : 18 : pfree(attval);
1070 : : }
1071 : : else
1072 [ + - ]: 3 : ereport(NOTICE,
1073 : : errmsg("skipping row due to data type incompatibility at line %" PRIu64 " for column \"%s\": null input",
1074 : : cstate->cur_lineno,
1075 : : cstate->cur_attname));
1076 : :
1077 : : /* reset relname_only */
1078 : 21 : cstate->relname_only = false;
1079 : : }
1080 : :
1081 : 64 : return true;
1082 : : }
1083 : :
1084 : 2359656 : cstate->cur_attname = NULL;
1085 : 2359656 : cstate->cur_attval = NULL;
1086 : : }
1087 : :
1088 [ - + ]: 731907 : Assert(fieldno == attr_count);
1089 : :
1090 : 731907 : return true;
1091 : : }
1092 : :
1093 : : /* Implementation of the per-row callback for binary format */
1094 : : bool
1095 : 21 : CopyFromBinaryOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values,
1096 : : bool *nulls)
1097 : : {
1098 : : TupleDesc tupDesc;
1099 : : AttrNumber attr_count;
1100 : 21 : FmgrInfo *in_functions = cstate->in_functions;
1101 : 21 : Oid *typioparams = cstate->typioparams;
1102 : : int16 fld_count;
1103 : : ListCell *cur;
1104 : :
1105 : 21 : tupDesc = RelationGetDescr(cstate->rel);
1106 : 21 : attr_count = list_length(cstate->attnumlist);
1107 : :
1108 : 21 : cstate->cur_lineno++;
1109 : :
1110 [ - + ]: 21 : if (!CopyGetInt16(cstate, &fld_count))
1111 : : {
1112 : : /* EOF detected (end of file, or protocol-level EOF) */
190 msawada@postgresql.o 1113 :UBC 0 : return false;
1114 : : }
1115 : :
190 msawada@postgresql.o 1116 [ + + ]:CBC 21 : if (fld_count == -1)
1117 : : {
1118 : : /*
1119 : : * Received EOF marker. Wait for the protocol-level EOF, and complain
1120 : : * if it doesn't come immediately. In COPY FROM STDIN, this ensures
1121 : : * that we correctly handle CopyFail, if client chooses to send that
1122 : : * now. When copying from file, we could ignore the rest of the file
1123 : : * like in text mode, but we choose to be consistent with the COPY
1124 : : * FROM STDIN case.
1125 : : */
1126 : : char dummy;
1127 : :
1128 [ - + ]: 6 : if (CopyReadBinaryData(cstate, &dummy, 1) > 0)
190 msawada@postgresql.o 1129 [ # # ]:UBC 0 : ereport(ERROR,
1130 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1131 : : errmsg("received copy data after EOF marker")));
190 msawada@postgresql.o 1132 :CBC 6 : return false;
1133 : : }
1134 : :
1135 [ - + ]: 15 : if (fld_count != attr_count)
190 msawada@postgresql.o 1136 [ # # ]:UBC 0 : ereport(ERROR,
1137 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1138 : : errmsg("row field count is %d, expected %d",
1139 : : (int) fld_count, attr_count)));
1140 : :
190 msawada@postgresql.o 1141 [ + - + + :CBC 93 : foreach(cur, cstate->attnumlist)
+ + ]
1142 : : {
1143 : 79 : int attnum = lfirst_int(cur);
1144 : 79 : int m = attnum - 1;
1145 : 79 : Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1146 : :
1147 : 79 : cstate->cur_attname = NameStr(att->attname);
1148 : 157 : values[m] = CopyReadBinaryAttribute(cstate,
1149 : 79 : &in_functions[m],
1150 : 79 : typioparams[m],
1151 : : att->atttypmod,
1152 : : &nulls[m]);
1153 : 78 : cstate->cur_attname = NULL;
1154 : : }
1155 : :
1748 heikki.linnakangas@i 1156 : 14 : return true;
1157 : : }
1158 : :
1159 : : /*
1160 : : * Read the next input line and stash it in line_buf.
1161 : : *
1162 : : * Result is true if read was terminated by EOF, false if terminated
1163 : : * by newline. The terminating newline or EOF marker is not included
1164 : : * in the final value of line_buf.
1165 : : */
1166 : : static bool
190 msawada@postgresql.o 1167 : 732946 : CopyReadLine(CopyFromState cstate, bool is_csv)
1168 : : {
1169 : : bool result;
1170 : :
1748 heikki.linnakangas@i 1171 : 732946 : resetStringInfo(&cstate->line_buf);
1619 1172 : 732946 : cstate->line_buf_valid = false;
1173 : :
1174 : : /* Parse data and transfer into line_buf */
190 msawada@postgresql.o 1175 : 732946 : result = CopyReadLineText(cstate, is_csv);
1176 : :
1748 heikki.linnakangas@i 1177 [ + + ]: 732932 : if (result)
1178 : : {
1179 : : /*
1180 : : * Reached EOF. In protocol version 3, we should ignore anything
1181 : : * after \. up to the protocol end of copy data. (XXX maybe better
1182 : : * not to treat \. as special?)
1183 : : */
1647 1184 [ + + ]: 828 : if (cstate->copy_src == COPY_FRONTEND)
1185 : : {
1186 : : int inbytes;
1187 : :
1188 : : do
1189 : : {
1619 1190 : 437 : inbytes = CopyGetData(cstate, cstate->input_buf,
1191 : : 1, INPUT_BUF_SIZE);
1192 [ - + ]: 437 : } while (inbytes > 0);
1193 : 437 : cstate->input_buf_index = 0;
1194 : 437 : cstate->input_buf_len = 0;
1195 : 437 : cstate->raw_buf_index = 0;
1196 : 437 : cstate->raw_buf_len = 0;
1197 : : }
1198 : : }
1199 : : else
1200 : : {
1201 : : /*
1202 : : * If we didn't hit EOF, then we must have transferred the EOL marker
1203 : : * to line_buf along with the data. Get rid of it.
1204 : : */
1748 1205 [ + - - - : 732104 : switch (cstate->eol_type)
- ]
1206 : : {
1207 : 732104 : case EOL_NL:
1208 [ - + ]: 732104 : Assert(cstate->line_buf.len >= 1);
1209 [ - + ]: 732104 : Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
1210 : 732104 : cstate->line_buf.len--;
1211 : 732104 : cstate->line_buf.data[cstate->line_buf.len] = '\0';
1212 : 732104 : break;
1748 heikki.linnakangas@i 1213 :UBC 0 : case EOL_CR:
1214 [ # # ]: 0 : Assert(cstate->line_buf.len >= 1);
1215 [ # # ]: 0 : Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\r');
1216 : 0 : cstate->line_buf.len--;
1217 : 0 : cstate->line_buf.data[cstate->line_buf.len] = '\0';
1218 : 0 : break;
1219 : 0 : case EOL_CRNL:
1220 [ # # ]: 0 : Assert(cstate->line_buf.len >= 2);
1221 [ # # ]: 0 : Assert(cstate->line_buf.data[cstate->line_buf.len - 2] == '\r');
1222 [ # # ]: 0 : Assert(cstate->line_buf.data[cstate->line_buf.len - 1] == '\n');
1223 : 0 : cstate->line_buf.len -= 2;
1224 : 0 : cstate->line_buf.data[cstate->line_buf.len] = '\0';
1225 : 0 : break;
1226 : 0 : case EOL_UNKNOWN:
1227 : : /* shouldn't get here */
1228 : 0 : Assert(false);
1229 : : break;
1230 : : }
1231 : : }
1232 : :
1233 : : /* Now it's safe to use the buffer in error messages */
1619 heikki.linnakangas@i 1234 :CBC 732932 : cstate->line_buf_valid = true;
1235 : :
1748 1236 : 732932 : return result;
1237 : : }
1238 : :
1239 : : /*
1240 : : * CopyReadLineText - inner loop of CopyReadLine for text mode
1241 : : */
1242 : : static bool
190 msawada@postgresql.o 1243 : 732946 : CopyReadLineText(CopyFromState cstate, bool is_csv)
1244 : : {
1245 : : char *copy_input_buf;
1246 : : int input_buf_ptr;
1247 : : int copy_buf_len;
1748 heikki.linnakangas@i 1248 : 732946 : bool need_data = false;
1249 : 732946 : bool hit_eof = false;
1250 : 732946 : bool result = false;
1251 : :
1252 : : /* CSV variables */
1253 : 732946 : bool in_quote = false,
1254 : 732946 : last_was_esc = false;
1255 : 732946 : char quotec = '\0';
1256 : 732946 : char escapec = '\0';
1257 : :
190 msawada@postgresql.o 1258 [ + + ]: 732946 : if (is_csv)
1259 : : {
1748 heikki.linnakangas@i 1260 : 405 : quotec = cstate->opts.quote[0];
1261 : 405 : escapec = cstate->opts.escape[0];
1262 : : /* ignore special escape processing if it's the same as quotec */
1263 [ + + ]: 405 : if (quotec == escapec)
1264 : 308 : escapec = '\0';
1265 : : }
1266 : :
1267 : : /*
1268 : : * The objective of this loop is to transfer the entire next input line
1269 : : * into line_buf. Hence, we only care for detecting newlines (\r and/or
1270 : : * \n) and the end-of-copy marker (\.).
1271 : : *
1272 : : * In CSV mode, \r and \n inside a quoted field are just part of the data
1273 : : * value and are put in line_buf. We keep just enough state to know if we
1274 : : * are currently in a quoted field or not.
1275 : : *
1276 : : * The input has already been converted to the database encoding. All
1277 : : * supported server encodings have the property that all bytes in a
1278 : : * multi-byte sequence have the high bit set, so a multibyte character
1279 : : * cannot contain any newline or escape characters embedded in the
1280 : : * multibyte sequence. Therefore, we can process the input byte-by-byte,
1281 : : * regardless of the encoding.
1282 : : *
1283 : : * For speed, we try to move data from input_buf to line_buf in chunks
1284 : : * rather than one character at a time. input_buf_ptr points to the next
1285 : : * character to examine; any characters from input_buf_index to
1286 : : * input_buf_ptr have been determined to be part of the line, but not yet
1287 : : * transferred to line_buf.
1288 : : *
1289 : : * For a little extra speed within the loop, we copy input_buf and
1290 : : * input_buf_len into local variables.
1291 : : */
1619 1292 : 732946 : copy_input_buf = cstate->input_buf;
1293 : 732946 : input_buf_ptr = cstate->input_buf_index;
1294 : 732946 : copy_buf_len = cstate->input_buf_len;
1295 : :
1296 : : for (;;)
1748 1297 : 13218513 : {
1298 : : int prev_raw_ptr;
1299 : : char c;
1300 : :
1301 : : /*
1302 : : * Load more data if needed.
1303 : : *
1304 : : * TODO: We could just force four bytes of read-ahead and avoid the
1305 : : * many calls to IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(). That was
1306 : : * unsafe with the old v2 COPY protocol, but we don't support that
1307 : : * anymore.
1308 : : */
1619 1309 [ + + - + ]: 13951459 : if (input_buf_ptr >= copy_buf_len || need_data)
1310 : : {
1748 1311 [ + + ]: 215561 : REFILL_LINEBUF;
1312 : :
1619 1313 : 215561 : CopyLoadInputBuf(cstate);
1314 : : /* update our local variables */
1315 : 215553 : hit_eof = cstate->input_reached_eof;
1316 : 215553 : input_buf_ptr = cstate->input_buf_index;
1317 : 215553 : copy_buf_len = cstate->input_buf_len;
1318 : :
1319 : : /*
1320 : : * If we are completely out of data, break out of the loop,
1321 : : * reporting EOF.
1322 : : */
1323 [ + + ]: 215553 : if (INPUT_BUF_BYTES(cstate) <= 0)
1324 : : {
1748 1325 : 757 : result = true;
1326 : 757 : break;
1327 : : }
1328 : 214796 : need_data = false;
1329 : : }
1330 : :
1331 : : /* OK to fetch a character */
1619 1332 : 13950694 : prev_raw_ptr = input_buf_ptr;
1333 : 13950694 : c = copy_input_buf[input_buf_ptr++];
1334 : :
190 msawada@postgresql.o 1335 [ + + ]: 13950694 : if (is_csv)
1336 : : {
1337 : : /*
1338 : : * If character is '\r', we may need to look ahead below. Force
1339 : : * fetch of the next character if we don't already have it. We
1340 : : * need to do this before changing CSV state, in case '\r' is also
1341 : : * the quote or escape character.
1342 : : */
341 tgl@sss.pgh.pa.us 1343 [ + + ]: 3276 : if (c == '\r')
1344 : : {
1748 heikki.linnakangas@i 1345 [ - + - - ]: 18 : IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0);
1346 : : }
1347 : :
1348 : : /*
1349 : : * Dealing with quotes and escapes here is mildly tricky. If the
1350 : : * quote char is also the escape char, there's no problem - we
1351 : : * just use the char as a toggle. If they are different, we need
1352 : : * to ensure that we only take account of an escape inside a
1353 : : * quoted field and immediately preceding a quote char, and not
1354 : : * the second in an escape-escape sequence.
1355 : : */
1356 [ + + + + ]: 3276 : if (in_quote && c == escapec)
1357 : 24 : last_was_esc = !last_was_esc;
1358 [ + + + - ]: 3276 : if (c == quotec && !last_was_esc)
1359 : 254 : in_quote = !in_quote;
1360 [ + + ]: 3276 : if (c != escapec)
1361 : 3249 : last_was_esc = false;
1362 : :
1363 : : /*
1364 : : * Updating the line count for embedded CR and/or LF chars is
1365 : : * necessarily a little fragile - this test is probably about the
1366 : : * best we can do. (XXX it's arguable whether we should do this
1367 : : * at all --- is cur_lineno a physical or logical count?)
1368 : : */
1369 [ + + + + : 3276 : if (in_quote && c == (cstate->eol_type == EOL_NL ? '\n' : '\r'))
+ + ]
1370 : 18 : cstate->cur_lineno++;
1371 : : }
1372 : :
1373 : : /* Process \r */
190 msawada@postgresql.o 1374 [ + + + - : 13950694 : if (c == '\r' && (!is_csv || !in_quote))
- + ]
1375 : : {
1376 : : /* Check for \r\n on first line, _and_ handle \r\n. */
1748 heikki.linnakangas@i 1377 [ # # ]:UBC 0 : if (cstate->eol_type == EOL_UNKNOWN ||
1378 [ # # ]: 0 : cstate->eol_type == EOL_CRNL)
1379 : : {
1380 : : /*
1381 : : * If need more data, go back to loop top to load it.
1382 : : *
1383 : : * Note that if we are at EOF, c will wind up as '\0' because
1384 : : * of the guaranteed pad of input_buf.
1385 : : */
1386 [ # # # # ]: 0 : IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0);
1387 : :
1388 : : /* get next char */
1619 1389 : 0 : c = copy_input_buf[input_buf_ptr];
1390 : :
1748 1391 [ # # ]: 0 : if (c == '\n')
1392 : : {
1619 1393 : 0 : input_buf_ptr++; /* eat newline */
1748 1394 : 0 : cstate->eol_type = EOL_CRNL; /* in case not set yet */
1395 : : }
1396 : : else
1397 : : {
1398 : : /* found \r, but no \n */
1399 [ # # ]: 0 : if (cstate->eol_type == EOL_CRNL)
1400 [ # # # # : 0 : ereport(ERROR,
# # ]
1401 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1402 : : !is_csv ?
1403 : : errmsg("literal carriage return found in data") :
1404 : : errmsg("unquoted carriage return found in data"),
1405 : : !is_csv ?
1406 : : errhint("Use \"\\r\" to represent carriage return.") :
1407 : : errhint("Use quoted CSV field to represent carriage return.")));
1408 : :
1409 : : /*
1410 : : * if we got here, it is the first line and we didn't find
1411 : : * \n, so don't consume the peeked character
1412 : : */
1413 : 0 : cstate->eol_type = EOL_CR;
1414 : : }
1415 : : }
1416 [ # # ]: 0 : else if (cstate->eol_type == EOL_NL)
1417 [ # # # # : 0 : ereport(ERROR,
# # ]
1418 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1419 : : !is_csv ?
1420 : : errmsg("literal carriage return found in data") :
1421 : : errmsg("unquoted carriage return found in data"),
1422 : : !is_csv ?
1423 : : errhint("Use \"\\r\" to represent carriage return.") :
1424 : : errhint("Use quoted CSV field to represent carriage return.")));
1425 : : /* If reach here, we have found the line terminator */
1426 : 0 : break;
1427 : : }
1428 : :
1429 : : /* Process \n */
190 msawada@postgresql.o 1430 [ + + + + :CBC 13950694 : if (c == '\n' && (!is_csv || !in_quote))
+ + ]
1431 : : {
1748 heikki.linnakangas@i 1432 [ + - - + ]: 732104 : if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL)
1748 heikki.linnakangas@i 1433 [ # # # # :UBC 0 : ereport(ERROR,
# # ]
1434 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1435 : : !is_csv ?
1436 : : errmsg("literal newline found in data") :
1437 : : errmsg("unquoted newline found in data"),
1438 : : !is_csv ?
1439 : : errhint("Use \"\\n\" to represent newline.") :
1440 : : errhint("Use quoted CSV field to represent newline.")));
1748 heikki.linnakangas@i 1441 :CBC 732104 : cstate->eol_type = EOL_NL; /* in case not set yet */
1442 : : /* If reach here, we have found the line terminator */
1443 : 732104 : break;
1444 : : }
1445 : :
1446 : : /*
1447 : : * Process backslash, except in CSV mode where backslash is a normal
1448 : : * character.
1449 : : */
190 msawada@postgresql.o 1450 [ + + + + ]: 13218590 : if (c == '\\' && !is_csv)
1451 : : {
1452 : : char c2;
1453 : :
1748 heikki.linnakangas@i 1454 [ - + - - ]: 4077 : IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0);
1455 [ - + - - ]: 4077 : IF_NEED_REFILL_AND_EOF_BREAK(0);
1456 : :
1457 : : /* -----
1458 : : * get next character
1459 : : * Note: we do not change c so if it isn't \., we can fall
1460 : : * through and continue processing.
1461 : : * -----
1462 : : */
1619 1463 : 4077 : c2 = copy_input_buf[input_buf_ptr];
1464 : :
1748 1465 [ + + ]: 4077 : if (c2 == '.')
1466 : : {
1619 1467 : 77 : input_buf_ptr++; /* consume the '.' */
1748 1468 [ - + ]: 77 : if (cstate->eol_type == EOL_CRNL)
1469 : : {
1470 : : /* Get the next character */
1748 heikki.linnakangas@i 1471 [ # # # # ]:UBC 0 : IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0);
1472 : : /* if hit_eof, c2 will become '\0' */
1619 1473 : 0 : c2 = copy_input_buf[input_buf_ptr++];
1474 : :
1748 1475 [ # # ]: 0 : if (c2 == '\n')
341 tgl@sss.pgh.pa.us 1476 [ # # ]: 0 : ereport(ERROR,
1477 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1478 : : errmsg("end-of-copy marker does not match previous newline style")));
1748 heikki.linnakangas@i 1479 [ # # ]: 0 : else if (c2 != '\r')
341 tgl@sss.pgh.pa.us 1480 [ # # ]: 0 : ereport(ERROR,
1481 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1482 : : errmsg("end-of-copy marker is not alone on its line")));
1483 : : }
1484 : :
1485 : : /* Get the next character */
1748 heikki.linnakangas@i 1486 [ - + - - ]:CBC 77 : IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0);
1487 : : /* if hit_eof, c2 will become '\0' */
1619 1488 : 77 : c2 = copy_input_buf[input_buf_ptr++];
1489 : :
1748 1490 [ + - + + ]: 77 : if (c2 != '\r' && c2 != '\n')
341 tgl@sss.pgh.pa.us 1491 [ + - ]: 3 : ereport(ERROR,
1492 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1493 : : errmsg("end-of-copy marker is not alone on its line")));
1494 : :
1748 heikki.linnakangas@i 1495 [ + + + - ]: 74 : if ((cstate->eol_type == EOL_NL && c2 != '\n') ||
1496 [ - + - - ]: 74 : (cstate->eol_type == EOL_CRNL && c2 != '\n') ||
1497 [ - + - - ]: 74 : (cstate->eol_type == EOL_CR && c2 != '\r'))
1748 heikki.linnakangas@i 1498 [ # # ]:UBC 0 : ereport(ERROR,
1499 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1500 : : errmsg("end-of-copy marker does not match previous newline style")));
1501 : :
1502 : : /*
1503 : : * If there is any data on this line before the \., complain.
1504 : : */
340 tgl@sss.pgh.pa.us 1505 [ + - ]:CBC 74 : if (cstate->line_buf.len > 0 ||
1506 [ + + ]: 74 : prev_raw_ptr > cstate->input_buf_index)
1507 [ + - ]: 3 : ereport(ERROR,
1508 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1509 : : errmsg("end-of-copy marker is not alone on its line")));
1510 : :
1511 : : /*
1512 : : * Discard the \. and newline, then report EOF.
1513 : : */
1619 heikki.linnakangas@i 1514 : 71 : cstate->input_buf_index = input_buf_ptr;
1748 1515 : 71 : result = true; /* report EOF */
1516 : 71 : break;
1517 : : }
1518 : : else
1519 : : {
1520 : : /*
1521 : : * If we are here, it means we found a backslash followed by
1522 : : * something other than a period. In non-CSV mode, anything
1523 : : * after a backslash is special, so we skip over that second
1524 : : * character too. If we didn't do that \\. would be
1525 : : * considered an eof-of copy, while in non-CSV mode it is a
1526 : : * literal backslash followed by a period.
1527 : : */
1619 1528 : 4000 : input_buf_ptr++;
1529 : : }
1530 : : }
1531 : : } /* end of outer loop */
1532 : :
1533 : : /*
1534 : : * Transfer any still-uncopied data to line_buf.
1535 : : */
1748 1536 [ + + ]: 732932 : REFILL_LINEBUF;
1537 : :
1538 : 732932 : return result;
1539 : : }
1540 : :
1541 : : /*
1542 : : * Return decimal value for a hexadecimal digit
1543 : : */
1544 : : static int
1748 heikki.linnakangas@i 1545 :UBC 0 : GetDecimalFromHex(char hex)
1546 : : {
1547 [ # # ]: 0 : if (isdigit((unsigned char) hex))
1548 : 0 : return hex - '0';
1549 : : else
67 jdavis@postgresql.or 1550 :UNC 0 : return pg_ascii_tolower((unsigned char) hex) - 'a' + 10;
1551 : : }
1552 : :
1553 : : /*
1554 : : * Parse the current line into separate attributes (fields),
1555 : : * performing de-escaping as needed.
1556 : : *
1557 : : * The input is in line_buf. We use attribute_buf to hold the result
1558 : : * strings. cstate->raw_fields[k] is set to point to the k'th attribute
1559 : : * string, or NULL when the input matches the null marker string.
1560 : : * This array is expanded as necessary.
1561 : : *
1562 : : * (Note that the caller cannot check for nulls since the returned
1563 : : * string would be the post-de-escaping equivalent, which may look
1564 : : * the same as some valid data string.)
1565 : : *
1566 : : * delim is the column delimiter string (must be just one byte for now).
1567 : : * null_print is the null marker string. Note that this is compared to
1568 : : * the pre-de-escaped input string.
1569 : : *
1570 : : * The return value is the number of fields actually read.
1571 : : */
1572 : : static int
1748 heikki.linnakangas@i 1573 :CBC 731809 : CopyReadAttributesText(CopyFromState cstate)
1574 : : {
1575 : 731809 : char delimc = cstate->opts.delim[0];
1576 : : int fieldno;
1577 : : char *output_ptr;
1578 : : char *cur_ptr;
1579 : : char *line_end_ptr;
1580 : :
1581 : : /*
1582 : : * We need a special case for zero-column tables: check that the input
1583 : : * line is empty, and return.
1584 : : */
1585 [ + + ]: 731809 : if (cstate->max_fields <= 0)
1586 : : {
1587 [ - + ]: 4 : if (cstate->line_buf.len != 0)
1748 heikki.linnakangas@i 1588 [ # # ]:UBC 0 : ereport(ERROR,
1589 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1590 : : errmsg("extra data after last expected column")));
1748 heikki.linnakangas@i 1591 :CBC 4 : return 0;
1592 : : }
1593 : :
1594 : 731805 : resetStringInfo(&cstate->attribute_buf);
1595 : :
1596 : : /*
1597 : : * The de-escaped attributes will certainly not be longer than the input
1598 : : * data line, so we can just force attribute_buf to be large enough and
1599 : : * then transfer data without any checks for enough space. We need to do
1600 : : * it this way because enlarging attribute_buf mid-stream would invalidate
1601 : : * pointers already stored into cstate->raw_fields[].
1602 : : */
1603 [ + + ]: 731805 : if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
1604 : 4 : enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
1605 : 731805 : output_ptr = cstate->attribute_buf.data;
1606 : :
1607 : : /* set pointer variables for loop */
1608 : 731805 : cur_ptr = cstate->line_buf.data;
1609 : 731805 : line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
1610 : :
1611 : : /* Outer loop iterates over fields */
1612 : 731805 : fieldno = 0;
1613 : : for (;;)
1614 : 1627636 : {
1615 : 2359441 : bool found_delim = false;
1616 : : char *start_ptr;
1617 : : char *end_ptr;
1618 : : int input_len;
1619 : 2359441 : bool saw_non_ascii = false;
1620 : :
1621 : : /* Make sure there is enough space for the next value */
1622 [ + + ]: 2359441 : if (fieldno >= cstate->max_fields)
1623 : : {
1624 : 18 : cstate->max_fields *= 2;
1625 : 18 : cstate->raw_fields =
1626 : 18 : repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
1627 : : }
1628 : :
1629 : : /* Remember start of field on both input and output sides */
1630 : 2359441 : start_ptr = cur_ptr;
1631 : 2359441 : cstate->raw_fields[fieldno] = output_ptr;
1632 : :
1633 : : /*
1634 : : * Scan data for field.
1635 : : *
1636 : : * Note that in this loop, we are scanning to locate the end of field
1637 : : * and also speculatively performing de-escaping. Once we find the
1638 : : * end-of-field, we can match the raw field contents against the null
1639 : : * marker string. Only after that comparison fails do we know that
1640 : : * de-escaping is actually the right thing to do; therefore we *must
1641 : : * not* throw any syntax errors before we've done the null-marker
1642 : : * check.
1643 : : */
1644 : : for (;;)
1645 : 11587638 : {
1646 : : char c;
1647 : :
1648 : 13947079 : end_ptr = cur_ptr;
1649 [ + + ]: 13947079 : if (cur_ptr >= line_end_ptr)
1650 : 731802 : break;
1651 : 13215277 : c = *cur_ptr++;
1652 [ + + ]: 13215277 : if (c == delimc)
1653 : : {
1654 : 1627639 : found_delim = true;
1655 : 1627639 : break;
1656 : : }
1657 [ + + ]: 11587638 : if (c == '\\')
1658 : : {
1659 [ - + ]: 4000 : if (cur_ptr >= line_end_ptr)
1748 heikki.linnakangas@i 1660 :UBC 0 : break;
1748 heikki.linnakangas@i 1661 :CBC 4000 : c = *cur_ptr++;
1662 [ + + - - : 4000 : switch (c)
+ - - -
+ ]
1663 : : {
1664 : 6 : case '0':
1665 : : case '1':
1666 : : case '2':
1667 : : case '3':
1668 : : case '4':
1669 : : case '5':
1670 : : case '6':
1671 : : case '7':
1672 : : {
1673 : : /* handle \013 */
1674 : : int val;
1675 : :
1676 : 6 : val = OCTVALUE(c);
1677 [ + + ]: 6 : if (cur_ptr < line_end_ptr)
1678 : : {
1679 : 3 : c = *cur_ptr;
1680 [ - + - - ]: 3 : if (ISOCTAL(c))
1681 : : {
1748 heikki.linnakangas@i 1682 :UBC 0 : cur_ptr++;
1683 : 0 : val = (val << 3) + OCTVALUE(c);
1684 [ # # ]: 0 : if (cur_ptr < line_end_ptr)
1685 : : {
1686 : 0 : c = *cur_ptr;
1687 [ # # # # ]: 0 : if (ISOCTAL(c))
1688 : : {
1689 : 0 : cur_ptr++;
1690 : 0 : val = (val << 3) + OCTVALUE(c);
1691 : : }
1692 : : }
1693 : : }
1694 : : }
1748 heikki.linnakangas@i 1695 :CBC 6 : c = val & 0377;
1696 [ - + - - ]: 6 : if (c == '\0' || IS_HIGHBIT_SET(c))
1697 : 6 : saw_non_ascii = true;
1698 : : }
1699 : 6 : break;
1700 : 6 : case 'x':
1701 : : /* Handle \x3F */
1702 [ + + ]: 6 : if (cur_ptr < line_end_ptr)
1703 : : {
1704 : 3 : char hexchar = *cur_ptr;
1705 : :
1706 [ - + ]: 3 : if (isxdigit((unsigned char) hexchar))
1707 : : {
1748 heikki.linnakangas@i 1708 :UBC 0 : int val = GetDecimalFromHex(hexchar);
1709 : :
1710 : 0 : cur_ptr++;
1711 [ # # ]: 0 : if (cur_ptr < line_end_ptr)
1712 : : {
1713 : 0 : hexchar = *cur_ptr;
1714 [ # # ]: 0 : if (isxdigit((unsigned char) hexchar))
1715 : : {
1716 : 0 : cur_ptr++;
1717 : 0 : val = (val << 4) + GetDecimalFromHex(hexchar);
1718 : : }
1719 : : }
1720 : 0 : c = val & 0xff;
1721 [ # # # # ]: 0 : if (c == '\0' || IS_HIGHBIT_SET(c))
1722 : 0 : saw_non_ascii = true;
1723 : : }
1724 : : }
1748 heikki.linnakangas@i 1725 :CBC 6 : break;
1748 heikki.linnakangas@i 1726 :UBC 0 : case 'b':
1727 : 0 : c = '\b';
1728 : 0 : break;
1729 : 0 : case 'f':
1730 : 0 : c = '\f';
1731 : 0 : break;
1748 heikki.linnakangas@i 1732 :CBC 1525 : case 'n':
1733 : 1525 : c = '\n';
1734 : 1525 : break;
1748 heikki.linnakangas@i 1735 :UBC 0 : case 'r':
1736 : 0 : c = '\r';
1737 : 0 : break;
1738 : 0 : case 't':
1739 : 0 : c = '\t';
1740 : 0 : break;
1741 : 0 : case 'v':
1742 : 0 : c = '\v';
1743 : 0 : break;
1744 : :
1745 : : /*
1746 : : * in all other cases, take the char after '\'
1747 : : * literally
1748 : : */
1749 : : }
1750 : : }
1751 : :
1752 : : /* Add c to output string */
1748 heikki.linnakangas@i 1753 :CBC 11587638 : *output_ptr++ = c;
1754 : : }
1755 : :
1756 : : /* Check whether raw input matched null marker */
1757 : 2359441 : input_len = end_ptr - start_ptr;
1758 [ + + ]: 2359441 : if (input_len == cstate->opts.null_print_len &&
1759 [ + + ]: 125120 : strncmp(start_ptr, cstate->opts.null_print, input_len) == 0)
1760 : 2407 : cstate->raw_fields[fieldno] = NULL;
1761 : : /* Check whether raw input matched default marker */
906 andrew@dunslane.net 1762 [ + + ]: 2357034 : else if (fieldno < list_length(cstate->attnumlist) &&
1763 [ + + ]: 2357013 : cstate->opts.default_print &&
908 1764 [ + + ]: 57 : input_len == cstate->opts.default_print_len &&
1765 [ + - ]: 15 : strncmp(start_ptr, cstate->opts.default_print, input_len) == 0)
1766 : 12 : {
1767 : : /* fieldno is 0-indexed and attnum is 1-indexed */
1768 : 15 : int m = list_nth_int(cstate->attnumlist, fieldno) - 1;
1769 : :
1770 [ + + ]: 15 : if (cstate->defexprs[m] != NULL)
1771 : : {
1772 : : /* defaults contain entries for all physical attributes */
1773 : 12 : cstate->defaults[m] = true;
1774 : : }
1775 : : else
1776 : : {
1777 : 3 : TupleDesc tupDesc = RelationGetDescr(cstate->rel);
1778 : 3 : Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1779 : :
1780 [ + - ]: 3 : ereport(ERROR,
1781 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1782 : : errmsg("unexpected default marker in COPY data"),
1783 : : errdetail("Column \"%s\" has no default value.",
1784 : : NameStr(att->attname))));
1785 : : }
1786 : : }
1787 : : else
1788 : : {
1789 : : /*
1790 : : * At this point we know the field is supposed to contain data.
1791 : : *
1792 : : * If we de-escaped any non-7-bit-ASCII chars, make sure the
1793 : : * resulting string is valid data for the db encoding.
1794 : : */
1748 heikki.linnakangas@i 1795 [ - + ]: 2357019 : if (saw_non_ascii)
1796 : : {
1748 heikki.linnakangas@i 1797 :UBC 0 : char *fld = cstate->raw_fields[fieldno];
1798 : :
1799 : 0 : pg_verifymbstr(fld, output_ptr - fld, false);
1800 : : }
1801 : : }
1802 : :
1803 : : /* Terminate attribute value in output area */
1748 heikki.linnakangas@i 1804 :CBC 2359438 : *output_ptr++ = '\0';
1805 : :
1806 : 2359438 : fieldno++;
1807 : : /* Done if we hit EOL instead of a delim */
1808 [ + + ]: 2359438 : if (!found_delim)
1809 : 731802 : break;
1810 : : }
1811 : :
1812 : : /* Clean up state of attribute_buf */
1813 : 731802 : output_ptr--;
1814 [ - + ]: 731802 : Assert(*output_ptr == '\0');
1815 : 731802 : cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
1816 : :
1817 : 731802 : return fieldno;
1818 : : }
1819 : :
1820 : : /*
1821 : : * Parse the current line into separate attributes (fields),
1822 : : * performing de-escaping as needed. This has exactly the same API as
1823 : : * CopyReadAttributesText, except we parse the fields according to
1824 : : * "standard" (i.e. common) CSV usage.
1825 : : */
1826 : : static int
1827 : 243 : CopyReadAttributesCSV(CopyFromState cstate)
1828 : : {
1829 : 243 : char delimc = cstate->opts.delim[0];
1830 : 243 : char quotec = cstate->opts.quote[0];
1831 : 243 : char escapec = cstate->opts.escape[0];
1832 : : int fieldno;
1833 : : char *output_ptr;
1834 : : char *cur_ptr;
1835 : : char *line_end_ptr;
1836 : :
1837 : : /*
1838 : : * We need a special case for zero-column tables: check that the input
1839 : : * line is empty, and return.
1840 : : */
1841 [ - + ]: 243 : if (cstate->max_fields <= 0)
1842 : : {
1748 heikki.linnakangas@i 1843 [ # # ]:UBC 0 : if (cstate->line_buf.len != 0)
1844 [ # # ]: 0 : ereport(ERROR,
1845 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1846 : : errmsg("extra data after last expected column")));
1847 : 0 : return 0;
1848 : : }
1849 : :
1748 heikki.linnakangas@i 1850 :CBC 243 : resetStringInfo(&cstate->attribute_buf);
1851 : :
1852 : : /*
1853 : : * The de-escaped attributes will certainly not be longer than the input
1854 : : * data line, so we can just force attribute_buf to be large enough and
1855 : : * then transfer data without any checks for enough space. We need to do
1856 : : * it this way because enlarging attribute_buf mid-stream would invalidate
1857 : : * pointers already stored into cstate->raw_fields[].
1858 : : */
1859 [ - + ]: 243 : if (cstate->attribute_buf.maxlen <= cstate->line_buf.len)
1748 heikki.linnakangas@i 1860 :UBC 0 : enlargeStringInfo(&cstate->attribute_buf, cstate->line_buf.len);
1748 heikki.linnakangas@i 1861 :CBC 243 : output_ptr = cstate->attribute_buf.data;
1862 : :
1863 : : /* set pointer variables for loop */
1864 : 243 : cur_ptr = cstate->line_buf.data;
1865 : 243 : line_end_ptr = cstate->line_buf.data + cstate->line_buf.len;
1866 : :
1867 : : /* Outer loop iterates over fields */
1868 : 243 : fieldno = 0;
1869 : : for (;;)
1870 : 265 : {
1871 : 508 : bool found_delim = false;
1872 : 508 : bool saw_quote = false;
1873 : : char *start_ptr;
1874 : : char *end_ptr;
1875 : : int input_len;
1876 : :
1877 : : /* Make sure there is enough space for the next value */
1878 [ - + ]: 508 : if (fieldno >= cstate->max_fields)
1879 : : {
1748 heikki.linnakangas@i 1880 :UBC 0 : cstate->max_fields *= 2;
1881 : 0 : cstate->raw_fields =
1882 : 0 : repalloc(cstate->raw_fields, cstate->max_fields * sizeof(char *));
1883 : : }
1884 : :
1885 : : /* Remember start of field on both input and output sides */
1748 heikki.linnakangas@i 1886 :CBC 508 : start_ptr = cur_ptr;
1887 : 508 : cstate->raw_fields[fieldno] = output_ptr;
1888 : :
1889 : : /*
1890 : : * Scan data for field,
1891 : : *
1892 : : * The loop starts in "not quote" mode and then toggles between that
1893 : : * and "in quote" mode. The loop exits normally if it is in "not
1894 : : * quote" mode and a delimiter or line end is seen.
1895 : : */
1896 : : for (;;)
1897 : 111 : {
1898 : : char c;
1899 : :
1900 : : /* Not in quote */
1901 : : for (;;)
1902 : : {
1903 : 1627 : end_ptr = cur_ptr;
1904 [ + + ]: 1627 : if (cur_ptr >= line_end_ptr)
1905 : 240 : goto endfield;
1906 : 1387 : c = *cur_ptr++;
1907 : : /* unquoted field delimiter */
1908 [ + + ]: 1387 : if (c == delimc)
1909 : : {
1910 : 268 : found_delim = true;
1911 : 268 : goto endfield;
1912 : : }
1913 : : /* start of quoted field (or part of field) */
1914 [ + + ]: 1119 : if (c == quotec)
1915 : : {
1916 : 111 : saw_quote = true;
1917 : 111 : break;
1918 : : }
1919 : : /* Add c to output string */
1920 : 1008 : *output_ptr++ = c;
1921 : : }
1922 : :
1923 : : /* In quote */
1924 : : for (;;)
1925 : : {
1926 : 695 : end_ptr = cur_ptr;
1927 [ - + ]: 695 : if (cur_ptr >= line_end_ptr)
1748 heikki.linnakangas@i 1928 [ # # ]:UBC 0 : ereport(ERROR,
1929 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1930 : : errmsg("unterminated CSV quoted field")));
1931 : :
1748 heikki.linnakangas@i 1932 :CBC 695 : c = *cur_ptr++;
1933 : :
1934 : : /* escape within a quoted field */
1935 [ + + ]: 695 : if (c == escapec)
1936 : : {
1937 : : /*
1938 : : * peek at the next char if available, and escape it if it
1939 : : * is an escape char or a quote char
1940 : : */
1941 [ + + ]: 59 : if (cur_ptr < line_end_ptr)
1942 : : {
1943 : 36 : char nextc = *cur_ptr;
1944 : :
1945 [ + + - + ]: 36 : if (nextc == escapec || nextc == quotec)
1946 : : {
1947 : 12 : *output_ptr++ = nextc;
1948 : 12 : cur_ptr++;
1949 : 12 : continue;
1950 : : }
1951 : : }
1952 : : }
1953 : :
1954 : : /*
1955 : : * end of quoted field. Must do this test after testing for
1956 : : * escape in case quote char and escape char are the same
1957 : : * (which is the common case).
1958 : : */
1959 [ + + ]: 683 : if (c == quotec)
1960 : 111 : break;
1961 : :
1962 : : /* Add c to output string */
1963 : 572 : *output_ptr++ = c;
1964 : : }
1965 : : }
1966 : 508 : endfield:
1967 : :
1968 : : /* Terminate attribute value in output area */
1969 : 508 : *output_ptr++ = '\0';
1970 : :
1971 : : /* Check whether raw input matched null marker */
1972 : 508 : input_len = end_ptr - start_ptr;
1973 [ + + + + ]: 508 : if (!saw_quote && input_len == cstate->opts.null_print_len &&
1974 [ + - ]: 22 : strncmp(start_ptr, cstate->opts.null_print, input_len) == 0)
1975 : 22 : cstate->raw_fields[fieldno] = NULL;
1976 : : /* Check whether raw input matched default marker */
906 andrew@dunslane.net 1977 [ + - ]: 486 : else if (fieldno < list_length(cstate->attnumlist) &&
1978 [ + + ]: 486 : cstate->opts.default_print &&
908 1979 [ + + ]: 75 : input_len == cstate->opts.default_print_len &&
1980 [ + - ]: 21 : strncmp(start_ptr, cstate->opts.default_print, input_len) == 0)
1981 : : {
1982 : : /* fieldno is 0-index and attnum is 1-index */
1983 : 21 : int m = list_nth_int(cstate->attnumlist, fieldno) - 1;
1984 : :
1985 [ + + ]: 21 : if (cstate->defexprs[m] != NULL)
1986 : : {
1987 : : /* defaults contain entries for all physical attributes */
1988 : 18 : cstate->defaults[m] = true;
1989 : : }
1990 : : else
1991 : : {
1992 : 3 : TupleDesc tupDesc = RelationGetDescr(cstate->rel);
1993 : 3 : Form_pg_attribute att = TupleDescAttr(tupDesc, m);
1994 : :
1995 [ + - ]: 3 : ereport(ERROR,
1996 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
1997 : : errmsg("unexpected default marker in COPY data"),
1998 : : errdetail("Column \"%s\" has no default value.",
1999 : : NameStr(att->attname))));
2000 : : }
2001 : : }
2002 : :
1748 heikki.linnakangas@i 2003 : 505 : fieldno++;
2004 : : /* Done if we hit EOL instead of a delim */
2005 [ + + ]: 505 : if (!found_delim)
2006 : 240 : break;
2007 : : }
2008 : :
2009 : : /* Clean up state of attribute_buf */
2010 : 240 : output_ptr--;
2011 [ - + ]: 240 : Assert(*output_ptr == '\0');
2012 : 240 : cstate->attribute_buf.len = (output_ptr - cstate->attribute_buf.data);
2013 : :
2014 : 240 : return fieldno;
2015 : : }
2016 : :
2017 : :
2018 : : /*
2019 : : * Read a binary attribute
2020 : : */
2021 : : static Datum
2022 : 79 : CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo,
2023 : : Oid typioparam, int32 typmod,
2024 : : bool *isnull)
2025 : : {
2026 : : int32 fld_size;
2027 : : Datum result;
2028 : :
2029 [ - + ]: 79 : if (!CopyGetInt32(cstate, &fld_size))
1748 heikki.linnakangas@i 2030 [ # # ]:UBC 0 : ereport(ERROR,
2031 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
2032 : : errmsg("unexpected EOF in COPY data")));
1748 heikki.linnakangas@i 2033 [ + + ]:CBC 79 : if (fld_size == -1)
2034 : : {
2035 : 15 : *isnull = true;
2036 : 15 : return ReceiveFunctionCall(flinfo, NULL, typioparam, typmod);
2037 : : }
2038 [ - + ]: 64 : if (fld_size < 0)
1748 heikki.linnakangas@i 2039 [ # # ]:UBC 0 : ereport(ERROR,
2040 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
2041 : : errmsg("invalid field size")));
2042 : :
2043 : : /* reset attribute_buf to empty, and load raw data in it */
1748 heikki.linnakangas@i 2044 :CBC 64 : resetStringInfo(&cstate->attribute_buf);
2045 : :
2046 : 64 : enlargeStringInfo(&cstate->attribute_buf, fld_size);
2047 : 64 : if (CopyReadBinaryData(cstate, cstate->attribute_buf.data,
2048 [ - + ]: 64 : fld_size) != fld_size)
1748 heikki.linnakangas@i 2049 [ # # ]:UBC 0 : ereport(ERROR,
2050 : : (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
2051 : : errmsg("unexpected EOF in COPY data")));
2052 : :
1748 heikki.linnakangas@i 2053 :CBC 64 : cstate->attribute_buf.len = fld_size;
2054 : 64 : cstate->attribute_buf.data[fld_size] = '\0';
2055 : :
2056 : : /* Call the column type's binary input converter */
2057 : 64 : result = ReceiveFunctionCall(flinfo, &cstate->attribute_buf,
2058 : : typioparam, typmod);
2059 : :
2060 : : /* Trouble if it didn't eat the whole buffer */
2061 [ + + ]: 64 : if (cstate->attribute_buf.cursor != cstate->attribute_buf.len)
2062 [ + - ]: 1 : ereport(ERROR,
2063 : : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
2064 : : errmsg("incorrect binary data format")));
2065 : :
2066 : 63 : *isnull = false;
2067 : 63 : return result;
2068 : : }
|