]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/quote.c
Update copyright to 2004.
[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-2004, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  *        $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.13 2004/08/29 04:12:52 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <ctype.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  * Check if a given identifier needs quoting
69  */
70 static bool
71 quote_ident_required(text *iptr)
72 {
73         char       *cp;
74         char       *ep;
75
76         cp = VARDATA(iptr);
77         ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
78
79         if (cp >= ep)
80                 return true;
81
82         if (pg_mblen(cp) != 1)
83                 return true;
84         if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
85                 return true;
86
87         while ((++cp) < ep)
88         {
89                 if (pg_mblen(cp) != 1)
90                         return true;
91
92                 if (*cp >= 'a' && *cp <= 'z')
93                         continue;
94                 if (*cp >= '0' && *cp <= '9')
95                         continue;
96                 if (*cp == '_')
97                         continue;
98
99                 return true;
100         }
101
102         return false;
103 }
104
105 /*
106  * Return a properly quoted identifier
107  */
108 static text *
109 do_quote_ident(text *iptr)
110 {
111         text       *result;
112         char       *cp1;
113         char       *cp2;
114         int                     len;
115         int                     wl;
116
117         len = VARSIZE(iptr) - VARHDRSZ;
118         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
119
120         cp1 = VARDATA(iptr);
121         cp2 = VARDATA(result);
122
123         *cp2++ = '"';
124         while (len > 0)
125         {
126                 if ((wl = pg_mblen(cp1)) != 1)
127                 {
128                         len -= wl;
129
130                         while (wl-- > 0)
131                                 *cp2++ = *cp1++;
132                         continue;
133                 }
134
135                 if (*cp1 == '"')
136                         *cp2++ = '"';
137                 *cp2++ = *cp1++;
138
139                 len--;
140         }
141         *cp2++ = '"';
142
143         VARATT_SIZEP(result) = cp2 - ((char *) result);
144
145         return result;
146 }
147
148 /*
149  * Return a properly quoted literal value
150  */
151 static text *
152 do_quote_literal(text *lptr)
153 {
154         text       *result;
155         char       *cp1;
156         char       *cp2;
157         int                     len;
158         int                     wl;
159
160         len = VARSIZE(lptr) - VARHDRSZ;
161         result = (text *) palloc(len * 2 + VARHDRSZ + 2);
162
163         cp1 = VARDATA(lptr);
164         cp2 = VARDATA(result);
165
166         *cp2++ = '\'';
167         while (len > 0)
168         {
169                 if ((wl = pg_mblen(cp1)) != 1)
170                 {
171                         len -= wl;
172
173                         while (wl-- > 0)
174                                 *cp2++ = *cp1++;
175                         continue;
176                 }
177
178                 if (*cp1 == '\'')
179                         *cp2++ = '\'';
180                 if (*cp1 == '\\')
181                         *cp2++ = '\\';
182                 *cp2++ = *cp1++;
183
184                 len--;
185         }
186         *cp2++ = '\'';
187
188         VARATT_SIZEP(result) = cp2 - ((char *) result);
189
190         return result;
191 }