]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/quote.c
pgindent run on all C files. Java run to follow. initdb/regression
[postgresql] / src / backend / utils / adt / quote.c
1 /*-------------------------------------------------------------------------
2  *
3  * quote.c
4  *        Functions for quoting identifiers and literals
5  *
6  * Portions Copyright (c) 2000, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.5 2001/10/25 05:49:45 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <ctype.h>
15
16 #include "postgres.h"
17
18 #include "mb/pg_wchar.h"
19 #include "utils/builtins.h"
20
21
22 static bool quote_ident_required(text *iptr);
23 static text *do_quote_ident(text *iptr);
24 static text *do_quote_literal(text *iptr);
25
26
27 /*
28  * quote_ident -
29  *        returns a properly quoted identifier
30  */
31 Datum
32 quote_ident(PG_FUNCTION_ARGS)
33 {
34         text       *t = PG_GETARG_TEXT_P(0);
35         text       *result;
36
37         if (quote_ident_required(t))
38                 result = do_quote_ident(t);
39         else
40         {
41                 result = (text *) palloc(VARSIZE(t));
42                 memcpy(result, t, VARSIZE(t));
43         }
44
45         PG_FREE_IF_COPY(t, 0);
46
47         PG_RETURN_TEXT_P(result);
48 }
49
50 /*
51  * quote_literal -
52  *        returns a properly quoted literal
53  */
54 Datum
55 quote_literal(PG_FUNCTION_ARGS)
56 {
57         text       *t = PG_GETARG_TEXT_P(0);
58         text       *result;
59
60         result = do_quote_literal(t);
61
62         PG_FREE_IF_COPY(t, 0);
63
64         PG_RETURN_TEXT_P(result);
65 }
66
67
68 /*
69  * MULTIBYTE dependant internal functions follow
70  *
71  */
72
73
74 #ifndef MULTIBYTE
75
76 /* Check if a given identifier needs quoting */
77 static bool
78 quote_ident_required(text *iptr)
79 {
80         char       *cp;
81         char       *ep;
82
83         cp = VARDATA(iptr);
84         ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
85
86         if (cp >= ep)
87                 return true;
88
89         if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
90                 return true;
91
92         while ((++cp) < ep)
93         {
94                 if (*cp >= 'a' && *cp <= 'z')
95                         continue;
96                 if (*cp >= '0' && *cp <= '9')
97                         continue;
98                 if (*cp == '_')
99                         continue;
100
101                 return true;
102         }
103
104         return false;
105 }
106
107 /* Return a properly quoted identifier */
108 static text *
109 do_quote_ident(text *iptr)
110 {
111         text       *result;
112         char       *cp1;
113         char       *cp2;
114         int                     len;
115
116         len = VARSIZE(iptr) - VARHDRSZ;
117         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
118
119         cp1 = VARDATA(iptr);
120         cp2 = VARDATA(result);
121
122         *cp2++ = '"';
123         while (len-- > 0)
124         {
125                 if (*cp1 == '"')
126                         *cp2++ = '"';
127                 if (*cp1 == '\\')
128                         *cp2++ = '\\';
129                 *cp2++ = *cp1++;
130         }
131         *cp2++ = '"';
132
133         VARATT_SIZEP(result) = cp2 - ((char *) result);
134
135         return result;
136 }
137
138 /* Return a properly quoted literal value */
139 static text *
140 do_quote_literal(text *lptr)
141 {
142         text       *result;
143         char       *cp1;
144         char       *cp2;
145         int                     len;
146
147         len = VARSIZE(lptr) - VARHDRSZ;
148         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
149
150         cp1 = VARDATA(lptr);
151         cp2 = VARDATA(result);
152
153         *cp2++ = '\'';
154         while (len-- > 0)
155         {
156                 if (*cp1 == '\'')
157                         *cp2++ = '\'';
158                 if (*cp1 == '\\')
159                         *cp2++ = '\\';
160                 *cp2++ = *cp1++;
161         }
162         *cp2++ = '\'';
163
164         VARATT_SIZEP(result) = cp2 - ((char *) result);
165
166         return result;
167 }
168
169 #else
170
171 /* Check if a given identifier needs quoting (MULTIBYTE version) */
172 static bool
173 quote_ident_required(text *iptr)
174 {
175         char       *cp;
176         char       *ep;
177
178         cp = VARDATA(iptr);
179         ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
180
181         if (cp >= ep)
182                 return true;
183
184         if (pg_mblen(cp) != 1)
185                 return true;
186         if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
187                 return true;
188
189         while ((++cp) < ep)
190         {
191                 if (pg_mblen(cp) != 1)
192                         return true;
193
194                 if (*cp >= 'a' && *cp <= 'z')
195                         continue;
196                 if (*cp >= '0' && *cp <= '9')
197                         continue;
198                 if (*cp == '_')
199                         continue;
200
201                 return true;
202         }
203
204         return false;
205 }
206
207 /* Return a properly quoted identifier (MULTIBYTE version) */
208 static text *
209 do_quote_ident(text *iptr)
210 {
211         text       *result;
212         char       *cp1;
213         char       *cp2;
214         int                     len;
215         int                     wl;
216
217         len = VARSIZE(iptr) - VARHDRSZ;
218         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
219
220         cp1 = VARDATA(iptr);
221         cp2 = VARDATA(result);
222
223         *cp2++ = '"';
224         while (len > 0)
225         {
226                 if ((wl = pg_mblen(cp1)) != 1)
227                 {
228                         len -= wl;
229
230                         while (wl-- > 0)
231                                 *cp2++ = *cp1++;
232                         continue;
233                 }
234
235                 if (*cp1 == '"')
236                         *cp2++ = '"';
237                 if (*cp1 == '\\')
238                         *cp2++ = '\\';
239                 *cp2++ = *cp1++;
240
241                 len--;
242         }
243         *cp2++ = '"';
244
245         VARATT_SIZEP(result) = cp2 - ((char *) result);
246
247         return result;
248 }
249
250 /* Return a properly quoted literal value (MULTIBYTE version) */
251 static text *
252 do_quote_literal(text *lptr)
253 {
254         text       *result;
255         char       *cp1;
256         char       *cp2;
257         int                     len;
258         int                     wl;
259
260         len = VARSIZE(lptr) - VARHDRSZ;
261         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
262
263         cp1 = VARDATA(lptr);
264         cp2 = VARDATA(result);
265
266         *cp2++ = '\'';
267         while (len > 0)
268         {
269                 if ((wl = pg_mblen(cp1)) != 1)
270                 {
271                         len -= wl;
272
273                         while (wl-- > 0)
274                                 *cp2++ = *cp1++;
275                         continue;
276                 }
277
278                 if (*cp1 == '\'')
279                         *cp2++ = '\'';
280                 if (*cp1 == '\\')
281                         *cp2++ = '\\';
282                 *cp2++ = *cp1++;
283
284                 len--;
285         }
286         *cp2++ = '\'';
287
288         VARATT_SIZEP(result) = cp2 - ((char *) result);
289
290         return result;
291 }
292 #endif