Re: Cleanup for new escape handling
От | Bruce Momjian |
---|---|
Тема | Re: Cleanup for new escape handling |
Дата | |
Msg-id | 200605262348.k4QNmmZ28474@candle.pha.pa.us обсуждение исходный текст |
Ответ на | Cleanup for new escape handling (Bruce Momjian <pgman@candle.pha.pa.us>) |
Список | pgsql-patches |
Patch applied. --------------------------------------------------------------------------- Bruce Momjian wrote: > This patch cleans up the use of E'' strings in 8.2. 8.2 is the first > release where standard_conforming_strings can be 'on', and when 'on', > escape_string_warning is disabled. > > In 8.1, the behavior was to use E'' strings for any case where > backslashes exist. For 8.2, per suggestion from Tom, we should use E'' > strings only for standard_conforming_strings = 'off'. This would allow > pg_dump output with standard_conforming_strings = 'on' to generate > proper strings that can be loaded into other databases without the > backslash doubling we typically do. I have added the dumping of the > standard_conforming_strings to pg_dump, like we do now for > client_encoding. The only risk of the patch is that someone will use > one of the adt/ruleutils.c functions like pg_get_constraintdef() with > one setting of standard_conforming_strings and then try to load it into > a database with a different standard_conforming_strings setting. > > I also added standard backslash handling for plpgsql. > > I also checked ecpg and that uses E'' for all strings that have \ > because it doesn't know if the target database is going to have > standard_conforming_strings on or off. That seems best, and no one > expects the _output_ of ecpg to be portable. > > The macros we use for escape processing really makes these changes easy. > > -- > Bruce Momjian http://candle.pha.pa.us > EnterpriseDB http://www.enterprisedb.com > > + If your life is a hard drive, Christ can be your backup. + > Index: src/backend/utils/adt/quote.c > =================================================================== > RCS file: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v > retrieving revision 1.18 > diff -c -c -r1.18 quote.c > *** src/backend/utils/adt/quote.c 5 Mar 2006 15:58:43 -0000 1.18 > --- src/backend/utils/adt/quote.c 25 May 2006 22:15:36 -0000 > *************** > *** 14,19 **** > --- 14,20 ---- > #include "postgres.h" > > #include "utils/builtins.h" > + #include "parser/gramparse.h" > > > /* > *************** > *** 65,83 **** > cp1 = VARDATA(t); > cp2 = VARDATA(result); > > ! 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)) > *cp2++ = *cp1; > *cp2++ = *cp1++; > } > --- 66,85 ---- > cp1 = VARDATA(t); > cp2 = VARDATA(result); > > ! 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, !standard_conforming_strings)) > *cp2++ = *cp1; > *cp2++ = *cp1++; > } > Index: src/backend/utils/adt/ruleutils.c > =================================================================== > RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v > retrieving revision 1.221 > diff -c -c -r1.221 ruleutils.c > *** src/backend/utils/adt/ruleutils.c 30 Apr 2006 18:30:40 -0000 1.221 > --- src/backend/utils/adt/ruleutils.c 25 May 2006 22:15:41 -0000 > *************** > *** 31,36 **** > --- 31,37 ---- > #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,545 **** > { > if (i > 0) > appendStringInfo(&buf, ", "); > ! if (strchr(p, '\\') != NULL) > appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); > appendStringInfoChar(&buf, '\''); > > while (*p) > { > ! if (SQL_STR_DOUBLE(*p)) > appendStringInfoChar(&buf, *p); > appendStringInfoChar(&buf, *p++); > } > --- 534,546 ---- > { > if (i > 0) > appendStringInfo(&buf, ", "); > ! if (!standard_conforming_strings && strchr(p, '\\') != NULL) > appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); > appendStringInfoChar(&buf, '\''); > > while (*p) > { > ! if (SQL_STR_DOUBLE(*p, !standard_conforming_strings)) > appendStringInfoChar(&buf, *p); > appendStringInfoChar(&buf, *p++); > } > *************** > *** 3882,3888 **** > char *valptr; > bool isfloat = false; > bool needlabel; > ! > if (constval->constisnull) > { > /* > --- 3883,3890 ---- > char *valptr; > bool isfloat = false; > bool needlabel; > ! bool is_e_string = false; > ! > if (constval->constisnull) > { > /* > *************** > *** 3948,3957 **** > * representation. XXX Any MULTIBYTE considerations here? > */ > for (valptr = extval; *valptr; valptr++) > ! if (*valptr == '\\' || > (unsigned char) *valptr < (unsigned char) ' ') > { > appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX); > break; > } > > --- 3950,3960 ---- > * representation. XXX Any MULTIBYTE considerations here? > */ > for (valptr = extval; *valptr; valptr++) > ! if ((!standard_conforming_strings && *valptr == '\\') || > (unsigned char) *valptr < (unsigned char) ' ') > { > appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX); > + is_e_string = true; > break; > } > > *************** > *** 3960,3966 **** > { > char ch = *valptr; > > ! if (SQL_STR_DOUBLE(ch)) > { > appendStringInfoChar(buf, ch); > appendStringInfoChar(buf, ch); > --- 3963,3969 ---- > { > char ch = *valptr; > > ! if (SQL_STR_DOUBLE(ch, is_e_string)) > { > appendStringInfoChar(buf, ch); > appendStringInfoChar(buf, ch); > Index: src/bin/initdb/initdb.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/initdb/initdb.c,v > retrieving revision 1.114 > diff -c -c -r1.114 initdb.c > *** src/bin/initdb/initdb.c 21 Mar 2006 17:54:28 -0000 1.114 > --- src/bin/initdb/initdb.c 25 May 2006 22:15:48 -0000 > *************** > *** 2103,2109 **** > } > > /* > ! * Escape any single quotes or backslashes in given string > */ > static char * > escape_quotes(const char *src) > --- 2103,2110 ---- > } > > /* > ! * Escape any single quotes or backslashes in given string; > ! * postgresql.conf always enables backslash escapes > */ > static char * > escape_quotes(const char *src) > *************** > *** 2115,2121 **** > > for (i = 0, j = 0; i < len; i++) > { > ! if (SQL_STR_DOUBLE(src[i])) > result[j++] = src[i]; > result[j++] = src[i]; > } > --- 2116,2122 ---- > > for (i = 0, j = 0; i < len; i++) > { > ! if (SQL_STR_DOUBLE(src[i], true)) > result[j++] = src[i]; > result[j++] = src[i]; > } > Index: src/bin/pg_dump/dumputils.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v > retrieving revision 1.27 > diff -c -c -r1.27 dumputils.c > *** src/bin/pg_dump/dumputils.c 30 Apr 2006 21:15:33 -0000 1.27 > --- src/bin/pg_dump/dumputils.c 25 May 2006 22:15:49 -0000 > *************** > *** 105,128 **** > * 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. > */ > void > ! appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) > { > char ch; > const char *p; > > for (p = str; *p; p++) > { > ch = *p; > ! if (ch == '\\' || > ((unsigned char) ch < (unsigned char) ' ' && > (escapeAll || > (ch != '\t' && ch != '\n' && ch != '\v' && > ch != '\f' && ch != '\r')))) > { > appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); > break; > } > } > --- 105,133 ---- > * 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. Using E'' strings for > ! * backslashes is always safe for standard_conforming_strings on or off. > */ > void > ! 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 ((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,137 **** > for (p = str; *p; p++) > { > ch = *p; > ! if (SQL_STR_DOUBLE(ch)) > { > appendPQExpBufferChar(buf, ch); > appendPQExpBufferChar(buf, ch); > --- 136,142 ---- > for (p = str; *p; p++) > { > ch = *p; > ! if (SQL_STR_DOUBLE(ch, is_e_string)) > { > appendPQExpBufferChar(buf, ch); > appendPQExpBufferChar(buf, ch); > *************** > *** 208,214 **** > bool escapeAll, const char *dqprefix) > { > if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL) > ! appendStringLiteral(buf, str, escapeAll); > else > appendStringLiteralDQ(buf, str, dqprefix); > } > --- 213,219 ---- > bool escapeAll, const char *dqprefix) > { > if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL) > ! appendStringLiteral(buf, str, escapeAll, true); > else > appendStringLiteralDQ(buf, str, dqprefix); > } > Index: src/bin/pg_dump/dumputils.h > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v > retrieving revision 1.15 > diff -c -c -r1.15 dumputils.h > *** src/bin/pg_dump/dumputils.h 5 Mar 2006 15:58:50 -0000 1.15 > --- src/bin/pg_dump/dumputils.h 25 May 2006 22:15:49 -0000 > *************** > *** 17,26 **** > > #include "pqexpbuffer.h" > > - > 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, > --- 17,25 ---- > > #include "pqexpbuffer.h" > > extern const char *fmtId(const char *identifier); > extern void appendStringLiteral(PQExpBuffer buf, const char *str, > ! 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, > Index: src/bin/pg_dump/pg_backup_archiver.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v > retrieving revision 1.129 > diff -c -c -r1.129 pg_backup_archiver.c > *** src/bin/pg_dump/pg_backup_archiver.c 24 May 2006 21:20:11 -0000 1.129 > --- src/bin/pg_dump/pg_backup_archiver.c 25 May 2006 22:15:50 -0000 > *************** > *** 1900,1908 **** > { > teReqs res = REQ_ALL; > > ! /* ENCODING objects are dumped specially, so always reject here */ > if (strcmp(te->desc, "ENCODING") == 0) > return 0; > > /* If it's an ACL, maybe ignore it */ > if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0) > --- 1900,1910 ---- > { > teReqs res = REQ_ALL; > > ! /* 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,2019 **** > { > TocEntry *te; > > ! /* If we have an encoding setting, emit that */ > te = AH->toc->next; > while (te != AH->toc) > { > if (strcmp(te->desc, "ENCODING") == 0) > - { > ahprintf(AH, "%s", te->defn); > ! break; > ! } > te = te->next; > } > > --- 2007,2020 ---- > { > TocEntry *te; > > ! /* 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); > ! if (strcmp(te->desc, "STDSTRINGS") == 0) > ! ahprintf(AH, "%s", te->defn); > te = te->next; > } > > *************** > *** 2042,2048 **** > * SQL requires a string literal here. Might as well be correct. > */ > if (user && *user) > ! appendStringLiteral(cmd, user, false); > else > appendPQExpBuffer(cmd, "DEFAULT"); > appendPQExpBuffer(cmd, ";"); > --- 2043,2049 ---- > * SQL requires a string literal here. Might as well be correct. > */ > if (user && *user) > ! appendStringLiteral(cmd, user, false, true); > else > appendPQExpBuffer(cmd, "DEFAULT"); > appendPQExpBuffer(cmd, ";"); > Index: src/bin/pg_dump/pg_dump.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v > retrieving revision 1.433 > diff -c -c -r1.433 pg_dump.c > *** src/bin/pg_dump/pg_dump.c 5 Mar 2006 15:58:50 -0000 1.433 > --- src/bin/pg_dump/pg_dump.c 25 May 2006 22:15:57 -0000 > *************** > *** 82,87 **** > --- 82,88 ---- > * 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,179 **** > --- 175,181 ---- > 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,624 **** > --- 621,628 ---- > /* 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,1090 **** > default: > /* All other types are printed as string literals. */ > resetPQExpBuffer(q); > ! appendStringLiteral(q, PQgetvalue(res, tuple, field), false); > archputs(q->data, fout); > break; > } > --- 1088,1094 ---- > default: > /* All other types are printed as string literals. */ > resetPQExpBuffer(q); > ! appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings); > archputs(q->data, fout); > break; > } > *************** > *** 1236,1242 **** > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true); > } > else if (g_fout->remoteVersion >= 80000) > { > --- 1240,1246 ---- > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true, !std_strings); > } > else if (g_fout->remoteVersion >= 80000) > { > *************** > *** 1247,1253 **** > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true); > } > else if (g_fout->remoteVersion >= 70100) > { > --- 1251,1257 ---- > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true, !std_strings); > } > else if (g_fout->remoteVersion >= 70100) > { > *************** > *** 1258,1264 **** > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true); > } > else > { > --- 1262,1268 ---- > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true, !std_strings); > } > else > { > *************** > *** 1271,1277 **** > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true); > } > > res = PQexec(g_conn, dbQry->data); > --- 1275,1281 ---- > "FROM pg_database " > "WHERE datname = ", > username_subquery); > ! appendStringLiteral(dbQry, datname, true, !std_strings); > } > > res = PQexec(g_conn, dbQry->data); > *************** > *** 1310,1316 **** > if (strlen(encoding) > 0) > { > appendPQExpBuffer(creaQry, " ENCODING = "); > ! appendStringLiteral(creaQry, encoding, true); > } > if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0) > appendPQExpBuffer(creaQry, " TABLESPACE = %s", > --- 1314,1320 ---- > if (strlen(encoding) > 0) > { > appendPQExpBuffer(creaQry, " ENCODING = "); > ! appendStringLiteral(creaQry, encoding, true, !std_strings); > } > if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0) > appendPQExpBuffer(creaQry, " TABLESPACE = %s", > *************** > *** 1349,1355 **** > if (comment && strlen(comment)) { > resetPQExpBuffer(dbQry); > appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); > ! appendStringLiteral(dbQry, comment, false); > appendPQExpBuffer(dbQry, ";\n"); > > ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL, > --- 1353,1359 ---- > if (comment && strlen(comment)) { > resetPQExpBuffer(dbQry); > appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); > ! appendStringLiteral(dbQry, comment, false, !std_strings); > appendPQExpBuffer(dbQry, ";\n"); > > ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL, > *************** > *** 1398,1404 **** > resetPQExpBuffer(qry); > > appendPQExpBuffer(qry, "SET client_encoding = "); > ! appendStringLiteral(qry, PQgetvalue(res, 0, 0), true); > appendPQExpBuffer(qry, ";\n"); > > ArchiveEntry(AH, nilCatalogId, createDumpId(), > --- 1402,1408 ---- > resetPQExpBuffer(qry); > > appendPQExpBuffer(qry, "SET client_encoding = "); > ! appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings); > appendPQExpBuffer(qry, ";\n"); > > ArchiveEntry(AH, nilCatalogId, createDumpId(), > *************** > *** 1414,1419 **** > --- 1418,1473 ---- > > > /* > + * 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,1592 **** > > printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ", > blobOid); > ! appendStringLiteral(commentcmd, comment, false); > appendPQExpBuffer(commentcmd, ";\n"); > > archputs(commentcmd->data, AH); > --- 1640,1646 ---- > > printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ", > blobOid); > ! appendStringLiteral(commentcmd, comment, false, !std_strings); > appendPQExpBuffer(commentcmd, ";\n"); > > archputs(commentcmd->data, AH); > *************** > *** 4340,4346 **** > PQExpBuffer query = createPQExpBuffer(); > > appendPQExpBuffer(query, "COMMENT ON %s IS ", target); > ! appendStringLiteral(query, comments->descr, false); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > --- 4394,4400 ---- > PQExpBuffer query = createPQExpBuffer(); > > appendPQExpBuffer(query, "COMMENT ON %s IS ", target); > ! appendStringLiteral(query, comments->descr, false, !std_strings); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > *************** > *** 4398,4404 **** > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); > ! appendStringLiteral(query, descr, false); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > --- 4452,4458 ---- > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); > ! appendStringLiteral(query, descr, false, !std_strings); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > *************** > *** 4420,4426 **** > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); > ! appendStringLiteral(query, descr, false); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > --- 4474,4480 ---- > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); > ! appendStringLiteral(query, descr, false, !std_strings); > appendPQExpBuffer(query, ";\n"); > > ArchiveEntry(fout, nilCatalogId, createDumpId(), > *************** > *** 4986,4992 **** > { > appendPQExpBuffer(q, ",\n DEFAULT = "); > if (typdefault_is_literal) > ! appendStringLiteral(q, typdefault, true); > else > appendPQExpBufferStr(q, typdefault); > } > --- 5040,5046 ---- > { > appendPQExpBuffer(q, ",\n DEFAULT = "); > if (typdefault_is_literal) > ! appendStringLiteral(q, typdefault, true, !std_strings); > else > appendPQExpBufferStr(q, typdefault); > } > *************** > *** 5005,5011 **** > if (typdelim && strcmp(typdelim, ",") != 0) > { > appendPQExpBuffer(q, ",\n DELIMITER = "); > ! appendStringLiteral(q, typdelim, true); > } > > if (strcmp(typalign, "c") == 0) > --- 5059,5065 ---- > if (typdelim && strcmp(typdelim, ",") != 0) > { > appendPQExpBuffer(q, ",\n DELIMITER = "); > ! appendStringLiteral(q, typdelim, true, !std_strings); > } > > if (strcmp(typalign, "c") == 0) > *************** > *** 5120,5126 **** > { > appendPQExpBuffer(q, " DEFAULT "); > if (typdefault_is_literal) > ! appendStringLiteral(q, typdefault, true); > else > appendPQExpBufferStr(q, typdefault); > } > --- 5174,5180 ---- > { > appendPQExpBuffer(q, " DEFAULT "); > if (typdefault_is_literal) > ! appendStringLiteral(q, typdefault, true, !std_strings); > else > appendPQExpBufferStr(q, typdefault); > } > *************** > *** 5690,5696 **** > if (strcmp(probin, "-") != 0) > { > appendPQExpBuffer(asPart, "AS "); > ! appendStringLiteral(asPart, probin, true); > if (strcmp(prosrc, "-") != 0) > { > appendPQExpBuffer(asPart, ", "); > --- 5744,5750 ---- > if (strcmp(probin, "-") != 0) > { > appendPQExpBuffer(asPart, "AS "); > ! appendStringLiteral(asPart, probin, true, !std_strings); > if (strcmp(prosrc, "-") != 0) > { > appendPQExpBuffer(asPart, ", "); > *************** > *** 5700,5706 **** > * contains quote or backslash; else use regular quoting. > */ > if (disable_dollar_quoting) > ! appendStringLiteral(asPart, prosrc, false); > else > appendStringLiteralDQOpt(asPart, prosrc, false, NULL); > } > --- 5754,5760 ---- > * contains quote or backslash; else use regular quoting. > */ > if (disable_dollar_quoting) > ! appendStringLiteral(asPart, prosrc, false, !std_strings); > else > appendStringLiteralDQOpt(asPart, prosrc, false, NULL); > } > *************** > *** 5712,5718 **** > appendPQExpBuffer(asPart, "AS "); > /* with no bin, dollar quote src unconditionally if allowed */ > if (disable_dollar_quoting) > ! appendStringLiteral(asPart, prosrc, false); > else > appendStringLiteralDQ(asPart, prosrc, NULL); > } > --- 5766,5772 ---- > appendPQExpBuffer(asPart, "AS "); > /* with no bin, dollar quote src unconditionally if allowed */ > if (disable_dollar_quoting) > ! appendStringLiteral(asPart, prosrc, false, !std_strings); > else > appendStringLiteralDQ(asPart, prosrc, NULL); > } > *************** > *** 6628,6636 **** > appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", > (condefault) ? "DEFAULT " : "", > fmtId(convinfo->dobj.name)); > ! appendStringLiteral(q, conforencoding, true); > appendPQExpBuffer(q, " TO "); > ! appendStringLiteral(q, contoencoding, true); > /* regproc is automatically quoted in 7.3 and above */ > appendPQExpBuffer(q, " FROM %s;\n", conproc); > > --- 6682,6690 ---- > appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", > (condefault) ? "DEFAULT " : "", > fmtId(convinfo->dobj.name)); > ! appendStringLiteral(q, conforencoding, true, !std_strings); > appendPQExpBuffer(q, " TO "); > ! appendStringLiteral(q, contoencoding, true, !std_strings); > /* regproc is automatically quoted in 7.3 and above */ > appendPQExpBuffer(q, " FROM %s;\n", conproc); > > *************** > *** 6871,6877 **** > if (!PQgetisnull(res, 0, i_agginitval)) > { > appendPQExpBuffer(details, ",\n INITCOND = "); > ! appendStringLiteral(details, agginitval, true); > } > > if (strcmp(aggfinalfn, "-") != 0) > --- 6925,6931 ---- > if (!PQgetisnull(res, 0, i_agginitval)) > { > appendPQExpBuffer(details, ",\n INITCOND = "); > ! appendStringLiteral(details, agginitval, true, !std_strings); > } > > if (strcmp(aggfinalfn, "-") != 0) > *************** > *** 7058,7064 **** > { > appendPQExpBuffer(query, "SELECT definition as viewdef " > " from pg_views where viewname = "); > ! appendStringLiteral(query, tbinfo->dobj.name, true); > appendPQExpBuffer(query, ";"); > } > > --- 7112,7118 ---- > { > appendPQExpBuffer(query, "SELECT definition as viewdef " > " from pg_views where viewname = "); > ! appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings); > appendPQExpBuffer(query, ";"); > } > > *************** > *** 7707,7713 **** > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = "); > ! appendStringLiteral(query, dbname, true); > > res = PQexec(g_conn, query->data); > check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK); > --- 7761,7767 ---- > > resetPQExpBuffer(query); > appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = "); > ! appendStringLiteral(query, dbname, true, !std_strings); > > res = PQexec(g_conn, query->data); > check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK); > *************** > *** 7908,7920 **** > (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL) > { > appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence("); > ! appendStringLiteral(query, fmtId(owning_tab->dobj.name), true); > appendPQExpBuffer(query, ", "); > ! appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true); > appendPQExpBuffer(query, ")"); > } > else > ! appendStringLiteral(query, fmtId(tbinfo->dobj.name), true); > appendPQExpBuffer(query, ", %s, %s);\n", > last, (called ? "true" : "false")); > > --- 7962,7974 ---- > (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL) > { > appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence("); > ! appendStringLiteral(query, fmtId(owning_tab->dobj.name), true, !std_strings); > appendPQExpBuffer(query, ", "); > ! appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true, !std_strings); > appendPQExpBuffer(query, ")"); > } > else > ! appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings); > appendPQExpBuffer(query, ", %s, %s);\n", > last, (called ? "true" : "false")); > > *************** > *** 8083,8090 **** > appendPQExpBufferChar(query, '\''); > while (s < p) > { > ! if (*s == '\'') /* bytea already doubles backslashes */ > appendPQExpBufferChar(query, '\''); > appendPQExpBufferChar(query, *s++); > } > appendPQExpBufferChar(query, '\''); > --- 8137,8150 ---- > appendPQExpBufferChar(query, '\''); > while (s < p) > { > ! 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, '\''); > Index: src/bin/pg_dump/pg_dumpall.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v > retrieving revision 1.75 > diff -c -c -r1.75 pg_dumpall.c > *** src/bin/pg_dump/pg_dumpall.c 22 May 2006 11:21:54 -0000 1.75 > --- src/bin/pg_dump/pg_dumpall.c 25 May 2006 22:15:58 -0000 > *************** > *** 535,541 **** > if (!PQgetisnull(res, i, i_rolpassword)) > { > appendPQExpBuffer(buf, " PASSWORD "); > ! appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true); > } > > if (!PQgetisnull(res, i, i_rolvaliduntil)) > --- 535,541 ---- > if (!PQgetisnull(res, i, i_rolpassword)) > { > appendPQExpBuffer(buf, " PASSWORD "); > ! appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true, true); > } > > if (!PQgetisnull(res, i, i_rolvaliduntil)) > *************** > *** 546,552 **** > > if (!PQgetisnull(res, i, i_rolcomment)) { > appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename)); > ! appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true); > appendPQExpBuffer(buf, ";\n"); > } > > --- 546,552 ---- > > if (!PQgetisnull(res, i, i_rolcomment)) { > appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename)); > ! appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true, true); > appendPQExpBuffer(buf, ";\n"); > } > > *************** > *** 730,736 **** > appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); > > appendPQExpBuffer(buf, " LOCATION "); > ! appendStringLiteral(buf, spclocation, true); > appendPQExpBuffer(buf, ";\n"); > > if (!skip_acls && > --- 730,736 ---- > appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); > > appendPQExpBuffer(buf, " LOCATION "); > ! appendStringLiteral(buf, spclocation, true, true); > appendPQExpBuffer(buf, ";\n"); > > if (!skip_acls && > *************** > *** 745,751 **** > > if (spccomment && strlen(spccomment)) { > appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname); > ! appendStringLiteral(buf, spccomment, true); > appendPQExpBuffer(buf, ";\n"); > } > > --- 745,751 ---- > > if (spccomment && strlen(spccomment)) { > appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname); > ! appendStringLiteral(buf, spccomment, true, true); > appendPQExpBuffer(buf, ";\n"); > } > > *************** > *** 868,874 **** > appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner)); > > appendPQExpBuffer(buf, " ENCODING = "); > ! appendStringLiteral(buf, dbencoding, true); > > /* Output tablespace if it isn't default */ > if (strcmp(dbtablespace, "pg_default") != 0) > --- 868,874 ---- > appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner)); > > appendPQExpBuffer(buf, " ENCODING = "); > ! appendStringLiteral(buf, dbencoding, true, true); > > /* Output tablespace if it isn't default */ > if (strcmp(dbtablespace, "pg_default") != 0) > *************** > *** 884,890 **** > if (strcmp(dbistemplate, "t") == 0) > { > appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = "); > ! appendStringLiteral(buf, dbname, true); > appendPQExpBuffer(buf, ";\n"); > } > } > --- 884,890 ---- > if (strcmp(dbistemplate, "t") == 0) > { > appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = "); > ! appendStringLiteral(buf, dbname, true, true); > appendPQExpBuffer(buf, ";\n"); > } > } > *************** > *** 929,935 **** > PGresult *res; > > printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); > ! appendStringLiteral(buf, dbname, true); > appendPQExpBuffer(buf, ";"); > > res = executeQuery(conn, buf->data); > --- 929,935 ---- > PGresult *res; > > printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); > ! appendStringLiteral(buf, dbname, true, true); > appendPQExpBuffer(buf, ";"); > > res = executeQuery(conn, buf->data); > *************** > *** 968,974 **** > 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); > > res = executeQuery(conn, buf->data); > if (PQntuples(res) == 1 && > --- 968,974 ---- > 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, true); > > res = executeQuery(conn, buf->data); > if (PQntuples(res) == 1 && > *************** > *** 1016,1022 **** > || pg_strcasecmp(mine, "search_path") == 0) > appendPQExpBuffer(buf, "%s", pos + 1); > else > ! appendStringLiteral(buf, pos + 1, false); > appendPQExpBuffer(buf, ";\n"); > > printf("%s", buf->data); > --- 1016,1022 ---- > || pg_strcasecmp(mine, "search_path") == 0) > appendPQExpBuffer(buf, "%s", pos + 1); > else > ! appendStringLiteral(buf, pos + 1, false, true); > appendPQExpBuffer(buf, ";\n"); > > printf("%s", buf->data); > Index: src/bin/psql/describe.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/psql/describe.c,v > retrieving revision 1.134 > diff -c -c -r1.134 describe.c > *** src/bin/psql/describe.c 26 Apr 2006 23:15:45 -0000 1.134 > --- src/bin/psql/describe.c 25 May 2006 22:15:59 -0000 > *************** > *** 1867,1873 **** > appendPQExpBuffer(&namebuf, "\\\\"); > > /* Ensure chars special to string literals are passed properly */ > ! if (SQL_STR_DOUBLE(*cp)) > appendPQExpBufferChar(&namebuf, *cp); > > i = PQmblen(cp, pset.encoding); > --- 1867,1873 ---- > appendPQExpBuffer(&namebuf, "\\\\"); > > /* Ensure chars special to string literals are passed properly */ > ! if (SQL_STR_DOUBLE(*cp, true)) > appendPQExpBufferChar(&namebuf, *cp); > > i = PQmblen(cp, pset.encoding); > Index: src/bin/psql/large_obj.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/psql/large_obj.c,v > retrieving revision 1.41 > diff -c -c -r1.41 large_obj.c > *** src/bin/psql/large_obj.c 5 Mar 2006 15:58:51 -0000 1.41 > --- src/bin/psql/large_obj.c 25 May 2006 22:15:59 -0000 > *************** > *** 178,187 **** > > if (strchr(comment_arg, '\\') != NULL) > *bufptr++ = ESCAPE_STRING_SYNTAX; > *bufptr++ = '\''; > for (i = 0; i < slen; i++) > { > ! if (SQL_STR_DOUBLE(comment_arg[i])) > *bufptr++ = comment_arg[i]; > *bufptr++ = comment_arg[i]; > } > --- 178,188 ---- > > if (strchr(comment_arg, '\\') != NULL) > *bufptr++ = ESCAPE_STRING_SYNTAX; > + > *bufptr++ = '\''; > for (i = 0; i < slen; i++) > { > ! if (SQL_STR_DOUBLE(comment_arg[i], true)) > *bufptr++ = comment_arg[i]; > *bufptr++ = comment_arg[i]; > } > Index: src/bin/scripts/createdb.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/scripts/createdb.c,v > retrieving revision 1.16 > diff -c -c -r1.16 createdb.c > *** src/bin/scripts/createdb.c 5 Mar 2006 15:58:52 -0000 1.16 > --- src/bin/scripts/createdb.c 25 May 2006 22:15:59 -0000 > *************** > *** 184,190 **** > if (comment) > { > printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname)); > ! appendStringLiteral(&sql, comment, false); > appendPQExpBuffer(&sql, ";\n"); > > conn = connectDatabase(dbname, host, port, username, password, progname); > --- 184,190 ---- > if (comment) > { > printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname)); > ! appendStringLiteral(&sql, comment, false, true); > appendPQExpBuffer(&sql, ";\n"); > > conn = connectDatabase(dbname, host, port, username, password, progname); > Index: src/bin/scripts/createuser.c > =================================================================== > RCS file: /cvsroot/pgsql/src/bin/scripts/createuser.c,v > retrieving revision 1.27 > diff -c -c -r1.27 createuser.c > *** src/bin/scripts/createuser.c 5 Mar 2006 15:58:52 -0000 1.27 > --- src/bin/scripts/createuser.c 25 May 2006 22:15:59 -0000 > *************** > *** 258,268 **** > fprintf(stderr, _("Password encryption failed.\n")); > exit(1); > } > ! appendStringLiteral(&sql, encrypted_password, false); > PQfreemem(encrypted_password); > } > else > ! appendStringLiteral(&sql, newpassword, false); > } > if (superuser == TRI_YES) > appendPQExpBuffer(&sql, " SUPERUSER"); > --- 258,268 ---- > fprintf(stderr, _("Password encryption failed.\n")); > exit(1); > } > ! appendStringLiteral(&sql, encrypted_password, false, true); > PQfreemem(encrypted_password); > } > else > ! appendStringLiteral(&sql, newpassword, false, true); > } > if (superuser == TRI_YES) > appendPQExpBuffer(&sql, " SUPERUSER"); > Index: src/include/c.h > =================================================================== > RCS file: /cvsroot/pgsql/src/include/c.h,v > retrieving revision 1.200 > diff -c -c -r1.200 c.h > *** src/include/c.h 14 Apr 2006 03:38:56 -0000 1.200 > --- src/include/c.h 25 May 2006 22:15:59 -0000 > *************** > *** 472,478 **** > > #define NameStr(name) ((name).data) > > ! #define SQL_STR_DOUBLE(ch) ((ch) == '\'' || (ch) == '\\') > #define ESCAPE_STRING_SYNTAX 'E' > > /* ---------------------------------------------------------------- > --- 472,485 ---- > > #define NameStr(name) ((name).data) > > ! /* > ! * 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' > > /* ---------------------------------------------------------------- > Index: src/interfaces/ecpg/ecpglib/execute.c > =================================================================== > RCS file: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v > retrieving revision 1.45 > diff -c -c -r1.45 execute.c > *** src/interfaces/ecpg/ecpglib/execute.c 24 Apr 2006 09:45:22 -0000 1.45 > --- src/interfaces/ecpg/ecpglib/execute.c 25 May 2006 22:16:02 -0000 > *************** > *** 32,39 **** > #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. > */ > static char * > quote_postgres(char *arg, int lineno) > --- 32,40 ---- > #include "pgtypes_timestamp.h" > #include "pgtypes_interval.h" > > ! /* > ! * This function returns a newly malloced string that has ' and \ > ! * escaped. > */ > static char * > quote_postgres(char *arg, int lineno) > *************** > *** 45,57 **** > if (!res) > return (res); > > if (strchr(arg, '\\') != NULL) > res[ri++] = ESCAPE_STRING_SYNTAX; > res[ri++] = '\''; > > for (i = 0; arg[i]; i++, ri++) > { > ! if (SQL_STR_DOUBLE(arg[i])) > res[ri++] = arg[i]; > res[ri] = arg[i]; > } > --- 46,62 ---- > 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], true)) > res[ri++] = arg[i]; > res[ri] = arg[i]; > } > Index: src/pl/plpgsql/src/gram.y > =================================================================== > RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v > retrieving revision 1.88 > diff -c -c -r1.88 gram.y > *** src/pl/plpgsql/src/gram.y 23 Mar 2006 04:22:36 -0000 1.88 > --- src/pl/plpgsql/src/gram.y 25 May 2006 22:16:05 -0000 > *************** > *** 17,22 **** > --- 17,23 ---- > #include "plpgsql.h" > > #include "parser/parser.h" > + #include "parser/gramparse.h" > > static PLpgSQL_expr *read_sql_construct(int until, > int until2, > *************** > *** 376,387 **** > strcpy(buf, "SELECT "); > cp1 = new->refname; > cp2 = buf + strlen(buf); > ! if (strchr(cp1, '\\') != NULL) > *cp2++ = ESCAPE_STRING_SYNTAX; > *cp2++ = '\''; > while (*cp1) > { > ! if (SQL_STR_DOUBLE(*cp1)) > *cp2++ = *cp1; > *cp2++ = *cp1++; > } > --- 377,388 ---- > strcpy(buf, "SELECT "); > cp1 = new->refname; > cp2 = buf + strlen(buf); > ! if (!standard_conforming_strings && strchr(cp1, '\\') != NULL) > *cp2++ = ESCAPE_STRING_SYNTAX; > *cp2++ = '\''; > while (*cp1) > { > ! if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings)) > *cp2++ = *cp1; > *cp2++ = *cp1++; > } > > ---------------------------(end of broadcast)--------------------------- > TIP 6: explain analyze is your friend -- Bruce Momjian http://candle.pha.pa.us EnterpriseDB http://www.enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
В списке pgsql-patches по дате отправления: