From daf1e3a7026e367d630be3ac34ac0a9e7cf1340f Mon Sep 17 00:00:00 2001
From: Jan Wieck <JanWieck@Yahoo.com>
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 62ec9bcb87f..40e70c19cc7 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 00000000000..aaa4aaaa1b8
--- /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 <ctype.h>
+
+#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 c7e092c7020..04109473d8e 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 2c42899b1c0..cbb0aabe498 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 */
-- 
GitLab