diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c index 6d9cdeef8b50659653db293eaf879727db88a059..31991ee51edc73c7607139e2004b2168adb343d2 100644 --- a/src/backend/utils/adt/quote.c +++ b/src/backend/utils/adt/quote.c @@ -7,13 +7,14 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.18 2006/03/05 15:58:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.19 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "utils/builtins.h" +#include "parser/gramparse.h" /* @@ -65,19 +66,20 @@ quote_literal(PG_FUNCTION_ARGS) cp1 = VARDATA(t); cp2 = VARDATA(result); - for (; len-- > 0; cp1++) - if (*cp1 == '\\') - { - *cp2++ = ESCAPE_STRING_SYNTAX; - break; - } + if (!standard_conforming_strings) + for (; len-- > 0; cp1++) + if (*cp1 == '\\') + { + *cp2++ = ESCAPE_STRING_SYNTAX; + break; + } len = VARSIZE(t) - VARHDRSZ; cp1 = VARDATA(t); *cp2++ = '\''; while (len-- > 0) { - if (SQL_STR_DOUBLE(*cp1)) + if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings)) *cp2++ = *cp1; *cp2++ = *cp1++; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 67897a2938a61c87b9b9897df7b2bbe90b853b0b..8a06f7bcb660931ff946be5d91f95cc93d16c8cd 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2,7 +2,7 @@ * ruleutils.c - Functions to convert stored expressions/querytrees * back to source text * - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.221 2006/04/30 18:30:40 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.222 2006/05/26 23:48:54 momjian Exp $ **********************************************************************/ #include "postgres.h" @@ -31,6 +31,7 @@ #include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/tlist.h" +#include "parser/gramparse.h" #include "parser/keywords.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" @@ -533,13 +534,13 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) { if (i > 0) appendStringInfo(&buf, ", "); - if (strchr(p, '\\') != NULL) + if (!standard_conforming_strings && strchr(p, '\\') != NULL) appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); appendStringInfoChar(&buf, '\''); while (*p) { - if (SQL_STR_DOUBLE(*p)) + if (SQL_STR_DOUBLE(*p, !standard_conforming_strings)) appendStringInfoChar(&buf, *p); appendStringInfoChar(&buf, *p++); } @@ -3882,7 +3883,8 @@ get_const_expr(Const *constval, deparse_context *context) char *valptr; bool isfloat = false; bool needlabel; - + bool is_e_string = false; + if (constval->constisnull) { /* @@ -3948,10 +3950,11 @@ get_const_expr(Const *constval, deparse_context *context) * representation. XXX Any MULTIBYTE considerations here? */ for (valptr = extval; *valptr; valptr++) - if (*valptr == '\\' || + if ((!standard_conforming_strings && *valptr == '\\') || (unsigned char) *valptr < (unsigned char) ' ') { appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX); + is_e_string = true; break; } @@ -3960,7 +3963,7 @@ get_const_expr(Const *constval, deparse_context *context) { char ch = *valptr; - if (SQL_STR_DOUBLE(ch)) + if (SQL_STR_DOUBLE(ch, is_e_string)) { appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch); diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index b6ed4bfa6791fcb9575d154ddfb087ac1133e3d8..e32c4cf3a992b93bfed1f06bfb054d926ccb3108 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions taken from FreeBSD. * - * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.114 2006/03/21 17:54:28 alvherre Exp $ + * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.115 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2103,7 +2103,8 @@ check_ok(void) } /* - * Escape any single quotes or backslashes in given string + * Escape any single quotes or backslashes in given string; + * postgresql.conf always enables backslash escapes */ static char * escape_quotes(const char *src) @@ -2115,7 +2116,7 @@ escape_quotes(const char *src) for (i = 0, j = 0; i < len; i++) { - if (SQL_STR_DOUBLE(src[i])) + if (SQL_STR_DOUBLE(src[i], true)) result[j++] = src[i]; result[j++] = src[i]; } diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 86c930b8add3642c613b600b13b916c71312df91..795ce2b986db595e4ddc5cdb8234bcd9fc4ea421 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.27 2006/04/30 21:15:33 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.28 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -105,24 +105,29 @@ fmtId(const char *rawid) * Special characters are escaped. Quote mark ' goes to '' per SQL * standard, other stuff goes to \ sequences. If escapeAll is false, * whitespace characters are not escaped (tabs, newlines, etc.). This - * is appropriate for dump file output. + * is appropriate for dump file output. Using E'' strings for + * backslashes is always safe for standard_conforming_strings on or off. */ void -appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) +appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll, + bool e_string_for_backslash) { char ch; const char *p; + bool is_e_string = false; for (p = str; *p; p++) { ch = *p; - if (ch == '\\' || + + if ((e_string_for_backslash && ch == '\\') || ((unsigned char) ch < (unsigned char) ' ' && (escapeAll || (ch != '\t' && ch != '\n' && ch != '\v' && ch != '\f' && ch != '\r')))) { appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); + is_e_string = true; break; } } @@ -131,7 +136,7 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) for (p = str; *p; p++) { ch = *p; - if (SQL_STR_DOUBLE(ch)) + if (SQL_STR_DOUBLE(ch, is_e_string)) { appendPQExpBufferChar(buf, ch); appendPQExpBufferChar(buf, ch); @@ -208,7 +213,7 @@ appendStringLiteralDQOpt(PQExpBuffer buf, const char *str, bool escapeAll, const char *dqprefix) { if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL) - appendStringLiteral(buf, str, escapeAll); + appendStringLiteral(buf, str, escapeAll, true); else appendStringLiteralDQ(buf, str, dqprefix); } diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index ecf1ea92520fe7547624aeb17fde8bf90557f745..73bc91d6a66c21a70501059b9271597d685219f0 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.15 2006/03/05 15:58:50 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.16 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,10 +17,9 @@ #include "pqexpbuffer.h" - extern const char *fmtId(const char *identifier); extern void appendStringLiteral(PQExpBuffer buf, const char *str, - bool escapeAll); + bool escapeAll, bool e_string_for_backslash); extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix); extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str, diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 4db4e4b9e3a9973b381770823f57000396209301..35042f305042c73cc56c78e568099a286599a716 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.129 2006/05/24 21:20:11 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.130 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1900,9 +1900,11 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) { teReqs res = REQ_ALL; - /* ENCODING objects are dumped specially, so always reject here */ + /* ENCODING and STDSTRINGS objects are dumped specially, so always reject */ if (strcmp(te->desc, "ENCODING") == 0) return 0; + if (strcmp(te->desc, "STDSTRINGS") == 0) + return 0; /* If it's an ACL, maybe ignore it */ if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0) @@ -2005,15 +2007,14 @@ _doSetFixedOutputState(ArchiveHandle *AH) { TocEntry *te; - /* If we have an encoding setting, emit that */ + /* If we have an encoding or std_strings setting, emit that */ te = AH->toc->next; while (te != AH->toc) { if (strcmp(te->desc, "ENCODING") == 0) - { ahprintf(AH, "%s", te->defn); - break; - } + if (strcmp(te->desc, "STDSTRINGS") == 0) + ahprintf(AH, "%s", te->defn); te = te->next; } @@ -2042,7 +2043,7 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user) * SQL requires a string literal here. Might as well be correct. */ if (user && *user) - appendStringLiteral(cmd, user, false); + appendStringLiteral(cmd, user, false, true); else appendPQExpBuffer(cmd, "DEFAULT"); appendPQExpBuffer(cmd, ";"); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 42af06ba5e20f407b0b52f48dd42180d6eacd550..950d47a44cb383f8396e4fe62bf3dd0eb29a5c61 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.433 2006/03/05 15:58:50 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.434 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -82,6 +82,7 @@ bool g_verbose; /* User wants verbose narration of our * activities. */ Archive *g_fout; /* the script file */ PGconn *g_conn; /* the database connection */ +bool std_strings = false; /* GUC variable */ /* various user-settable parameters */ bool dumpInserts; /* dump data using proper insert strings */ @@ -174,6 +175,7 @@ static int dumpBlobs(Archive *AH, void *arg); static int dumpBlobComments(Archive *AH, void *arg); static void dumpDatabase(Archive *AH); static void dumpEncoding(Archive *AH); +static void dumpStdStrings(Archive *AH); static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *fmtCopyColumnList(const TableInfo *ti); static void do_sql_command(PGconn *conn, const char *query); @@ -619,6 +621,8 @@ main(int argc, char **argv) /* First the special encoding entry. */ dumpEncoding(g_fout); + dumpStdStrings(g_fout); + /* The database item is always second, unless we don't want it at all */ if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL) dumpDatabase(g_fout); @@ -1084,7 +1088,7 @@ dumpTableData_insert(Archive *fout, void *dcontext) default: /* All other types are printed as string literals. */ resetPQExpBuffer(q); - appendStringLiteral(q, PQgetvalue(res, tuple, field), false); + appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings); archputs(q->data, fout); break; } @@ -1236,7 +1240,7 @@ dumpDatabase(Archive *AH) "FROM pg_database " "WHERE datname = ", username_subquery); - appendStringLiteral(dbQry, datname, true); + appendStringLiteral(dbQry, datname, true, !std_strings); } else if (g_fout->remoteVersion >= 80000) { @@ -1247,7 +1251,7 @@ dumpDatabase(Archive *AH) "FROM pg_database " "WHERE datname = ", username_subquery); - appendStringLiteral(dbQry, datname, true); + appendStringLiteral(dbQry, datname, true, !std_strings); } else if (g_fout->remoteVersion >= 70100) { @@ -1258,7 +1262,7 @@ dumpDatabase(Archive *AH) "FROM pg_database " "WHERE datname = ", username_subquery); - appendStringLiteral(dbQry, datname, true); + appendStringLiteral(dbQry, datname, true, !std_strings); } else { @@ -1271,7 +1275,7 @@ dumpDatabase(Archive *AH) "FROM pg_database " "WHERE datname = ", username_subquery); - appendStringLiteral(dbQry, datname, true); + appendStringLiteral(dbQry, datname, true, !std_strings); } res = PQexec(g_conn, dbQry->data); @@ -1310,7 +1314,7 @@ dumpDatabase(Archive *AH) if (strlen(encoding) > 0) { appendPQExpBuffer(creaQry, " ENCODING = "); - appendStringLiteral(creaQry, encoding, true); + appendStringLiteral(creaQry, encoding, true, !std_strings); } if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0) appendPQExpBuffer(creaQry, " TABLESPACE = %s", @@ -1349,7 +1353,7 @@ dumpDatabase(Archive *AH) if (comment && strlen(comment)) { resetPQExpBuffer(dbQry); appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); - appendStringLiteral(dbQry, comment, false); + appendStringLiteral(dbQry, comment, false, !std_strings); appendPQExpBuffer(dbQry, ";\n"); ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL, @@ -1398,7 +1402,7 @@ dumpEncoding(Archive *AH) resetPQExpBuffer(qry); appendPQExpBuffer(qry, "SET client_encoding = "); - appendStringLiteral(qry, PQgetvalue(res, 0, 0), true); + appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings); appendPQExpBuffer(qry, ";\n"); ArchiveEntry(AH, nilCatalogId, createDumpId(), @@ -1413,6 +1417,56 @@ dumpEncoding(Archive *AH) } +/* + * dumpStdStrings: put the correct escape string behavior into the archive + */ +static void +dumpStdStrings(Archive *AH) +{ + PQExpBuffer qry; + PGresult *res; + + if (g_verbose) + write_msg(NULL, "saving standard_conforming_strings setting\n"); + + qry = createPQExpBuffer(); + + /* standard_conforming_strings not used in pre-8.2 servers */ + if (AH->remoteVersion < 80200) + { + appendPQExpBuffer(qry, "SET standard_conforming_strings = 'off';\n"); + std_strings = false; + } + else + { + appendPQExpBuffer(qry, "SHOW standard_conforming_strings"); + + res = PQexec(g_conn, qry->data); + + check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK); + + PQclear(res); + + resetPQExpBuffer(qry); + + std_strings = (strcmp(PQgetvalue(res, 0, 0), "on") == 0); + appendPQExpBuffer(qry, "SET standard_conforming_strings = "); + appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings); + appendPQExpBuffer(qry, ";\n"); + puts(PQgetvalue(res, 0, 0)); + + } + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + "STDSTRINGS", NULL, NULL, "", + false, "STDSTRINGS", qry->data, "", NULL, + NULL, 0, + NULL, NULL); + + destroyPQExpBuffer(qry); +} + + /* * hasBlobs: * Test whether database contains any large objects @@ -1586,7 +1640,7 @@ dumpBlobComments(Archive *AH, void *arg) printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ", blobOid); - appendStringLiteral(commentcmd, comment, false); + appendStringLiteral(commentcmd, comment, false, !std_strings); appendPQExpBuffer(commentcmd, ";\n"); archputs(commentcmd->data, AH); @@ -4340,7 +4394,7 @@ dumpComment(Archive *fout, const char *target, PQExpBuffer query = createPQExpBuffer(); appendPQExpBuffer(query, "COMMENT ON %s IS ", target); - appendStringLiteral(query, comments->descr, false); + appendStringLiteral(query, comments->descr, false, !std_strings); appendPQExpBuffer(query, ";\n"); ArchiveEntry(fout, nilCatalogId, createDumpId(), @@ -4398,7 +4452,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, resetPQExpBuffer(query); appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); - appendStringLiteral(query, descr, false); + appendStringLiteral(query, descr, false, !std_strings); appendPQExpBuffer(query, ";\n"); ArchiveEntry(fout, nilCatalogId, createDumpId(), @@ -4420,7 +4474,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, resetPQExpBuffer(query); appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); - appendStringLiteral(query, descr, false); + appendStringLiteral(query, descr, false, !std_strings); appendPQExpBuffer(query, ";\n"); ArchiveEntry(fout, nilCatalogId, createDumpId(), @@ -4986,7 +5040,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo) { appendPQExpBuffer(q, ",\n DEFAULT = "); if (typdefault_is_literal) - appendStringLiteral(q, typdefault, true); + appendStringLiteral(q, typdefault, true, !std_strings); else appendPQExpBufferStr(q, typdefault); } @@ -5005,7 +5059,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo) if (typdelim && strcmp(typdelim, ",") != 0) { appendPQExpBuffer(q, ",\n DELIMITER = "); - appendStringLiteral(q, typdelim, true); + appendStringLiteral(q, typdelim, true, !std_strings); } if (strcmp(typalign, "c") == 0) @@ -5120,7 +5174,7 @@ dumpDomain(Archive *fout, TypeInfo *tinfo) { appendPQExpBuffer(q, " DEFAULT "); if (typdefault_is_literal) - appendStringLiteral(q, typdefault, true); + appendStringLiteral(q, typdefault, true, !std_strings); else appendPQExpBufferStr(q, typdefault); } @@ -5690,7 +5744,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) if (strcmp(probin, "-") != 0) { appendPQExpBuffer(asPart, "AS "); - appendStringLiteral(asPart, probin, true); + appendStringLiteral(asPart, probin, true, !std_strings); if (strcmp(prosrc, "-") != 0) { appendPQExpBuffer(asPart, ", "); @@ -5700,7 +5754,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) * contains quote or backslash; else use regular quoting. */ if (disable_dollar_quoting) - appendStringLiteral(asPart, prosrc, false); + appendStringLiteral(asPart, prosrc, false, !std_strings); else appendStringLiteralDQOpt(asPart, prosrc, false, NULL); } @@ -5712,7 +5766,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) appendPQExpBuffer(asPart, "AS "); /* with no bin, dollar quote src unconditionally if allowed */ if (disable_dollar_quoting) - appendStringLiteral(asPart, prosrc, false); + appendStringLiteral(asPart, prosrc, false, !std_strings); else appendStringLiteralDQ(asPart, prosrc, NULL); } @@ -6628,9 +6682,9 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", (condefault) ? "DEFAULT " : "", fmtId(convinfo->dobj.name)); - appendStringLiteral(q, conforencoding, true); + appendStringLiteral(q, conforencoding, true, !std_strings); appendPQExpBuffer(q, " TO "); - appendStringLiteral(q, contoencoding, true); + appendStringLiteral(q, contoencoding, true, !std_strings); /* regproc is automatically quoted in 7.3 and above */ appendPQExpBuffer(q, " FROM %s;\n", conproc); @@ -6871,7 +6925,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) if (!PQgetisnull(res, 0, i_agginitval)) { appendPQExpBuffer(details, ",\n INITCOND = "); - appendStringLiteral(details, agginitval, true); + appendStringLiteral(details, agginitval, true, !std_strings); } if (strcmp(aggfinalfn, "-") != 0) @@ -7058,7 +7112,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) { appendPQExpBuffer(query, "SELECT definition as viewdef " " from pg_views where viewname = "); - appendStringLiteral(query, tbinfo->dobj.name, true); + appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings); appendPQExpBuffer(query, ";"); } @@ -7707,7 +7761,7 @@ findLastBuiltinOid_V71(const char *dbname) resetPQExpBuffer(query); appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = "); - appendStringLiteral(query, dbname, true); + appendStringLiteral(query, dbname, true, !std_strings); res = PQexec(g_conn, query->data); check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK); @@ -7908,13 +7962,13 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL) { appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence("); - appendStringLiteral(query, fmtId(owning_tab->dobj.name), true); + appendStringLiteral(query, fmtId(owning_tab->dobj.name), true, !std_strings); appendPQExpBuffer(query, ", "); - appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true); + appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true, !std_strings); appendPQExpBuffer(query, ")"); } else - appendStringLiteral(query, fmtId(tbinfo->dobj.name), true); + appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings); appendPQExpBuffer(query, ", %s, %s);\n", last, (called ? "true" : "false")); @@ -8083,8 +8137,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) appendPQExpBufferChar(query, '\''); while (s < p) { - if (*s == '\'') /* bytea already doubles backslashes */ + if (*s == '\'') appendPQExpBufferChar(query, '\''); + /* + * bytea unconditionally doubles backslashes, so we suppress + * the doubling for standard_conforming_strings. + */ + if (std_strings && *s == '\\') + s++; appendPQExpBufferChar(query, *s++); } appendPQExpBufferChar(query, '\''); diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index e8c22e510df39eda6e3f9775cfbd76db5097516a..cb03fbda07b929ec3d74273a76d3d19a02e67dcc 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.75 2006/05/22 11:21:54 petere Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.76 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -535,7 +535,7 @@ dumpRoles(PGconn *conn) if (!PQgetisnull(res, i, i_rolpassword)) { appendPQExpBuffer(buf, " PASSWORD "); - appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true); + appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true, true); } if (!PQgetisnull(res, i, i_rolvaliduntil)) @@ -546,7 +546,7 @@ dumpRoles(PGconn *conn) if (!PQgetisnull(res, i, i_rolcomment)) { appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename)); - appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true); + appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true, true); appendPQExpBuffer(buf, ";\n"); } @@ -730,7 +730,7 @@ dumpTablespaces(PGconn *conn) appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); appendPQExpBuffer(buf, " LOCATION "); - appendStringLiteral(buf, spclocation, true); + appendStringLiteral(buf, spclocation, true, true); appendPQExpBuffer(buf, ";\n"); if (!skip_acls && @@ -745,7 +745,7 @@ dumpTablespaces(PGconn *conn) if (spccomment && strlen(spccomment)) { appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname); - appendStringLiteral(buf, spccomment, true); + appendStringLiteral(buf, spccomment, true, true); appendPQExpBuffer(buf, ";\n"); } @@ -868,7 +868,7 @@ dumpCreateDB(PGconn *conn) appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner)); appendPQExpBuffer(buf, " ENCODING = "); - appendStringLiteral(buf, dbencoding, true); + appendStringLiteral(buf, dbencoding, true, true); /* Output tablespace if it isn't default */ if (strcmp(dbtablespace, "pg_default") != 0) @@ -884,7 +884,7 @@ dumpCreateDB(PGconn *conn) if (strcmp(dbistemplate, "t") == 0) { appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = "); - appendStringLiteral(buf, dbname, true); + appendStringLiteral(buf, dbname, true, true); appendPQExpBuffer(buf, ";\n"); } } @@ -929,7 +929,7 @@ dumpDatabaseConfig(PGconn *conn, const char *dbname) PGresult *res; printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); - appendStringLiteral(buf, dbname, true); + appendStringLiteral(buf, dbname, true, true); appendPQExpBuffer(buf, ";"); res = executeQuery(conn, buf->data); @@ -968,7 +968,7 @@ dumpUserConfig(PGconn *conn, const char *username) printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count); else printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count); - appendStringLiteral(buf, username, true); + appendStringLiteral(buf, username, true, true); res = executeQuery(conn, buf->data); if (PQntuples(res) == 1 && @@ -1016,7 +1016,7 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name || pg_strcasecmp(mine, "search_path") == 0) appendPQExpBuffer(buf, "%s", pos + 1); else - appendStringLiteral(buf, pos + 1, false); + appendStringLiteral(buf, pos + 1, false, true); appendPQExpBuffer(buf, ";\n"); printf("%s", buf->data); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 6bb6b591e20f17f0bd0632693c46533f256c3726..d2c808f583d07749dfdd3217fbb551f101fa425e 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.134 2006/04/26 23:15:45 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.135 2006/05/26 23:48:54 momjian Exp $ */ #include "postgres_fe.h" #include "describe.h" @@ -1867,7 +1867,7 @@ processNamePattern(PQExpBuffer buf, const char *pattern, appendPQExpBuffer(&namebuf, "\\\\"); /* Ensure chars special to string literals are passed properly */ - if (SQL_STR_DOUBLE(*cp)) + if (SQL_STR_DOUBLE(*cp, true)) appendPQExpBufferChar(&namebuf, *cp); i = PQmblen(cp, pset.encoding); diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index 2cb195b353973a854c25f8233c14896958b833f9..f4b107538ac0ec38c7f8012d4b38dfc20105103e 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.41 2006/03/05 15:58:51 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.42 2006/05/26 23:48:54 momjian Exp $ */ #include "postgres_fe.h" #include "large_obj.h" @@ -178,10 +178,11 @@ do_lo_import(const char *filename_arg, const char *comment_arg) if (strchr(comment_arg, '\\') != NULL) *bufptr++ = ESCAPE_STRING_SYNTAX; + *bufptr++ = '\''; for (i = 0; i < slen; i++) { - if (SQL_STR_DOUBLE(comment_arg[i])) + if (SQL_STR_DOUBLE(comment_arg[i], true)) *bufptr++ = comment_arg[i]; *bufptr++ = comment_arg[i]; } diff --git a/src/bin/scripts/createdb.c b/src/bin/scripts/createdb.c index 54227de2b370ed121fe9d5d4b859e3c6e73e55d8..7413cdec52cf6f0f1dec3c062d1a4fb28b0b5aff 100644 --- a/src/bin/scripts/createdb.c +++ b/src/bin/scripts/createdb.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.16 2006/03/05 15:58:52 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.17 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -184,7 +184,7 @@ main(int argc, char *argv[]) if (comment) { printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname)); - appendStringLiteral(&sql, comment, false); + appendStringLiteral(&sql, comment, false, true); appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c index ce6700d8ef448a6fa9784cd60228eecf00da5461..0d816b02e9326a14bee02566827dd0f1e7e312b9 100644 --- a/src/bin/scripts/createuser.c +++ b/src/bin/scripts/createuser.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.27 2006/03/05 15:58:52 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.28 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -258,11 +258,11 @@ main(int argc, char *argv[]) fprintf(stderr, _("Password encryption failed.\n")); exit(1); } - appendStringLiteral(&sql, encrypted_password, false); + appendStringLiteral(&sql, encrypted_password, false, true); PQfreemem(encrypted_password); } else - appendStringLiteral(&sql, newpassword, false); + appendStringLiteral(&sql, newpassword, false, true); } if (superuser == TRI_YES) appendPQExpBuffer(&sql, " SUPERUSER"); diff --git a/src/include/c.h b/src/include/c.h index 32082809ec19bab74e6e3174876330253645bd95..284367547ed835c8aef6d5364fef390e30f3af35 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/c.h,v 1.200 2006/04/14 03:38:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/c.h,v 1.201 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -472,7 +472,14 @@ typedef NameData *Name; #define NameStr(name) ((name).data) -#define SQL_STR_DOUBLE(ch) ((ch) == '\'' || (ch) == '\\') +/* + * In 8.2, we are warning for \ in a non-E string if std_strings are off. + * For this reason, we use E for \ strings, unless standard_conforming_strings + * is on. + */ +#define SQL_STR_DOUBLE(ch, escape_backslash) \ + ((ch) == '\'' || ((escape_backslash) && (ch) == '\\')) + #define ESCAPE_STRING_SYNTAX 'E' /* ---------------------------------------------------------------- diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 2cca58aa0982a5dbd09a1e5a37b889850ef733c9..a3a14e2e4815cded6112c757cbae4f701045fa7c 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.45 2006/04/24 09:45:22 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.46 2006/05/26 23:48:54 momjian Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -32,8 +32,9 @@ #include "pgtypes_timestamp.h" #include "pgtypes_interval.h" -/* This function returns a newly malloced string that has the \ - in the argument quoted with \ and the ' quoted with ' as SQL92 says. +/* + * This function returns a newly malloced string that has ' and \ + * escaped. */ static char * quote_postgres(char *arg, int lineno) @@ -45,13 +46,17 @@ quote_postgres(char *arg, int lineno) if (!res) return (res); + /* + * We don't know if the target database is using + * standard_conforming_strings, so we always use E'' strings. + */ if (strchr(arg, '\\') != NULL) res[ri++] = ESCAPE_STRING_SYNTAX; res[ri++] = '\''; for (i = 0; arg[i]; i++, ri++) { - if (SQL_STR_DOUBLE(arg[i])) + if (SQL_STR_DOUBLE(arg[i], true)) res[ri++] = arg[i]; res[ri] = arg[i]; } diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 7364e89b949ed109c6e6fcec13a63efcaea8ac14..dfff1963503184240380bd5e1535ab597975b4a6 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.88 2006/03/23 04:22:36 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.89 2006/05/26 23:48:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "plpgsql.h" #include "parser/parser.h" +#include "parser/gramparse.h" static PLpgSQL_expr *read_sql_construct(int until, int until2, @@ -376,12 +377,12 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval strcpy(buf, "SELECT "); cp1 = new->refname; cp2 = buf + strlen(buf); - if (strchr(cp1, '\\') != NULL) + if (!standard_conforming_strings && strchr(cp1, '\\') != NULL) *cp2++ = ESCAPE_STRING_SYNTAX; *cp2++ = '\''; while (*cp1) { - if (SQL_STR_DOUBLE(*cp1)) + if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings)) *cp2++ = *cp1; *cp2++ = *cp1++; }