Use E'' strings internally only when standard_conforming_strings =

'off'. This allows 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 value to pg_dump.

I also added standard backslash handling for plpgsql.
This commit is contained in:
Bruce Momjian 2006-05-26 23:48:54 +00:00
parent 4d63e26774
commit 7a846ecc00
15 changed files with 174 additions and 89 deletions

View File

@ -7,13 +7,14 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "parser/gramparse.h"
/* /*
@ -65,6 +66,7 @@ quote_literal(PG_FUNCTION_ARGS)
cp1 = VARDATA(t); cp1 = VARDATA(t);
cp2 = VARDATA(result); cp2 = VARDATA(result);
if (!standard_conforming_strings)
for (; len-- > 0; cp1++) for (; len-- > 0; cp1++)
if (*cp1 == '\\') if (*cp1 == '\\')
{ {
@ -77,7 +79,7 @@ quote_literal(PG_FUNCTION_ARGS)
*cp2++ = '\''; *cp2++ = '\'';
while (len-- > 0) while (len-- > 0)
{ {
if (SQL_STR_DOUBLE(*cp1)) if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
*cp2++ = *cp1; *cp2++ = *cp1;
*cp2++ = *cp1++; *cp2++ = *cp1++;
} }

View File

@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees * ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text * 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" #include "postgres.h"
@ -31,6 +31,7 @@
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/tlist.h" #include "optimizer/tlist.h"
#include "parser/gramparse.h"
#include "parser/keywords.h" #include "parser/keywords.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
@ -533,13 +534,13 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
{ {
if (i > 0) if (i > 0)
appendStringInfo(&buf, ", "); appendStringInfo(&buf, ", ");
if (strchr(p, '\\') != NULL) if (!standard_conforming_strings && strchr(p, '\\') != NULL)
appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
appendStringInfoChar(&buf, '\''); appendStringInfoChar(&buf, '\'');
while (*p) while (*p)
{ {
if (SQL_STR_DOUBLE(*p)) if (SQL_STR_DOUBLE(*p, !standard_conforming_strings))
appendStringInfoChar(&buf, *p); appendStringInfoChar(&buf, *p);
appendStringInfoChar(&buf, *p++); appendStringInfoChar(&buf, *p++);
} }
@ -3882,6 +3883,7 @@ get_const_expr(Const *constval, deparse_context *context)
char *valptr; char *valptr;
bool isfloat = false; bool isfloat = false;
bool needlabel; bool needlabel;
bool is_e_string = false;
if (constval->constisnull) if (constval->constisnull)
{ {
@ -3948,10 +3950,11 @@ get_const_expr(Const *constval, deparse_context *context)
* representation. XXX Any MULTIBYTE considerations here? * representation. XXX Any MULTIBYTE considerations here?
*/ */
for (valptr = extval; *valptr; valptr++) for (valptr = extval; *valptr; valptr++)
if (*valptr == '\\' || if ((!standard_conforming_strings && *valptr == '\\') ||
(unsigned char) *valptr < (unsigned char) ' ') (unsigned char) *valptr < (unsigned char) ' ')
{ {
appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX); appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
is_e_string = true;
break; break;
} }
@ -3960,7 +3963,7 @@ get_const_expr(Const *constval, deparse_context *context)
{ {
char ch = *valptr; char ch = *valptr;
if (SQL_STR_DOUBLE(ch)) if (SQL_STR_DOUBLE(ch, is_e_string))
{ {
appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch);
appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch);

View File

@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD. * 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 * static char *
escape_quotes(const char *src) escape_quotes(const char *src)
@ -2115,7 +2116,7 @@ escape_quotes(const char *src)
for (i = 0, j = 0; i < len; i++) 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];
result[j++] = src[i]; result[j++] = src[i];
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * Special characters are escaped. Quote mark ' goes to '' per SQL
* standard, other stuff goes to \ sequences. If escapeAll is false, * standard, other stuff goes to \ sequences. If escapeAll is false,
* whitespace characters are not escaped (tabs, newlines, etc.). This * 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 void
appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
bool e_string_for_backslash)
{ {
char ch; char ch;
const char *p; const char *p;
bool is_e_string = false;
for (p = str; *p; p++) for (p = str; *p; p++)
{ {
ch = *p; ch = *p;
if (ch == '\\' ||
if ((e_string_for_backslash && ch == '\\') ||
((unsigned char) ch < (unsigned char) ' ' && ((unsigned char) ch < (unsigned char) ' ' &&
(escapeAll || (escapeAll ||
(ch != '\t' && ch != '\n' && ch != '\v' && (ch != '\t' && ch != '\n' && ch != '\v' &&
ch != '\f' && ch != '\r')))) ch != '\f' && ch != '\r'))))
{ {
appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
is_e_string = true;
break; break;
} }
} }
@ -131,7 +136,7 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
for (p = str; *p; p++) for (p = str; *p; p++)
{ {
ch = *p; ch = *p;
if (SQL_STR_DOUBLE(ch)) if (SQL_STR_DOUBLE(ch, is_e_string))
{ {
appendPQExpBufferChar(buf, ch); appendPQExpBufferChar(buf, ch);
appendPQExpBufferChar(buf, ch); appendPQExpBufferChar(buf, ch);
@ -208,7 +213,7 @@ appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
bool escapeAll, const char *dqprefix) bool escapeAll, const char *dqprefix)
{ {
if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL) if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
appendStringLiteral(buf, str, escapeAll); appendStringLiteral(buf, str, escapeAll, true);
else else
appendStringLiteralDQ(buf, str, dqprefix); appendStringLiteralDQ(buf, str, dqprefix);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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" #include "pqexpbuffer.h"
extern const char *fmtId(const char *identifier); extern const char *fmtId(const char *identifier);
extern void appendStringLiteral(PQExpBuffer buf, const char *str, 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, extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
const char *dqprefix); const char *dqprefix);
extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str, extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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; 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) if (strcmp(te->desc, "ENCODING") == 0)
return 0; return 0;
if (strcmp(te->desc, "STDSTRINGS") == 0)
return 0;
/* If it's an ACL, maybe ignore it */ /* If it's an ACL, maybe ignore it */
if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0) if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
@ -2005,15 +2007,14 @@ _doSetFixedOutputState(ArchiveHandle *AH)
{ {
TocEntry *te; 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; te = AH->toc->next;
while (te != AH->toc) while (te != AH->toc)
{ {
if (strcmp(te->desc, "ENCODING") == 0) if (strcmp(te->desc, "ENCODING") == 0)
{
ahprintf(AH, "%s", te->defn); ahprintf(AH, "%s", te->defn);
break; if (strcmp(te->desc, "STDSTRINGS") == 0)
} ahprintf(AH, "%s", te->defn);
te = te->next; te = te->next;
} }
@ -2042,7 +2043,7 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user)
* SQL requires a string literal here. Might as well be correct. * SQL requires a string literal here. Might as well be correct.
*/ */
if (user && *user) if (user && *user)
appendStringLiteral(cmd, user, false); appendStringLiteral(cmd, user, false, true);
else else
appendPQExpBuffer(cmd, "DEFAULT"); appendPQExpBuffer(cmd, "DEFAULT");
appendPQExpBuffer(cmd, ";"); appendPQExpBuffer(cmd, ";");

View File

@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * 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. */ * activities. */
Archive *g_fout; /* the script file */ Archive *g_fout; /* the script file */
PGconn *g_conn; /* the database connection */ PGconn *g_conn; /* the database connection */
bool std_strings = false; /* GUC variable */
/* various user-settable parameters */ /* various user-settable parameters */
bool dumpInserts; /* dump data using proper insert strings */ 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 int dumpBlobComments(Archive *AH, void *arg);
static void dumpDatabase(Archive *AH); static void dumpDatabase(Archive *AH);
static void dumpEncoding(Archive *AH); static void dumpEncoding(Archive *AH);
static void dumpStdStrings(Archive *AH);
static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *getAttrName(int attrnum, TableInfo *tblInfo);
static const char *fmtCopyColumnList(const TableInfo *ti); static const char *fmtCopyColumnList(const TableInfo *ti);
static void do_sql_command(PGconn *conn, const char *query); static void do_sql_command(PGconn *conn, const char *query);
@ -619,6 +621,8 @@ main(int argc, char **argv)
/* First the special encoding entry. */ /* First the special encoding entry. */
dumpEncoding(g_fout); dumpEncoding(g_fout);
dumpStdStrings(g_fout);
/* The database item is always second, unless we don't want it at all */ /* The database item is always second, unless we don't want it at all */
if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL) if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL)
dumpDatabase(g_fout); dumpDatabase(g_fout);
@ -1084,7 +1088,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
default: default:
/* All other types are printed as string literals. */ /* All other types are printed as string literals. */
resetPQExpBuffer(q); resetPQExpBuffer(q);
appendStringLiteral(q, PQgetvalue(res, tuple, field), false); appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings);
archputs(q->data, fout); archputs(q->data, fout);
break; break;
} }
@ -1236,7 +1240,7 @@ dumpDatabase(Archive *AH)
"FROM pg_database " "FROM pg_database "
"WHERE datname = ", "WHERE datname = ",
username_subquery); username_subquery);
appendStringLiteral(dbQry, datname, true); appendStringLiteral(dbQry, datname, true, !std_strings);
} }
else if (g_fout->remoteVersion >= 80000) else if (g_fout->remoteVersion >= 80000)
{ {
@ -1247,7 +1251,7 @@ dumpDatabase(Archive *AH)
"FROM pg_database " "FROM pg_database "
"WHERE datname = ", "WHERE datname = ",
username_subquery); username_subquery);
appendStringLiteral(dbQry, datname, true); appendStringLiteral(dbQry, datname, true, !std_strings);
} }
else if (g_fout->remoteVersion >= 70100) else if (g_fout->remoteVersion >= 70100)
{ {
@ -1258,7 +1262,7 @@ dumpDatabase(Archive *AH)
"FROM pg_database " "FROM pg_database "
"WHERE datname = ", "WHERE datname = ",
username_subquery); username_subquery);
appendStringLiteral(dbQry, datname, true); appendStringLiteral(dbQry, datname, true, !std_strings);
} }
else else
{ {
@ -1271,7 +1275,7 @@ dumpDatabase(Archive *AH)
"FROM pg_database " "FROM pg_database "
"WHERE datname = ", "WHERE datname = ",
username_subquery); username_subquery);
appendStringLiteral(dbQry, datname, true); appendStringLiteral(dbQry, datname, true, !std_strings);
} }
res = PQexec(g_conn, dbQry->data); res = PQexec(g_conn, dbQry->data);
@ -1310,7 +1314,7 @@ dumpDatabase(Archive *AH)
if (strlen(encoding) > 0) if (strlen(encoding) > 0)
{ {
appendPQExpBuffer(creaQry, " ENCODING = "); appendPQExpBuffer(creaQry, " ENCODING = ");
appendStringLiteral(creaQry, encoding, true); appendStringLiteral(creaQry, encoding, true, !std_strings);
} }
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0) if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
appendPQExpBuffer(creaQry, " TABLESPACE = %s", appendPQExpBuffer(creaQry, " TABLESPACE = %s",
@ -1349,7 +1353,7 @@ dumpDatabase(Archive *AH)
if (comment && strlen(comment)) { if (comment && strlen(comment)) {
resetPQExpBuffer(dbQry); resetPQExpBuffer(dbQry);
appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
appendStringLiteral(dbQry, comment, false); appendStringLiteral(dbQry, comment, false, !std_strings);
appendPQExpBuffer(dbQry, ";\n"); appendPQExpBuffer(dbQry, ";\n");
ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL, ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
@ -1398,7 +1402,7 @@ dumpEncoding(Archive *AH)
resetPQExpBuffer(qry); resetPQExpBuffer(qry);
appendPQExpBuffer(qry, "SET client_encoding = "); appendPQExpBuffer(qry, "SET client_encoding = ");
appendStringLiteral(qry, PQgetvalue(res, 0, 0), true); appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
appendPQExpBuffer(qry, ";\n"); appendPQExpBuffer(qry, ";\n");
ArchiveEntry(AH, nilCatalogId, createDumpId(), 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: * hasBlobs:
* Test whether database contains any large objects * Test whether database contains any large objects
@ -1586,7 +1640,7 @@ dumpBlobComments(Archive *AH, void *arg)
printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ", printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
blobOid); blobOid);
appendStringLiteral(commentcmd, comment, false); appendStringLiteral(commentcmd, comment, false, !std_strings);
appendPQExpBuffer(commentcmd, ";\n"); appendPQExpBuffer(commentcmd, ";\n");
archputs(commentcmd->data, AH); archputs(commentcmd->data, AH);
@ -4340,7 +4394,7 @@ dumpComment(Archive *fout, const char *target,
PQExpBuffer query = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query, "COMMENT ON %s IS ", target); appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
appendStringLiteral(query, comments->descr, false); appendStringLiteral(query, comments->descr, false, !std_strings);
appendPQExpBuffer(query, ";\n"); appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(), ArchiveEntry(fout, nilCatalogId, createDumpId(),
@ -4398,7 +4452,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
resetPQExpBuffer(query); resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
appendStringLiteral(query, descr, false); appendStringLiteral(query, descr, false, !std_strings);
appendPQExpBuffer(query, ";\n"); appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(), ArchiveEntry(fout, nilCatalogId, createDumpId(),
@ -4420,7 +4474,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
resetPQExpBuffer(query); resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
appendStringLiteral(query, descr, false); appendStringLiteral(query, descr, false, !std_strings);
appendPQExpBuffer(query, ";\n"); appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(), ArchiveEntry(fout, nilCatalogId, createDumpId(),
@ -4986,7 +5040,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
{ {
appendPQExpBuffer(q, ",\n DEFAULT = "); appendPQExpBuffer(q, ",\n DEFAULT = ");
if (typdefault_is_literal) if (typdefault_is_literal)
appendStringLiteral(q, typdefault, true); appendStringLiteral(q, typdefault, true, !std_strings);
else else
appendPQExpBufferStr(q, typdefault); appendPQExpBufferStr(q, typdefault);
} }
@ -5005,7 +5059,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
if (typdelim && strcmp(typdelim, ",") != 0) if (typdelim && strcmp(typdelim, ",") != 0)
{ {
appendPQExpBuffer(q, ",\n DELIMITER = "); appendPQExpBuffer(q, ",\n DELIMITER = ");
appendStringLiteral(q, typdelim, true); appendStringLiteral(q, typdelim, true, !std_strings);
} }
if (strcmp(typalign, "c") == 0) if (strcmp(typalign, "c") == 0)
@ -5120,7 +5174,7 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
{ {
appendPQExpBuffer(q, " DEFAULT "); appendPQExpBuffer(q, " DEFAULT ");
if (typdefault_is_literal) if (typdefault_is_literal)
appendStringLiteral(q, typdefault, true); appendStringLiteral(q, typdefault, true, !std_strings);
else else
appendPQExpBufferStr(q, typdefault); appendPQExpBufferStr(q, typdefault);
} }
@ -5690,7 +5744,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
if (strcmp(probin, "-") != 0) if (strcmp(probin, "-") != 0)
{ {
appendPQExpBuffer(asPart, "AS "); appendPQExpBuffer(asPart, "AS ");
appendStringLiteral(asPart, probin, true); appendStringLiteral(asPart, probin, true, !std_strings);
if (strcmp(prosrc, "-") != 0) if (strcmp(prosrc, "-") != 0)
{ {
appendPQExpBuffer(asPart, ", "); appendPQExpBuffer(asPart, ", ");
@ -5700,7 +5754,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
* contains quote or backslash; else use regular quoting. * contains quote or backslash; else use regular quoting.
*/ */
if (disable_dollar_quoting) if (disable_dollar_quoting)
appendStringLiteral(asPart, prosrc, false); appendStringLiteral(asPart, prosrc, false, !std_strings);
else else
appendStringLiteralDQOpt(asPart, prosrc, false, NULL); appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
} }
@ -5712,7 +5766,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
appendPQExpBuffer(asPart, "AS "); appendPQExpBuffer(asPart, "AS ");
/* with no bin, dollar quote src unconditionally if allowed */ /* with no bin, dollar quote src unconditionally if allowed */
if (disable_dollar_quoting) if (disable_dollar_quoting)
appendStringLiteral(asPart, prosrc, false); appendStringLiteral(asPart, prosrc, false, !std_strings);
else else
appendStringLiteralDQ(asPart, prosrc, NULL); appendStringLiteralDQ(asPart, prosrc, NULL);
} }
@ -6628,9 +6682,9 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
(condefault) ? "DEFAULT " : "", (condefault) ? "DEFAULT " : "",
fmtId(convinfo->dobj.name)); fmtId(convinfo->dobj.name));
appendStringLiteral(q, conforencoding, true); appendStringLiteral(q, conforencoding, true, !std_strings);
appendPQExpBuffer(q, " TO "); appendPQExpBuffer(q, " TO ");
appendStringLiteral(q, contoencoding, true); appendStringLiteral(q, contoencoding, true, !std_strings);
/* regproc is automatically quoted in 7.3 and above */ /* regproc is automatically quoted in 7.3 and above */
appendPQExpBuffer(q, " FROM %s;\n", conproc); appendPQExpBuffer(q, " FROM %s;\n", conproc);
@ -6871,7 +6925,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
if (!PQgetisnull(res, 0, i_agginitval)) if (!PQgetisnull(res, 0, i_agginitval))
{ {
appendPQExpBuffer(details, ",\n INITCOND = "); appendPQExpBuffer(details, ",\n INITCOND = ");
appendStringLiteral(details, agginitval, true); appendStringLiteral(details, agginitval, true, !std_strings);
} }
if (strcmp(aggfinalfn, "-") != 0) if (strcmp(aggfinalfn, "-") != 0)
@ -7058,7 +7112,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
{ {
appendPQExpBuffer(query, "SELECT definition as viewdef " appendPQExpBuffer(query, "SELECT definition as viewdef "
" from pg_views where viewname = "); " from pg_views where viewname = ");
appendStringLiteral(query, tbinfo->dobj.name, true); appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings);
appendPQExpBuffer(query, ";"); appendPQExpBuffer(query, ";");
} }
@ -7707,7 +7761,7 @@ findLastBuiltinOid_V71(const char *dbname)
resetPQExpBuffer(query); resetPQExpBuffer(query);
appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = "); 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); res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK); 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) (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
{ {
appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence("); 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, ", "); 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, ")"); appendPQExpBuffer(query, ")");
} }
else else
appendStringLiteral(query, fmtId(tbinfo->dobj.name), true); appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings);
appendPQExpBuffer(query, ", %s, %s);\n", appendPQExpBuffer(query, ", %s, %s);\n",
last, (called ? "true" : "false")); last, (called ? "true" : "false"));
@ -8083,8 +8137,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
appendPQExpBufferChar(query, '\''); appendPQExpBufferChar(query, '\'');
while (s < p) while (s < p)
{ {
if (*s == '\'') /* bytea already doubles backslashes */ if (*s == '\'')
appendPQExpBufferChar(query, '\''); 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, *s++);
} }
appendPQExpBufferChar(query, '\''); appendPQExpBufferChar(query, '\'');

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * 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)) if (!PQgetisnull(res, i, i_rolpassword))
{ {
appendPQExpBuffer(buf, " PASSWORD "); 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)) if (!PQgetisnull(res, i, i_rolvaliduntil))
@ -546,7 +546,7 @@ dumpRoles(PGconn *conn)
if (!PQgetisnull(res, i, i_rolcomment)) { if (!PQgetisnull(res, i, i_rolcomment)) {
appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename)); 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"); appendPQExpBuffer(buf, ";\n");
} }
@ -730,7 +730,7 @@ dumpTablespaces(PGconn *conn)
appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
appendPQExpBuffer(buf, " LOCATION "); appendPQExpBuffer(buf, " LOCATION ");
appendStringLiteral(buf, spclocation, true); appendStringLiteral(buf, spclocation, true, true);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
if (!skip_acls && if (!skip_acls &&
@ -745,7 +745,7 @@ dumpTablespaces(PGconn *conn)
if (spccomment && strlen(spccomment)) { if (spccomment && strlen(spccomment)) {
appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname); appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
appendStringLiteral(buf, spccomment, true); appendStringLiteral(buf, spccomment, true, true);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
} }
@ -868,7 +868,7 @@ dumpCreateDB(PGconn *conn)
appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner)); appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
appendPQExpBuffer(buf, " ENCODING = "); appendPQExpBuffer(buf, " ENCODING = ");
appendStringLiteral(buf, dbencoding, true); appendStringLiteral(buf, dbencoding, true, true);
/* Output tablespace if it isn't default */ /* Output tablespace if it isn't default */
if (strcmp(dbtablespace, "pg_default") != 0) if (strcmp(dbtablespace, "pg_default") != 0)
@ -884,7 +884,7 @@ dumpCreateDB(PGconn *conn)
if (strcmp(dbistemplate, "t") == 0) if (strcmp(dbistemplate, "t") == 0)
{ {
appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = "); appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
appendStringLiteral(buf, dbname, true); appendStringLiteral(buf, dbname, true, true);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
} }
} }
@ -929,7 +929,7 @@ dumpDatabaseConfig(PGconn *conn, const char *dbname)
PGresult *res; PGresult *res;
printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count); printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
appendStringLiteral(buf, dbname, true); appendStringLiteral(buf, dbname, true, true);
appendPQExpBuffer(buf, ";"); appendPQExpBuffer(buf, ";");
res = executeQuery(conn, buf->data); 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); printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
else else
printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count); 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); res = executeQuery(conn, buf->data);
if (PQntuples(res) == 1 && if (PQntuples(res) == 1 &&
@ -1016,7 +1016,7 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name
|| pg_strcasecmp(mine, "search_path") == 0) || pg_strcasecmp(mine, "search_path") == 0)
appendPQExpBuffer(buf, "%s", pos + 1); appendPQExpBuffer(buf, "%s", pos + 1);
else else
appendStringLiteral(buf, pos + 1, false); appendStringLiteral(buf, pos + 1, false, true);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
printf("%s", buf->data); printf("%s", buf->data);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * 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 "postgres_fe.h"
#include "describe.h" #include "describe.h"
@ -1867,7 +1867,7 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
appendPQExpBuffer(&namebuf, "\\\\"); appendPQExpBuffer(&namebuf, "\\\\");
/* Ensure chars special to string literals are passed properly */ /* Ensure chars special to string literals are passed properly */
if (SQL_STR_DOUBLE(*cp)) if (SQL_STR_DOUBLE(*cp, true))
appendPQExpBufferChar(&namebuf, *cp); appendPQExpBufferChar(&namebuf, *cp);
i = PQmblen(cp, pset.encoding); i = PQmblen(cp, pset.encoding);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * 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 "postgres_fe.h"
#include "large_obj.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) if (strchr(comment_arg, '\\') != NULL)
*bufptr++ = ESCAPE_STRING_SYNTAX; *bufptr++ = ESCAPE_STRING_SYNTAX;
*bufptr++ = '\''; *bufptr++ = '\'';
for (i = 0; i < slen; i++) 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];
*bufptr++ = comment_arg[i]; *bufptr++ = comment_arg[i];
} }

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) if (comment)
{ {
printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname)); printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
appendStringLiteral(&sql, comment, false); appendStringLiteral(&sql, comment, false, true);
appendPQExpBuffer(&sql, ";\n"); appendPQExpBuffer(&sql, ";\n");
conn = connectDatabase(dbname, host, port, username, password, progname); conn = connectDatabase(dbname, host, port, username, password, progname);

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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")); fprintf(stderr, _("Password encryption failed.\n"));
exit(1); exit(1);
} }
appendStringLiteral(&sql, encrypted_password, false); appendStringLiteral(&sql, encrypted_password, false, true);
PQfreemem(encrypted_password); PQfreemem(encrypted_password);
} }
else else
appendStringLiteral(&sql, newpassword, false); appendStringLiteral(&sql, newpassword, false, true);
} }
if (superuser == TRI_YES) if (superuser == TRI_YES)
appendPQExpBuffer(&sql, " SUPERUSER"); appendPQExpBuffer(&sql, " SUPERUSER");

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 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' #define ESCAPE_STRING_SYNTAX 'E'
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------

