33 *
44 * Copyright (c) 2000-2003, PostgreSQL Global Development Group
55 *
6- * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.40 2004/01/26 22:35:32 tgl Exp $
6+ * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.41 2004/01/28 22:14:04 tgl Exp $
77 */
88#include "postgres_fe.h"
99#include "copy.h"
3636 * parse_slash_copy
3737 * -- parses \copy command line
3838 *
39- * Accepted syntax: \copy table [(columnlist)] [with oids] from|to filename [with ] [ oids ] [ delimiter char] [ null as string ]
39+ * The documented preferred syntax is:
40+ * \copy tablename [(columnlist)] from|to filename
41+ * [ with ] [ oids ] [ delimiter [as] char ] [ null [as] string ]
4042 * (binary is not here yet)
4143 *
42- * Old syntax for backward compatibility: (2002-06-19):
43- * \copy table [(columnlist)] [with oids] from|to filename [ using delimiters char] [ with null as string ]
44+ * The pre-7.3 syntax was:
45+ * \copy tablename [(columnlist)] [with oids] from|to filename
46+ * [ [using] delimiters char ] [ with null as string ]
47+ *
48+ * The actual accepted syntax is a rather unholy combination of these,
49+ * plus some undocumented flexibility (for instance, the clauses after
50+ * WITH can appear in any order). The accepted syntax matches what
51+ * the backend grammar actually accepts (see backend/parser/gram.y).
4452 *
4553 * table name can be double-quoted and can have a schema part.
4654 * column names can be double-quoted.
@@ -243,6 +251,9 @@ parse_slash_copy(const char *args)
243251 0 , false, pset .encoding );
244252 if (!(token && strcasecmp (token , "delimiters" ) == 0 ))
245253 goto error ;
254+ }
255+ if (token && strcasecmp (token , "delimiters" ) == 0 )
256+ {
246257 token = strtokx (NULL , whitespace , NULL , "'" ,
247258 '\\' , false, pset .encoding );
248259 if (!token )
@@ -254,12 +265,22 @@ parse_slash_copy(const char *args)
254265
255266 if (token )
256267 {
257- if (strcasecmp (token , "with" ) != 0 )
258- goto error ;
259- while ((token = strtokx (NULL , whitespace , NULL , NULL ,
260- 0 , false, pset .encoding )) != NULL )
268+ /*
269+ * WITH is optional. Also, the backend will allow WITH followed by
270+ * nothing, so we do too.
271+ */
272+ if (strcasecmp (token , "with" ) == 0 )
273+ token = strtokx (NULL , whitespace , NULL , NULL ,
274+ 0 , false, pset .encoding );
275+
276+ while (token )
261277 {
262- if (strcasecmp (token , "delimiter" ) == 0 )
278+ /* someday allow BINARY here */
279+ if (strcasecmp (token , "oids" ) == 0 )
280+ {
281+ result -> oids = true;
282+ }
283+ else if (strcasecmp (token , "delimiter" ) == 0 )
263284 {
264285 token = strtokx (NULL , whitespace , NULL , "'" ,
265286 '\\' , false, pset .encoding );
@@ -285,6 +306,9 @@ parse_slash_copy(const char *args)
285306 }
286307 else
287308 goto error ;
309+
310+ token = strtokx (NULL , whitespace , NULL , NULL ,
311+ 0 , false, pset .encoding );
288312 }
289313 }
290314
0 commit comments