aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2010-11-20 10:04:48 -0500
committerRobert Haas <rhaas@postgresql.org>2010-11-20 10:04:48 -0500
commit4343c0e546b216ab38a3397a4f0f7476d557b352 (patch)
tree5a5676ac12ebe9f480851e2bb963ac1418c86921
parente8bf683fbee935181e207d7171630194ed01f6a1 (diff)
downloadpostgresql-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.c20
-rw-r--r--contrib/tablefunc/tablefunc.c20
-rw-r--r--src/backend/utils/adt/quote.c75
-rw-r--r--src/include/utils/builtins.h1
-rw-r--r--src/test/regress/expected/text.out18
-rw-r--r--src/test/regress/sql/text.sql3
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'\\');