View File

@ -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. * The aim is to get a simpler inteface to the database routines.
@ -32,8 +32,9 @@
#include "pgtypes_timestamp.h" #include "pgtypes_timestamp.h"
#include "pgtypes_interval.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 * static char *
quote_postgres(char *arg, int lineno) quote_postgres(char *arg, int lineno)
@ -45,13 +46,17 @@ quote_postgres(char *arg, int lineno)
if (!res) if (!res)
return (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) if (strchr(arg, '\\') != NULL)
res[ri++] = ESCAPE_STRING_SYNTAX; res[ri++] = ESCAPE_STRING_SYNTAX;
res[ri++] = '\''; res[ri++] = '\'';
for (i = 0; arg[i]; i++, 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];
res[ri] = arg[i]; res[ri] = arg[i];
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 "plpgsql.h"
#include "parser/parser.h" #include "parser/parser.h"
#include "parser/gramparse.h"
static PLpgSQL_expr *read_sql_construct(int until, static PLpgSQL_expr *read_sql_construct(int until,
int until2, int until2,
@ -376,12 +377,12 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
strcpy(buf, "SELECT "); strcpy(buf, "SELECT ");
cp1 = new->refname; cp1 = new->refname;
cp2 = buf + strlen(buf); cp2 = buf + strlen(buf);
if (strchr(cp1, '\\') != NULL) if (!standard_conforming_strings && strchr(cp1, '\\') != NULL)
*cp2++ = ESCAPE_STRING_SYNTAX; *cp2++ = ESCAPE_STRING_SYNTAX;
*cp2++ = '\''; *cp2++ = '\'';
while (*cp1) while (*cp1)
{ {
if (SQL_STR_DOUBLE(*cp1)) if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
*cp2++ = *cp1; *cp2++ = *cp1;
*cp2++ = *cp1++; *cp2++ = *cp1++;
} }