Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita836abe

Browse files
committed
Modify error context callback functions to not assume that they can fetch
catalog entries via SearchSysCache and related operations. Although, at thetime that these callbacks are called by elog.c, we have not officially abortedthe current transaction, it still seems rather risky to initiate any newcatalog fetches. In all these cases the needed information is readilyavailable in the caller and so it's just a matter of a bit of extra notationto pass it to the callback.Per crash report from Dennis Koegel. I've concluded that the real fix forhis problem is to clear the error context stack at entry to proc_exit, butit still seems like a good idea to make the callbacks a bit less fragilefor other cases.Backpatch to 8.4. We could go further back, but the patch doesn't applycleanly. In the absence of proof that this fixes something and isn't justparanoia, I'm not going to expend the effort.
1 parent865b295 commita836abe

File tree

3 files changed

+94
-98
lines changed

3 files changed

+94
-98
lines changed

‎src/backend/catalog/pg_proc.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.172 2010/02/26 02:00:37 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.173 2010/03/19 22:54:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -41,6 +41,12 @@ Datumfmgr_internal_validator(PG_FUNCTION_ARGS);
4141
Datumfmgr_c_validator(PG_FUNCTION_ARGS);
4242
Datumfmgr_sql_validator(PG_FUNCTION_ARGS);
4343

44+
typedefstruct
45+
{
46+
char*proname;
47+
char*prosrc;
48+
}parse_error_callback_arg;
49+
4450
staticvoidsql_function_parse_error_callback(void*arg);
4551
staticintmatch_prosrc_to_query(constchar*prosrc,constchar*queryText,
4652
intcursorpos);
@@ -733,6 +739,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
733739
boolisnull;
734740
Datumtmp;
735741
char*prosrc;
742+
parse_error_callback_argcallback_arg;
736743
ErrorContextCallbacksqlerrcontext;
737744
boolhaspolyarg;
738745
inti;
@@ -782,8 +789,11 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
782789
/*
783790
* Setup error traceback support for ereport().
784791
*/
792+
callback_arg.proname=NameStr(proc->proname);
793+
callback_arg.prosrc=prosrc;
794+
785795
sqlerrcontext.callback=sql_function_parse_error_callback;
786-
sqlerrcontext.arg=tuple;
796+
sqlerrcontext.arg=(void*)&callback_arg;
787797
sqlerrcontext.previous=error_context_stack;
788798
error_context_stack=&sqlerrcontext;
789799

@@ -822,25 +832,14 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
822832
staticvoid
823833
sql_function_parse_error_callback(void*arg)
824834
{
825-
HeapTupletuple= (HeapTuple)arg;
826-
Form_pg_procproc= (Form_pg_proc)GETSTRUCT(tuple);
827-
boolisnull;
828-
Datumtmp;
829-
char*prosrc;
835+
parse_error_callback_arg*callback_arg= (parse_error_callback_arg*)arg;
830836

831837
/* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
832-
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
833-
if (isnull)
834-
elog(ERROR,"null prosrc");
835-
prosrc=TextDatumGetCString(tmp);
836-
837-
if (!function_parse_error_transpose(prosrc))
838+
if (!function_parse_error_transpose(callback_arg->prosrc))
838839
{
839840
/* If it's not a syntax error, push info onto context stack */
840-
errcontext("SQL function \"%s\"",NameStr(proc->proname));
841+
errcontext("SQL function \"%s\"",callback_arg->proname);
841842
}
842-
843-
pfree(prosrc);
844843
}
845844

