From 74b49a81294b2943179078272bc3413b33d16e6f Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 2 Jul 2005 17:01:59 +0000 Subject: [PATCH] Add E'' to internally created SQL strings that contain backslashes. Improve code clarity by using macros for E'' processing. --- src/backend/utils/adt/quote.c | 20 +++++++++++------- src/backend/utils/adt/ruleutils.c | 25 +++++++++++++++-------- src/bin/initdb/initdb.c | 6 +++--- src/bin/pg_dump/dumputils.c | 29 +++++++++++---------------- src/bin/pg_dump/pg_dump.c | 7 +++---- src/bin/psql/describe.c | 6 +++--- src/bin/psql/large_obj.c | 12 +++++++---- src/include/c.h | 4 +++- src/interfaces/ecpg/ecpglib/execute.c | 17 +++++----------- src/interfaces/ecpg/preproc/preproc.y | 17 ++++++++++------ src/interfaces/libpq/fe-exec.c | 24 +++++----------------- src/pl/plpgsql/src/gram.y | 13 +++++++----- 12 files changed, 91 insertions(+), 89 deletions(-) diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c index 8650a0d2e8..808ae6142e 100644 --- a/src/backend/utils/adt/quote.c +++ b/src/backend/utils/adt/quote.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.15 2005/03/21 16:29:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.16 2005/07/02 17:01:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -60,19 +60,25 @@ quote_literal(PG_FUNCTION_ARGS) len = VARSIZE(t) - VARHDRSZ; /* We make a worst-case result area; wasting a little space is OK */ - result = (text *) palloc(len * 2 + 2 + VARHDRSZ); + result = (text *) palloc(len * 2 + 3 + VARHDRSZ); cp1 = VARDATA(t); cp2 = VARDATA(result); + for(; len-- > 0; cp1++) + if (*cp1 == '\\') + { + *cp2++ = ESCAPE_STRING_SYNTAX; + break; + } + + len = VARSIZE(t) - VARHDRSZ; + cp1 = VARDATA(t); *cp2++ = '\''; while (len-- > 0) { - if (*cp1 == '\'') - *cp2++ = '\''; - else if (*cp1 == '\\') - *cp2++ = '\\'; - + if (SQL_STR_DOUBLE(*cp1)) + *cp2++ = *cp1; *cp2++ = *cp1++; } *cp2++ = '\''; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index cbebd5495c..0943c71f42 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.202 2005/06/28 05:09:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.203 2005/07/02 17:01:50 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -564,12 +564,14 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) { if (i > 0) appendStringInfo(&buf, ", "); + if (strchr(p, '\\') != NULL) + appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX); appendStringInfoChar(&buf, '\''); + while (*p) { - /* escape quotes and backslashes */ - if (*p == '\'' || *p == '\\') - appendStringInfoChar(&buf, '\\'); + if (SQL_STR_DOUBLE(*p)) + appendStringInfoChar(&buf, *p); appendStringInfoChar(&buf, *p++); } p++; @@ -3869,22 +3871,29 @@ get_const_expr(Const *constval, deparse_context *context) break; default: - /* * We must quote any funny characters in the constant's * representation. XXX Any MULTIBYTE considerations here? */ + for (valptr = extval; *valptr; valptr++) + if (*valptr == '\\' || + (unsigned char)*valptr < (unsigned char)' ') + { + appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX); + break; + } + appendStringInfoChar(buf, '\''); for (valptr = extval; *valptr; valptr++) { char ch = *valptr; - if (ch == '\'' || ch == '\\') + if (SQL_STR_DOUBLE(ch)) { - appendStringInfoChar(buf, '\\'); + appendStringInfoChar(buf, ch); appendStringInfoChar(buf, ch); } - else if (((unsigned char) ch) < ((unsigned char) ' ')) + else if ((unsigned char)ch < (unsigned char)' ') appendStringInfo(buf, "\\%03o", (int) ch); else appendStringInfoChar(buf, ch); diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 250b2563a7..b61c56d721 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions taken from FreeBSD. * - * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.89 2005/07/01 17:40:28 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.90 2005/07/02 17:01:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1986,8 +1986,8 @@ escape_quotes(const char *src) for (i = 0, j = 0; i < len; i++) { - if (src[i] == '\\' || src[i] == '\'') - result[j++] = src[i]; /* double these */ + if (SQL_STR_DOUBLE(src[i])) + result[j++] = src[i]; result[j++] = src[i]; } result[j] = '\0'; diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index b1622d55ae..267a8573ac 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.18 2005/07/01 21:03:25 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.19 2005/07/02 17:01:51 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -111,38 +111,33 @@ fmtId(const char *rawid) void appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll) { - bool has_escapes = false; - const char *str2 = str; + char ch; + const char *p; - while (*str2) + for (p = str; *p; p++) { - char ch = *str2++; - + ch = *p; if (ch == '\\' || - ((unsigned char) ch < (unsigned char) ' ' && + ((unsigned char)ch < (unsigned char)' ' && (escapeAll || (ch != '\t' && ch != '\n' && ch != '\v' && ch != '\f' && ch != '\r')))) { - has_escapes = true; + appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); break; } } - if (has_escapes) - appendPQExpBufferChar(buf, 'E'); - appendPQExpBufferChar(buf, '\''); - while (*str) + for (p = str; *p; p++) { - char ch = *str++; - - if (ch == '\\' || ch == '\'') + ch = *p; + if (SQL_STR_DOUBLE(ch)) { - appendPQExpBufferChar(buf, ch); /* double these */ + appendPQExpBufferChar(buf, ch); appendPQExpBufferChar(buf, ch); } - else if ((unsigned char) ch < (unsigned char) ' ' && + else if ((unsigned char)ch < (unsigned char)' ' && (escapeAll || (ch != '\t' && ch != '\n' && ch != '\v' && ch != '\f' && ch != '\r'))) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 7708083f35..86ca52a924 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.412 2005/07/01 21:03:25 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.413 2005/07/02 17:01:51 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -7792,18 +7792,17 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) } p--; - /* do we need E''? */ while (s2 < p) if (*s2++ == '\\') { - appendPQExpBufferChar(query, 'E'); + appendPQExpBufferChar(query, ESCAPE_STRING_SYNTAX); break; } appendPQExpBufferChar(query, '\''); while (s < p) { - if (*s == '\'') + if (*s == '\'') /* bytea already doubles backslashes */ appendPQExpBufferChar(query, '\''); appendPQExpBufferChar(query, *s++); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 49553268c6..603c709022 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.119 2005/07/01 17:40:28 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.120 2005/07/02 17:01:52 momjian Exp $ */ #include "postgres_fe.h" #include "describe.h" @@ -1898,8 +1898,8 @@ processNamePattern(PQExpBuffer buf, const char *pattern, appendPQExpBuffer(&namebuf, "\\\\"); /* Ensure chars special to string literals are passed properly */ - if (*cp == '\'' || *cp == '\\') - appendPQExpBufferChar(&namebuf, *cp); /* double these */ + if (SQL_STR_DOUBLE(*cp)) + appendPQExpBufferChar(&namebuf, *cp); i = PQmblen(cp, pset.encoding); while (i--) diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index f7f9b2fd25..8bdcdc3682 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.38 2005/07/01 17:40:28 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.39 2005/07/02 17:01:52 momjian Exp $ */ #include "postgres_fe.h" #include "large_obj.h" @@ -172,13 +172,17 @@ do_lo_import(const char *filename_arg, const char *comment_arg) if (!cmdbuf) return fail_lo_xact("\\lo_import", own_transaction); sprintf(cmdbuf, - "COMMENT ON LARGE OBJECT %u IS '", + "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 (comment_arg[i] == '\'' || comment_arg[i] == '\\') - *bufptr++ = comment_arg[i]; /* double these */ + if (SQL_STR_DOUBLE(comment_arg[i])) + *bufptr++ = comment_arg[i]; *bufptr++ = comment_arg[i]; } strcpy(bufptr, "'"); diff --git a/src/include/c.h b/src/include/c.h index 202e45271e..4567e2102d 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/c.h,v 1.186 2005/06/28 05:09:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/c.h,v 1.187 2005/07/02 17:01:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -479,6 +479,8 @@ typedef NameData *Name; #define NameStr(name) ((name).data) +#define SQL_STR_DOUBLE(ch) ((ch) == '\'' || (ch) == '\\') +#define ESCAPE_STRING_SYNTAX 'E' /* ---------------------------------------------------------------- * Section 4: IsValid macros for system types diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index c585a81b58..e1e8a43f4f 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.40 2005/06/02 12:35:11 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.41 2005/07/02 17:01:53 momjian Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -45,21 +45,14 @@ quote_postgres(char *arg, int lineno) if (!res) return (res); + if (strchr(arg, '\\') != NULL) + res[ri++] = ESCAPE_STRING_SYNTAX; res[ri++] = '\''; for (i = 0; arg[i]; i++, ri++) { - switch (arg[i]) - { - case '\'': - res[ri++] = '\''; - break; - case '\\': - res[ri++] = '\\'; - break; - default: - ; - } + if (SQL_STR_DOUBLE(arg[i])) + res[ri++] = arg[i]; res[ri] = arg[i]; } diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 0dba4251a0..e0cadf8784 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.307 2005/02/10 08:06:35 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.308 2005/07/02 17:01:53 momjian Exp $ */ /* Copyright comment */ %{ @@ -4216,11 +4216,16 @@ Bconst: BCONST { $$ = make_name();}; Xconst: XCONST { $$ = make_name();}; Sconst: SCONST { - $$ = (char *)mm_alloc(strlen($1) + 3); - $$[0]='\''; - strcpy($$+1, $1); - $$[strlen($1)+2]='\0'; - $$[strlen($1)+1]='\''; + char *ret; + + $$ = ret = (char *)mm_alloc(strlen($1) + 4); + if (strchr($1, '\\') != NULL) + *ret++ = ESCAPE_STRING_SYNTAX; + *ret++ = '\''; + strcpy(ret, $1); + ret += strlen($1); + *ret++ = '\''; + *ret++ = '\0'; free($1); } ; diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 64ef9cd428..64b4638b69 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.169 2005/06/12 00:00:21 neilc Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.170 2005/07/02 17:01:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2368,23 +2368,9 @@ PQescapeString(char *to, const char *from, size_t length) while (remaining > 0 && *source != '\0') { - switch (*source) - { - case '\\': - *target++ = '\\'; - *target++ = '\\'; - break; - - case '\'': - *target++ = '\''; - *target++ = '\''; - break; - - default: - *target++ = *source; - break; - } - source++; + if (SQL_STR_DOUBLE(*source)) + *target++ = *source; + *target++ = *source++; remaining--; } @@ -2449,7 +2435,7 @@ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen) } else if (*vp == '\'') { - rp[0] = '\\'; + rp[0] = '\''; rp[1] = '\''; rp += 2; } diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 6209d2d9dd..e210d9e803 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.79 2005/07/02 08:59:47 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.80 2005/07/02 17:01:59 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -389,13 +389,16 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval curname_def = palloc0(sizeof(PLpgSQL_expr)); curname_def->dtype = PLPGSQL_DTYPE_EXPR; - strcpy(buf, "SELECT '"); + strcpy(buf, "SELECT "); cp1 = new->refname; cp2 = buf + strlen(buf); - while (*cp1 != '\0') + if (strchr(cp1, '\\') != NULL) + *cp2++ = ESCAPE_STRING_SYNTAX; + *cp2++ = '\''; + while (*cp1) { - if (*cp1 == '\\' || *cp1 == '\'') - *cp2++ = *cp1; /* double these */ + if (SQL_STR_DOUBLE(*cp1)) + *cp2++ = *cp1; *cp2++ = *cp1++; } strcpy(cp2, "'::refcursor");