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

Attachment: 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)
{
}

Attachment: simple--1.0.sql
Description: application/sql

Attachment: simple.control
Description: Binary data

Reply via email to