846845
/*

‎src/backend/executor/functions.c

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.142 2010/02/26 02:00:41 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.143 2010/03/19 22:54:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -74,6 +74,7 @@ typedef struct execution_state
7474
*/
7575
typedefstruct
7676
{
77+
char*fname;/* function name (for error msgs) */
7778
char*src;/* function body text (for error msgs) */
7879

7980
Oid*argtypes;/* resolved types of arguments */
@@ -228,6 +229,7 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
228229
boolisNull;
229230

230231
fcache= (SQLFunctionCachePtr)palloc0(sizeof(SQLFunctionCache));
232+
finfo->fn_extra= (void*)fcache;
231233

232234
/*
233235
* get the procedure tuple corresponding to the given function Oid
@@ -237,6 +239,11 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
237239
elog(ERROR,"cache lookup failed for function %u",foid);
238240
procedureStruct= (Form_pg_proc)GETSTRUCT(procedureTuple);
239241

242+
/*
243+
* copy function name immediately for use by error reporting callback
244+
*/
245+
fcache->fname=pstrdup(NameStr(procedureStruct->proname));
246+
240247
/*
241248
* get the result type from the procedure tuple, and check for polymorphic
242249
* result type; if so, find out the actual result type.
@@ -361,8 +368,6 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
361368
lazyEvalOK);
362369

363370
ReleaseSysCache(procedureTuple);
364-
365-
finfo->fn_extra= (void*)fcache;
366371
}
367372

368373
/* Start up execution of one execution_state node */
@@ -877,37 +882,24 @@ sql_exec_error_callback(void *arg)
877882
{
878883
FmgrInfo*flinfo= (FmgrInfo*)arg;
879884
SQLFunctionCachePtrfcache= (SQLFunctionCachePtr)flinfo->fn_extra;
880-
HeapTuplefunc_tuple;
881-
Form_pg_procfunctup;
882-
char*fn_name;
883885
intsyntaxerrposition;
884886

885-
/* Need access to function's pg_proc tuple */
886-
func_tuple=SearchSysCache1(PROCOID,ObjectIdGetDatum(flinfo->fn_oid));
887-
if (!HeapTupleIsValid(func_tuple))
888-
return;/* shouldn't happen */
889-
functup= (Form_pg_proc)GETSTRUCT(func_tuple);
890-
fn_name=NameStr(functup->proname);
887+
/*
888+
* We can do nothing useful if init_sql_fcache() didn't get as far as
889+
* saving the function name
890+
*/
891+
if (fcache==NULL||fcache->fname==NULL)
892+
return;
891893

892894
/*
893895
* If there is a syntax error position, convert to internal syntax error
894896
*/
895897
syntaxerrposition=geterrposition();
896-
if (syntaxerrposition>0)
898+
if (syntaxerrposition>0&&fcache->src!=NULL)
897899
{
898-
boolisnull;
899-
Datumtmp;
900-
char*prosrc;
901-
902-
tmp=SysCacheGetAttr(PROCOID,func_tuple,Anum_pg_proc_prosrc,
903-
&isnull);
904-
if (isnull)
905-
elog(ERROR,"null prosrc");
906-
prosrc=TextDatumGetCString(tmp);
907900
errposition(0);
908901
internalerrposition(syntaxerrposition);
909-
internalerrquery(prosrc);
910-
pfree(prosrc);
902+
internalerrquery(fcache->src);
911903
}
912904

913905
/*
@@ -917,7 +909,7 @@ sql_exec_error_callback(void *arg)
917909
* ExecutorEnd are blamed on the appropriate query; see postquel_start and
918910
* postquel_end.)
919911
*/
920-
if (fcache)
912+
if (fcache->func_state)
921913
{
922914
execution_state*es;
923915
intquery_num;
@@ -929,7 +921,7 @@ sql_exec_error_callback(void *arg)
929921
if (es->qd)
930922
{
931923
errcontext("SQL function \"%s\" statement %d",
932-
fn_name,query_num);
924+
fcache->fname,query_num);
933925
break;
934926
}
935927
es=es->next;
@@ -941,16 +933,18 @@ sql_exec_error_callback(void *arg)
941933
* couldn't identify a running query; might be function entry,
942934
* function exit, or between queries.
943935
*/
944-
errcontext("SQL function \"%s\"",fn_name);
936+
errcontext("SQL function \"%s\"",fcache->fname);
945937
}
946938
}
947939
else
948940
{
949-
/* must have failed during init_sql_fcache() */
950-
errcontext("SQL function \"%s\" during startup",fn_name);
941+
/*
942+
* Assume we failed during init_sql_fcache(). (It's possible that
943+
* the function actually has an empty body, but in that case we may
944+
* as well report all errors as being "during startup".)
945+
*/
946+
errcontext("SQL function \"%s\" during startup",fcache->fname);
951947
}
952-
953-
ReleaseSysCache(func_tuple);
954948
}
955949

