]> granicus.if.org Git - postgresql/commitdiff
Make USING and WITH optional to bring the syntax of \copy into exact
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 28 Jan 2004 22:14:04 +0000 (22:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 28 Jan 2004 22:14:04 +0000 (22:14 +0000)
agreement with what the backend grammar actually accepts (which is a
bit looser than what its documentation claims).  Per report from Bill
Moran, though I did not use his patch since it removed all the
undocumented flexibility that the code historically had and the backend
still has.

src/bin/psql/copy.c

index c2f89550c7ff8e0b8d161dfa842101222eaf84a4..9766bece96d9b1a2ecdac55f44abd0455aa5bc56 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.40 2004/01/26 22:35:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.41 2004/01/28 22:14:04 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
  * parse_slash_copy
  * -- parses \copy command line
  *
- * Accepted syntax: \copy table [(columnlist)] [with oids] from|to filename [with ] [ oids ] [ delimiter char] [ null as string ]
+ * The documented preferred syntax is:
+ *     \copy tablename [(columnlist)] from|to filename
+ *             [ with ] [ oids ] [ delimiter [as] char ] [ null [as] string ]
  * (binary is not here yet)
  *
- * Old syntax for backward compatibility: (2002-06-19):
- * \copy table [(columnlist)] [with oids] from|to filename [ using delimiters char] [ with null as string ]
+ * The pre-7.3 syntax was:
+ *     \copy tablename [(columnlist)] [with oids] from|to filename
+ *             [ [using] delimiters char ] [ with null as string ]
+ *
+ * The actual accepted syntax is a rather unholy combination of these,
+ * plus some undocumented flexibility (for instance, the clauses after
+ * WITH can appear in any order).  The accepted syntax matches what
+ * the backend grammar actually accepts (see backend/parser/gram.y).
  *
  * table name can be double-quoted and can have a schema part.
  * column names can be double-quoted.
@@ -243,6 +251,9 @@ parse_slash_copy(const char *args)
                                                0, false, pset.encoding);
                if (!(token && strcasecmp(token, "delimiters") == 0))
                        goto error;
+       }
+       if (token && strcasecmp(token, "delimiters") == 0)
+       {
                token = strtokx(NULL, whitespace, NULL, "'",
                                                '\\', false, pset.encoding);
                if (!token)
@@ -254,12 +265,22 @@ parse_slash_copy(const char *args)
 
        if (token)
        {
-               if (strcasecmp(token, "with") != 0)
-                       goto error;
-               while ((token = strtokx(NULL, whitespace, NULL, NULL,
-                                                               0, false, pset.encoding)) != NULL)
+               /*
+                * WITH is optional.  Also, the backend will allow WITH followed by
+                * nothing, so we do too.
+                */
+               if (strcasecmp(token, "with") == 0)
+                       token = strtokx(NULL, whitespace, NULL, NULL,
+                                                       0, false, pset.encoding);
+
+               while (token)
                {
-                       if (strcasecmp(token, "delimiter") == 0)
+                       /* someday allow BINARY here */
+                       if (strcasecmp(token, "oids") == 0)
+                       {
+                               result->oids = true;
+                       }
+                       else if (strcasecmp(token, "delimiter") == 0)
                        {
                                token = strtokx(NULL, whitespace, NULL, "'",
                                                                '\\', false, pset.encoding);
@@ -285,6 +306,9 @@ parse_slash_copy(const char *args)
                        }
                        else
                                goto error;
+
+                       token = strtokx(NULL, whitespace, NULL, NULL,
+                                                       0, false, pset.encoding);
                }
        }