diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index b962873470..3ea2af44d3 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -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)); +} diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source index 44e74fb527..e3886febaa 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -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"