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)
2432510 , false,pset .encoding );
244252if (!(token && strcasecmp (token ,"delimiters" )== 0 ))
245253gotoerror ;
254+ }
255+ if (token && strcasecmp (token ,"delimiters" )== 0 )
256+ {
246257token = strtokx (NULL ,whitespace ,NULL ,"'" ,
247258'\\' , false,pset .encoding );
248259if (!token )
@@ -254,12 +265,22 @@ parse_slash_copy(const char *args)
254265
255266if (token )
256267{
257- if (strcasecmp (token ,"with" )!= 0 )
258- gotoerror ;
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{
264285token = strtokx (NULL ,whitespace ,NULL ,"'" ,
265286'\\' , false,pset .encoding );
@@ -285,6 +306,9 @@ parse_slash_copy(const char *args)
285306}
286307else
287308gotoerror ;
309+
310+ token = strtokx (NULL ,whitespace ,NULL ,NULL ,
311+ 0 , false,pset .encoding );
288312}
289313}
290314