Обсуждение: proposal: extensible plpgsql executor - related to assertions

Поиск
Список
Период
Сортировка

proposal: extensible plpgsql executor - related to assertions

От
Pavel Stehule
Дата:
Hello

I am thinking how to implement a assertions and tracking to plpgsql. This area is not strict and clear - everybody would little bit different functionality - and implementation can be different if someone use a psql as main client or some GUI. So I am sceptical to implement assertion directly to plpgsql.  Now I finished plpgsql_check_function as extension and I had to use a plpgsql plugin API again.

This API is good enough to enable extensible plpgsql executor. It can be implemened via stmt_beg call, although a special hook can be better.

typedef struct
{
        /* Function pointers set up by the plugin */
        void            (*func_setup) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
        void            (*func_beg) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
        void            (*func_end) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
        void            (*stmt_beg) (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt);
        void            (*stmt_end) (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt);

        /* Function pointers set by PL/pgSQL itself */
        void            (*error_callback) (void *arg);
        void            (*assign_expr) (PLpgSQL_execstate *estate, PLpgSQL_datum *target,
                                                                                        PLpgSQL_expr *expr);
} PLpgSQL_plugin;


What is missing is a possibility to invoke some custom functionality (implemented in plugin-extension) from plpgsql code. What example, I can try to print function parameters, local variables at some point, assertions, tracking, ... Usually we would to ignore any action, when plugin is not active. This ensure a minimal slowdown on production when we don´t would to enable assertions, but we don´t would to modify source code.

I propose a enhance the PLpgSQL_plugin struct by a new hook

      void  (*pragma)(PLpgSQL_execstate *estate, PLpgSQL_pragma *pragma_stmt)

typedef struct
{
   int cmd_type;
   int lineno;
   char *refname;
   List *exprs;
} pragma_stmt;

PLpgSQL executor should to execute this statement only when pragma hook is defined.

Syntax of PL/pgSQL should be enhanced about statement pragma

Syntax:

pragma pragmaname [ [ ( ]  expr, [expr .. ]  [ ) ] ]

This syntax should be checked by plpgsql compiler, but and it is important - it is not executed by plpgsql executor ever (minimally in this proposal). So if you don´t would active assertions, then you don´t load a plugin with assertion implementation.

Expressions are executed by plugin, and it is on plugin responsibility.

So with this functionality we can implement tracking, variable dumping, assertions

pragma dump_local_variables;
pragma dump_parameters;
pragma assert(a = 10, ´variable a is not 10´);
pragma warning(a > 100, ´a > 100´);
pragma notice a > 100, format('a = "%s"', a);
  ...

This proposal should not break any current plpgsql code and it is generic - require only minimal changes in plpgsql runtime. Any current plpgsql plugins should be workable after compilation (but recompilation is required for any new version).

Pragma can be used for other plpgsql plugin as other way how to push a some complex (or simple) parameters to plpgsql related extensions

pragma disable_plpgsql_check;

Opinions, ideas?

Regards

Pavel

Re: proposal: extensible plpgsql executor - related to assertions

От
Tom Lane
Дата:
Pavel Stehule <pavel.stehule@gmail.com> writes:
> I propose a enhance the PLpgSQL_plugin struct by a new hook
>       void  (*pragma)(PLpgSQL_execstate *estate, PLpgSQL_pragma
> *pragma_stmt)

I repeat what I said a couple of days ago: it's a very bad idea to be
enabling more plpgsql plugins as long as the infrastructure can only
support one.  We need to fix that *first* before we go merrily designing
more.

I don't like the notion of a pragma statement in this form anyway,
because you've essentially made it an executable statement; usually
pragmas are compile-time things.  It appears to me that you've basically
commandeered the word "pragma" for "SET affecting a plugin's variable".
If we're inventing new callbacks for plugins, why not one that will extend
an existing statement having the right kind of semantics?  Or actually,
why would it not be better for the plugin to be using a custom GUC for
its variable?  There's a large amount of infrastructure that custom GUCs
can take advantage of, which you'd otherwise have to reinvent piece
by piece.
        regards, tom lane



Re: proposal: extensible plpgsql executor - related to assertions

От
Pavel Stehule
Дата:



2014/1/4 Tom Lane <tgl@sss.pgh.pa.us>
Pavel Stehule <pavel.stehule@gmail.com> writes:
> I propose a enhance the PLpgSQL_plugin struct by a new hook
>       void  (*pragma)(PLpgSQL_execstate *estate, PLpgSQL_pragma
> *pragma_stmt)

I repeat what I said a couple of days ago: it's a very bad idea to be
enabling more plpgsql plugins as long as the infrastructure can only
support one.  We need to fix that *first* before we go merrily designing
more.

It means a some additional mechanism to find_rendezvous_variable.

What about two new rendezvous variables? One for publishing a PLpgSQL internal API, and second a list of plpgsql_plugin structures?  It would be very nice, if we can better access to other plpgsql public functions. A implementation in plpgsql_lint and plpgsql_check is working, but I agree so it is ugly designed (with some disadvantages) - and any change can be better. I minimize these bad references to plpgsq - but plpgsql requires "plpgsql_compile" and "plpgsql_parser_setup" still.

Other possibility is new V1 function for plugin registration.
 

I don't like the notion of a pragma statement in this form anyway,
because you've essentially made it an executable statement; usually
pragmas are compile-time things.  It appears to me that you've basically
commandeered the word "pragma" for "SET affecting a plugin's variable".

It should not be named pragma - I have not better name now. It should not be used as plugin's variable primary.

It should to invoke a external routine - with or without additional parameters. When I would to support tracking, then user should to explicitly set point, where tracking is defined - same is with assertions.
 
If we're inventing new callbacks for plugins, why not one that will extend
an existing statement having the right kind of semantics?

yes, it is possible - I can to image some like PERFORM assert(exprlist)

and inside callback, we can check a expression and when we find a expected pattern, we can change a semantic. I plan to use this workaround for first plpgsql dumper and tracking extension. But it can have some performance (probably minimal) impact - and it is difficult to implement a mode when this functionality is disabled without any performance impact. So special statement can simplify life to plugin' developers.

 
 Or actually,
why would it not be better for the plugin to be using a custom GUC for
its variable?  There's a large amount of infrastructure that custom GUCs
can take advantage of, which you'd otherwise have to reinvent piece
by piece.


GUC doesn't help me with marking some position in source code  important for plugin.

Regards

Pavel
 

                        regards, tom lane