From 17841ddbbf48706c13b4388cf6d8e4255f4a781c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 20 Oct 2003 17:25:42 +0000
Subject: [PATCH] Improve error reporting in parseTypeString(), motivated by
 confusing behavior reported by Martin Marques.

---
 src/backend/parser/parse_type.c | 34 +++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index a706ee0b437..a6a87f06ed8 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.62 2003/09/25 06:58:01 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.63 2003/10/20 17:25:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -430,14 +430,21 @@ typeidTypeRelid(Oid type_id)
 	return result;
 }
 
+/*
+ * error context callback for parse failure during parseTypeString()
+ */
+static void
+pts_error_callback(void *arg)
+{
+	const char *str = (const char *) arg;
+
+	errcontext("invalid type name \"%s\"", str);
+}
+
 /*
  * Given a string that is supposed to be a SQL-compatible type declaration,
  * such as "int4" or "integer" or "character varying(32)", parse
  * the string and convert it to a type OID and type modifier.
- *
- * This routine is not currently used by the main backend, but it is
- * exported for use by add-on modules such as plpgsql, in hopes of
- * centralizing parsing knowledge about SQL type declarations.
  */
 void
 parseTypeString(const char *str, Oid *type_id, int32 *typmod)
@@ -448,12 +455,27 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
 	ResTarget  *restarget;
 	TypeCast   *typecast;
 	TypeName   *typename;
+	ErrorContextCallback ptserrcontext;
+
+	/* make sure we give useful error for empty input */
+	if (strspn(str, " \t\n\r\f") == strlen(str))
+		goto fail;
 
 	initStringInfo(&buf);
-	appendStringInfo(&buf, "SELECT (NULL::%s)", str);
+	appendStringInfo(&buf, "SELECT NULL::%s", str);
+
+	/*
+	 * Setup error traceback support in case of ereport() during parse
+	 */
+	ptserrcontext.callback = pts_error_callback;
+	ptserrcontext.arg = (void *) str;
+	ptserrcontext.previous = error_context_stack;
+	error_context_stack = &ptserrcontext;
 
 	raw_parsetree_list = raw_parser(buf.data);
 
+	error_context_stack = ptserrcontext.previous;
+
 	/*
 	 * Make sure we got back exactly what we expected and no more;
 	 * paranoia is justified since the string might contain anything.
-- 
GitLab