956950

‎src/backend/optimizer/util/clauses.c

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.286 2010/02/26 02:00:46 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.287 2010/03/19 22:54:41 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -71,6 +71,12 @@ typedef struct
7171
intsublevels_up;
7272
}substitute_actual_srf_parameters_context;
7373

74+
typedefstruct
75+
{
76+
char*proname;
77+
char*prosrc;
78+
}inline_error_callback_arg;
79+
7480
staticboolcontain_agg_clause_walker(Node*node,void*context);
7581
staticboolpull_agg_clause_walker(Node*node,List**context);
7682
staticboolcount_agg_clauses_walker(Node*node,AggClauseCounts*counts);
@@ -3678,6 +3684,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
36783684
boolmodifyTargetList;
36793685
MemoryContextoldcxt;
36803686
MemoryContextmycxt;
3687+
inline_error_callback_argcallback_arg;
36813688
ErrorContextCallbacksqlerrcontext;
36823689
List*raw_parsetree_list;
36833690
Query*querytree;
@@ -3705,15 +3712,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
37053712
if (pg_proc_aclcheck(funcid,GetUserId(),ACL_EXECUTE)!=ACLCHECK_OK)
37063713
returnNULL;
37073714

3708-
/*
3709-
* Setup error traceback support for ereport(). This is so that we can
3710-
* finger the function that bad information came from.
3711-
*/
3712-
sqlerrcontext.callback=sql_inline_error_callback;
3713-
sqlerrcontext.arg=func_tuple;
3714-
sqlerrcontext.previous=error_context_stack;
3715-
error_context_stack=&sqlerrcontext;
3716-
37173715
/*
37183716
* Make a temporary memory context, so that we don't leak all the stuff
37193717
* that parsing might create.
@@ -3725,6 +3723,27 @@ inline_function(Oid funcid, Oid result_type, List *args,
37253723
ALLOCSET_DEFAULT_MAXSIZE);
37263724
oldcxt=MemoryContextSwitchTo(mycxt);
37273725

3726+
/* Fetch the function body */
3727+
tmp=SysCacheGetAttr(PROCOID,
3728+
func_tuple,
3729+
Anum_pg_proc_prosrc,
3730+
&isNull);
3731+
if (isNull)
3732+
elog(ERROR,"null prosrc for function %u",funcid);
3733+
src=TextDatumGetCString(tmp);
3734+
3735+
/*
3736+
* Setup error traceback support for ereport(). This is so that we can
3737+
* finger the function that bad information came from.
3738+
*/
3739+
callback_arg.proname=NameStr(funcform->proname);
3740+
callback_arg.prosrc=src;
3741+
3742+
sqlerrcontext.callback=sql_inline_error_callback;
3743+
sqlerrcontext.arg= (void*)&callback_arg;
3744+
sqlerrcontext.previous=error_context_stack;
3745+
error_context_stack=&sqlerrcontext;
3746+
37283747
/* Check for polymorphic arguments, and substitute actual arg types */
37293748
argtypes= (Oid*)palloc(funcform->pronargs*sizeof(Oid));
37303749
memcpy(argtypes,funcform->proargtypes.values,
@@ -3737,15 +3756,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
37373756
}
37383757
}
37393758

