Hlavní navigace

Letmé letní seznámení s PL/pgSQL v PostgreSQL 7.5

Pavel Stěhule

Brzy bude k dispozici alfa verze PostgreSQL 7.5 (8.0). Předpokládám, že si Karel Žák nenechá ujít tuto příležitost a na stránkách roota poreferuje o všech novinkách této verze, kterých není málo. Nebudu se mu proto míchat do řemesla, nastíním jen několik užitečných změn v PL/pgSQL.

Mimochodem, tuto verzi používám bezproblémově několik měsíců v produkční bázi. Což svědčí jednak o mé lehkomyslnosti, jednak o kvalitní práci vývojového týmu PostgreSQL. V mém případě se nejedná o příliš zatíženou databázi, jde mi hlavně o rychlé provádění komplikovanějších SQL dotazů, a to PostgreSQL 7.5 zvládá s přehledem. Vyzkoušel jsem si i nativní verzi pro WinNT (bez cygwina), a řekl bych, že je PostgreSQL rychlejší nebo stejně rychlá jako MSSQL. Nerozumím tunningu MSSQL, konfigurace PostgreSQL zůstala ale také výchozí.

Snad nejpodstatnější změnou je možnost zápisu těla funkce mezi dvojici symbolů $$. Pokud použijeme tuto variantu zápisu, nemusíme zdvojovat apostrofy. Že se zpřehlední zápis, je bez diskuse. Ve všech příkladech používám tento zápis.

V dřívějších verzích jsme mohli určit výchozí hodnoty proměnných, nicméně zápis povoloval pouze konstanty. Počínaje 7.5 můžeme výchozí hodnotu dopočítat. Můžeme tak např. lépe simulovat parametry předávané hodnotou (alias i pojmenované parametry jsou stále read only). PL/pgSQL podporuje konečně pojmenované parametry. V dřívějších verzích byly parametry funkce přístupné pouze prostřednictvím $index proměnných. Pozor: stávající PhpPgAdmin tuto vlastnost nepodporuje, a pokud se pokusíte editovat funkci s pojmenovanými parametry, dočkáte se nemilého překvapení. PostgreSQL stále nepodporuje OUT a INOUT parametry. Výchozí hodnotu proměnné nelze určit pro složené typy.

CREATE OR REPLACE FUNCTION foo1(IN par1 integer) RETURNS bool AS $$
DECLARE
  x ALIAS FOR $1;
  y integer = par1;
BEGIN
  RAISE NOTICE '% % %', par1, x, y;
  -- par1 := 11; ERROR: "$1" is declared CONSTANT
  -- x := 10;  ERROR: "$1" is declared CONSTANT
  y := 10;
  RETURN 't';
END; $$ LANGUAGE plpgsql; 

Touto verzí PostgreSQL zásadně rozšiřuje možnosti kompozitních (složených) typů (terminologie: composite types, row types). Kromě jiného můžeme lépe zacházet s proměnnými NEW a OLD v funkcích triggerů.

DROP TYPE footype CASCADE;
CREATE TYPE footype AS (x integer, y integer, z varchar);

CREATE OR REPLACE FUNCTION foo2(footype) RETURNS bool AS $$
DECLARE
  x integer = $1.x;
  y footype;
BEGIN
  RAISE NOTICE '% %', x, $1.y;
  y := $1; y := (10, 10, 'Pavel');
  RETURN 't';
END; $$ LANGUAGE plpgsql;

SELECT foo2((10, 10, 'Pavel'));

CREATE OR REPLACE FUNCTION foo3() RETURNS footype AS $$
DECLARE
  x footype;
BEGIN
  x := row(10, 12, 'Jirka');
  x := (10, 12, 'Jirka');
  RETURN x;
END; $$ LANGUAGE plpgsql;

SELECT foo3(); -- NELZE
SELECT (foo3()).z; 

V předchozích verzích nebylo možné předat proměnné OLD a NEW mimo tělo funkce triggeru. Nyní to díky větší podpoře složených typů není problém.

DROP TABLE testxx CASCADE;
CREATE TABLE testxx(x integer, y integer);

CREATE OR REPLACE FUNCTION trig01(anyelement) RETURNS integer AS $$
BEGIN RAISE NOTICE 'trig01: %', $1.x;
END; $$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION trig02(testxx) RETURNS integer AS $$
BEGIN RAISE NOTICE 'trig02: %', $1.y;
END; $$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION footrig() RETURNS TRIGGER AS $$
DECLARE
  s1 integer; s2 integer;

BEGIN
  s1 := trig01(NEW); s2 := trig02(NEW);
  RAISE NOTICE '% %', s1, s2;
  RETURN NEW;
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER xxx BEFORE INSERT ON testxx
  FOR EACH ROW EXECUTE PROCEDURE footrig(); 

PL/pgSQL představuje velice dobře prověřenou a velmi rychlou platformu (natolik, že mezi členy vývojového týmu je zřejmá nechuť zavádět další jazyk pro uložené procedury, např. SQL/psm, a to přestože PSM (Persistent Stored Modules) zavádí SQL3 a standard PostgreSQL respektuje), stále je ale prostor pro další vylepšení:

  • Ošetření chyb (snad v souvislosti s podporou vnořených transakcí by se mohl stav v blízké budoucnosti zlepšit)
  • Práce s dočasnými tabulkami
  • RAISE NOTICE nedokáže stále zobrazit výraz, dokáže zobrazit celé pole, ale nikoliv jeden konkrétní prvek pole, dokáže zobrazit konkrétní prvek složeného typu, ale už opět ne složený typ.
  • Podpora interaktivního ladění
  • Packages

Změny se neudály pouze v PL/pgSQL. Jako Fénix se obrodil PL/Perl v podobě PL/PerlNG, který nyní podporuje SPI, spouště, SRF atd. Mimo distribuci lze použít PL/R, PL/PHP, PL/Java. Co se týče podporovaných rozhraní, PostgreSQL nemělo a stále nemá konkurenci.

Odkazy:

www.postgresql­.org
postgresql.ok.cz

Našli jste v článku chybu?