1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * quote.c |
4 | * Functions for quoting identifiers and literals |
5 | * |
6 | * Portions Copyright (c) 2000-2019, 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 | |