From daf1e3a7026e367d630be3ac34ac0a9e7cf1340f Mon Sep 17 00:00:00 2001 From: Jan Wieck Date: Tue, 5 Sep 2000 20:25:14 +0000 Subject: [PATCH] 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 --- src/backend/utils/adt/Makefile | 4 +- src/backend/utils/adt/quote.c | 291 +++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.h | 7 +- src/include/utils/builtins.h | 6 +- 4 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 src/backend/utils/adt/quote.c diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index 62ec9bcb87..40e70c19cc 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -1,7 +1,7 @@ # # Makefile for utils/adt # -# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.45 2000/08/31 16:10:45 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.46 2000/09/05 20:25:12 wieck Exp $ # subdir = src/backend/utils/adt @@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o \ tid.o timestamp.o varbit.o varchar.o varlena.o version.o \ network.o mac.o inet_net_ntop.o inet_net_pton.o \ ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \ - ascii.o + ascii.o quote.o all: SUBSYS.o diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c new file mode 100644 index 0000000000..aaa4aaaa1b --- /dev/null +++ b/src/backend/utils/adt/quote.c @@ -0,0 +1,291 @@ +/*------------------------------------------------------------------------- + * + * quote.c + * Functions for quoting identifiers and literals + * + * Portions Copyright (c) 2000, PostgreSQL, Inc + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.1 2000/09/05 20:25:13 wieck Exp $ + * + *------------------------------------------------------------------------- + */ +#include + +#include "postgres.h" + +#include "mb/pg_wchar.h" +#include "utils/builtins.h" + + +static bool quote_ident_required(text *iptr); +static text *do_quote_ident(text *iptr); +static text *do_quote_literal(text *iptr); + + +/* + * quote_ident - + * returns a properly quoted identifier + */ +Datum +quote_ident(PG_FUNCTION_ARGS) +{ + text *t = PG_GETARG_TEXT_P(0); + text *result; + + if (quote_ident_required(t)) + { + result = do_quote_ident(t); + } + else + { + result = (text *)palloc(VARSIZE(t)); + memcpy(result, t, VARSIZE(t)); + } + + PG_FREE_IF_COPY(t, 0); + + return result; +} + +/* + * quote_literal - + * returns a properly quoted literal + */ +Datum +quote_literal(PG_FUNCTION_ARGS) +{ + text *t = PG_GETARG_TEXT_P(0); + text *result; + + result = do_quote_literal(t); + + PG_FREE_IF_COPY(t, 0); + + return result; +} + + +/* + * MULTIBYTE dependant internal functions follow + * + */ + + +#ifndef MULTIBYTE + +/* Check if a given identifier needs quoting */ +static bool +quote_ident_required(text *iptr) +{ + char *cp; + char *ep; + + cp = VARDATA(iptr); + ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ; + + if (cp >= ep) + return true; + + if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z'))) + return true; + + while((++cp) < ep) + { + if (*cp >= 'a' && *cp <= 'z') continue; + if (*cp >= '0' && *cp <= '9') continue; + if (*cp == '_') continue; + + return true; + } + + return false; +} + +/* Return a properly quoted identifier */ +static text * +do_quote_ident(text *iptr) +{ + text *result; + char *cp1; + char *cp2; + int len; + + len = VARSIZE(iptr) - VARHDRSZ; + result = (text *)palloc(len * 2 + VARHDRSZ + 2); + + cp1 = VARDATA(iptr); + cp2 = VARDATA(result); + + *cp2++ = '"'; + while(len-- > 0) + { + if (*cp1 == '"') + *cp2++ = '"'; + if (*cp1 == '\\') + *cp2++ = '\\'; + *cp2++ = *cp1++; + } + *cp2++ = '"'; + + VARATT_SIZEP(result) = cp2 - ((char *)result); + + return result; +} + +/* Return a properly quoted literal value */ +static text * +do_quote_literal(text *lptr) +{ + text *result; + char *cp1; + char *cp2; + int len; + + len = VARSIZE(lptr) - VARHDRSZ; + result = (text *)palloc(len * 2 + VARHDRSZ + 2); + + cp1 = VARDATA(lptr); + cp2 = VARDATA(result); + + *cp2++ = '\''; + while(len-- > 0) + { + if (*cp1 == '\'') + *cp2++ = '\''; + if (*cp1 == '\\') + *cp2++ = '\\'; + *cp2++ = *cp1++; + } + *cp2++ = '\''; + + VARATT_SIZEP(result) = cp2 - ((char *)result); + + return result; +} + +#else + +/* Check if a given identifier needs quoting (MULTIBYTE version) */ +static bool +quote_ident_required(text *iptr) +{ + char *cp; + char *ep; + + cp = VARDATA(iptr); + ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ; + + if (cp >= ep) + return true; + + if(pg_mblen(cp) != 1) + return true; + if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z'))) + return true; + + while((++cp) < ep) + { + if (pg_mblen(cp) != 1) + return true; + + if (*cp >= 'a' && *cp <= 'z') continue; + if (*cp >= '0' && *cp <= '9') continue; + if (*cp == '_') continue; + + return true; + } + + return false; +} + +/* Return a properly quoted identifier (MULTIBYTE version) */ +static text * +do_quote_ident(text *iptr) +{ + text *result; + char *cp1; + char *cp2; + int len; + int wl; + + len = VARSIZE(iptr) - VARHDRSZ; + result = (text *)palloc(len * 2 + VARHDRSZ + 2); + + cp1 = VARDATA(iptr); + cp2 = VARDATA(result); + + *cp2++ = '"'; + while(len > 0) + { + if ((wl = pg_mblen(cp1)) != 1) + { + len -= wl; + + while(wl-- > 0) + *cp2++ = *cp1++; + continue; + } + + if (*cp1 == '"') + *cp2++ = '"'; + if (*cp1 == '\\') + *cp2++ = '\\'; + *cp2++ = *cp1++; + + len--; + } + *cp2++ = '"'; + + VARATT_SIZEP(result) = cp2 - ((char *)result); + + return result; +} + +/* Return a properly quoted literal value (MULTIBYTE version) */ +static text * +do_quote_literal(text *lptr) +{ + text *result; + char *cp1; + char *cp2; + int len; + int wl; + + len = VARSIZE(lptr) - VARHDRSZ; + result = (text *)palloc(len * 2 + VARHDRSZ + 2); + + cp1 = VARDATA(lptr); + cp2 = VARDATA(result); + + *cp2++ = '\''; + while(len > 0) + { + if ((wl = pg_mblen(cp1)) != 1) + { + len -= wl; + + while(wl-- > 0) + *cp2++ = *cp1++; + continue; + } + + if (*cp1 == '\'') + *cp2++ = '\''; + if (*cp1 == '\\') + *cp2++ = '\\'; + *cp2++ = *cp1++; + + len--; + } + *cp2++ = '\''; + + VARATT_SIZEP(result) = cp2 - ((char *)result); + + return result; +} + +#endif + + diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index c7e092c702..04109473d8 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.164 2000/08/24 03:29:08 tgl Exp $ + * $Id: pg_proc.h,v 1.165 2000/09/05 20:25:13 wieck Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -2409,6 +2409,11 @@ DESCR("convert text to timestamp"); DATA(insert OID = 1780 ( to_date PGUID 12 f t f t 2 f 1082 "25 25" 100 0 0 100 to_date - )); DESCR("convert text to date"); +DATA(insert OID = 1282 ( quote_ident PGUID 12 f t t t 1 f 25 "25" 100 0 0 100 quote_ident - )); +DESCR("quote an identifier for usage in a querystring"); +DATA(insert OID = 1283 ( quote_literal PGUID 12 f t t t 1 f 25 "25" 100 0 0 100 quote_literal - )); +DESCR("quote a literal for usage in a querystring"); + DATA(insert OID = 1798 ( oidin PGUID 12 f t t t 1 f 26 "0" 100 0 0 100 oidin - )); DESCR("(internal)"); DATA(insert OID = 1799 ( oidout PGUID 12 f t t t 1 f 23 "0" 100 0 0 100 oidout - )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 2c42899b1c..cbb0aabe49 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.135 2000/08/25 18:05:53 tgl Exp $ + * $Id: builtins.h,v 1.136 2000/09/05 20:25:14 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -585,4 +585,8 @@ extern Datum format_type(PG_FUNCTION_ARGS); extern Datum oidvectortypes(PG_FUNCTION_ARGS); extern int32 type_maximum_size(Oid type_oid, int32 typemod); +/* quote.c */ +extern Datum quote_ident(PG_FUNCTION_ARGS); +extern Datum quote_literal(PG_FUNCTION_ARGS); + #endif /* BUILTINS_H */ -- 2.40.0