* quote.c
* Functions for quoting identifiers and literals
*
- * Portions Copyright (c) 2000-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2000-2017, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.19 2006/05/26 23:48:54 momjian Exp $
+ * src/backend/utils/adt/quote.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "utils/builtins.h"
-#include "parser/gramparse.h"
/*
Datum
quote_ident(PG_FUNCTION_ARGS)
{
- text *t = PG_GETARG_TEXT_P(0);
- text *result;
+ text *t = PG_GETARG_TEXT_PP(0);
const char *qstr;
char *str;
- int len;
-
- /* We have to convert to a C string to use quote_identifier */
- len = VARSIZE(t) - VARHDRSZ;
- str = (char *) palloc(len + 1);
- memcpy(str, VARDATA(t), len);
- str[len] = '\0';
+ str = text_to_cstring(t);
qstr = quote_identifier(str);
+ PG_RETURN_TEXT_P(cstring_to_text(qstr));
+}
- len = strlen(qstr);
- result = (text *) palloc(len + VARHDRSZ);
- VARATT_SIZEP(result) = len + VARHDRSZ;
- memcpy(VARDATA(result), qstr, len);
+/*
+ * 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
+ * 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.
+ */
+static size_t
+quote_literal_internal(char *dst, const char *src, size_t len)
+{
+ const char *s;
+ char *savedst = dst;
- PG_RETURN_TEXT_P(result);
+ 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;
}
/*
Datum
quote_literal(PG_FUNCTION_ARGS)
{
- text *t = PG_GETARG_TEXT_P(0);
+ text *t = PG_GETARG_TEXT_PP(0);
text *result;
char *cp1;
char *cp2;
int len;
- len = VARSIZE(t) - VARHDRSZ;
+ len = VARSIZE_ANY_EXHDR(t);
/* We make a worst-case result area; wasting a little space is OK */
result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
- cp1 = VARDATA(t);
+ cp1 = VARDATA_ANY(t);
cp2 = VARDATA(result);
- if (!standard_conforming_strings)
- 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))
- *cp2++ = *cp1;
- *cp2++ = *cp1++;
- }
- *cp2++ = '\'';
-
- VARATT_SIZEP(result) = cp2 - ((char *) result);
+ SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
PG_RETURN_TEXT_P(result);
}
+
+/*
+ * quote_literal_cstr -
+ * returns a properly quoted literal
+ */
+char *
+quote_literal_cstr(const char *rawstr)
+{
+ char *result;
+ int len;
+ int newlen;
+
+ len = strlen(rawstr);
+ /* We make a worst-case result area; wasting a little space is OK */
+ result = palloc(len * 2 + 3 + 1);
+
+ newlen = quote_literal_internal(result, rawstr, len);
+ result[newlen] = '\0';
+
+ return result;
+}
+
+/*
+ * quote_nullable -
+ * Returns a properly quoted literal, with null values returned
+ * as the text string 'NULL'.
+ */
+Datum
+quote_nullable(PG_FUNCTION_ARGS)
+{
+ if (PG_ARGISNULL(0))
+ PG_RETURN_TEXT_P(cstring_to_text("NULL"));
+ else
+ PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
+ PG_GETARG_DATUM(0)));
+}