1 /*-------------------------------------------------------------------------
2  *
3  * quote.c
4  *	  Functions for quoting identifiers and literals
5  *
6  * Portions Copyright (c) 2000-2018, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  *	  src/backend/utils/adt/quote.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "utils/builtins.h"
17 
18 
19 /*
20  * quote_ident -
21  *	  returns a properly quoted identifier
22  */
23 Datum
24 quote_ident(PG_FUNCTION_ARGS)
25 {
26 	text	   *t = PG_GETARG_TEXT_PP(0);
27 	const char *qstr;
28 	char	   *str;
29 
30 	str = text_to_cstring(t);
31 	qstr = quote_identifier(str);
32 	PG_RETURN_TEXT_P(cstring_to_text(qstr));
33 }
34 
35 /*
36  * quote_literal_internal -
37  *	  helper function for quote_literal and quote_literal_cstr
38  *
39  * NOTE: think not to make this function's behavior change with
40  * standard_conforming_strings.  We don't know where the result
41  * literal will be used, and so we must generate a result that
42  * will work with either setting.  Take a look at what dblink
43  * uses this for before thinking you know better.
44  */
45 static size_t
46 quote_literal_internal(char *dst, const char *src, size_t len)
47 {
48 	const char *s;
49 	char	   *savedst = dst;
50 
51 	for (s = src; s < src + len; s++)
52 	{
53 		if (*s == '\\')
54 		{
55 			*dst++ = ESCAPE_STRING_SYNTAX;
56 			break;
57 		}
58 	}
59 
60 	*dst++ = '\'';
61 	while (len-- > 0)
62 	{
63 		if (SQL_STR_DOUBLE(*src, true))
64 			*dst++ = *src;
65 		*dst++ = *src++;
66 	}
67 	*dst++ = '\'';
68 
69 	return dst - savedst;
70 }
71 
72 /*
73  * quote_literal -
74  *	  returns a properly quoted literal
75  */
76 Datum
77 quote_literal(PG_FUNCTION_ARGS)
78 {
79 	text	   *t = PG_GETARG_TEXT_PP(0);
80 	text	   *result;
81 	char	   *cp1;
82 	char	   *cp2;
83 	int			len;
84 
85 	len = VARSIZE_ANY_EXHDR(t);
86 	/* We make a worst-case result area; wasting a little space is OK */
87 	result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
88 
89 	cp1 = VARDATA_ANY(t);
90 	cp2 = VARDATA(result);
91 
92 	SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
93 
94 	PG_RETURN_TEXT_P(result);
95 }
96 
97 /*
98  * quote_literal_cstr -
99  *	  returns a properly quoted literal
100  */
101 char *
102 quote_literal_cstr(const char *rawstr)
103 {
104 	char	   *result;
105 	int			len;
106 	int			newlen;
107 
108 	len = strlen(rawstr);
109 	/* We make a worst-case result area; wasting a little space is OK */
110 	result = palloc(len * 2 + 3 + 1);
111 
112 	newlen = quote_literal_internal(result, rawstr, len);
113 	result[newlen] = '\0';
114 
115 	return result;
116 }
117 
118 /*
119  * quote_nullable -
120  *	  Returns a properly quoted literal, with null values returned
121  *	  as the text string 'NULL'.
122  */
123 Datum
124 quote_nullable(PG_FUNCTION_ARGS)
125 {
126 	if (PG_ARGISNULL(0))
127 		PG_RETURN_TEXT_P(cstring_to_text("NULL"));
128 	else
129 		PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
130 											PG_GETARG_DATUM(0)));
131 }
132