*
*
* 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 "utils/builtins.h"
-#include "parser/gramparse.h"
/*
/*
* quote_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
quote_literal(PG_FUNCTION_ARGS)
cp1 = VARDATA(t);
cp2 = VARDATA(result);
- if (!standard_conforming_strings)
- for (; len-- > 0; cp1++)
- if (*cp1 == '\\')
- {
- *cp2++ = ESCAPE_STRING_SYNTAX;
- break;
- }
+ 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))
+ if (SQL_STR_DOUBLE(*cp1, true))
*cp2++ = *cp1;
*cp2++ = *cp1++;
}
* ruleutils.c - Functions to convert stored expressions/querytrees
* 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"
{
if (i > 0)
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, '\'');
-
while (*p)
{
- if (SQL_STR_DOUBLE(*p, !standard_conforming_strings))
- appendStringInfoChar(&buf, *p);
- appendStringInfoChar(&buf, *p++);
+ char ch = *p++;
+
+ if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
+ appendStringInfoChar(&buf, ch);
+ appendStringInfoChar(&buf, ch);
}
- p++;
appendStringInfoChar(&buf, '\'');
+ /* advance p to next string embedded in tgargs */
+ p++;
}
}
char *valptr;
bool isfloat = false;
bool needlabel;
- bool is_e_string = false;
-
+
if (constval->constisnull)
{
/*
default:
/*
- * We must quote any funny characters in the constant's
- * representation. XXX Any MULTIBYTE considerations here?
+ * 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.
*/
- 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, '\'');
for (valptr = extval; *valptr; valptr++)
{
char ch = *valptr;
- if (SQL_STR_DOUBLE(ch, is_e_string))
- {
- appendStringInfoChar(buf, ch);
- appendStringInfoChar(buf, ch);
- }
- else if ((unsigned char) ch < (unsigned char) ' ')
- appendStringInfo(buf, "\\%03o", (int) ch);
- else
+ if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
}
appendStringInfoChar(buf, '\'');
break;
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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
- * 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.
+ * This is essentially equivalent to libpq's PQescapeStringInternal,
+ * except for the output buffer structure. We need it in situations
+ * where we do not have a PGconn available. Where we do,
+ * appendStringLiteralConn is a better choice.
*/
void
-appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
- bool e_string_for_backslash)
+appendStringLiteral(PQExpBuffer buf, const char *str,
+ int encoding, bool std_strings)
{
- char ch;
- const char *p;
- bool is_e_string = false;
+ size_t length = strlen(str);
+ const char *source = str;
+ 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 == '\\') ||
- ((unsigned char) ch < (unsigned char) ' ' &&
- (escapeAll ||
- (ch != '\t' && ch != '\n' && ch != '\v' &&
- ch != '\f' && ch != '\r'))))
+ /* Fast path for plain ASCII */
+ if (!IS_HIGHBIT_SET(c))
{
- appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
- is_e_string = true;
- break;
+ /* Apply quoting if needed */
+ if (SQL_STR_DOUBLE(c, !std_strings))
+ *target++ = c;
+ /* Copy the character */
+ *target++ = c;
+ source++;
+ continue;
}
- }
- appendPQExpBufferChar(buf, '\'');
- for (p = str; *p; p++)
- {
- ch = *p;
- if (SQL_STR_DOUBLE(ch, is_e_string))
+ /* Slow path for possible multibyte characters */
+ len = PQmblen(source, encoding);
+
+ /* Copy the character */
+ for (i = 0; i < len; i++)
{
- appendPQExpBufferChar(buf, ch);
- appendPQExpBufferChar(buf, ch);
+ if (*source == '\0')
+ break;
+ *target++ = *source++;
}
- else if ((unsigned char) ch < (unsigned char) ' ' &&
- (escapeAll ||
- (ch != '\t' && ch != '\n' && ch != '\v' &&
- ch != '\f' && ch != '\r')))
+
+ /*
+ * 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.
+ */
+ if (i < len)
{
- /*
- * generate octal escape for control chars other than whitespace
- */
- appendPQExpBufferChar(buf, '\\');
- appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
- appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
- appendPQExpBufferChar(buf, (ch & 7) + '0');
+ char *stop = buf->data + buf->maxlen - 2;
+
+ for (; i < len; i++)
+ {
+ if (target >= stop)
+ break;
+ *target++ = ' ';
+ }
+ break;
}
- else
- 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, '\'');
}
* dollar quote delimiter will begin with that (after the opening $).
*
* No escaping is done at all on str, in compliance with the rules
- * for parsing dollar quoted strings.
+ * for parsing dollar quoted strings. Also, we need not worry about
+ * encoding issues.
*/
void
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.
*/
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.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 $
*
*-------------------------------------------------------------------------
*/
#ifndef DUMPUTILS_H
#define DUMPUTILS_H
+#include "libpq-fe.h"
#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);
+ int encoding, bool std_strings);
+extern void appendStringLiteralConn(PQExpBuffer buf, const char *str,
+ PGconn *conn);
extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
const char *dqprefix);
-extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
- bool escapeAll, const char *dqprefix);
extern int parse_version(const char *versionString);
extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
extern bool buildACLCommands(const char *name, const char *type,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
int minRemoteVersion; /* allowable range */
int maxRemoteVersion;
+ /* info needed for string escaping */
+ int encoding; /* libpq code for client_encoding */
+ bool std_strings; /* standard_conforming_strings */
+
/* error handling */
bool exit_on_error; /* whether to exit on SQL errors... */
int n_errors; /* number of errors (if no die) */
/* This extension allows gcc to check the format string */
__attribute__((format(printf, 2, 3)));
+#define appendStringLiteralAH(buf,str,AH) \
+ appendStringLiteral(buf, str, (AH)->encoding, (AH)->std_strings)
+
#endif /* PG_BACKUP_H */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "pqexpbuffer.h"
#include "libpq/libpq-fs.h"
+#include "mb/pg_wchar.h"
const char *progname;
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
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 void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
AH->vmin = K_VERS_MINOR;
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->intSize = sizeof(int);
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;
}
ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
i, te->dumpId, te->desc, te->tag);
+ /* link completed entry into TOC circular list */
te->prev = AH->toc->prev;
AH->toc->prev->next = te;
AH->toc->prev = te;
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
{
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)
+ /* ENCODING and STDSTRINGS items are dumped specially, so always reject */
+ if (strcmp(te->desc, "ENCODING") == 0 ||
+ strcmp(te->desc, "STDSTRINGS") == 0)
return 0;
/* If it's an ACL, maybe ignore it */
static void
_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 */
- 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;
- }
+ /* Select the correct string literal syntax */
+ ahprintf(AH, "SET standard_conforming_strings = %s;\n",
+ AH->public.std_strings ? "on" : "off");
/* Make sure function checking is disabled */
ahprintf(AH, "SET check_function_bodies = false;\n");
/* Avoid annoying notices etc */
ahprintf(AH, "SET client_min_messages = warning;\n");
+ if (!AH->public.std_strings)
+ ahprintf(AH, "SET escape_string_warning = off;\n");
ahprintf(AH, "\n");
}
* SQL requires a string literal here. Might as well be correct.
*/
if (user && *user)
- appendStringLiteral(cmd, user, false, true);
+ appendStringLiteralAHX(cmd, user, AH);
else
appendPQExpBuffer(cmd, "DEFAULT");
appendPQExpBuffer(cmd, ";");
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt);
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
*/
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.435 2006/05/28 17:23:29 alvherre Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.436 2006/05/28 21:13:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
+#include "mb/pg_wchar.h"
#include "pg_dump.h"
#include "pg_backup.h"
* 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 */
const char *pgport = NULL;
const char *username = NULL;
const char *dumpencoding = NULL;
+ const char *std_strings;
bool oids = false;
TableInfo *tblinfo;
int numTables;
g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
username, force_password, ignore_version);
+ /* Set the client encoding if requested */
+ if (dumpencoding)
+ {
+ if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
+ {
+ write_msg(NULL, "invalid client encoding \"%s\" specified\n",
+ dumpencoding);
+ exit(1);
+ }
+ }
+
/*
- * Start serializable transaction to dump consistent data.
+ * Get the active encoding and the standard_conforming_strings setting,
+ * so we know how to escape strings.
*/
- do_sql_command(g_conn, "BEGIN");
+ g_fout->encoding = PQclientEncoding(g_conn);
- do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+ std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
+ g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
/* Set the datestyle to ISO to ensure the dump's portability */
do_sql_command(g_conn, "SET DATESTYLE = ISO");
- /* Set the client encoding */
- if (dumpencoding)
- {
- char *cmd = malloc(strlen(dumpencoding) + 32);
+ /*
+ * Start serializable transaction to dump consistent data.
+ */
+ do_sql_command(g_conn, "BEGIN");
- sprintf(cmd, "SET client_encoding='%s'", dumpencoding);
- do_sql_command(g_conn, cmd);
- free(cmd);
- }
+ do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
/* Select the appropriate subquery to convert user IDs to names */
if (g_fout->remoteVersion >= 80100)
* order.
*/
- /* First the special encoding entry. */
+ /* First the special ENCODING and STDSTRINGS entries. */
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 next, unless we don't want it at all */
if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL)
dumpDatabase(g_fout);
default:
/* All other types are printed as string literals. */
resetPQExpBuffer(q);
- appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings);
+ appendStringLiteralAH(q,
+ PQgetvalue(res, tuple, field),
+ fout);
archputs(q->data, fout);
break;
}
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteral(dbQry, datname, true, !std_strings);
+ appendStringLiteralAH(dbQry, datname, AH);
}
else if (g_fout->remoteVersion >= 80000)
{
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteral(dbQry, datname, true, !std_strings);
+ appendStringLiteralAH(dbQry, datname, AH);
}
else if (g_fout->remoteVersion >= 70100)
{
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteral(dbQry, datname, true, !std_strings);
+ appendStringLiteralAH(dbQry, datname, AH);
}
else
{
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteral(dbQry, datname, true, !std_strings);
+ appendStringLiteralAH(dbQry, datname, AH);
}
res = PQexec(g_conn, dbQry->data);
if (strlen(encoding) > 0)
{
appendPQExpBuffer(creaQry, " ENCODING = ");
- appendStringLiteral(creaQry, encoding, true, !std_strings);
+ appendStringLiteralAH(creaQry, encoding, AH);
}
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
appendPQExpBuffer(creaQry, " TABLESPACE = %s",
if (comment && strlen(comment)) {
resetPQExpBuffer(dbQry);
appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
- appendStringLiteral(dbQry, comment, false, !std_strings);
+ appendStringLiteralAH(dbQry, comment, AH);
appendPQExpBuffer(dbQry, ";\n");
ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
static void
dumpEncoding(Archive *AH)
{
- PQExpBuffer qry;
- PGresult *res;
-
- /* Can't read the encoding from pre-7.3 servers (SHOW isn't a query) */
- if (AH->remoteVersion < 70300)
- return;
+ const char *encname = pg_encoding_to_char(AH->encoding);
+ PQExpBuffer qry = createPQExpBuffer();
if (g_verbose)
- write_msg(NULL, "saving encoding\n");
-
- qry = createPQExpBuffer();
-
- appendPQExpBuffer(qry, "SHOW client_encoding");
-
- res = PQexec(g_conn, qry->data);
-
- check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
-
- resetPQExpBuffer(qry);
+ write_msg(NULL, "saving encoding = %s\n", encname);
appendPQExpBuffer(qry, "SET client_encoding = ");
- appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
+ appendStringLiteralAH(qry, encname, AH);
appendPQExpBuffer(qry, ";\n");
ArchiveEntry(AH, nilCatalogId, createDumpId(),
NULL, 0,
NULL, NULL);
- PQclear(res);
-
destroyPQExpBuffer(qry);
}
static void
dumpStdStrings(Archive *AH)
{
- PQExpBuffer qry;
- PGresult *res;
+ const char *stdstrings = AH->std_strings ? "on" : "off";
+ PQExpBuffer qry = createPQExpBuffer();
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");
+ write_msg(NULL, "saving standard_conforming_strings = %s\n",
+ stdstrings);
- res = PQexec(g_conn, qry->data);
+ appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
+ stdstrings);
- check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
-
- 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));
-
- PQclear(res);
- }
-
ArchiveEntry(AH, nilCatalogId, createDumpId(),
"STDSTRINGS", NULL, NULL, "",
false, "STDSTRINGS", qry->data, "", NULL,
printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
blobOid);
- appendStringLiteral(commentcmd, comment, false, !std_strings);
+ appendStringLiteralAH(commentcmd, comment, AH);
appendPQExpBuffer(commentcmd, ";\n");
archputs(commentcmd->data, AH);
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
- appendStringLiteral(query, comments->descr, false, !std_strings);
+ appendStringLiteralAH(query, comments->descr, fout);
appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
- appendStringLiteral(query, descr, false, !std_strings);
+ appendStringLiteralAH(query, descr, fout);
appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
- appendStringLiteral(query, descr, false, !std_strings);
+ appendStringLiteralAH(query, descr, fout);
appendPQExpBuffer(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
{
appendPQExpBuffer(q, ",\n DEFAULT = ");
if (typdefault_is_literal)
- appendStringLiteral(q, typdefault, true, !std_strings);
+ appendStringLiteralAH(q, typdefault, fout);
else
appendPQExpBufferStr(q, typdefault);
}
if (typdelim && strcmp(typdelim, ",") != 0)
{
appendPQExpBuffer(q, ",\n DELIMITER = ");
- appendStringLiteral(q, typdelim, true, !std_strings);
+ appendStringLiteralAH(q, typdelim, fout);
}
if (strcmp(typalign, "c") == 0)
{
appendPQExpBuffer(q, " DEFAULT ");
if (typdefault_is_literal)
- appendStringLiteral(q, typdefault, true, !std_strings);
+ appendStringLiteralAH(q, typdefault, fout);
else
appendPQExpBufferStr(q, typdefault);
}
if (strcmp(probin, "-") != 0)
{
appendPQExpBuffer(asPart, "AS ");
- appendStringLiteral(asPart, probin, true, !std_strings);
+ appendStringLiteralAH(asPart, probin, fout);
if (strcmp(prosrc, "-") != 0)
{
appendPQExpBuffer(asPart, ", ");
* where we have bin, use dollar quoting if allowed and src
* contains quote or backslash; else use regular quoting.
*/
- if (disable_dollar_quoting)
- appendStringLiteral(asPart, prosrc, false, !std_strings);
+ if (disable_dollar_quoting ||
+ (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
+ appendStringLiteralAH(asPart, prosrc, fout);
else
- appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
+ appendStringLiteralDQ(asPart, prosrc, NULL);
}
}
else
appendPQExpBuffer(asPart, "AS ");
/* with no bin, dollar quote src unconditionally if allowed */
if (disable_dollar_quoting)
- appendStringLiteral(asPart, prosrc, false, !std_strings);
+ appendStringLiteralAH(asPart, prosrc, fout);
else
appendStringLiteralDQ(asPart, prosrc, NULL);
}
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
(condefault) ? "DEFAULT " : "",
fmtId(convinfo->dobj.name));
- appendStringLiteral(q, conforencoding, true, !std_strings);
+ appendStringLiteralAH(q, conforencoding, fout);
appendPQExpBuffer(q, " TO ");
- appendStringLiteral(q, contoencoding, true, !std_strings);
+ appendStringLiteralAH(q, contoencoding, fout);
/* regproc is automatically quoted in 7.3 and above */
appendPQExpBuffer(q, " FROM %s;\n", conproc);
if (!PQgetisnull(res, 0, i_agginitval))
{
appendPQExpBuffer(details, ",\n INITCOND = ");
- appendStringLiteral(details, agginitval, true, !std_strings);
+ appendStringLiteralAH(details, agginitval, fout);
}
if (strcmp(aggfinalfn, "-") != 0)
{
appendPQExpBuffer(query, "SELECT definition as viewdef "
" from pg_views where viewname = ");
- appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings);
+ appendStringLiteralAH(query, tbinfo->dobj.name, fout);
appendPQExpBuffer(query, ";");
}
resetPQExpBuffer(query);
appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
- appendStringLiteral(query, dbname, true, !std_strings);
+ appendStringLiteralAH(query, dbname, g_fout);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
(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);
+ appendStringLiteralAH(query, fmtId(owning_tab->dobj.name), fout);
appendPQExpBuffer(query, ", ");
- appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true, !std_strings);
+ appendStringLiteralAH(query, owning_tab->attnames[tbinfo->owning_col - 1], fout);
appendPQExpBuffer(query, ")");
}
else
- appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings);
+ appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
appendPQExpBuffer(query, ", %s, %s);\n",
last, (called ? "true" : "false"));
p = tginfo->tgargs;
for (findx = 0; findx < tginfo->tgnargs; findx++)
{
- const char *s = p,
- *s2 = p;
+ const char *s = p;
/* Set 'p' to end of arg string. marked by '\000' */
for (;;)
}
p--;
- while (s2 < p)
- if (*s2++ == '\\')
- {
- appendPQExpBufferChar(query, ESCAPE_STRING_SYNTAX);
- break;
- }
-
appendPQExpBufferChar(query, '\'');
while (s < p)
{
* bytea unconditionally doubles backslashes, so we suppress
* the doubling for standard_conforming_strings.
*/
- if (std_strings && *s == '\\')
+ if (fout->std_strings && *s == '\\' && s[1] == '\\')
s++;
appendPQExpBufferChar(query, *s++);
}
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "libpq-fe.h"
#include "pg_backup.h"
#include "pqexpbuffer.h"
+#include "mb/pg_wchar.h"
/* version string we expect back from pg_dump */
static void dumpCreateDB(PGconn *conn);
static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
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 dumpTimestamp(char *msg);
bool globals_only = false;
bool schema_only = false;
PGconn *conn;
+ int encoding;
+ const char *std_strings;
int c,
ret;
conn = connectDatabase("template1", pghost, pgport, pguser,
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");
if (verbose)
dumpTimestamp("Started on");
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) */
dumpRoles(conn);
if (!PQgetisnull(res, i, i_rolpassword))
{
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_rolcomment)) {
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, " OWNER %s", fmtId(spcowner));
appendPQExpBuffer(buf, " LOCATION ");
- appendStringLiteral(buf, spclocation, true, true);
+ appendStringLiteralConn(buf, spclocation, conn);
appendPQExpBuffer(buf, ";\n");
if (!skip_acls &&
if (spccomment && strlen(spccomment)) {
appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
- appendStringLiteral(buf, spccomment, true, true);
+ appendStringLiteralConn(buf, spccomment, conn);
appendPQExpBuffer(buf, ";\n");
}
appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
appendPQExpBuffer(buf, " ENCODING = ");
- appendStringLiteral(buf, dbencoding, true, true);
+ appendStringLiteralConn(buf, dbencoding, conn);
/* Output tablespace if it isn't default */
if (strcmp(dbtablespace, "pg_default") != 0)
if (strcmp(dbistemplate, "t") == 0)
{
appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
- appendStringLiteral(buf, dbname, true, true);
+ appendStringLiteralConn(buf, dbname, conn);
appendPQExpBuffer(buf, ";\n");
}
}
PGresult *res;
printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
- appendStringLiteral(buf, dbname, true, true);
+ appendStringLiteralConn(buf, dbname, conn);
appendPQExpBuffer(buf, ";");
res = executeQuery(conn, buf->data);
if (!PQgetisnull(res, 0, 0))
{
- makeAlterConfigCommand(PQgetvalue(res, 0, 0), "DATABASE", dbname);
+ makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
+ "DATABASE", dbname);
PQclear(res);
count++;
}
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);
+ appendStringLiteralConn(buf, username, conn);
res = executeQuery(conn, buf->data);
if (PQntuples(res) == 1 &&
!PQgetisnull(res, 0, 0))
{
- makeAlterConfigCommand(PQgetvalue(res, 0, 0), "ROLE", username);
+ makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
+ "ROLE", username);
PQclear(res);
count++;
}
* Helper function for dumpXXXConfig().
*/
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 *mine;
|| pg_strcasecmp(mine, "search_path") == 0)
appendPQExpBuffer(buf, "%s", pos + 1);
else
- appendStringLiteral(buf, pos + 1, false, true);
+ appendStringLiteralConn(buf, pos + 1, conn);
appendPQExpBuffer(buf, ";\n");
printf("%s", buf->data);
*
* 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 "describe.h"
-#include "libpq-fe.h"
-#include "pqexpbuffer.h"
+#include "dumputils.h"
#include "common.h"
#include "settings.h"
* Parse the pattern, converting quotes and lower-casing unquoted letters;
* we assume this was NOT done by scan_option. Also, adjust shell-style
* 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;
cp = pattern;
resetPQExpBuffer(&schemabuf);
appendPQExpBufferStr(&schemabuf, namebuf.data);
resetPQExpBuffer(&namebuf);
+ appendPQExpBufferChar(&namebuf, '^');
cp++;
}
else
*/
if ((inquotes || force_escape) &&
strchr("|*+?()[]{}.^$\\", *cp))
- appendPQExpBuffer(&namebuf, "\\\\");
-
- /* Ensure chars special to string literals are passed properly */
- if (SQL_STR_DOUBLE(*cp, true))
- appendPQExpBufferChar(&namebuf, *cp);
-
+ appendPQExpBufferChar(&namebuf, '\\');
i = PQmblen(cp, pset.encoding);
- while (i--)
+ while (i-- && *cp)
{
appendPQExpBufferChar(&namebuf, *cp);
cp++;
}
/*
- * 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) */
appendPQExpBufferChar(&namebuf, '$');
/* Optimize away ".*$", and possibly the whole pattern */
- if (namebuf.len >= 3 &&
+ if (namebuf.len >= 4 &&
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();
if (altnamevar)
- appendPQExpBuffer(buf,
- "(%s ~ '^%s'\n"
- " OR %s ~ '^%s')\n",
- namevar, namebuf.data,
- altnamevar, namebuf.data);
+ {
+ appendPQExpBuffer(buf, "(%s ~ ", namevar);
+ appendStringLiteralConn(buf, namebuf.data, pset.db);
+ appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
+ appendStringLiteralConn(buf, namebuf.data, pset.db);
+ appendPQExpBuffer(buf, ")\n");
+ }
else
- appendPQExpBuffer(buf,
- "%s ~ '^%s'\n",
- namevar, namebuf.data);
+ {
+ appendPQExpBuffer(buf, "%s ~ ", namevar);
+ 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 */
appendPQExpBufferChar(&schemabuf, '$');
/* Optimize away ".*$", and possibly the whole pattern */
- if (schemabuf.len >= 3 &&
+ if (schemabuf.len >= 4 &&
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();
- appendPQExpBuffer(buf, "%s ~ '^%s'\n",
- schemavar, schemabuf.data);
+ appendPQExpBuffer(buf, "%s ~ ", schemavar);
+ appendStringLiteralConn(buf, schemabuf.data, pset.db);
+ appendPQExpBufferChar(buf, '\n');
}
}
else
*
* 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 "large_obj.h"
PGresult *res;
Oid loid;
char oidbuf[32];
- unsigned int i;
bool own_transaction;
if (!start_lo_xact("\\lo_import", &own_transaction))
cmdbuf = malloc(slen * 2 + 256);
if (!cmdbuf)
return fail_lo_xact("\\lo_import", own_transaction);
- sprintf(cmdbuf,
- "COMMENT ON LARGE OBJECT %u IS ",
- loid);
+ sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid);
bufptr = cmdbuf + strlen(cmdbuf);
-
- 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];
- }
+ bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL);
strcpy(bufptr, "'");
if (!(res = PSQLexec(cmdbuf, false)))
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.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 $
*
*-------------------------------------------------------------------------
*/
if (comment)
{
+ conn = connectDatabase(dbname, host, port, username, password, progname);
+
printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
- appendStringLiteral(&sql, comment, false, true);
+ appendStringLiteralConn(&sql, comment, conn);
appendPQExpBuffer(&sql, ";\n");
- conn = connectDatabase(dbname, host, port, username, password, progname);
if (echo)
printf("%s", sql.data);
result = PQexec(conn, sql.data);
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.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 $
*
*-------------------------------------------------------------------------
*/
if (login == 0)
login = TRI_YES;
+ conn = connectDatabase("postgres", host, port, username, password, progname);
+
initPQExpBuffer(&sql);
printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
char *encrypted_password;
encrypted_password = PQencryptPassword(newpassword,
- newuser);
+ newuser);
if (!encrypted_password)
{
fprintf(stderr, _("Password encryption failed.\n"));
exit(1);
}
- appendStringLiteral(&sql, encrypted_password, false, true);
+ appendStringLiteralConn(&sql, encrypted_password, conn);
PQfreemem(encrypted_password);
}
else
- appendStringLiteral(&sql, newpassword, false, true);
+ appendStringLiteralConn(&sql, newpassword, conn);
}
if (superuser == TRI_YES)
appendPQExpBuffer(&sql, " SUPERUSER");
appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit);
appendPQExpBuffer(&sql, ";\n");
- conn = connectDatabase("postgres", host, port, username, password, progname);
-
if (echo)
printf("%s", sql.data);
result = PQexec(conn, sql.data);
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/c.h,v 1.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 $
*
*-------------------------------------------------------------------------
*/
#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.
+ * Support macros for escaping strings. escape_backslash should be TRUE
+ * if generating a non-standard-conforming string. Prefixing a string
+ * 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) \
- ((ch) == '\'' || ((escape_backslash) && (ch) == '\\'))
+ ((ch) == '\'' || ((ch) == '\\' && (escape_backslash)))
#define ESCAPE_STRING_SYNTAX 'E'
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
if (!IS_HIGHBIT_SET(c))
{
/* Apply quoting if needed */
- if (c == '\'' ||
- (c == '\\' && !std_strings))
+ if (SQL_STR_DOUBLE(c, !std_strings))
*target++ = c;
/* Copy the character */
*target++ = c;