This patch brings the \copy syntax of psql more in line with the SQL copy syntax as described in the reference manual, while maintaining backward compatibility with what was there prior to the patch.
The change to the syntax is to the DELIMITER[S] portion.
The man page for psql refers the reader to the SQL copy command docs for details of syntax. The SQL docs state that the syntax for COPY is ... [ DELIMITER [ AS ] 'delimiter' ] ... (7.4 docs), while 7.2 docs use the syntax: ... [ [USING] DELIMITERS 'delimiter' ] Reading through the psql source code, it's obvious that at one time, the syntax was ... [ WITH DELIMITER 'delimiter' ] ...
The patch results in the following syntax for the DELIMITER clause of \copy: [ [WITH|USING] DELIMITER[S] 'delimiter' ]
Ideally, this should cover all cases of old and new syntax, except where "AS" is present. The only drawback I can see is that \copy is now more liberal in what it accepts, and may accept incomplete statements without issuing an error (i.e. a WITH or USING clause at the end of a \copy statement will simply be ignored, and no error generated)
This patch is against version 1.36 of src/bin/psql/copy.c The resulting psql binary (based off a cvsup from HEAD on 1/18) compiles and works for me on FreeBSD 5.1.
-- Bill Moran Potential Technologies http://www.potentialtech.com
*** copy.c.old Sat Jan 17 22:17:58 2004 --- copy.c Sat Jan 17 23:06:30 2004 *************** *** 226,283 **** token = strtokx(NULL, whitespace, NULL, NULL, 0, false, pset.encoding); ! /* ! * Allows old COPY syntax for backward compatibility 2002-06-19 ! */ ! if (token && strcasecmp(token, "using") == 0) { token = strtokx(NULL, whitespace, NULL, NULL, 0, false, pset.encoding); ! if (!(token && strcasecmp(token, "delimiters") == 0)) ! goto error; token = strtokx(NULL, whitespace, NULL, "'", '\\', false, pset.encoding); if (!token) goto error; result->delim = xstrdup(token); - token = strtokx(NULL, whitespace, NULL, NULL, - 0, false, pset.encoding); - } - - if (token) - { - if (strcasecmp(token, "with") != 0) - goto error; - while ((token = strtokx(NULL, whitespace, NULL, NULL, - 0, false, pset.encoding)) != NULL) - { - if (strcasecmp(token, "delimiter") == 0) - { - token = strtokx(NULL, whitespace, NULL, "'", - '\\', false, pset.encoding); - if (token && strcasecmp(token, "as") == 0) - token = strtokx(NULL, whitespace, NULL, "'", - '\\', false, pset.encoding); - if (token) - result->delim = xstrdup(token); - else - goto error; - } - else if (strcasecmp(token, "null") == 0) - { - token = strtokx(NULL, whitespace, NULL, "'", - '\\', false, pset.encoding); - if (token && strcasecmp(token, "as") == 0) - token = strtokx(NULL, whitespace, NULL, "'", - '\\', false, pset.encoding); - if (token) - result->null = xstrdup(token); - else - goto error; - } - else - goto error; - } } free(line); --- 226,252 ---- token = strtokx(NULL, whitespace, NULL, NULL, 0, false, pset.encoding); ! // Discard both "with" and "using" as syntactically neutral ! if (token && ! (strcasecmp(token, "using") == 0 || ! strcasecmp(token, "with") == 0)) { token = strtokx(NULL, whitespace, NULL, NULL, 0, false, pset.encoding); ! } ! ! /* ! * Allow any combination of "with"|"using" and "delimiter"|"delimiters" ! */ ! if (token && ! (strcasecmp(token, "delimiters") == 0 || ! strcasecmp(token, "delimiter") == 0)) ! { token = strtokx(NULL, whitespace, NULL, "'", '\\', false, pset.encoding); if (!token) goto error; result->delim = xstrdup(token); } free(line);
---------------------------(end of broadcast)--------------------------- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])