3740-
/* Fetch and parse the function body */
3741-
tmp=SysCacheGetAttr(PROCOID,
3742-
func_tuple,
3743-
Anum_pg_proc_prosrc,
3744-
&isNull);
3745-
if (isNull)
3746-
elog(ERROR,"null prosrc for function %u",funcid);
3747-
src=TextDatumGetCString(tmp);
3748-
37493759
/*
37503760
* We just do parsing and parse analysis, not rewriting, because rewriting
37513761
* will not affect table-free-SELECT-only queries, which is all that we
@@ -3965,30 +3975,19 @@ substitute_actual_parameters_mutator(Node *node,
39653975
staticvoid
39663976
sql_inline_error_callback(void*arg)
39673977
{
3968-
HeapTuplefunc_tuple= (HeapTuple)arg;
3969-
Form_pg_procfuncform= (Form_pg_proc)GETSTRUCT(func_tuple);
3978+
inline_error_callback_arg*callback_arg= (inline_error_callback_arg*)arg;
39703979
intsyntaxerrposition;
39713980

39723981
/* If it's a syntax error, convert to internal syntax error report */
39733982
syntaxerrposition=geterrposition();
39743983
if (syntaxerrposition>0)
39753984
{
3976-
boolisnull;
3977-
Datumtmp;
3978-
char*prosrc;
3979-
3980-
tmp=SysCacheGetAttr(PROCOID,func_tuple,Anum_pg_proc_prosrc,
3981-
&isnull);
3982-
if (isnull)
3983-
elog(ERROR,"null prosrc");
3984-
prosrc=TextDatumGetCString(tmp);
39853985
errposition(0);
39863986
internalerrposition(syntaxerrposition);
3987-
internalerrquery(prosrc);
3987+
internalerrquery(callback_arg->prosrc);
39883988
}
39893989

3990-
errcontext("SQL function \"%s\" during inlining",
3991-
NameStr(funcform->proname));
3990+
errcontext("SQL function \"%s\" during inlining",callback_arg->proname);
39923991
}
39933992

39943993
/*
@@ -4096,6 +4095,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
40964095
boolmodifyTargetList;
40974096
MemoryContextoldcxt;
40984097
MemoryContextmycxt;
4098+
inline_error_callback_argcallback_arg;
40994099
ErrorContextCallbacksqlerrcontext;
41004100
List*raw_parsetree_list;
41014101
List*querytree_list;
@@ -4170,15 +4170,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41704170
returnNULL;
41714171
}
41724172

4173-
/*
4174-
* Setup error traceback support for ereport(). This is so that we can
4175-
* finger the function that bad information came from.
4176-
*/
4177-
sqlerrcontext.callback=sql_inline_error_callback;
4178-
sqlerrcontext.arg=func_tuple;
4179-
sqlerrcontext.previous=error_context_stack;
4180-
error_context_stack=&sqlerrcontext;
4181-
41824173
/*
41834174
* Make a temporary memory context, so that we don't leak all the stuff
41844175
* that parsing might create.
@@ -4190,6 +4181,27 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41904181
ALLOCSET_DEFAULT_MAXSIZE);
41914182
oldcxt=MemoryContextSwitchTo(mycxt);
41924183

4184+
/* Fetch the function body */
4185+
tmp=SysCacheGetAttr(PROCOID,
4186+
func_tuple,
4187+
Anum_pg_proc_prosrc,
4188+
&isNull);
4189+
if (isNull)
4190+
elog(ERROR,"null prosrc for function %u",func_oid);
4191+
src=TextDatumGetCString(tmp);
4192+
4193+
/*
4194+
* Setup error traceback support for ereport(). This is so that we can
4195+
* finger the function that bad information came from.
4196+
*/
4197+
callback_arg.proname=NameStr(funcform->proname);
4198+
callback_arg.prosrc=src;
4199+
4200+
sqlerrcontext.callback=sql_inline_error_callback;
4201+
sqlerrcontext.arg= (void*)&callback_arg;
4202+
sqlerrcontext.previous=error_context_stack;
4203+
error_context_stack=&sqlerrcontext;
4204+
41934205
/*
41944206
* Run eval_const_expressions on the function call. This is necessary to
41954207
* ensure that named-argument notation is converted to positional notation
@@ -4220,15 +4232,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
42204232
}
42214233
}
42224234

4223-
/* Fetch and parse the function body */
4224-
tmp=SysCacheGetAttr(PROCOID,
4225-
func_tuple,
4226-
Anum_pg_proc_prosrc,
4227-
&isNull);
4228-
if (isNull)
4229-
elog(ERROR,"null prosrc for function %u",func_oid);
4230-
src=TextDatumGetCString(tmp);
4231-
42324235
/*
42334236
* Parse, analyze, and rewrite (unlike inline_function(), we can't skip
42344237
* rewriting here). We can fail as soon as we find more than one query,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp