]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/quote.c
Authentication improvements:
[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.7 2002/04/04 04:25:49 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                 *cp2++ = *cp1++;
128         }
129         *cp2++ = '"';
130
131         VARATT_SIZEP(result) = cp2 - ((char *) result);
132
133         return result;
134 }
135
136 /* Return a properly quoted literal value */
137 static text *
138 do_quote_literal(text *lptr)
139 {
140         text       *result;
141         char       *cp1;
142         char       *cp2;
143         int                     len;
144
145         len = VARSIZE(lptr) - VARHDRSZ;
146         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
147
148         cp1 = VARDATA(lptr);
149         cp2 = VARDATA(result);
150
151         *cp2++ = '\'';
152         while (len-- > 0)
153         {
154                 if (*cp1 == '\'')
155                         *cp2++ = '\'';
156                 if (*cp1 == '\\')
157                         *cp2++ = '\\';
158                 *cp2++ = *cp1++;
159         }
160         *cp2++ = '\'';
161
162         VARATT_SIZEP(result) = cp2 - ((char *) result);
163
164         return result;
165 }
166
167 #else
168
169 /* Check if a given identifier needs quoting (MULTIBYTE version) */
170 static bool
171 quote_ident_required(text *iptr)
172 {
173         char       *cp;
174         char       *ep;
175
176         cp = VARDATA(iptr);
177         ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
178
179         if (cp >= ep)
180                 return true;
181
182         if (pg_mblen(cp) != 1)
183                 return true;
184         if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
185                 return true;
186
187         while ((++cp) < ep)
188         {
189                 if (pg_mblen(cp) != 1)
190                         return true;
191
192                 if (*cp >= 'a' && *cp <= 'z')
193                         continue;
194                 if (*cp >= '0' && *cp <= '9')
195                         continue;
196                 if (*cp == '_')
197                         continue;
198
199                 return true;
200         }
201
202         return false;
203 }
204
205 /* Return a properly quoted identifier (MULTIBYTE version) */
206 static text *
207 do_quote_ident(text *iptr)
208 {
209         text       *result;
210         char       *cp1;
211         char       *cp2;
212         int                     len;
213         int                     wl;
214
215         len = VARSIZE(iptr) - VARHDRSZ;
216         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
217
218         cp1 = VARDATA(iptr);
219         cp2 = VARDATA(result);
220
221         *cp2++ = '"';
222         while (len > 0)
223         {
224                 if ((wl = pg_mblen(cp1)) != 1)
225                 {
226                         len -= wl;
227
228                         while (wl-- > 0)
229                                 *cp2++ = *cp1++;
230                         continue;
231                 }
232
233                 if (*cp1 == '"')
234                         *cp2++ = '"';
235                 *cp2++ = *cp1++;
236
237                 len--;
238         }
239         *cp2++ = '"';
240
241         VARATT_SIZEP(result) = cp2 - ((char *) result);
242
243         return result;
244 }
245
246 /* Return a properly quoted literal value (MULTIBYTE version) */
247 static text *
248 do_quote_literal(text *lptr)
249 {
250         text       *result;
251         char       *cp1;
252         char       *cp2;
253         int                     len;
254         int                     wl;
255
256         len = VARSIZE(lptr) - VARHDRSZ;
257         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
258
259         cp1 = VARDATA(lptr);
260         cp2 = VARDATA(result);
261
262         *cp2++ = '\'';
263         while (len > 0)
264         {
265                 if ((wl = pg_mblen(cp1)) != 1)
266                 {
267                         len -= wl;
268
269                         while (wl-- > 0)
270                                 *cp2++ = *cp1++;
271                         continue;
272                 }
273
274                 if (*cp1 == '\'')
275                         *cp2++ = '\'';
276                 if (*cp1 == '\\')
277                         *cp2++ = '\\';
278                 *cp2++ = *cp1++;
279
280                 len--;
281         }
282         *cp2++ = '\'';
283
284         VARATT_SIZEP(result) = cp2 - ((char *) result);
285
286         return result;
287 }
288
289 #endif