2017-04-05 22:33 GMT+02:00 Andres Freund <and...@anarazel.de>: > Hi, > > > I'd like some input from other committers whether we want this. I'm > somewhat doubtful, but don't have particularly strong feelings. > > > > + > > + <sect2 id="plpgsql-declaration-pragma"> > > + <title>Block level PRAGMA</title> > > + > > + <indexterm> > > + <primary>PRAGMA</> > > + <secondary>in PL/pgSQL</> > > + </indexterm> > > + > > + <para> > > + The block level <literal>PRAGMA</literal> allows to change the > > + <application>PL/pgSQL</application> compiler behavior. Currently > > + only <literal>PRAGMA PLAN_CACHE</literal> is supported. > > Why are we doing this on a block level? >
There are few reasons: 1. it is practical for some cases to mix more plan strategies in one function a) FOR IN simple_select LOOP ENFORCE ONE SHOT PLANS BEGIN .. queries .. END; END LOOP; b) ENFORCE ONE SHOT PLANS BEGIN FOR IN complex query requires one shot plan LOOP RETURNS TO DEFAULT PLAN CACHE BEGIN .. queries .. END; END LOOP; 2. This behave is defined in Ada language, and in PL/SQL too. If we will have autonomous transactions, then we can have a equal functionality a) run complete function under autonomous transaction b) run some parts of function (some blocks) under autonomous transaction It is not necessary, but it can avoid to generate auxiliary functions. > > > > +<programlisting> > > +CREATE FUNCTION enforce_fresh_plan(_id text) RETURNS boolean AS $$ > > +DECLARE > > + PRAGMA PLAN_CACHE(force_custom_plan); > > +BEGIN > > + -- in this block every embedded query uses one shot plan > > *plans > > > > + <sect3 id="PRAGMA-PLAN_CACHE"> > > + <title>PRAGMA PLAN_CACHE</title> > > + > > + <para> > > + The plan cache behavior can be controlled using > > + <literal>PRAGMA PLAN_CACHE</>. This <literal>PRAGMA</> can be > used both > > + for whole function or in individual blocks. The following options > are > > *functions > > > > + possible: <literal>DEFAULT</literal> - default > > + <application>PL/pgSQL</application> implementation - the system > tries > > + to decide between custom plan and generic plan after five query > > + executions, <literal>FORCE_CUSTOM_PLAN</literal> - the chosen > execution > > + plan will be the one shot plan - it is specific for every set of > > + used paramaters, <literal>FORCE_GENERIC_PLAN</literal> - the > generic > > + plan will be used from the start. > > I don't think it's a good idea to explain this here, this'll just get > outdated. I think we should rather have a link here. > > > > + </para> > > + > > + <para> > > + <indexterm> > > + <primary>PRAGMA PLAN_CACHE</> > > + <secondary>in PL/pgSQL</> > > + </indexterm> > > + The plan for <command>INSERT</command> is always a generic > > plan. > > That's this specific insert, right? Should be mentioned, sounds more > generic to me. > > > +/* ---------- > > + * Returns pointer to current compiler settings > > + * ---------- > > + */ > > +PLpgSQL_settings * > > +plpgsql_current_settings(void) > > +{ > > + return current_settings; > > +} > > + > > + > > +/* ---------- > > + * Setup default compiler settings > > + * ---------- > > + */ > > +void > > +plpgsql_settings_init(PLpgSQL_settings *settings) > > +{ > > + current_settings = settings; > > +} > > Hm. This is only ever set to &default_settings. > > > > +/* ---------- > > + * Set compiler settings > > + * ---------- > > + */ > > +void > > +plpgsql_settings_set(PLpgSQL_settings *settings) > > +{ > > + PLpgSQL_nsitem *ns_cur = ns_top; > > + > > + /* > > + * Modify settings directly, when ns has local settings data. > > + * When ns uses shared settings, create settings first. > > + */ > > + while (ns_cur->itemtype != PLPGSQL_NSTYPE_LABEL) > > + ns_cur = ns_cur->prev; > > + > > + if (ns_cur->local_settings == NULL) > > + { > > + ns_cur->local_settings = palloc(sizeof(PLpgSQL_settings)); > > + ns_cur->local_settings->prev = current_settings; > > + current_settings = ns_cur->local_settings; > > + } > > + > > + current_settings->cursor_options = settings->cursor_options; > > +} > > This seems like a somewhat weird method. Why do we have a global > settings, when we essentially just want to use something in the current > ns? > > I am not sure if I understand to question. This settings is implemented as lazy. If ns has not any own settings, then nothing is done. It requires some global variable, because some ns can be skipped. My first implementation was 1:1 .. ns:settings - but it add some overhead for any ns although ns has not own settings. Regards Pavel > > > - Andres >