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

Commit1f902d4

Browse files
committed
Inline plpgsql's exec_stmt() into exec_stmts().
This saves one level of C function call per plpgsql statement executed,and permits a tiny additional optimization of not saving and restoringestate->err_stmt for each statement in a block. The net effect seemsnearly un-measurable on x86_64, but there's a clear win on aarch64,amounting to two or three percent in a loop over a few simple plpgsqlstatements.To do this, we have to get rid of the other existing call sites forexec_stmt(). Replace them with exec_toplevel_block(), which is justdefined to do what exec_stmts() does, but for a singlePLpgSQL_stmt_block statement. Hard-wiring the expectation of whichstatement type applies here allows us to skip the dispatch switch,making this not much uglier than the previous factorization.Amit Khandekar, tweaked a bit by meDiscussion:https://postgr.es/m/CAJ3gD9eBNrmUD7WBBLG8ohaZ485H9y+4eihQTgr+K8Lhka3vcQ@mail.gmail.com
1 parentecd9e9f commit1f902d4

File tree

1 file changed

+147
-133
lines changed

1 file changed

+147
-133
lines changed

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 147 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,12 @@ static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate);
260260
staticvoidpush_stmt_mcontext(PLpgSQL_execstate*estate);
261261
staticvoidpop_stmt_mcontext(PLpgSQL_execstate*estate);
262262

263+
staticintexec_toplevel_block(PLpgSQL_execstate*estate,
264+
PLpgSQL_stmt_block*block);
263265
staticintexec_stmt_block(PLpgSQL_execstate*estate,
264266
PLpgSQL_stmt_block*block);
265267
staticintexec_stmts(PLpgSQL_execstate*estate,
266268
List*stmts);
267-
staticintexec_stmt(PLpgSQL_execstate*estate,
268-
PLpgSQL_stmt*stmt);
269269
staticintexec_stmt_assign(PLpgSQL_execstate*estate,
270270
PLpgSQL_stmt_assign*stmt);
271271
staticintexec_stmt_perform(PLpgSQL_execstate*estate,
@@ -599,11 +599,9 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
599599
* Now call the toplevel block of statements
600600
*/
601601
estate.err_text=NULL;
602-
estate.err_stmt= (PLpgSQL_stmt*) (func->action);
603-
rc=exec_stmt(&estate, (PLpgSQL_stmt*)func->action);
602+
rc=exec_toplevel_block(&estate,func->action);
604603
if (rc!=PLPGSQL_RC_RETURN)
605604
{
606-
estate.err_stmt=NULL;
607605
estate.err_text=NULL;
608606
ereport(ERROR,
609607
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
@@ -613,7 +611,6 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
613611
/*
614612
* We got a return value - process it
615613
*/
616-
estate.err_stmt=NULL;
617614
estate.err_text=gettext_noop("while casting return value to function's return type");
618615

619616
fcinfo->isnull=estate.retisnull;
@@ -1015,18 +1012,15 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
10151012
* Now call the toplevel block of statements
10161013
*/
10171014
estate.err_text=NULL;
1018-
estate.err_stmt= (PLpgSQL_stmt*) (func->action);
1019-
rc=exec_stmt(&estate, (PLpgSQL_stmt*)func->action);
1015+
rc=exec_toplevel_block(&estate,func->action);
10201016
if (rc!=PLPGSQL_RC_RETURN)
10211017
{
1022-
estate.err_stmt=NULL;
10231018
estate.err_text=NULL;
10241019
ereport(ERROR,
10251020
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
10261021
errmsg("control reached end of trigger procedure without RETURN")));
10271022
}
10281023

1029-
estate.err_stmt=NULL;
10301024
estate.err_text=gettext_noop("during function exit");
10311025

10321026
if (estate.retisset)
@@ -1176,18 +1170,15 @@ plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
11761170
* Now call the toplevel block of statements
11771171
*/
11781172
estate.err_text=NULL;
1179-
estate.err_stmt= (PLpgSQL_stmt*) (func->action);
1180-
rc=exec_stmt(&estate, (PLpgSQL_stmt*)func->action);
1173+
rc=exec_toplevel_block(&estate,func->action);
11811174
if (rc!=PLPGSQL_RC_RETURN)
11821175
{
1183-
estate.err_stmt=NULL;
11841176
estate.err_text=NULL;
11851177
ereport(ERROR,
11861178
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
11871179
errmsg("control reached end of trigger procedure without RETURN")));
11881180
}
11891181

1190-
estate.err_stmt=NULL;
11911182
estate.err_text=gettext_noop("during function exit");
11921183

11931184
/*
@@ -1584,6 +1575,40 @@ exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
15841575
}
15851576

15861577

1578+
/* ----------
1579+
* exec_toplevel_blockExecute the toplevel block
1580+
*
1581+
* This is intentionally equivalent to executing exec_stmts() with a
1582+
* list consisting of the one statement. One tiny difference is that
1583+
* we do not bother to save the entry value of estate->err_stmt;
1584+
* that's assumed to be NULL.
1585+
* ----------
1586+
*/
1587+
staticint
1588+
exec_toplevel_block(PLpgSQL_execstate*estate,PLpgSQL_stmt_block*block)
1589+
{
1590+
intrc;
1591+
1592+
estate->err_stmt= (PLpgSQL_stmt*)block;
1593+
1594+
/* Let the plugin know that we are about to execute this statement */
1595+
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_beg)
1596+
((*plpgsql_plugin_ptr)->stmt_beg) (estate, (PLpgSQL_stmt*)block);
1597+
1598+
CHECK_FOR_INTERRUPTS();
1599+
1600+
rc=exec_stmt_block(estate,block);
1601+
1602+
/* Let the plugin know that we have finished executing this statement */
1603+
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_end)
1604+
((*plpgsql_plugin_ptr)->stmt_end) (estate, (PLpgSQL_stmt*)block);
1605+
1606+
estate->err_stmt=NULL;
1607+
1608+
returnrc;
1609+
}
1610+
1611+
15871612
/* ----------
15881613
* exec_stmt_blockExecute a block of statements
15891614
* ----------
@@ -1917,6 +1942,7 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
19171942
staticint
19181943
exec_stmts(PLpgSQL_execstate*estate,List*stmts)
19191944
{
1945+
PLpgSQL_stmt*save_estmt=estate->err_stmt;
19201946
ListCell*s;
19211947

19221948
if (stmts==NIL)
@@ -1933,162 +1959,150 @@ exec_stmts(PLpgSQL_execstate *estate, List *stmts)
19331959
foreach(s,stmts)
19341960
{
19351961
PLpgSQL_stmt*stmt= (PLpgSQL_stmt*)lfirst(s);
1936-
intrc=exec_stmt(estate,stmt);
1937-
1938-
if (rc!=PLPGSQL_RC_OK)
1939-
returnrc;
1940-
}
1962+
intrc;
19411963

1942-
returnPLPGSQL_RC_OK;
1943-
}
1964+
estate->err_stmt=stmt;
19441965

1966+
/* Let the plugin know that we are about to execute this statement */
1967+
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_beg)
1968+
((*plpgsql_plugin_ptr)->stmt_beg) (estate,stmt);
19451969

