Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * quote.c
4 : : * Functions for quoting identifiers and literals
5 : : *
6 : : * Portions Copyright (c) 2000-2026, 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 : : #include "varatt.h"
18 : :
19 : :
20 : : /*
21 : : * quote_ident -
22 : : * returns a properly quoted identifier
23 : : */
24 : : Datum
25 : 1111 : quote_ident(PG_FUNCTION_ARGS)
26 : : {
27 : 1111 : text *t = PG_GETARG_TEXT_PP(0);
28 : 1111 : const char *qstr;
29 : 1111 : char *str;
30 : :
31 : 1111 : str = text_to_cstring(t);
32 : 1111 : qstr = quote_identifier(str);
33 : 2222 : PG_RETURN_TEXT_P(cstring_to_text(qstr));
34 : 1111 : }
35 : :
36 : : /*
37 : : * quote_literal_internal -
38 : : * helper function for quote_literal and quote_literal_cstr
39 : : *
40 : : * NOTE: This must produce output that will work in old servers with
41 : : * standard_conforming_strings = off. It's used for example by
42 : : * dblink, which may send the result to another server.
43 : : */
44 : : static size_t
45 : 0 : quote_literal_internal(char *dst, const char *src, size_t len)
46 : : {
47 : 0 : const char *s;
48 : 0 : char *savedst = dst;
49 : :
50 [ # # ]: 0 : for (s = src; s < src + len; s++)
51 : : {
52 [ # # ]: 0 : if (*s == '\\')
53 : : {
54 : 0 : *dst++ = ESCAPE_STRING_SYNTAX;
55 : 0 : break;
56 : : }
57 : 0 : }
58 : :
59 : 0 : *dst++ = '\'';
60 [ # # ]: 0 : while (len-- > 0)
61 : : {
62 [ # # # # ]: 0 : if (SQL_STR_DOUBLE(*src, true))
63 : 0 : *dst++ = *src;
64 : 0 : *dst++ = *src++;
65 : : }
66 : 0 : *dst++ = '\'';
67 : :
68 : 0 : return dst - savedst;
69 : 0 : }
70 : :
71 : : /*
72 : : * quote_literal -
73 : : * returns a properly quoted literal
74 : : */
75 : : Datum
76 : 0 : quote_literal(PG_FUNCTION_ARGS)
77 : : {
78 : 0 : text *t = PG_GETARG_TEXT_PP(0);
79 : 0 : text *result;
80 : 0 : char *cp1;
81 : 0 : char *cp2;
82 : 0 : int len;
83 : :
84 : 0 : len = VARSIZE_ANY_EXHDR(t);
85 : : /* We make a worst-case result area; wasting a little space is OK */
86 : 0 : result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
87 : :
88 : 0 : cp1 = VARDATA_ANY(t);
89 : 0 : cp2 = VARDATA(result);
90 : :
91 : 0 : SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
92 : :
93 : 0 : PG_RETURN_TEXT_P(result);
94 : 0 : }
95 : :
96 : : /*
97 : : * quote_literal_cstr -
98 : : * returns a properly quoted literal
99 : : */
100 : : char *
101 : 0 : quote_literal_cstr(const char *rawstr)
102 : : {
103 : 0 : char *result;
104 : 0 : int len;
105 : 0 : int newlen;
106 : :
107 : 0 : len = strlen(rawstr);
108 : : /* We make a worst-case result area; wasting a little space is OK */
109 : 0 : result = palloc(
110 : 0 : (len * 2) /* doubling for every character if each one is
111 : : * a quote */
112 : 0 : + 3 /* two outer quotes + possibly 'E' if needed */
113 : 0 : + 1 /* null terminator */
114 : : );
115 : :
116 : 0 : newlen = quote_literal_internal(result, rawstr, len);
117 : 0 : result[newlen] = '\0';
118 : :
119 : 0 : return result;
120 : 0 : }
121 : :
122 : : /*
123 : : * quote_nullable -
124 : : * Returns a properly quoted literal, with null values returned
125 : : * as the text string 'NULL'.
126 : : */
127 : : Datum
128 : 0 : quote_nullable(PG_FUNCTION_ARGS)
129 : : {
130 [ # # ]: 0 : if (PG_ARGISNULL(0))
131 : 0 : PG_RETURN_TEXT_P(cstring_to_text("NULL"));
132 : : else
133 : 0 : PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
134 : : PG_GETARG_DATUM(0)));
135 : 0 : }
|