aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/pg_proc.c31
-rw-r--r--src/backend/executor/functions.c56
-rw-r--r--src/backend/optimizer/util/clauses.c105
3 files changed, 94 insertions, 98 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 2b216098939..f97641d5555 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.172 2010/02/26 02:00:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.173 2010/03/19 22:54:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -41,6 +41,12 @@ Datum fmgr_internal_validator(PG_FUNCTION_ARGS);
Datum fmgr_c_validator(PG_FUNCTION_ARGS);
Datum fmgr_sql_validator(PG_FUNCTION_ARGS);
+typedef struct
+{
+ char *proname;
+ char *prosrc;
+} parse_error_callback_arg;
+
static void sql_function_parse_error_callback(void *arg);
static int match_prosrc_to_query(const char *prosrc, const char *queryText,
int cursorpos);
@@ -733,6 +739,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
bool isnull;
Datum tmp;
char *prosrc;
+ parse_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext;
bool haspolyarg;
int i;
@@ -782,8 +789,11 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
/*
* Setup error traceback support for ereport().
*/
+ callback_arg.proname = NameStr(proc->proname);
+ callback_arg.prosrc = prosrc;
+
sqlerrcontext.callback = sql_function_parse_error_callback;
- sqlerrcontext.arg = tuple;
+ sqlerrcontext.arg = (void *) &callback_arg;
sqlerrcontext.previous = error_context_stack;
error_context_stack = &sqlerrcontext;
@@ -822,25 +832,14 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
static void
sql_function_parse_error_callback(void *arg)
{
- HeapTuple tuple = (HeapTuple) arg;
- Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(tuple);
- bool isnull;
- Datum tmp;
- char *prosrc;
+ parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg;
/* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
- tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
- if (isnull)
- elog(ERROR, "null prosrc");
- prosrc = TextDatumGetCString(tmp);
-
- if (!function_parse_error_transpose(prosrc))
+ if (!function_parse_error_transpose(callback_arg->prosrc))
{
/* If it's not a syntax error, push info onto context stack */
- errcontext("SQL function \"%s\"", NameStr(proc->proname));
+ errcontext("SQL function \"%s\"", callback_arg->proname);
}
-
- pfree(prosrc);
}
/*
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index d2bd23da750..1f6d530f91d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.142 2010/02/26 02:00:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.143 2010/03/19 22:54:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -74,6 +74,7 @@ typedef struct execution_state
*/
typedef struct
{
+ char *fname; /* function name (for error msgs) */
char *src; /* function body text (for error msgs) */
Oid *argtypes; /* resolved types of arguments */
@@ -228,6 +229,7 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
bool isNull;
fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
+ finfo->fn_extra = (void *) fcache;
/*
* get the procedure tuple corresponding to the given function Oid
@@ -238,6 +240,11 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
/*
+ * copy function name immediately for use by error reporting callback
+ */
+ fcache->fname = pstrdup(NameStr(procedureStruct->proname));
+
+ /*
* get the result type from the procedure tuple, and check for polymorphic
* result type; if so, find out the actual result type.
*/
@@ -361,8 +368,6 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
lazyEvalOK);
ReleaseSysCache(procedureTuple);
-
- finfo->fn_extra = (void *) fcache;
}
/* Start up execution of one execution_state node */
@@ -877,37 +882,24 @@ sql_exec_error_callback(void *arg)
{
FmgrInfo *flinfo = (FmgrInfo *) arg;
SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) flinfo->fn_extra;
- HeapTuple func_tuple;
- Form_pg_proc functup;
- char *fn_name;
int syntaxerrposition;
- /* Need access to function's pg_proc tuple */
- func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(flinfo->fn_oid));
- if (!HeapTupleIsValid(func_tuple))
- return; /* shouldn't happen */
- functup = (Form_pg_proc) GETSTRUCT(func_tuple);
- fn_name = NameStr(functup->proname);
+ /*
+ * We can do nothing useful if init_sql_fcache() didn't get as far as
+ * saving the function name
+ */
+ if (fcache == NULL || fcache->fname == NULL)
+ return;
/*
* If there is a syntax error position, convert to internal syntax error
*/
syntaxerrposition = geterrposition();
- if (syntaxerrposition > 0)
+ if (syntaxerrposition > 0 && fcache->src != NULL)
{
- bool isnull;
- Datum tmp;
- char *prosrc;
-
- tmp = SysCacheGetAttr(PROCOID, func_tuple, Anum_pg_proc_prosrc,
- &isnull);
- if (isnull)
- elog(ERROR, "null prosrc");
- prosrc = TextDatumGetCString(tmp);
errposition(0);
internalerrposition(syntaxerrposition);
- internalerrquery(prosrc);
- pfree(prosrc);
+ internalerrquery(fcache->src);
}
/*
@@ -917,7 +909,7 @@ sql_exec_error_callback(void *arg)
* ExecutorEnd are blamed on the appropriate query; see postquel_start and
* postquel_end.)
*/
- if (fcache)
+ if (fcache->func_state)
{
execution_state *es;
int query_num;
@@ -929,7 +921,7 @@ sql_exec_error_callback(void *arg)
if (es->qd)
{
errcontext("SQL function \"%s\" statement %d",
- fn_name, query_num);
+ fcache->fname, query_num);
break;
}
es = es->next;
@@ -941,16 +933,18 @@ sql_exec_error_callback(void *arg)
* couldn't identify a running query; might be function entry,
* function exit, or between queries.
*/
- errcontext("SQL function \"%s\"", fn_name);
+ errcontext("SQL function \"%s\"", fcache->fname);
}
}
else
{
- /* must have failed during init_sql_fcache() */
- errcontext("SQL function \"%s\" during startup", fn_name);
+ /*
+ * Assume we failed during init_sql_fcache(). (It's possible that
+ * the function actually has an empty body, but in that case we may
+ * as well report all errors as being "during startup".)
+ */
+ errcontext("SQL function \"%s\" during startup", fcache->fname);
}
-
- ReleaseSysCache(func_tuple);
}
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index cb1735725a7..f6a943fcab4 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.286 2010/02/26 02:00:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.287 2010/03/19 22:54:41 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -71,6 +71,12 @@ typedef struct
int sublevels_up;
} substitute_actual_srf_parameters_context;
+typedef struct
+{
+ char *proname;
+ char *prosrc;
+} inline_error_callback_arg;
+
static bool contain_agg_clause_walker(Node *node, void *context);
static bool pull_agg_clause_walker(Node *node, List **context);
static bool count_agg_clauses_walker(Node *node, AggClauseCounts *counts);
@@ -3678,6 +3684,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
bool modifyTargetList;
MemoryContext oldcxt;
MemoryContext mycxt;
+ inline_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext;
List *raw_parsetree_list;
Query *querytree;
@@ -3706,15 +3713,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
return NULL;
/*
- * Setup error traceback support for ereport(). This is so that we can
- * finger the function that bad information came from.
- */
- sqlerrcontext.callback = sql_inline_error_callback;
- sqlerrcontext.arg = func_tuple;
- sqlerrcontext.previous = error_context_stack;
- error_context_stack = &sqlerrcontext;
-
- /*
* Make a temporary memory context, so that we don't leak all the stuff
* that parsing might create.
*/
@@ -3725,6 +3723,27 @@ inline_function(Oid funcid, Oid result_type, List *args,
ALLOCSET_DEFAULT_MAXSIZE);
oldcxt = MemoryContextSwitchTo(mycxt);
+ /* Fetch the function body */
+ tmp = SysCacheGetAttr(PROCOID,
+ func_tuple,
+ Anum_pg_proc_prosrc,
+ &isNull);
+ if (isNull)
+ elog(ERROR, "null prosrc for function %u", funcid);
+ src = TextDatumGetCString(tmp);
+
+ /*
+ * Setup error traceback support for ereport(). This is so that we can
+ * finger the function that bad information came from.
+ */
+ callback_arg.proname = NameStr(funcform->proname);
+ callback_arg.prosrc = src;
+
+ sqlerrcontext.callback = sql_inline_error_callback;
+ sqlerrcontext.arg = (void *) &callback_arg;
+ sqlerrcontext.previous = error_context_stack;
+ error_context_stack = &sqlerrcontext;
+
/* Check for polymorphic arguments, and substitute actual arg types */
argtypes = (Oid *) palloc(funcform->pronargs * sizeof(Oid));
memcpy(argtypes, funcform->proargtypes.values,
@@ -3737,15 +3756,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
}
}
- /* Fetch and parse the function body */
- tmp = SysCacheGetAttr(PROCOID,
- func_tuple,
- Anum_pg_proc_prosrc,
- &isNull);
- if (isNull)
- elog(ERROR, "null prosrc for function %u", funcid);
- src = TextDatumGetCString(tmp);
-
/*
* We just do parsing and parse analysis, not rewriting, because rewriting
* will not affect table-free-SELECT-only queries, which is all that we
@@ -3965,30 +3975,19 @@ substitute_actual_parameters_mutator(Node *node,
static void
sql_inline_error_callback(void *arg)
{
- HeapTuple func_tuple = (HeapTuple) arg;
- Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
+ inline_error_callback_arg *callback_arg = (inline_error_callback_arg *) arg;
int syntaxerrposition;
/* If it's a syntax error, convert to internal syntax error report */
syntaxerrposition = geterrposition();
if (syntaxerrposition > 0)
{
- bool isnull;
- Datum tmp;
- char *prosrc;
-
- tmp = SysCacheGetAttr(PROCOID, func_tuple, Anum_pg_proc_prosrc,
- &isnull);
- if (isnull)
- elog(ERROR, "null prosrc");
- prosrc = TextDatumGetCString(tmp);
errposition(0);
internalerrposition(syntaxerrposition);
- internalerrquery(prosrc);
+ internalerrquery(callback_arg->prosrc);
}
- errcontext("SQL function \"%s\" during inlining",
- NameStr(funcform->proname));
+ errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
}
/*
@@ -4096,6 +4095,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
bool modifyTargetList;
MemoryContext oldcxt;
MemoryContext mycxt;
+ inline_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext;
List *raw_parsetree_list;
List *querytree_list;
@@ -4171,15 +4171,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
}
/*
- * Setup error traceback support for ereport(). This is so that we can
- * finger the function that bad information came from.
- */
- sqlerrcontext.callback = sql_inline_error_callback;
- sqlerrcontext.arg = func_tuple;
- sqlerrcontext.previous = error_context_stack;
- error_context_stack = &sqlerrcontext;
-
- /*
* Make a temporary memory context, so that we don't leak all the stuff
* that parsing might create.
*/
@@ -4190,6 +4181,27 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
ALLOCSET_DEFAULT_MAXSIZE);
oldcxt = MemoryContextSwitchTo(mycxt);
+ /* Fetch the function body */
+ tmp = SysCacheGetAttr(PROCOID,
+ func_tuple,
+ Anum_pg_proc_prosrc,
+ &isNull);
+ if (isNull)
+ elog(ERROR, "null prosrc for function %u", func_oid);
+ src = TextDatumGetCString(tmp);
+
+ /*
+ * Setup error traceback support for ereport(). This is so that we can
+ * finger the function that bad information came from.
+ */
+ callback_arg.proname = NameStr(funcform->proname);
+ callback_arg.prosrc = src;
+
+ sqlerrcontext.callback = sql_inline_error_callback;
+ sqlerrcontext.arg = (void *) &callback_arg;
+ sqlerrcontext.previous = error_context_stack;
+ error_context_stack = &sqlerrcontext;
+
/*
* Run eval_const_expressions on the function call. This is necessary to
* ensure that named-argument notation is converted to positional notation
@@ -4220,15 +4232,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
}
}
- /* Fetch and parse the function body */
- tmp = SysCacheGetAttr(PROCOID,
- func_tuple,
- Anum_pg_proc_prosrc,
- &isNull);
- if (isNull)
- elog(ERROR, "null prosrc for function %u", func_oid);
- src = TextDatumGetCString(tmp);
-
/*
* Parse, analyze, and rewrite (unlike inline_function(), we can't skip
* rewriting here). We can fail as soon as we find more than one query,