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 4372 : quote_ident(PG_FUNCTION_ARGS)
26 : {
27 4372 : text *t = PG_GETARG_TEXT_PP(0);
28 : const char *qstr;
29 : char *str;
30 :
31 4372 : str = text_to_cstring(t);
32 4372 : qstr = quote_identifier(str);
33 4372 : PG_RETURN_TEXT_P(cstring_to_text(qstr));
34 : }
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 4793 : quote_literal_internal(char *dst, const char *src, size_t len)
46 : {
47 : const char *s;
48 4793 : char *savedst = dst;
49 :
50 350422 : for (s = src; s < src + len; s++)
51 : {
52 345634 : if (*s == '\\')
53 : {
54 5 : *dst++ = ESCAPE_STRING_SYNTAX;
55 5 : break;
56 : }
57 : }
58 :
59 4793 : *dst++ = '\'';
60 350429 : while (len-- > 0)
61 : {
62 345636 : if (SQL_STR_DOUBLE(*src, true))
63 24 : *dst++ = *src;
64 345636 : *dst++ = *src++;
65 : }
66 4793 : *dst++ = '\'';
67 :
68 4793 : return dst - savedst;
69 : }
70 :
71 : /*
72 : * quote_literal -
73 : * returns a properly quoted literal
74 : */
75 : Datum
76 1769 : quote_literal(PG_FUNCTION_ARGS)
77 : {
78 1769 : text *t = PG_GETARG_TEXT_PP(0);
79 : text *result;
80 : char *cp1;
81 : char *cp2;
82 : int len;
83 :
84 1769 : len = VARSIZE_ANY_EXHDR(t);
85 : /* We make a worst-case result area; wasting a little space is OK */
86 1769 : result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
87 :
88 1769 : cp1 = VARDATA_ANY(t);
89 1769 : cp2 = VARDATA(result);
90 :
91 1769 : SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
92 :
93 1769 : PG_RETURN_TEXT_P(result);
94 : }
95 :
96 : /*
97 : * quote_literal_cstr -
98 : * returns a properly quoted literal
99 : */
100 : char *
101 3024 : quote_literal_cstr(const char *rawstr)
102 : {
103 : char *result;
104 : int len;
105 : int newlen;
106 :
107 3024 : len = strlen(rawstr);
108 : /* We make a worst-case result area; wasting a little space is OK */
109 3024 : result = palloc(
110 : (len * 2) /* doubling for every character if each one is
111 : * a quote */
112 : + 3 /* two outer quotes + possibly 'E' if needed */
113 3024 : + 1 /* null terminator */
114 : );
115 :
116 3024 : newlen = quote_literal_internal(result, rawstr, len);
117 3024 : result[newlen] = '\0';
118 :
119 3024 : return result;
120 : }
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 790 : quote_nullable(PG_FUNCTION_ARGS)
129 : {
130 790 : if (PG_ARGISNULL(0))
131 42 : PG_RETURN_TEXT_P(cstring_to_text("NULL"));
132 : else
133 748 : PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
134 : PG_GETARG_DATUM(0)));
135 : }
|