1946-
/* ----------
1947-
* exec_stmtDistribute one statement to the statements
1948-
*type specific execution function.
1949-
* ----------
1950-
*/
1951-
staticint
1952-
exec_stmt(PLpgSQL_execstate*estate,PLpgSQL_stmt*stmt)
1953-
{
1954-
PLpgSQL_stmt*save_estmt;
1955-
intrc=-1;
1956-
1957-
save_estmt=estate->err_stmt;
1958-
estate->err_stmt=stmt;
1970+
CHECK_FOR_INTERRUPTS();
19591971

1960-
/* Let the plugin know that we are about to execute this statement */
1961-
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_beg)
1962-
((*plpgsql_plugin_ptr)->stmt_beg) (estate,stmt);
1972+
switch (stmt->cmd_type)
1973+
{
1974+
casePLPGSQL_STMT_BLOCK:
1975+
rc=exec_stmt_block(estate, (PLpgSQL_stmt_block*)stmt);
1976+
break;
19631977

1964-
CHECK_FOR_INTERRUPTS();
1978+
casePLPGSQL_STMT_ASSIGN:
1979+
rc=exec_stmt_assign(estate, (PLpgSQL_stmt_assign*)stmt);
1980+
break;
19651981

1966-
switch (stmt->cmd_type)
1967-
{
1968-
casePLPGSQL_STMT_BLOCK:
1969-
rc=exec_stmt_block(estate, (PLpgSQL_stmt_block*)stmt);
1970-
break;
1982+
casePLPGSQL_STMT_PERFORM:
1983+
rc=exec_stmt_perform(estate, (PLpgSQL_stmt_perform*)stmt);
1984+
break;
19711985

1972-
casePLPGSQL_STMT_ASSIGN:
1973-
rc=exec_stmt_assign(estate, (PLpgSQL_stmt_assign*)stmt);
1974-
break;
1986+
casePLPGSQL_STMT_CALL:
1987+
rc=exec_stmt_call(estate, (PLpgSQL_stmt_call*)stmt);
1988+
break;
19751989

1976-
casePLPGSQL_STMT_PERFORM:
1977-
rc=exec_stmt_perform(estate, (PLpgSQL_stmt_perform*)stmt);
1978-
break;
1990+
casePLPGSQL_STMT_GETDIAG:
1991+
rc=exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag*)stmt);
1992+
break;
19791993

