diff options
author | Robert Haas <rhaas@postgresql.org> | 2010-11-20 10:04:48 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2010-11-20 10:04:48 -0500 |
commit | 4343c0e546b216ab38a3397a4f0f7476d557b352 (patch) | |
tree | 5a5676ac12ebe9f480851e2bb963ac1418c86921 | |
parent | e8bf683fbee935181e207d7171630194ed01f6a1 (diff) | |
download | postgresql-4343c0e546b216ab38a3397a4f0f7476d557b352.tar.gz postgresql-4343c0e546b216ab38a3397a4f0f7476d557b352.zip |
Expose quote_literal_cstr() from core.
This eliminates the need for inefficient implementions of this
functionality in both contrib/dblink and contrib/tablefunc, so remove
them. The upcoming patch implementing an in-core format() function
will also require this functionality.
In passing, add some regression tests.
-rw-r--r-- | contrib/dblink/dblink.c | 20 | ||||
-rw-r--r-- | contrib/tablefunc/tablefunc.c | 20 | ||||
-rw-r--r-- | src/backend/utils/adt/quote.c | 75 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/text.out | 18 | ||||
-rw-r--r-- | src/test/regress/sql/text.sql | 3 |
6 files changed, 75 insertions, 62 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index ce868292100..30f1b0eab02 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -91,7 +91,6 @@ static char **get_text_array_contents(ArrayType *array, int *numitems); static char *get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals); static char *get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals); static char *get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals); -static char *quote_literal_cstr(char *rawstr); static char *quote_ident_cstr(char *rawstr); static int get_attnum_pk_pos(int *pkattnums, int pknumatts, int key); static HeapTuple get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals); @@ -1894,25 +1893,6 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals } /* - * Return a properly quoted literal value. - * Uses quote_literal in quote.c - */ -static char * -quote_literal_cstr(char *rawstr) -{ - text *rawstr_text; - text *result_text; - char *result; - - rawstr_text = cstring_to_text(rawstr); - result_text = DatumGetTextP(DirectFunctionCall1(quote_literal, - PointerGetDatum(rawstr_text))); - result = text_to_cstring(result_text); - - return result; -} - -/* * Return a properly quoted identifier. * Uses quote_ident in quote.c */ diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c index ea2f2e15b0a..2e9ea1a626e 100644 --- a/contrib/tablefunc/tablefunc.c +++ b/contrib/tablefunc/tablefunc.c @@ -85,7 +85,6 @@ static Tuplestorestate *build_tuplestore_recursively(char *key_fld, MemoryContext per_query_ctx, AttInMetadata *attinmeta, Tuplestorestate *tupstore); -static char *quote_literal_cstr(char *rawstr); typedef struct { @@ -1564,22 +1563,3 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc) /* OK, the two tupdescs are compatible for our purposes */ return true; } - -/* - * Return a properly quoted literal value. - * Uses quote_literal in quote.c - */ -static char * -quote_literal_cstr(char *rawstr) -{ - text *rawstr_text; - text *result_text; - char *result; - - rawstr_text = cstring_to_text(rawstr); - result_text = DatumGetTextP(DirectFunctionCall1(quote_literal, - PointerGetDatum(rawstr_text))); - result = text_to_cstring(result_text); - - return result; -} diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c index 70e98cad84b..af07443f7df 100644 --- a/src/backend/utils/adt/quote.c +++ b/src/backend/utils/adt/quote.c @@ -33,8 +33,8 @@ quote_ident(PG_FUNCTION_ARGS) } /* - * quote_literal - - * returns a properly quoted literal + * quote_literal_internal - + * helper function for quote_literal and quote_literal_cstr * * NOTE: think not to make this function's behavior change with * standard_conforming_strings. We don't know where the result @@ -42,6 +42,37 @@ quote_ident(PG_FUNCTION_ARGS) * will work with either setting. Take a look at what dblink * uses this for before thinking you know better. */ +static size_t +quote_literal_internal(char *dst, char *src, size_t len) +{ + char *s; + char *savedst = dst; + + for (s = src; s < src + len; s++) + { + if (*s == '\\') + { + *dst++ = ESCAPE_STRING_SYNTAX; + break; + } + } + + *dst++ = '\''; + while (len-- > 0) + { + if (SQL_STR_DOUBLE(*src, true)) + *dst++ = *src; + *dst++ = *src++; + } + *dst++ = '\''; + + return dst - savedst; +} + +/* + * quote_literal - + * returns a properly quoted literal + */ Datum quote_literal(PG_FUNCTION_ARGS) { @@ -58,30 +89,30 @@ quote_literal(PG_FUNCTION_ARGS) cp1 = VARDATA(t); cp2 = VARDATA(result); - for (; len-- > 0; cp1++) - { - if (*cp1 == '\\') - { - *cp2++ = ESCAPE_STRING_SYNTAX; - break; - } - } + SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len)); - len = VARSIZE(t) - VARHDRSZ; - cp1 = VARDATA(t); + PG_RETURN_TEXT_P(result); +} - *cp2++ = '\''; - while (len-- > 0) - { - if (SQL_STR_DOUBLE(*cp1, true)) - *cp2++ = *cp1; - *cp2++ = *cp1++; - } - *cp2++ = '\''; +/* + * quote_literal_cstr - + * returns a properly quoted literal + */ +char * +quote_literal_cstr(char *rawstr) +{ + char *result; + int len; + int newlen; - SET_VARSIZE(result, cp2 - ((char *) result)); + len = strlen(rawstr); + /* We make a worst-case result area; wasting a little space is OK */ + result = palloc(len * 2 + 3); - PG_RETURN_TEXT_P(result); + newlen = quote_literal_internal(result, rawstr, len); + result[newlen] = '\0'; + + return result; } /* diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 7b1bb235383..ae267ab17ad 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -977,6 +977,7 @@ extern int32 type_maximum_size(Oid type_oid, int32 typemod); /* quote.c */ extern Datum quote_ident(PG_FUNCTION_ARGS); extern Datum quote_literal(PG_FUNCTION_ARGS); +extern char *quote_literal_cstr(char *rawstr); extern Datum quote_nullable(PG_FUNCTION_ARGS); /* guc.c */ diff --git a/src/test/regress/expected/text.out b/src/test/regress/expected/text.out index 84f4a5cda8b..0b0014a6e25 100644 --- a/src/test/regress/expected/text.out +++ b/src/test/regress/expected/text.out @@ -118,3 +118,21 @@ select i, left('ahoj', i), right('ahoj', i) from generate_series(-5, 5) t(i) ord 5 | ahoj | ahoj (11 rows) +select quote_literal(''); + quote_literal +--------------- + '' +(1 row) + +select quote_literal('abc'''); + quote_literal +--------------- + 'abc''' +(1 row) + +select quote_literal(e'\\'); + quote_literal +--------------- + E'\\' +(1 row) + diff --git a/src/test/regress/sql/text.sql b/src/test/regress/sql/text.sql index a8768ee81aa..50c3033d9eb 100644 --- a/src/test/regress/sql/text.sql +++ b/src/test/regress/sql/text.sql @@ -41,3 +41,6 @@ select concat_ws('',10,20,null,30); select concat_ws(NULL,10,20,null,30) is null; select reverse('abcde'); select i, left('ahoj', i), right('ahoj', i) from generate_series(-5, 5) t(i) order by i; +select quote_literal(''); +select quote_literal('abc'''); +select quote_literal(e'\\'); |