Commit 134b463f authored by Tom Lane's avatar Tom Lane

Fix up pg_dump to do string escaping fully correctly for client encoding

and standard_conforming_strings; likewise for the other client programs
that need it.  As per previous discussion, a pg_dump dump now conforms
to the standard_conforming_strings setting of the source database.
We don't use E'' syntax in the dump, thereby improving portability of
the SQL.  I added a SET escape_strings_warning = off command to keep
the dumps from getting a lot of back-chatter from that.
parent 117d73a9
...@@ -7,14 +7,13 @@ ...@@ -7,14 +7,13 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.19 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.20 2006/05/28 21:13:53 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "parser/gramparse.h"
/* /*
...@@ -49,6 +48,12 @@ quote_ident(PG_FUNCTION_ARGS) ...@@ -49,6 +48,12 @@ quote_ident(PG_FUNCTION_ARGS)
/* /*
* quote_literal - * quote_literal -
* returns a properly quoted literal * returns a properly quoted literal
*
* NOTE: think not to make this function's behavior change with
* standard_conforming_strings. We don't know where the result
* literal will be used, and so we must generate a result that
* will work with either setting. Take a look at what dblink
* uses this for before thinking you know better.
*/ */
Datum Datum
quote_literal(PG_FUNCTION_ARGS) quote_literal(PG_FUNCTION_ARGS)
...@@ -66,20 +71,22 @@ quote_literal(PG_FUNCTION_ARGS) ...@@ -66,20 +71,22 @@ 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 == '\\')
{ {
*cp2++ = ESCAPE_STRING_SYNTAX; *cp2++ = ESCAPE_STRING_SYNTAX;
break; break;
} }
}
len = VARSIZE(t) - VARHDRSZ; len = VARSIZE(t) - VARHDRSZ;
cp1 = VARDATA(t); cp1 = VARDATA(t);
*cp2++ = '\''; *cp2++ = '\'';
while (len-- > 0) while (len-- > 0)
{ {
if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings)) if (SQL_STR_DOUBLE(*cp1, true))
*cp2++ = *cp1; *cp2++ = *cp1;
*cp2++ = *cp1++; *cp2++ = *cp1++;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -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.222 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.223 2006/05/28 21:13:53 tgl Exp $
**********************************************************************/ **********************************************************************/
#include "postgres.h" #include "postgres.h"
...@@ -534,18 +534,23 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) ...@@ -534,18 +534,23 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
{ {
if (i > 0) if (i > 0)
appendStringInfo(&buf, ", "); appendStringInfo(&buf, ", ");
if (!standard_conforming_strings && strchr(p, '\\') != NULL) /*
appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); * We form the string literal according to the prevailing setting
* of standard_conforming_strings; we never use E''.
* User is responsible for making sure result is used correctly.
*/
appendStringInfoChar(&buf, '\''); appendStringInfoChar(&buf, '\'');
while (*p) while (*p)
{ {
if (SQL_STR_DOUBLE(*p, !standard_conforming_strings)) char ch = *p++;
appendStringInfoChar(&buf, *p);
appendStringInfoChar(&buf, *p++); if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
appendStringInfoChar(&buf, ch);
appendStringInfoChar(&buf, ch);
} }
p++;
appendStringInfoChar(&buf, '\''); appendStringInfoChar(&buf, '\'');
/* advance p to next string embedded in tgargs */
p++;
} }
} }
...@@ -3883,7 +3888,6 @@ get_const_expr(Const *constval, deparse_context *context) ...@@ -3883,7 +3888,6 @@ 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)
{ {
...@@ -3946,33 +3950,19 @@ get_const_expr(Const *constval, deparse_context *context) ...@@ -3946,33 +3950,19 @@ get_const_expr(Const *constval, deparse_context *context)
default: default:
/* /*
* We must quote any funny characters in the constant's * We form the string literal according to the prevailing setting
* representation. XXX Any MULTIBYTE considerations here? * of standard_conforming_strings; we never use E''.
* User is responsible for making sure result is used correctly.
*/ */
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;
}
appendStringInfoChar(buf, '\''); appendStringInfoChar(buf, '\'');
for (valptr = extval; *valptr; valptr++) for (valptr = extval; *valptr; valptr++)
{ {
char ch = *valptr; char ch = *valptr;
if (SQL_STR_DOUBLE(ch, is_e_string)) if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
{
appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch);
appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch);
} }
else if ((unsigned char) ch < (unsigned char) ' ')
appendStringInfo(buf, "\\%03o", (int) ch);
else
appendStringInfoChar(buf, ch);
}
appendStringInfoChar(buf, '\''); appendStringInfoChar(buf, '\'');
break; break;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -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.28 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.29 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -100,63 +100,102 @@ fmtId(const char *rawid) ...@@ -100,63 +100,102 @@ fmtId(const char *rawid)
/* /*
* Convert a string value to an SQL string literal and append it to * Convert a string value to an SQL string literal and append it to
* the given buffer. * the given buffer. We assume the specified client_encoding and
* standard_conforming_strings settings.
* *
* Special characters are escaped. Quote mark ' goes to '' per SQL * This is essentially equivalent to libpq's PQescapeStringInternal,
* standard, other stuff goes to \ sequences. If escapeAll is false, * except for the output buffer structure. We need it in situations
* whitespace characters are not escaped (tabs, newlines, etc.). This * where we do not have a PGconn available. Where we do,
* is appropriate for dump file output. Using E'' strings for * appendStringLiteralConn is a better choice.
* 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 e_string_for_backslash) int encoding, bool std_strings)
{ {
char ch; size_t length = strlen(str);
const char *p; const char *source = str;
bool is_e_string = false; char *target;
for (p = str; *p; p++) if (!enlargePQExpBuffer(buf, 2 * length + 2))
return;
target = buf->data + buf->len;
*target++ = '\'';
while (*source != '\0')
{ {
ch = *p; char c = *source;
int len;
int i;
if ((e_string_for_backslash && ch == '\\') || /* Fast path for plain ASCII */
((unsigned char) ch < (unsigned char) ' ' && if (!IS_HIGHBIT_SET(c))
(escapeAll ||
(ch != '\t' && ch != '\n' && ch != '\v' &&
ch != '\f' && ch != '\r'))))
{ {
appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); /* Apply quoting if needed */
is_e_string = true; if (SQL_STR_DOUBLE(c, !std_strings))
break; *target++ = c;
} /* Copy the character */
*target++ = c;
source++;
continue;
} }
appendPQExpBufferChar(buf, '\''); /* Slow path for possible multibyte characters */
for (p = str; *p; p++) len = PQmblen(source, encoding);
{
ch = *p; /* Copy the character */
if (SQL_STR_DOUBLE(ch, is_e_string)) for (i = 0; i < len; i++)
{ {
appendPQExpBufferChar(buf, ch); if (*source == '\0')
appendPQExpBufferChar(buf, ch); break;
*target++ = *source++;
} }
else if ((unsigned char) ch < (unsigned char) ' ' &&
(escapeAll ||
(ch != '\t' && ch != '\n' && ch != '\v' &&
ch != '\f' && ch != '\r')))
{
/* /*
* generate octal escape for control chars other than whitespace * If we hit premature end of string (ie, incomplete multibyte
* character), try to pad out to the correct length with spaces.
* We may not be able to pad completely, but we will always be able
* to insert at least one pad space (since we'd not have quoted a
* multibyte character). This should be enough to make a string that
* the server will error out on.
*/ */
appendPQExpBufferChar(buf, '\\'); if (i < len)
appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0'); {
appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0'); char *stop = buf->data + buf->maxlen - 2;
appendPQExpBufferChar(buf, (ch & 7) + '0');
for (; i < len; i++)
{
if (target >= stop)
break;
*target++ = ' ';
} }
else break;
appendPQExpBufferChar(buf, ch);
} }
}
/* Write the terminating quote and NUL character. */
*target++ = '\'';
*target = '\0';
buf->len = target - buf->data;
}
/*
* Convert a string value to an SQL string literal and append it to
* the given buffer. Encoding and string syntax rules are as indicated
* by current settings of the PGconn.
*/
void
appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
{
size_t length = strlen(str);
if (!enlargePQExpBuffer(buf, 2 * length + 2))
return;
appendPQExpBufferChar(buf, '\'');
buf->len += PQescapeStringConn(conn, buf->data + buf->len,
str, length, NULL);
appendPQExpBufferChar(buf, '\''); appendPQExpBufferChar(buf, '\'');
} }
...@@ -167,7 +206,8 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll, ...@@ -167,7 +206,8 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
* dollar quote delimiter will begin with that (after the opening $). * dollar quote delimiter will begin with that (after the opening $).
* *
* No escaping is done at all on str, in compliance with the rules * No escaping is done at all on str, in compliance with the rules
* for parsing dollar quoted strings. * for parsing dollar quoted strings. Also, we need not worry about
* encoding issues.
*/ */
void void
appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix) appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
...@@ -204,21 +244,6 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix) ...@@ -204,21 +244,6 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
} }
/*
* Use dollar quoting if the string to be quoted contains ' or \,
* otherwise use standard quoting.
*/
void
appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
bool escapeAll, const char *dqprefix)
{
if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
appendStringLiteral(buf, str, escapeAll, true);
else
appendStringLiteralDQ(buf, str, dqprefix);
}
/* /*
* Convert backend's version string into a number. * Convert backend's version string into a number.
*/ */
......
...@@ -7,7 +7,7 @@ ...@@ -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.16 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.17 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,15 +15,16 @@ ...@@ -15,15 +15,16 @@
#ifndef DUMPUTILS_H #ifndef DUMPUTILS_H
#define DUMPUTILS_H #define DUMPUTILS_H
#include "libpq-fe.h"
#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 e_string_for_backslash); int encoding, bool std_strings);
extern void appendStringLiteralConn(PQExpBuffer buf, const char *str,
PGconn *conn);
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,
bool escapeAll, const char *dqprefix);
extern int parse_version(const char *versionString); extern int parse_version(const char *versionString);
extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems); extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
extern bool buildACLCommands(const char *name, const char *type, extern bool buildACLCommands(const char *name, const char *type,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.38 2006/02/12 04:04:32 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.39 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -60,6 +60,10 @@ typedef struct _Archive ...@@ -60,6 +60,10 @@ typedef struct _Archive
int minRemoteVersion; /* allowable range */ int minRemoteVersion; /* allowable range */
int maxRemoteVersion; int maxRemoteVersion;
/* info needed for string escaping */
int encoding; /* libpq code for client_encoding */
bool std_strings; /* standard_conforming_strings */
/* error handling */ /* error handling */
bool exit_on_error; /* whether to exit on SQL errors... */ bool exit_on_error; /* whether to exit on SQL errors... */
int n_errors; /* number of errors (if no die) */ int n_errors; /* number of errors (if no die) */
...@@ -182,4 +186,7 @@ archprintf(Archive *AH, const char *fmt,...) ...@@ -182,4 +186,7 @@ archprintf(Archive *AH, const char *fmt,...)
/* This extension allows gcc to check the format string */ /* This extension allows gcc to check the format string */
__attribute__((format(printf, 2, 3))); __attribute__((format(printf, 2, 3)));
#define appendStringLiteralAH(buf,str,AH) \
appendStringLiteral(buf, str, (AH)->encoding, (AH)->std_strings)
#endif /* PG_BACKUP_H */ #endif /* PG_BACKUP_H */
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.130 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.131 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "pqexpbuffer.h" #include "pqexpbuffer.h"
#include "libpq/libpq-fs.h" #include "libpq/libpq-fs.h"
#include "mb/pg_wchar.h"
const char *progname; const char *progname;
...@@ -60,7 +61,8 @@ static void _becomeUser(ArchiveHandle *AH, const char *user); ...@@ -60,7 +61,8 @@ static void _becomeUser(ArchiveHandle *AH, const char *user);
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te); static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls); static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
...@@ -1589,6 +1591,14 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt, ...@@ -1589,6 +1591,14 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
AH->vmin = K_VERS_MINOR; AH->vmin = K_VERS_MINOR;
AH->vrev = K_VERS_REV; AH->vrev = K_VERS_REV;
/* initialize for backwards compatible string processing */
AH->public.encoding = PG_SQL_ASCII;
AH->public.std_strings = false;
/* sql error handling */
AH->public.exit_on_error = true;
AH->public.n_errors = 0;
AH->createDate = time(NULL); AH->createDate = time(NULL);
AH->intSize = sizeof(int); AH->intSize = sizeof(int);
...@@ -1676,10 +1686,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt, ...@@ -1676,10 +1686,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt); die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
} }
/* sql error handling */
AH->public.exit_on_error = true;
AH->public.n_errors = 0;
return AH; return AH;
} }
...@@ -1888,22 +1894,72 @@ ReadToc(ArchiveHandle *AH) ...@@ -1888,22 +1894,72 @@ ReadToc(ArchiveHandle *AH)
ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n", ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
i, te->dumpId, te->desc, te->tag); i, te->dumpId, te->desc, te->tag);
/* link completed entry into TOC circular list */
te->prev = AH->toc->prev; te->prev = AH->toc->prev;
AH->toc->prev->next = te; AH->toc->prev->next = te;
AH->toc->prev = te; AH->toc->prev = te;
te->next = AH->toc; te->next = AH->toc;
/* special processing immediately upon read for some items */
if (strcmp(te->desc, "ENCODING") == 0)
processEncodingEntry(AH, te);
else if (strcmp(te->desc, "STDSTRINGS") == 0)
processStdStringsEntry(AH, te);
} }
} }
static void
processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
{
/* te->defn should have the form SET client_encoding = 'foo'; */
char *defn = strdup(te->defn);
char *ptr1;
char *ptr2 = NULL;
int encoding;
ptr1 = strchr(defn, '\'');
if (ptr1)
ptr2 = strchr(++ptr1, '\'');
if (ptr2)
{
*ptr2 = '\0';
encoding = pg_char_to_encoding(ptr1);
if (encoding < 0)
die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
ptr1);
AH->public.encoding = encoding;
}
else
die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
te->defn);
free(defn);
}
static void
processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
{
/* te->defn should have the form SET standard_conforming_strings = 'x'; */
char *ptr1;
ptr1 = strchr(te->defn, '\'');
if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
AH->public.std_strings = true;
else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
AH->public.std_strings = false;
else
die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
te->defn);
}
static teReqs static teReqs
_tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
{ {
teReqs res = REQ_ALL; teReqs res = REQ_ALL;
/* ENCODING and STDSTRINGS objects are dumped specially, so always reject */ /* ENCODING and STDSTRINGS items are dumped specially, so always reject */
if (strcmp(te->desc, "ENCODING") == 0) if (strcmp(te->desc, "ENCODING") == 0 ||
return 0; strcmp(te->desc, "STDSTRINGS") == 0)
if (strcmp(te->desc, "STDSTRINGS") == 0)
return 0; return 0;
/* If it's an ACL, maybe ignore it */ /* If it's an ACL, maybe ignore it */
...@@ -2005,24 +2061,21 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) ...@@ -2005,24 +2061,21 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
static void static void
_doSetFixedOutputState(ArchiveHandle *AH) _doSetFixedOutputState(ArchiveHandle *AH)
{ {
TocEntry *te; /* Select the correct character set encoding */
ahprintf(AH, "SET client_encoding = '%s';\n",
pg_encoding_to_char(AH->public.encoding));
/* If we have an encoding or std_strings setting, emit that */ /* Select the correct string literal syntax */
te = AH->toc->next; ahprintf(AH, "SET standard_conforming_strings = %s;\n",
while (te != AH->toc) AH->public.std_strings ? "on" : "off");
{
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;
}
/* Make sure function checking is disabled */ /* Make sure function checking is disabled */
ahprintf(AH, "SET check_function_bodies = false;\n"); ahprintf(AH, "SET check_function_bodies = false;\n");
/* Avoid annoying notices etc */ /* Avoid annoying notices etc */
ahprintf(AH, "SET client_min_messages = warning;\n"); ahprintf(AH, "SET client_min_messages = warning;\n");
if (!AH->public.std_strings)
ahprintf(AH, "SET escape_string_warning = off;\n");
ahprintf(AH, "\n"); ahprintf(AH, "\n");
} }
...@@ -2043,7 +2096,7 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user) ...@@ -2043,7 +2096,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, true); appendStringLiteralAHX(cmd, user, AH);
else else
appendPQExpBuffer(cmd, "DEFAULT"); appendPQExpBuffer(cmd, "DEFAULT");
appendPQExpBuffer(cmd, ";"); appendPQExpBuffer(cmd, ";");
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.69 2006/02/05 20:58:47 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.70 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -326,6 +326,9 @@ extern void WriteDataChunks(ArchiveHandle *AH); ...@@ -326,6 +326,9 @@ extern void WriteDataChunks(ArchiveHandle *AH);
extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt); extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt);
extern bool checkSeek(FILE *fp); extern bool checkSeek(FILE *fp);
#define appendStringLiteralAHX(buf,str,AH) \
appendStringLiteral(buf, str, (AH)->public.encoding, (AH)->public.std_strings)
/* /*
* Mandatory routines for each supported format * Mandatory routines for each supported format
*/ */
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -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.76 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.77 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,7 @@ int optreset; ...@@ -36,6 +36,7 @@ int optreset;
#include "libpq-fe.h" #include "libpq-fe.h"
#include "pg_backup.h" #include "pg_backup.h"
#include "pqexpbuffer.h" #include "pqexpbuffer.h"
#include "mb/pg_wchar.h"
/* version string we expect back from pg_dump */ /* version string we expect back from pg_dump */
...@@ -53,7 +54,8 @@ static void dumpTablespaces(PGconn *conn); ...@@ -53,7 +54,8 @@ static void dumpTablespaces(PGconn *conn);
static void dumpCreateDB(PGconn *conn); static void dumpCreateDB(PGconn *conn);
static void dumpDatabaseConfig(PGconn *conn, const char *dbname); static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
static void dumpUserConfig(PGconn *conn, const char *username); static void dumpUserConfig(PGconn *conn, const char *username);
static void makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name); static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
const char *type, const char *name);
static void dumpDatabases(PGconn *conn); static void dumpDatabases(PGconn *conn);
static void dumpTimestamp(char *msg); static void dumpTimestamp(char *msg);
...@@ -88,6 +90,8 @@ main(int argc, char *argv[]) ...@@ -88,6 +90,8 @@ main(int argc, char *argv[])
bool globals_only = false; bool globals_only = false;
bool schema_only = false; bool schema_only = false;
PGconn *conn; PGconn *conn;
int encoding;
const char *std_strings;
int c, int c,
ret; ret;
...@@ -313,6 +317,15 @@ main(int argc, char *argv[]) ...@@ -313,6 +317,15 @@ main(int argc, char *argv[])
conn = connectDatabase("template1", pghost, pgport, pguser, conn = connectDatabase("template1", pghost, pgport, pguser,
force_password, true); force_password, true);
/*
* Get the active encoding and the standard_conforming_strings setting,
* so we know how to escape strings.
*/
encoding = PQclientEncoding(conn);
std_strings = PQparameterStatus(conn, "standard_conforming_strings");
if (!std_strings)
std_strings = "off";
printf("--\n-- PostgreSQL database cluster dump\n--\n\n"); printf("--\n-- PostgreSQL database cluster dump\n--\n\n");
if (verbose) if (verbose)
dumpTimestamp("Started on"); dumpTimestamp("Started on");
...@@ -321,6 +334,12 @@ main(int argc, char *argv[]) ...@@ -321,6 +334,12 @@ main(int argc, char *argv[])
if (!data_only) if (!data_only)
{ {
/* Replicate encoding and std_strings in output */
printf("SET client_encoding = '%s';\n",
pg_encoding_to_char(encoding));
printf("SET standard_conforming_strings = %s;\n", std_strings);
printf("\n");
/* Dump roles (users) */ /* Dump roles (users) */
dumpRoles(conn); dumpRoles(conn);
...@@ -535,7 +554,7 @@ dumpRoles(PGconn *conn) ...@@ -535,7 +554,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, true); appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
} }
if (!PQgetisnull(res, i, i_rolvaliduntil)) if (!PQgetisnull(res, i, i_rolvaliduntil))
...@@ -546,7 +565,7 @@ dumpRoles(PGconn *conn) ...@@ -546,7 +565,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, true); appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
} }
...@@ -730,7 +749,7 @@ dumpTablespaces(PGconn *conn) ...@@ -730,7 +749,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, true); appendStringLiteralConn(buf, spclocation, conn);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
if (!skip_acls && if (!skip_acls &&
...@@ -745,7 +764,7 @@ dumpTablespaces(PGconn *conn) ...@@ -745,7 +764,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, true); appendStringLiteralConn(buf, spccomment, conn);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
} }
...@@ -868,7 +887,7 @@ dumpCreateDB(PGconn *conn) ...@@ -868,7 +887,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, true); appendStringLiteralConn(buf, dbencoding, conn);
/* 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 +903,7 @@ dumpCreateDB(PGconn *conn) ...@@ -884,7 +903,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, true); appendStringLiteralConn(buf, dbname, conn);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
} }
} }
...@@ -929,13 +948,14 @@ dumpDatabaseConfig(PGconn *conn, const char *dbname) ...@@ -929,13 +948,14 @@ 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, true); appendStringLiteralConn(buf, dbname, conn);
appendPQExpBuffer(buf, ";"); appendPQExpBuffer(buf, ";");
res = executeQuery(conn, buf->data); res = executeQuery(conn, buf->data);
if (!PQgetisnull(res, 0, 0)) if (!PQgetisnull(res, 0, 0))
{ {
makeAlterConfigCommand(PQgetvalue(res, 0, 0), "DATABASE", dbname); makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
"DATABASE", dbname);
PQclear(res); PQclear(res);
count++; count++;
} }
...@@ -968,13 +988,14 @@ dumpUserConfig(PGconn *conn, const char *username) ...@@ -968,13 +988,14 @@ 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, true); appendStringLiteralConn(buf, username, conn);
res = executeQuery(conn, buf->data); res = executeQuery(conn, buf->data);
if (PQntuples(res) == 1 && if (PQntuples(res) == 1 &&
!PQgetisnull(res, 0, 0)) !PQgetisnull(res, 0, 0))
{ {
makeAlterConfigCommand(PQgetvalue(res, 0, 0), "ROLE", username); makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
"ROLE", username);
PQclear(res); PQclear(res);
count++; count++;
} }
...@@ -994,7 +1015,8 @@ dumpUserConfig(PGconn *conn, const char *username) ...@@ -994,7 +1015,8 @@ dumpUserConfig(PGconn *conn, const char *username)
* Helper function for dumpXXXConfig(). * Helper function for dumpXXXConfig().
*/ */
static void static void
makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name) makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
const char *type, const char *name)
{ {
char *pos; char *pos;
char *mine; char *mine;
...@@ -1016,7 +1038,7 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name ...@@ -1016,7 +1038,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, true); appendStringLiteralConn(buf, pos + 1, conn);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
printf("%s", buf->data); printf("%s", buf->data);
......
...@@ -3,13 +3,12 @@ ...@@ -3,13 +3,12 @@
* *
* 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.136 2006/05/28 02:27:08 alvherre Exp $ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.137 2006/05/28 21:13:54 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
#include "libpq-fe.h" #include "dumputils.h"
#include "pqexpbuffer.h"
#include "common.h" #include "common.h"
#include "settings.h" #include "settings.h"
...@@ -1815,7 +1814,12 @@ processNamePattern(PQExpBuffer buf, const char *pattern, ...@@ -1815,7 +1814,12 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
* Parse the pattern, converting quotes and lower-casing unquoted letters; * Parse the pattern, converting quotes and lower-casing unquoted letters;
* we assume this was NOT done by scan_option. Also, adjust shell-style * we assume this was NOT done by scan_option. Also, adjust shell-style
* wildcard characters into regexp notation. * wildcard characters into regexp notation.
*
* Note: the result of this pass is the actual regexp pattern we want
* to execute. Quoting/escaping it into a SQL literal will be done below.
*/ */
appendPQExpBufferChar(&namebuf, '^');
inquotes = false; inquotes = false;
cp = pattern; cp = pattern;
...@@ -1854,6 +1858,7 @@ processNamePattern(PQExpBuffer buf, const char *pattern, ...@@ -1854,6 +1858,7 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
resetPQExpBuffer(&schemabuf); resetPQExpBuffer(&schemabuf);
appendPQExpBufferStr(&schemabuf, namebuf.data); appendPQExpBufferStr(&schemabuf, namebuf.data);
resetPQExpBuffer(&namebuf); resetPQExpBuffer(&namebuf);
appendPQExpBufferChar(&namebuf, '^');
cp++; cp++;
} }
else else
...@@ -1869,14 +1874,9 @@ processNamePattern(PQExpBuffer buf, const char *pattern, ...@@ -1869,14 +1874,9 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
*/ */
if ((inquotes || force_escape) && if ((inquotes || force_escape) &&
strchr("|*+?()[]{}.^$\\", *cp)) strchr("|*+?()[]{}.^$\\", *cp))
appendPQExpBuffer(&namebuf, "\\\\"); appendPQExpBufferChar(&namebuf, '\\');
/* Ensure chars special to string literals are passed properly */
if (SQL_STR_DOUBLE(*cp, true))
appendPQExpBufferChar(&namebuf, *cp);
i = PQmblen(cp, pset.encoding); i = PQmblen(cp, pset.encoding);
while (i--) while (i-- && *cp)
{ {
appendPQExpBufferChar(&namebuf, *cp); appendPQExpBufferChar(&namebuf, *cp);
cp++; cp++;
...@@ -1885,49 +1885,61 @@ processNamePattern(PQExpBuffer buf, const char *pattern, ...@@ -1885,49 +1885,61 @@ processNamePattern(PQExpBuffer buf, const char *pattern,
} }
/* /*
* Now decide what we need to emit. * Now decide what we need to emit. Note there will be a leading '^'
* in the patterns in any case.
*/ */
if (namebuf.len > 0) if (namebuf.len > 1)
{ {
/* We have a name pattern, so constrain the namevar(s) */ /* We have a name pattern, so constrain the namevar(s) */
appendPQExpBufferChar(&namebuf, '$'); appendPQExpBufferChar(&namebuf, '$');
/* Optimize away ".*$", and possibly the whole pattern */ /* Optimize away ".*$", and possibly the whole pattern */
if (namebuf.len >= 3 && if (namebuf.len >= 4 &&
strcmp(namebuf.data + (namebuf.len - 3), ".*$") == 0) strcmp(namebuf.data + (namebuf.len - 3), ".*$") == 0)
namebuf.data[namebuf.len - 3] = '\0'; {
namebuf.len -= 3;
namebuf.data[namebuf.len] = '\0';
}
if (namebuf.data[0]) if (namebuf.len > 1)
{ {
WHEREAND(); WHEREAND();
if (altnamevar) if (altnamevar)
appendPQExpBuffer(buf, {
"(%s ~ '^%s'\n" appendPQExpBuffer(buf, "(%s ~ ", namevar);
" OR %s ~ '^%s')\n", appendStringLiteralConn(buf, namebuf.data, pset.db);
namevar, namebuf.data, appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
altnamevar, namebuf.data); appendStringLiteralConn(buf, namebuf.data, pset.db);
appendPQExpBuffer(buf, ")\n");
}
else else
appendPQExpBuffer(buf, {
"%s ~ '^%s'\n", appendPQExpBuffer(buf, "%s ~ ", namevar);
namevar, namebuf.data); appendStringLiteralConn(buf, namebuf.data, pset.db);
appendPQExpBufferChar(buf, '\n');
}
} }
} }
if (schemabuf.len > 0) if (schemabuf.len > 1)
{ {
/* We have a schema pattern, so constrain the schemavar */ /* We have a schema pattern, so constrain the schemavar */
appendPQExpBufferChar(&schemabuf, '$'); appendPQExpBufferChar(&schemabuf, '$');
/* Optimize away ".*$", and possibly the whole pattern */ /* Optimize away ".*$", and possibly the whole pattern */
if (schemabuf.len >= 3 && if (schemabuf.len >= 4 &&
strcmp(schemabuf.data + (schemabuf.len - 3), ".*$") == 0) strcmp(schemabuf.data + (schemabuf.len - 3), ".*$") == 0)
schemabuf.data[schemabuf.len - 3] = '\0'; {
schemabuf.len -= 3;
schemabuf.data[schemabuf.len] = '\0';
}
if (schemabuf.data[0] && schemavar) if (schemabuf.len > 1 && schemavar)
{ {
WHEREAND(); WHEREAND();
appendPQExpBuffer(buf, "%s ~ '^%s'\n", appendPQExpBuffer(buf, "%s ~ ", schemavar);
schemavar, schemabuf.data); appendStringLiteralConn(buf, schemabuf.data, pset.db);
appendPQExpBufferChar(buf, '\n');
} }
} }
else else
......
...@@ -3,7 +3,7 @@ ...@@ -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.42 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.43 2006/05/28 21:13:54 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "large_obj.h" #include "large_obj.h"
...@@ -148,7 +148,6 @@ do_lo_import(const char *filename_arg, const char *comment_arg) ...@@ -148,7 +148,6 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
PGresult *res; PGresult *res;
Oid loid; Oid loid;
char oidbuf[32]; char oidbuf[32];
unsigned int i;
bool own_transaction; bool own_transaction;
if (!start_lo_xact("\\lo_import", &own_transaction)) if (!start_lo_xact("\\lo_import", &own_transaction))
...@@ -171,21 +170,9 @@ do_lo_import(const char *filename_arg, const char *comment_arg) ...@@ -171,21 +170,9 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
cmdbuf = malloc(slen * 2 + 256); cmdbuf = malloc(slen * 2 + 256);
if (!cmdbuf) if (!cmdbuf)
return fail_lo_xact("\\lo_import", own_transaction); return fail_lo_xact("\\lo_import", own_transaction);
sprintf(cmdbuf, sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid);
"COMMENT ON LARGE OBJECT %u IS ",
loid);
bufptr = cmdbuf + strlen(cmdbuf); bufptr = cmdbuf + strlen(cmdbuf);
bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL);
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];
}
strcpy(bufptr, "'"); strcpy(bufptr, "'");
if (!(res = PSQLexec(cmdbuf, false))) if (!(res = PSQLexec(cmdbuf, false)))
......
...@@ -5,7 +5,7 @@ ...@@ -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.17 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.18 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -183,11 +183,12 @@ main(int argc, char *argv[]) ...@@ -183,11 +183,12 @@ main(int argc, char *argv[])
if (comment) if (comment)
{ {
conn = connectDatabase(dbname, host, port, username, password, progname);
printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname)); printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
appendStringLiteral(&sql, comment, false, true); appendStringLiteralConn(&sql, comment, conn);
appendPQExpBuffer(&sql, ";\n"); appendPQExpBuffer(&sql, ";\n");
conn = connectDatabase(dbname, host, port, username, password, progname);
if (echo) if (echo)
printf("%s", sql.data); printf("%s", sql.data);
result = PQexec(conn, sql.data); result = PQexec(conn, sql.data);
......
...@@ -5,7 +5,7 @@ ...@@ -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.28 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.29 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -236,6 +236,8 @@ main(int argc, char *argv[]) ...@@ -236,6 +236,8 @@ main(int argc, char *argv[])
if (login == 0) if (login == 0)
login = TRI_YES; login = TRI_YES;
conn = connectDatabase("postgres", host, port, username, password, progname);
initPQExpBuffer(&sql); initPQExpBuffer(&sql);
printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser)); printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
...@@ -258,11 +260,11 @@ main(int argc, char *argv[]) ...@@ -258,11 +260,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, true); appendStringLiteralConn(&sql, encrypted_password, conn);
PQfreemem(encrypted_password); PQfreemem(encrypted_password);
} }
else else
appendStringLiteral(&sql, newpassword, false, true); appendStringLiteralConn(&sql, newpassword, conn);
} }
if (superuser == TRI_YES) if (superuser == TRI_YES)
appendPQExpBuffer(&sql, " SUPERUSER"); appendPQExpBuffer(&sql, " SUPERUSER");
...@@ -288,8 +290,6 @@ main(int argc, char *argv[]) ...@@ -288,8 +290,6 @@ main(int argc, char *argv[])
appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit); appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit);
appendPQExpBuffer(&sql, ";\n"); appendPQExpBuffer(&sql, ";\n");
conn = connectDatabase("postgres", host, port, username, password, progname);
if (echo) if (echo)
printf("%s", sql.data); printf("%s", sql.data);
result = PQexec(conn, sql.data); result = PQexec(conn, sql.data);
......
...@@ -12,7 +12,7 @@ ...@@ -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.201 2006/05/26 23:48:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/c.h,v 1.202 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -473,12 +473,13 @@ typedef NameData *Name; ...@@ -473,12 +473,13 @@ typedef NameData *Name;
#define NameStr(name) ((name).data) #define NameStr(name) ((name).data)
/* /*
* In 8.2, we are warning for \ in a non-E string if std_strings are off. * Support macros for escaping strings. escape_backslash should be TRUE
* For this reason, we use E for \ strings, unless standard_conforming_strings * if generating a non-standard-conforming string. Prefixing a string
* is on. * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming.
* Beware of multiple evaluation of the "ch" argument!
*/ */
#define SQL_STR_DOUBLE(ch, escape_backslash) \ #define SQL_STR_DOUBLE(ch, escape_backslash) \
((ch) == '\'' || ((escape_backslash) && (ch) == '\\')) ((ch) == '\'' || ((ch) == '\\' && (escape_backslash)))
#define ESCAPE_STRING_SYNTAX 'E' #define ESCAPE_STRING_SYNTAX 'E'
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.185 2006/05/28 17:23:29 alvherre Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.186 2006/05/28 21:13:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2437,8 +2437,7 @@ PQescapeStringInternal(PGconn *conn, ...@@ -2437,8 +2437,7 @@ PQescapeStringInternal(PGconn *conn,
if (!IS_HIGHBIT_SET(c)) if (!IS_HIGHBIT_SET(c))
{ {
/* Apply quoting if needed */ /* Apply quoting if needed */
if (c == '\'' || if (SQL_STR_DOUBLE(c, !std_strings))
(c == '\\' && !std_strings))
*target++ = c; *target++ = c;
/* Copy the character */ /* Copy the character */
*target++ = c; *target++ = c;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment