Skip to content

Commit daf1e3a

Browse files
Jan WieckJan Wieck
authored andcommitted
Added functions
quote_ident(text) returns text quote_literal(text) returns text These are handy to build up properly quoted query strings for the new PL/pgSQL EXECUTE functionality to submit dynamic DDL statements. Jan
1 parent d7f1e11 commit daf1e3a

File tree

4 files changed

+304
-4
lines changed

4 files changed

+304
-4
lines changed

src/backend/utils/adt/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# Makefile for utils/adt
33
#
4-
# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.45 2000/08/31 16:10:45 petere Exp $
4+
# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.46 2000/09/05 20:25:12 wieck Exp $
55
#
66

77
subdir = src/backend/utils/adt
@@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o \
2424
tid.o timestamp.o varbit.o varchar.o varlena.o version.o \
2525
network.o mac.o inet_net_ntop.o inet_net_pton.o \
2626
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
27-
ascii.o
27+
ascii.o quote.o
2828

2929
all: SUBSYS.o
3030

src/backend/utils/adt/quote.c

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* quote.c
4+
* Functions for quoting identifiers and literals
5+
*
6+
* Portions Copyright (c) 2000, PostgreSQL, Inc
7+
*
8+
*
9+
* IDENTIFICATION
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.1 2000/09/05 20:25:13 wieck 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+
{
39+
result = do_quote_ident(t);
40+
}
41+
else
42+
{
43+
result = (text *)palloc(VARSIZE(t));
44+
memcpy(result, t, VARSIZE(t));
45+
}
46+
47+
PG_FREE_IF_COPY(t, 0);
48+
49+
return result;
50+
}
51+
52+
/*
53+
* quote_literal -
54+
* returns a properly quoted literal
55+
*/
56+
Datum
57+
quote_literal(PG_FUNCTION_ARGS)
58+
{
59+
text *t = PG_GETARG_TEXT_P(0);
60+
text *result;
61+
62+
result = do_quote_literal(t);
63+
64+
PG_FREE_IF_COPY(t, 0);
65+
66+
return result;
67+
}
68+
69+
70+
/*
71+
* MULTIBYTE dependant internal functions follow
72+
*
73+
*/
74+
75+
76+
#ifndef MULTIBYTE
77+
78+
/* Check if a given identifier needs quoting */
79+
static bool
80+
quote_ident_required(text *iptr)
81+
{
82+
char *cp;
83+
char *ep;
84+
85+
cp = VARDATA(iptr);
86+
ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
87+
88+
if (cp >= ep)
89+
return true;
90+
91+
if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
92+
return true;
93+
94+
while((++cp) < ep)
95+
{
96+
if (*cp >= 'a' && *cp <= 'z') continue;
97+
if (*cp >= '0' && *cp <= '9') continue;
98+
if (*cp == '_') continue;
99+
100+
return true;
101+
}
102+
103+
return false;
104+
}
105+
106+
/* Return a properly quoted identifier */
107+
static text *
108+
do_quote_ident(text *iptr)
109+
{
110+
text *result;
111+
char *cp1;
112+
char *cp2;
113+
int len;
114+
115+
len = VARSIZE(iptr) - VARHDRSZ;
116+
result = (text *)palloc(len * 2 + VARHDRSZ + 2);
117+
118+
cp1 = VARDATA(iptr);
119+
cp2 = VARDATA(result);
120+
121+
*cp2++ = '"';
122+
while(len-- > 0)
123+
{
124+
if (*cp1 == '"')
125+
*cp2++ = '"';
126+
if (*cp1 == '\\')
127+
*cp2++ = '\\';
128+
*cp2++ = *cp1++;
129+
}
130+
*cp2++ = '"';
131+
132+
VARATT_SIZEP(result) = cp2 - ((char *)result);
133+
134+
return result;
135+
}
136+
137+
/* Return a properly quoted literal value */
138+
static text *
139+
do_quote_literal(text *lptr)
140+
{
141+
text *result;
142+
char *cp1;
143+
char *cp2;
144+
int len;
145+
146+
len = VARSIZE(lptr) - VARHDRSZ;
147+
result = (text *)palloc(len * 2 + VARHDRSZ + 2);
148+
149+
cp1 = VARDATA(lptr);
150+
cp2 = VARDATA(result);
151+
152+
*cp2++ = '\'';
153+
while(len-- > 0)
154+
{
155+
if (*cp1 == '\'')
156+
*cp2++ = '\'';
157+
if (*cp1 == '\\')
158+
*cp2++ = '\\';
159+
*cp2++ = *cp1++;
160+
}
161+
*cp2++ = '\'';
162+
163+
VARATT_SIZEP(result) = cp2 - ((char *)result);
164+
165+
return result;
166+
}
167+
168+
#else
169+
170+
/* Check if a given identifier needs quoting (MULTIBYTE version) */
171+
static bool
172+
quote_ident_required(text *iptr)
173+
{
174+
char *cp;
175+
char *ep;
176+
177+
cp = VARDATA(iptr);
178+
ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
179+
180+
if (cp >= ep)
181+
return true;
182+
183+
if(pg_mblen(cp) != 1)
184+
return true;
185+
if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
186+
return true;
187+
188+
while((++cp) < ep)
189+
{
190+
if (pg_mblen(cp) != 1)
191+
return true;
192+
193+
if (*cp >= 'a' && *cp <= 'z') continue;
194+
if (*cp >= '0' && *cp <= '9') continue;
195+
if (*cp == '_') continue;
196+
197+
return true;
198+
}
199+
200+
return false;
201+
}
202+
203+
/* Return a properly quoted identifier (MULTIBYTE version) */
204+
static text *
205+
do_quote_ident(text *iptr)
206+
{
207+
text *result;
208+
char *cp1;
209+
char *cp2;
210+
int len;
211+
int wl;
212+
213+
len = VARSIZE(iptr) - VARHDRSZ;
214+
result = (text *)palloc(len * 2 + VARHDRSZ + 2);
215+
216+
cp1 = VARDATA(iptr);
217+
cp2 = VARDATA(result);
218+
219+
*cp2++ = '"';
220+
while(len > 0)
221+
{
222+
if ((wl = pg_mblen(cp1)) != 1)
223+
{
224+
len -= wl;
225+
226+
while(wl-- > 0)
227+
*cp2++ = *cp1++;
228+
continue;
229+
}
230+
231+
if (*cp1 == '"')
232+
*cp2++ = '"';
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
290+
291+

src/include/catalog/pg_proc.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: pg_proc.h,v 1.164 2000/08/24 03:29:08 tgl Exp $
10+
* $Id: pg_proc.h,v 1.165 2000/09/05 20:25:13 wieck Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2409,6 +2409,11 @@ DESCR("convert text to timestamp");
24092409
DATA(insert OID = 1780 ( to_date PGUID 12 f t f t 2 f 1082 "25 25" 100 0 0 100 to_date - ));
24102410
DESCR("convert text to date");
24112411

2412+
DATA(insert OID = 1282 ( quote_ident PGUID 12 f t t t 1 f 25 "25" 100 0 0 100 quote_ident - ));
2413+
DESCR("quote an identifier for usage in a querystring");
2414+
DATA(insert OID = 1283 ( quote_literal PGUID 12 f t t t 1 f 25 "25" 100 0 0 100 quote_literal - ));
2415+
DESCR("quote a literal for usage in a querystring");
2416+
24122417
DATA(insert OID = 1798 ( oidin PGUID 12 f t t t 1 f 26 "0" 100 0 0 100 oidin - ));
24132418
DESCR("(internal)");
24142419
DATA(insert OID = 1799 ( oidout PGUID 12 f t t t 1 f 23 "0" 100 0 0 100 oidout - ));

src/include/utils/builtins.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.135 2000/08/25 18:05:53 tgl Exp $
10+
* $Id: builtins.h,v 1.136 2000/09/05 20:25:14 wieck Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -585,4 +585,8 @@ extern Datum format_type(PG_FUNCTION_ARGS);
585585
extern Datum oidvectortypes(PG_FUNCTION_ARGS);
586586
extern int32 type_maximum_size(Oid type_oid, int32 typemod);
587587

588+
/* quote.c */
589+
extern Datum quote_ident(PG_FUNCTION_ARGS);
590+
extern Datum quote_literal(PG_FUNCTION_ARGS);
591+
588592
#endif /* BUILTINS_H */

0 commit comments

Comments
 (0)