1980-
casePLPGSQL_STMT_CALL:
1981-
rc=exec_stmt_call(estate, (PLpgSQL_stmt_call*)stmt);
1982-
break;
1994+
casePLPGSQL_STMT_IF:
1995+
rc=exec_stmt_if(estate, (PLpgSQL_stmt_if*)stmt);
1996+
break;
19831997

1984-
casePLPGSQL_STMT_GETDIAG:
1985-
rc=exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag*)stmt);
1986-
break;
1998+
casePLPGSQL_STMT_CASE:
1999+
rc=exec_stmt_case(estate, (PLpgSQL_stmt_case*)stmt);
2000+
break;
19872001

1988-
casePLPGSQL_STMT_IF:
1989-
rc=exec_stmt_if(estate, (PLpgSQL_stmt_if*)stmt);
1990-
break;
2002+
casePLPGSQL_STMT_LOOP:
2003+
rc=exec_stmt_loop(estate, (PLpgSQL_stmt_loop*)stmt);
2004+
break;
19912005

1992-
casePLPGSQL_STMT_CASE:
1993-
rc=exec_stmt_case(estate, (PLpgSQL_stmt_case*)stmt);
1994-
break;
2006+
casePLPGSQL_STMT_WHILE:
2007+
rc=exec_stmt_while(estate, (PLpgSQL_stmt_while*)stmt);
2008+
break;
19952009

1996-
casePLPGSQL_STMT_LOOP:
1997-
rc=exec_stmt_loop(estate, (PLpgSQL_stmt_loop*)stmt);
1998-
break;
2010+
casePLPGSQL_STMT_FORI:
2011+
rc=exec_stmt_fori(estate, (PLpgSQL_stmt_fori*)stmt);
2012+
break;
19992013

2000-
casePLPGSQL_STMT_WHILE:
2001-
rc=exec_stmt_while(estate, (PLpgSQL_stmt_while*)stmt);
2002-
break;
2014+
casePLPGSQL_STMT_FORS:
2015+
rc=exec_stmt_fors(estate, (PLpgSQL_stmt_fors*)stmt);
2016+
break;
20032017

2004-
casePLPGSQL_STMT_FORI:
2005-
rc=exec_stmt_fori(estate, (PLpgSQL_stmt_fori*)stmt);
2006-
break;
2018+
casePLPGSQL_STMT_FORC:
2019+
rc=exec_stmt_forc(estate, (PLpgSQL_stmt_forc*)stmt);
2020+
break;
20072021

2008-
casePLPGSQL_STMT_FORS:
2009-
rc=exec_stmt_fors(estate, (PLpgSQL_stmt_fors*)stmt);
2010-
break;
2022+
casePLPGSQL_STMT_FOREACH_A:
2023+
rc=exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a*)stmt);
2024+
break;
20112025

2012-
casePLPGSQL_STMT_FORC:
2013-
rc=exec_stmt_forc(estate, (PLpgSQL_stmt_forc*)stmt);
2014-
break;
2026+
casePLPGSQL_STMT_EXIT:
2027+
rc=exec_stmt_exit(estate, (PLpgSQL_stmt_exit*)stmt);
2028+
break;
20152029

2016-
casePLPGSQL_STMT_FOREACH_A:
2017-
rc=exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a*)stmt);
2018-
break;
2030+
casePLPGSQL_STMT_RETURN:
2031+
rc=exec_stmt_return(estate, (PLpgSQL_stmt_return*)stmt);
2032+
break;
20192033

2020-
casePLPGSQL_STMT_EXIT:
2021-
rc=exec_stmt_exit(estate, (PLpgSQL_stmt_exit*)stmt);
2022-
break;
2034+
casePLPGSQL_STMT_RETURN_NEXT:
2035+
rc=exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next*)stmt);
2036+
break;
20232037

2024-
casePLPGSQL_STMT_RETURN:
2025-
rc=exec_stmt_return(estate, (PLpgSQL_stmt_return*)stmt);
2026-
break;
2038+
casePLPGSQL_STMT_RETURN_QUERY:
2039+
rc=exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query*)stmt);
2040+
break;
20272041

2028-
casePLPGSQL_STMT_RETURN_NEXT:
2029-
rc=exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next*)stmt);
2030-
break;
2042+
casePLPGSQL_STMT_RAISE:
2043+
rc=exec_stmt_raise(estate, (PLpgSQL_stmt_raise*)stmt);
2044+
break;
20312045

