diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index c604123724..d9c6b05abb 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -1,5 +1,5 @@ @@ -420,17 +420,15 @@ PostgreSQL documentation - - + + - This option is obsolete but still accepted for backwards - compatibility. - pg_dump now always behaves in the - way formerly selected by this option. + This option disables the use of dollar quoting for function bodies, + and forces them to be quoted using SQL standard string syntax. - - + + @@ -438,18 +436,18 @@ PostgreSQL documentation This option is only relevant when creating a data-only dump. - It instructs pg_dump to include commands - to temporarily disable triggers on the target tables while - the data is reloaded. Use this if you have referential - integrity checks or other triggers on the tables that you - do not want to invoke during data reload. + It instructs pg_dump to include commands + to temporarily disable triggers on the target tables while + the data is reloaded. Use this if you have referential + integrity checks or other triggers on the tables that you + do not want to invoke during data reload. Presently, the commands emitted for @@ -460,14 +458,27 @@ PostgreSQL documentation + + + + + + This option is obsolete but still accepted for backwards + compatibility. + pg_dump now always behaves in the + way formerly selected by this option. + + + + - Specify the compression level to use in archive formats that - support compression. (Currently only the custom archive - format supports compression.) + Specify the compression level to use in archive formats that + support compression. (Currently only the custom archive + format supports compression.) diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 16f0bd8877..1dfe7801ec 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.11 2004/01/07 00:44:21 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.12 2004/03/23 22:06:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -142,6 +142,65 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) } +/* + * Convert a string value to a dollar quoted literal and append it to + * the given buffer. If the dqprefix parameter is not NULL then the + * dollar quote delimiter will begin with that (after the opening $). + * + * No escaping is done at all on str, in compliance with the rules + * for parsing dollar quoted strings. + */ +void +appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix) +{ + static const char suffixes[] = "_XXXXXXX"; + int nextchar = 0; + PQExpBuffer delimBuf = createPQExpBuffer(); + + /* start with $ + dqprefix if not NULL */ + appendPQExpBufferChar(delimBuf, '$'); + if (dqprefix) + appendPQExpBuffer(delimBuf, dqprefix); + + /* + * Make sure we choose a delimiter which (without the trailing $) + * is not present in the string being quoted. We don't check with the + * trailing $ because a string ending in $foo must not be quoted with + * $foo$. + */ + while (strstr(str, delimBuf->data) != NULL) + { + appendPQExpBufferChar(delimBuf, suffixes[nextchar++]); + nextchar %= sizeof(suffixes)-1; + } + + /* add trailing $ */ + appendPQExpBufferChar(delimBuf, '$'); + + /* quote it and we are all done */ + appendPQExpBufferStr(buf, delimBuf->data); + appendPQExpBufferStr(buf, str); + appendPQExpBufferStr(buf, delimBuf->data); + + destroyPQExpBuffer(delimBuf); +} + + +/* + * Use dollar quoting if the string to be quoted contains ' or \, + * otherwise use standard quoting. + */ +void +appendStringLiteralDQOpt(PQExpBuffer buf, const char *str, + bool escapeAll, const char *dqprefix) +{ + if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL) + appendStringLiteral(buf,str,escapeAll); + else + appendStringLiteralDQ(buf,str,dqprefix); +} + + /* * Convert backend's version string into a number. */ diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index c4a71f1c43..577e07b00f 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.10 2004/01/07 00:44:21 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.11 2004/03/23 22:06:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,10 @@ extern const char *fmtId(const char *identifier); extern void appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll); +extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str, + const char *dqprefix); +extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str, + bool escapeAll, const char *dqprefix); extern int parse_version(const char *versionString); extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems); extern bool buildACLCommands(const char *name, const char *type, diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 2449a881bc..1721ea3ddd 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.368 2004/03/20 20:09:45 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.369 2004/03/23 22:06:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -107,6 +107,9 @@ static const CatalogId nilCatalogId = { 0, 0 }; static NamespaceInfo *g_namespaces; static int g_numNamespaces; +/* flag to turn on/off dollar quoting */ +static int disable_dollar_quoting = 0; + static void help(const char *progname); static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid); @@ -231,8 +234,9 @@ main(int argc, char **argv) * the following options don't have an equivalent short option * letter, but are available as '-X long-name' */ - {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1}, {"disable-triggers", no_argument, &disable_triggers, 1}, + {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {NULL, 0, NULL, 0} }; @@ -385,10 +389,12 @@ main(int argc, char **argv) * require arguments should use '-X feature=foo'. */ case 'X': - if (strcmp(optarg, "use-set-session-authorization") == 0) - /* no-op, still allowed for compatibility */ ; + if (strcmp(optarg, "disable-dollar-quoting") == 0) + disable_dollar_quoting = 1; else if (strcmp(optarg, "disable-triggers") == 0) disable_triggers = 1; + else if (strcmp(optarg, "use-set-session-authorization") == 0) + /* no-op, still allowed for compatibility */ ; else { fprintf(stderr, @@ -679,6 +685,8 @@ help(const char *progname) " plain text format\n")); printf(_(" -t, --table=TABLE dump the named table only\n")); printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n")); + printf(_(" -X disable-dollar-quoting, --disable-dollar-quoting\n" + " disable dollar quoting, use SQL standard quoting\n")); printf(_(" -X disable-triggers, --disable-triggers\n" " disable triggers during data-only restore\n")); @@ -5076,7 +5084,14 @@ dumpFunc(Archive *fout, FuncInfo *finfo) if (strcmp(prosrc, "-") != 0) { appendPQExpBuffer(asPart, ", "); - appendStringLiteral(asPart, prosrc, false); + /* + * where we have bin, use dollar quoting if allowed and src + * contains quote or backslash; else use regular quoting. + */ + if (disable_dollar_quoting) + appendStringLiteral(asPart, prosrc, false); + else + appendStringLiteralDQOpt(asPart, prosrc, false, NULL); } } else @@ -5084,7 +5099,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo) if (strcmp(prosrc, "-") != 0) { appendPQExpBuffer(asPart, "AS "); - appendStringLiteral(asPart, prosrc, false); + /* with no bin, dollar quote src unconditionally if allowed */ + if (disable_dollar_quoting) + appendStringLiteral(asPart, prosrc, false); + else + appendStringLiteralDQ(asPart, prosrc, NULL); } }