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

Commitaad71b4

Browse files
committed
Add error stack traceback support for SQL-language functions.
1 parent1c24154 commitaad71b4

File tree

2 files changed

+107
-7
lines changed

2 files changed

+107
-7
lines changed

‎src/backend/executor/functions.c

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/*-------------------------------------------------------------------------
22
*
33
* functions.c
4-
*Routines to handle functions called from the executor
4+
*Execution of SQL-language functions
55
*
66
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.68 2003/07/21 17:05:09 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.69 2003/07/28 18:33:18 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -54,7 +54,6 @@ typedef struct local_es
5454
* An SQLFunctionCache record is built during the first call,
5555
* and linked to from the fn_extra field of the FmgrInfo struct.
5656
*/
57-
5857
typedefstruct
5958
{
6059
inttyplen;/* length of the return type */
@@ -88,6 +87,7 @@ static void postquel_sub_params(SQLFunctionCachePtr fcache,
8887
staticDatumpostquel_execute(execution_state*es,
8988
FunctionCallInfofcinfo,
9089
SQLFunctionCachePtrfcache);
90+
staticvoidsql_exec_error_callback(void*arg);
9191
staticvoidShutdownSQLFunction(Datumarg);
9292

9393

@@ -323,15 +323,15 @@ postquel_getnext(execution_state *es)
323323
staticvoid
324324
postquel_end(execution_state*es)
325325
{
326+
/* mark status done to ensure we don't do ExecutorEnd twice */
327+
es->status=F_EXEC_DONE;
328+
326329
/* Utility commands don't need Executor. */
327330
if (es->qd->operation!=CMD_UTILITY)
328331
ExecutorEnd(es->qd);
329332

330333
FreeQueryDesc(es->qd);
331-
332334
es->qd=NULL;
333-
334-
es->status=F_EXEC_DONE;
335335
}
336336

337337
/* Build ParamListInfo array representing current arguments */
@@ -492,6 +492,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
492492
{
493493
MemoryContextoldcontext;
494494
SQLFunctionCachePtrfcache;
495+
ErrorContextCallbacksqlerrcontext;
495496
execution_state*es;
496497
Datumresult=0;
497498

@@ -502,6 +503,14 @@ fmgr_sql(PG_FUNCTION_ARGS)
502503
*/
503504
oldcontext=MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
504505

506+
/*
507+
* Setup error traceback support for ereport()
508+
*/
509+
sqlerrcontext.callback=sql_exec_error_callback;
510+
sqlerrcontext.arg=fcinfo->flinfo;
511+
sqlerrcontext.previous=error_context_stack;
512+
error_context_stack=&sqlerrcontext;
513+
505514
/*
506515
* Initialize fcache (build plans) if first time through.
507516
*/
@@ -580,6 +589,8 @@ fmgr_sql(PG_FUNCTION_ARGS)
580589
}
581590
}
582591

592+
error_context_stack=sqlerrcontext.previous;
593+
583594
MemoryContextSwitchTo(oldcontext);
584595

585596
returnresult;
@@ -618,11 +629,74 @@ fmgr_sql(PG_FUNCTION_ARGS)
618629
}
619630
}
620631

632+
error_context_stack=sqlerrcontext.previous;
633+
621634
MemoryContextSwitchTo(oldcontext);
622635

623636
returnresult;
624637
}
625638