2032-
casePLPGSQL_STMT_RETURN_QUERY:
2033-
rc=exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query*)stmt);
2034-
break;
2046+
casePLPGSQL_STMT_ASSERT:
2047+
rc=exec_stmt_assert(estate, (PLpgSQL_stmt_assert*)stmt);
2048+
break;
20352049

2036-
casePLPGSQL_STMT_RAISE:
2037-
rc=exec_stmt_raise(estate, (PLpgSQL_stmt_raise*)stmt);
2038-
break;
2050+
casePLPGSQL_STMT_EXECSQL:
2051+
rc=exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql*)stmt);
2052+
break;
20392053

2040-
casePLPGSQL_STMT_ASSERT:
2041-
rc=exec_stmt_assert(estate, (PLpgSQL_stmt_assert*)stmt);
2042-
break;
2054+
casePLPGSQL_STMT_DYNEXECUTE:
2055+
rc=exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute*)stmt);
2056+
break;
20432057

2044-
casePLPGSQL_STMT_EXECSQL:
2045-
rc=exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql*)stmt);
2046-
break;
2058+
casePLPGSQL_STMT_DYNFORS:
2059+
rc=exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors*)stmt);
2060+
break;
20472061

2048-
casePLPGSQL_STMT_DYNEXECUTE:
2049-
rc=exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute*)stmt);
2050-
break;
2062+
casePLPGSQL_STMT_OPEN:
2063+
rc=exec_stmt_open(estate, (PLpgSQL_stmt_open*)stmt);
2064+
break;
20512065

2052-
casePLPGSQL_STMT_DYNFORS:
2053-
rc=exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors*)stmt);
2054-
break;
2066+
casePLPGSQL_STMT_FETCH:
2067+
rc=exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch*)stmt);
2068+
break;
20552069

2056-
casePLPGSQL_STMT_OPEN:
2057-
rc=exec_stmt_open(estate, (PLpgSQL_stmt_open*)stmt);
2058-
break;
2070+
casePLPGSQL_STMT_CLOSE:
2071+
rc=exec_stmt_close(estate, (PLpgSQL_stmt_close*)stmt);
2072+
break;
20592073

2060-
casePLPGSQL_STMT_FETCH:
2061-
rc=exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch*)stmt);
2062-
break;
2074+
casePLPGSQL_STMT_COMMIT:
2075+
rc=exec_stmt_commit(estate, (PLpgSQL_stmt_commit*)stmt);
2076+
break;
20632077

2064-
casePLPGSQL_STMT_CLOSE:
2065-
rc=exec_stmt_close(estate, (PLpgSQL_stmt_close*)stmt);
2066-
break;
2078+
casePLPGSQL_STMT_ROLLBACK:
2079+
rc=exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback*)stmt);
2080+
break;
20672081

2068-
casePLPGSQL_STMT_COMMIT:
2069-
rc=exec_stmt_commit(estate, (PLpgSQL_stmt_commit*)stmt);
2070-
break;
2082+
casePLPGSQL_STMT_SET:
2083+
rc=exec_stmt_set(estate, (PLpgSQL_stmt_set*)stmt);
2084+
break;
20712085

2072-
casePLPGSQL_STMT_ROLLBACK:
2073-
rc=exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback*)stmt);
2074-
break;
2086+
default:
2087+
/* point err_stmt to parent, since this one seems corrupt */
2088+
estate->err_stmt=save_estmt;
2089+
elog(ERROR,"unrecognized cmd_type: %d",stmt->cmd_type);
2090+
rc=-1;/* keep compiler quiet */
2091+
}
20752092

2076-
casePLPGSQL_STMT_SET:
2077-
rc=exec_stmt_set(estate, (PLpgSQL_stmt_set*)stmt);
2078-
break;
2093+
/* Let the plugin know that we have finished executing this statement */
2094+
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_end)
2095+
((*plpgsql_plugin_ptr)->stmt_end) (estate,stmt);
20792096

2080-
default:
2097+
if (rc!=PLPGSQL_RC_OK)
2098+
{
20812099
estate->err_stmt=save_estmt;
2082-
elog(ERROR,"unrecognized cmd_type: %d",stmt->cmd_type);
2083-
}
2084-
2085-
/* Let the plugin know that we have finished executing this statement */
2086-
if (*plpgsql_plugin_ptr&& (*plpgsql_plugin_ptr)->stmt_end)
2087-
((*plpgsql_plugin_ptr)->stmt_end) (estate,stmt);
2100+
returnrc;
2101+
}
2102+
}/* end of loop over statements */
20882103

20892104
estate->err_stmt=save_estmt;
2090-
2091-
returnrc;
2105+
returnPLPGSQL_RC_OK;
20922106
}
20932107

20942108

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp