VIP: plpgsql - early embedded sql plan preparation

Lists: pgsql-hackers
From: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: VIP: plpgsql - early embedded sql plan preparation
Date: 2011-08-23 11:30:19
Message-ID: CAFj8pRA5D203yTn3HNG1fyphLXsUNYSR+u93WaGuQ3sRs7HaJQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Hello

I am returning back to discus two months ago about usage of
plpgsql_lint. I integrated this module to plpgsql's core. This feature
is controlled via plpgsql GUC variable prepare_plans and via plpgsql
option. It works with all plpgsql's regress tests without tests where
dynamic sql or refcursors are used. Early plan preparation is disabled
default so it should not to break current applications.

This feature can live as contrib module too, but integration has one
advantage - there is still a possibility to use other plpgsql
extensions - mainly plpgsql debugger.

I didn't work on documentation yet, so I there is small example:

CREATE TYPE tp AS (a int, b int);

CREATE OR REPLACE FUNCTION test()
RETURNS int AS $$
DECLARE v tp;
BEGIN
v := (10,20);
IF false THEN
RAISE NOTICE '%', v.z;
END IF;
RETURN v.a;
END;
$$ LANGUAGE plpgsql;

postgres=# SELECT test();
test
------
10
(1 row)

with enabled early planning it found a bug in not executed code

CREATE OR REPLACE FUNCTION public.test()
RETURNS integer
LANGUAGE plpgsql
AS $function$
#prepare_plans on_start
DECLARE v tp;
BEGIN
v := (10,20);
IF false THEN
RAISE NOTICE '%', v.z;
END IF;
RETURN v.a;
END;
$function$

postgres=# select test();
ERROR: record "v" has no field "z"
LINE 1: SELECT v.z
^
QUERY: SELECT v.z
CONTEXT: PL/pgSQL function "test" line 7 at RAISE

you can set GUC

postgres=# set plpgsql.prepare_plans to on_start;
SET

and you can overwrite this global setting with directive
#prepare_plans on_demand

CREATE OR REPLACE FUNCTION public.test()
RETURNS integer
LANGUAGE plpgsql
AS $function$
#prepare_plans on_demand
DECLARE v tp;
BEGIN
v := (10,20);
IF false THEN
RAISE NOTICE '%', v.z;
END IF;
RETURN v.a;
END;
$function$

Regards

Pavel Stehule

Attachment Content-Type Size
prepare_plans.patch text/x-patch 52.4 KB

From: Merlin Moncure <mmoncure(at)gmail(dot)com>
To: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: VIP: plpgsql - early embedded sql plan preparation
Date: 2011-08-23 12:09:02
Message-ID: CAHyXU0wPLo6=yE5LPxABtq1k3foAOhvS4FwfQFN9O1dT5mJjtQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Aug 23, 2011 at 6:30 AM, Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com> wrote:
> Hello
>
> I am returning back to discus two months ago about usage of
> plpgsql_lint. I integrated this module to plpgsql's core. This feature
> is controlled via plpgsql GUC variable prepare_plans and via plpgsql
> option. It works with all plpgsql's regress tests without tests where
> dynamic sql or refcursors are used. Early plan preparation is disabled
> default so it should not to break current applications.
>
> This feature can live as contrib module too, but integration has one
> advantage - there is still a possibility to use other plpgsql
> extensions - mainly plpgsql debugger.
>
> I didn't work on documentation yet, so I there is small example:
>
> CREATE TYPE tp AS (a int, b int);
>
> CREATE OR REPLACE FUNCTION test()
> RETURNS int AS $$
> DECLARE v tp;
> BEGIN
> v := (10,20);
> IF false THEN
>  RAISE NOTICE '%', v.z;
> END IF;
> RETURN v.a;
> END;
> $$ LANGUAGE plpgsql;
>
> postgres=# SELECT test();
>  test
> ------
>   10
> (1 row)
>
> with enabled early planning it found a bug in not executed code
>
> CREATE OR REPLACE FUNCTION public.test()
>  RETURNS integer
>  LANGUAGE plpgsql
> AS $function$
> #prepare_plans on_start
> DECLARE v tp;
> BEGIN
> v := (10,20);
> IF false THEN
>  RAISE NOTICE '%', v.z;
> END IF;
> RETURN v.a;
> END;
> $function$
>
> postgres=# select test();
> ERROR:  record "v" has no field "z"
> LINE 1: SELECT v.z
>               ^
> QUERY:  SELECT v.z
> CONTEXT:  PL/pgSQL function "test" line 7 at RAISE
>
> you can set GUC
>
> postgres=# set plpgsql.prepare_plans to on_start;
> SET
>
> and you can overwrite this global setting with directive
> #prepare_plans on_demand
>
> CREATE OR REPLACE FUNCTION public.test()
>  RETURNS integer
>  LANGUAGE plpgsql
> AS $function$
> #prepare_plans on_demand
> DECLARE v tp;
> BEGIN
> v := (10,20);
> IF false THEN
>  RAISE NOTICE '%', v.z;
> END IF;
> RETURN v.a;
> END;
> $function$
>
> Regards
>
> Pavel Stehule

Is it possible to raise warnings at function creation time?

merlin


From: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
To: Merlin Moncure <mmoncure(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: VIP: plpgsql - early embedded sql plan preparation
Date: 2011-08-23 12:16:06
Message-ID: CAFj8pRDC3DgDrFRniA3zZErersa+TTeKjG95Rm19E5O=F1QPuA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

>
> Is it possible to raise warnings at function creation time?
>

when this code will be in core, then it is possible without one
significant exceptions - triggers :( I am not able to specify a target
table - and real type for NEW and OLD records.

Regards

Pavel

> merlin
>