639+
640+
/*
641+
* error context callback to let us supply a call-stack traceback
642+
*/
643+
staticvoid
644+
sql_exec_error_callback(void*arg)
645+
{
646+
FmgrInfo*flinfo= (FmgrInfo*)arg;
647+
SQLFunctionCachePtrfcache= (SQLFunctionCachePtr)flinfo->fn_extra;
648+
char*fn_name;
649+
650+
fn_name=get_func_name(flinfo->fn_oid);
651+
/* safety check, shouldn't happen */
652+
if (fn_name==NULL)
653+
return;
654+
655+
/*
656+
* Try to determine where in the function we failed. If there is a
657+
* query with non-null QueryDesc, finger it. (We check this rather
658+
* than looking for F_EXEC_RUN state, so that errors during ExecutorStart
659+
* or ExecutorEnd are blamed on the appropriate query; see postquel_start
660+
* and postquel_end.)
661+
*/
662+
if (fcache)
663+
{
664+
execution_state*es;
665+
intquery_num;
666+
667+
es=fcache->func_state;
668+
query_num=1;
669+
while (es)
670+
{
671+
if (es->qd)
672+
{
673+
errcontext("SQL function \"%s\" query %d",
674+
fn_name,query_num);
675+
break;
676+
}
677+
es=es->next;
678+
query_num++;
679+
}
680+
if (es==NULL)
681+
{
682+
/*
683+
* couldn't identify a running query; might be function entry,
684+
* function exit, or between queries.
685+
*/
686+
errcontext("SQL function \"%s\"",fn_name);
687+
}
688+
}
689+
else
690+
{
691+
/* must have failed during init_sql_fcache() */
692+
errcontext("SQL function \"%s\" during startup",fn_name);
693+
}
694+
695+
/* free result of get_func_name (in case this is only a notice) */
696+
pfree(fn_name);
697+
}
698+
699+
626700
/*
627701
* callback function in case a function-returning-set needs to be shut down
628702
* before it has been run to completion

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.147 2003/07/25 00:01:08 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.148 2003/07/28 18:33:18 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -70,6 +70,7 @@ static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,
7070
int*usecounts);
7171
staticNode*substitute_actual_parameters_mutator(Node*node,
7272
substitute_actual_parameters_context*context);
73+
staticvoidsql_inline_error_callback(void*arg);
7374
staticExpr*evaluate_expr(Expr*expr,Oidresult_type);
7475

7576

@@ -1730,6 +1731,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
17301731
boolisNull;
17311732
MemoryContextoldcxt;
17321733
MemoryContextmycxt;
1734+
ErrorContextCallbacksqlerrcontext;
17331735
List*raw_parsetree_list;
17341736
List*querytree_list;
17351737
Query*querytree;
@@ -1780,6 +1782,15 @@ inline_function(Oid funcid, Oid result_type, List *args,
17801782
}
17811783
}
17821784

1785+
/*
1786+
* Setup error traceback support for ereport(). This is so that we can
1787+
* finger the function that bad information came from.
1788+
*/
1789+
sqlerrcontext.callback=sql_inline_error_callback;
1790+
sqlerrcontext.arg=funcform;
1791+
sqlerrcontext.previous=error_context_stack;
1792+
error_context_stack=&sqlerrcontext;
1793+
17831794
/*
17841795
* Make a temporary memory context, so that we don't leak all the
17851796
* stuff that parsing might create.
@@ -1926,12 +1937,15 @@ inline_function(Oid funcid, Oid result_type, List *args,
19261937
newexpr=eval_const_expressions_mutator(newexpr,
19271938
lconso(funcid,active_fns));
19281939

1940+
error_context_stack=sqlerrcontext.previous;
1941+
19291942
return (Expr*)newexpr;
19301943

19311944
/* Here if func is not inlinable: release temp memory and return NULL */
19321945
fail:
19331946
MemoryContextSwitchTo(oldcxt);
19341947
MemoryContextDelete(mycxt);
1948+
error_context_stack=sqlerrcontext.previous;
19351949

19361950
returnNULL;
19371951
}
@@ -1978,6 +1992,18 @@ substitute_actual_parameters_mutator(Node *node,
19781992
(void*)context);
19791993
}
19801994

1995+
/*
1996+
* error context callback to let us supply a call-stack traceback
1997+
*/
1998+
staticvoid
1999+
sql_inline_error_callback(void*arg)
2000+
{
2001+
Form_pg_procfuncform= (Form_pg_proc)arg;
2002+
2003+
errcontext("SQL function \"%s\" during inlining",
2004+
NameStr(funcform->proname));
2005+
}
2006+
19812007
/*
19822008
* evaluate_expr: pre-evaluate a constant expression
19832009
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp