pá 28. 12. 2018 v 3:26 odesílatel Michael Paquier <mich...@paquier.xyz> napsal:
> On Wed, Dec 26, 2018 at 07:02:04AM +0100, Pavel Stehule wrote: > > is called two times, what is not expected, if you don't know some about > > this inconsistency. > > > > So it is reason, why I don't think so current behave is correct. On > second > > hand, the impact is very small - only few extensions uses plpgsql plugin > > API, and workaround is not hard. So I can live with current state if > nobody > > see this issue (sure - it is minor issue). > > Hm. Using the following functions based on the code of above, I can > see the following numbers if I place some trackers (elog(WARNING) > entries) at the beginning of each callback part of plpgsql_check.c to > measure how many times a callback is done: > CREATE OR REPLACE FUNCTION public.f2() > RETURNS void > LANGUAGE plpgsql > AS $$ > DECLARE x int; > BEGIN > x := 2; > RETURN; > END; > $$; > CREATE OR REPLACE FUNCTION public.f3() > RETURNS void > LANGUAGE plpgsql > AS $$ > DECLARE x int; > BEGIN > BEGIN > x := 3; > RETURN; > END; > END > $$; > > On HEAD, for plpgsql_check_function_tb('f2()'): > - stmt_beg is called 4 times. > - stmt_end is called 3 times. > - func_setup is called 2 times. > - func_beg is called 2 times. > - func_end is called 2 times. > For plpgsql_check_function_tb('f3()'): > - stmt_beg is called 3 times. > - stmt_end is called 3 times. > - func_setup is called 1 time. > - func_beg is called 1 time. > - func_end is called 2 times. > > So based on the previous example f2 gets over f3 one extra stmt_beg, > one extra func_beg and one extra func_setup. > > With patched HEAD, I got for f2: > - stmt_beg is called 6 times. > - stmt_end is called 5 times. > - func_setup is called 2 times. > - func_beg is called 2 times. > - func_end is called 2 times. > And for f3: > - stmt_beg is called 6 times. > - stmt_end is called 5 times. > - func_setup is called 2 times. > - func_beg is called 2 times. > - func_end is called 2 times. > -- > Michael > These numbers are little bit strange - maybe due using plpgsql_check. I wrote simple extension (see attachment) CREATE OR REPLACE FUNCTION public.f2() RETURNS void LANGUAGE plpgsql 1 AS $function$ 2 DECLARE x int; 3 BEGIN 4 x := 2; 5 RETURN; 6 END; 7 $function$ CREATE OR REPLACE FUNCTION public.f3() RETURNS void LANGUAGE plpgsql 1 AS $function$ 2 DECLARE x int; 3 BEGIN 4 BEGIN 5 x := 3; 6 RETURN; 7 END; 8 END 9 $function$ load 'simple'; select f2(); postgres=# select f2(); NOTICE: func setup: "f2()" NOTICE: func beg: "f2()" NOTICE: stmt beg - ln: 4 NOTICE: stmt end - ln: 4 NOTICE: stmt beg - ln: 5 NOTICE: stmt end - ln: 5 NOTICE: func end: "f2()" NOTICE: func setup: "f3()" NOTICE: func beg: "f3()" NOTICE: stmt beg - ln: 4 NOTICE: stmt beg - ln: 5 NOTICE: stmt end - ln: 5 NOTICE: stmt beg - ln: 6 NOTICE: stmt end - ln: 6 NOTICE: stmt end - ln: 4 NOTICE: func end: "f3()" patched postgres=# select f2(); NOTICE: func setup: "f2()" NOTICE: func beg: "f2()" NOTICE: stmt beg - ln: 3 NOTICE: stmt beg - ln: 4 NOTICE: stmt end - ln: 4 NOTICE: stmt beg - ln: 5 NOTICE: stmt end - ln: 5 NOTICE: stmt end - ln: 3 NOTICE: func end: "f2()" postgres=# select f3(); NOTICE: func setup: "f3()" NOTICE: func beg: "f3()" NOTICE: stmt beg - ln: 3 NOTICE: stmt beg - ln: 4 NOTICE: stmt beg - ln: 5 NOTICE: stmt end - ln: 5 NOTICE: stmt beg - ln: 6 NOTICE: stmt end - ln: 6 NOTICE: stmt end - ln: 4 NOTICE: stmt end - ln: 3 NOTICE: func end: "f3()" There is only one difference - the plugin routine stmt_begin and stmt_end is called for line 3. Nothing less, nothing more. Internal evaluation of plpgsql code is same - the change is only for plugin code - one more stmt_beg and stmt_end call - as expected and wanted. Real impact - now, I have to push my code to func_beg, func_end, stmt_beg, stmt_end. With patch I can push my code just to stmt_beg, stmt_end. Regards Pavel
Makefile
Description: Binary data
#include "postgres.h" #include "plpgsql.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif static void func_setup(PLpgSQL_execstate * estate, PLpgSQL_function * func); static void func_beg(PLpgSQL_execstate *estate, PLpgSQL_function *func); static void func_end(PLpgSQL_execstate *estate, PLpgSQL_function *func); static void stmt_beg(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt); static void stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt); static PLpgSQL_plugin plugin_funcs = { func_setup, func_beg, func_end, stmt_beg, stmt_end, NULL, NULL}; void _PG_init(void); void _PG_fini(void); static void func_setup(PLpgSQL_execstate * estate, PLpgSQL_function * func) { elog(NOTICE, "func setup: \"%s\"", func->fn_signature); } static void func_beg(PLpgSQL_execstate *estate, PLpgSQL_function *func) { elog(NOTICE, "func beg: \"%s\"", func->fn_signature); } static void func_end(PLpgSQL_execstate *estate, PLpgSQL_function *func) { elog(NOTICE, "func end: \"%s\"", func->fn_signature); } static void stmt_beg(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt) { elog(NOTICE, "stmt beg - ln: %d", stmt->lineno); } static void stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt) { elog(NOTICE, "stmt end - ln: %d", stmt->lineno); } void _PG_init(void) { PLpgSQL_plugin ** var_ptr = (PLpgSQL_plugin **) find_rendezvous_variable( "PLpgSQL_plugin" ); static bool inited = false; if (inited) return; *var_ptr = &plugin_funcs; } /* * Module unload callback */ void _PG_fini(void) { }
simple--1.0.sql
Description: application/sql
simple.control
Description: Binary data