Arrange to emit a CONTEXT: SQL function "foo" entry in an error
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Mar 2004 01:58:41 +0000 (01:58 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Mar 2004 01:58:41 +0000 (01:58 +0000)
message that is reporting a prechecking error in a SQL function.
This is to cue client-side code that the syntax error position,
if any, is with respect to the function body and not the outer command.

src/backend/catalog/pg_proc.c
src/test/regress/output/create_function_1.source

index b9628734701cf3edb6a221070cbc328b11ee30af..3ea2af44d3e11c950b20c41babb4b8f6de6f4d32 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.111 2004/01/06 23:55:18 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.112 2004/03/14 01:58:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,6 +44,7 @@ Datum     fmgr_sql_validator(PG_FUNCTION_ARGS);
 
 static Datum create_parameternames_array(int parameterCount,
                                         const char *parameterNames[]);
+static void sql_function_parse_error_callback(void *arg);
 
 
 /* ----------------------------------------------------------------
@@ -708,6 +709,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
    bool        isnull;
    Datum       tmp;
    char       *prosrc;
+   ErrorContextCallback sqlerrcontext;
    char        functyptype;
    bool        haspolyarg;
    int         i;
@@ -760,6 +762,16 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
 
        prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
 
+       /*
+        * Setup error traceback support for ereport().  This is mostly
+        * so we can add context info that shows that a syntax-error
+        * location is inside the function body, not out in CREATE FUNCTION.
+        */
+       sqlerrcontext.callback = sql_function_parse_error_callback;
+       sqlerrcontext.arg = proc;
+       sqlerrcontext.previous = error_context_stack;
+       error_context_stack = &sqlerrcontext;
+
        /*
         * We can't do full prechecking of the function definition if there
         * are any polymorphic input types, because actual datatypes of
@@ -778,9 +790,32 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
        }
        else
            querytree_list = pg_parse_query(prosrc);
+
+       error_context_stack = sqlerrcontext.previous;
    }
 
    ReleaseSysCache(tuple);
 
    PG_RETURN_VOID();
 }
+
+/*
+ * error context callback to let us supply a context marker
+ */
+static void
+sql_function_parse_error_callback(void *arg)
+{
+   Form_pg_proc proc = (Form_pg_proc) arg;
+
+   /*
+    * XXX it'd be really nice to adjust the syntax error position to
+    * account for the offset from the start of the statement to the
+    * function body string, not to mention any quoting characters in
+    * the string, but I can't see any decent way to do that...
+    *
+    * In the meantime, put in a CONTEXT entry that can cue clients
+    * not to trust the syntax error position completely.
+    */
+   errcontext("SQL function \"%s\"",
+              NameStr(proc->proname));
+}
index 44e74fb527e9241c82c2298dc98c980e56ec181e..e3886febaa9f0fd63cdf1b43b8b456387ba7f640 100644 (file)
@@ -52,16 +52,20 @@ CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
     AS 'SELECT ''not an integer'';';
 ERROR:  return type mismatch in function declared to return integer
 DETAIL:  Actual return type is "unknown".
+CONTEXT:  SQL function "test1"
 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
     AS 'not even SQL';
 ERROR:  syntax error at or near "not" at character 1
+CONTEXT:  SQL function "test1"
 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
     AS 'SELECT 1, 2, 3;';
 ERROR:  return type mismatch in function declared to return integer
 DETAIL:  Final SELECT must return exactly one column.
+CONTEXT:  SQL function "test1"
 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
     AS 'SELECT $2;';
 ERROR:  there is no parameter $2
+CONTEXT:  SQL function "test1"
 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
     AS 'a', 'b';
 ERROR:  only one AS item needed for language "sql"