Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Krátce o PL/Perl

Tento článek stručně, leč s užitím názorných příkladů, přibližuje programovací jazyk plperl, jejž lze využít při práci s databází PostgreSQL.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Neznám žádnou jinou SQL databázi, které by měla bohatší nabídku programovacích jazyků než PostgreSQL. Pravdou je, že tuto vlastnost jsem nikdy nevyužil – oblíbil jsem si jednoduchý a relativně přehledný zápis SQL příkazů v PL/pgSQL a neměl jsem potřebu zkoušet nic dalšího, ačkoliv jsem sem tam v konferenci narazil na příklady použití pltcl a plperl. Na libůstky typy plR se stále dívám jako na čistě akademickou záležitost – patrně asi nikdy nebudu spouštět z uložené procedury komplikované statistické výpočty a R použiji nejspíš jen na klientské straně. Následující příklady ukazují možnosti, které plpgsql nemá (spoušť v pltcl konvertující všechny pole na malá písmena, R – agregační funkce pro určení mediánu).

CREATE OR REPLACE FUNCTION lowercase() RETURNS TRIGGER AS '
  set NEW($1) [string tolower $NEW($1)]
  return [array get NEW]' LANGUAGE pltcl;

CREATE OR REPLACE FUNCTION r_median(_float8) RETURNS float as '
  median(arg1)
' language 'plr';

CREATE AGGREGATE median (
  sfunc = plr_array_accum,
  basetype = float8,
  stype = _float8,
  finalfunc = r_median
); 

Když jsem poprvé viděl plperl, nechápal jsem, k čemu vůbec může být. V předchozích verzích měl relativně velká omezení, víceméně se z něj nedaly spouštět dotazy, nedal se použít pro tvorbu spouští. Snad jen masochista by si místo plpgsql vybral plperl. Nedávno jsem svůj názor musel přehodnotit. Procedury v plperlu se mi náramně hodily.

SELECT substring('žlutý kůň 23' FROM '^[[:alpha:]]+'); --> žlutý
SELECT substring('žlutý kůň 23' FROM '[[:digit:]]+');  --> 23
SELECT * FROM lidi WHERE prijmeni ~* 'a$'; 

PostgreSQL sice obsahuje podporu regulárních výrazů (funkce substring a operátory ~ a ~*), pro složitější úlohy ale vestavěná podpora nestačí. Pokud chceme s regulárními výrazy pracovat více – použít náhrady, výběr řetězců – pak vlastně nemáme žádnou jinou možnost než použít plperl. Ovšem co jiného použít na regulární výrazy než Perl, že? plpgsql regulární výrazy nepodporuje, alespoň já o žádné podpoře nevím. (Kromě plperlu samozřejmě můžeme použít plphp, případně pltcl nebo plpython.) Otázka zní, proč pracovat s regulárními výrazy. Potřeboval jsem čistit databázi. V MySQL, MSSQL bych si musel napsat externí aplikaci, kterou data proženu. V MSSQL si mohu pomoci DTS (data transformation services), kde mám regulární výrazy přístupné ve VB scriptu. V Oracle je package owa_pattern. Teprve nyní mi přijde cena za možnost použití více jazyků přijatelná – komplikovaný zápis, resp. kód, se předává jako string – následně vznikají problémy s nečitelností v plpgsql (přehršel apostrofů).

CREATE OR REPLACE FUNCTION get_numbers(VARCHAR) RETURNS INTEGER[] AS '
  my($source) = @_; $retval = "";
  while ( $source =~ m/([[:digit:]]+)/g ) {
    $retval = $retval . ", " if ($retval ne "");
    $retval = $retval . $1;
  }
  return "{$retval}"; ' LANGUAGE plperl;

work=#SELECT get_numbers('dasf adfsadf 10 dasf dasf 20 adsf 111');
get_numbers
--
{10,20,111}
{1 řádka} 

Bohužel plperl má pravděpodobně nejkomplikovanější instalaci z jazyků podporovaných PostgreSQL. Vyžaduje knihovnu libperl, která obyčejně není na počítačích nainstalována (perl je slinkován staticky). Až budete překládat perl, nezapomeňte, že napřed musíte mít přeloženou a zaregistrovanou knihovnu libperl, pak teprve můžete znova provést configure PostgreSQL se svými parametry a navíc s –with-perl. Není nutné překládat kompletní PostgreSQL, stačí jen adresář /src/pl/plperl.

plperl můžeme použít bez problémů (běží v safe módu). Bohužel se opět jednou projeví naše česká specifika. Aby se operace s řetězci chovaly správně vůči diakritice, je třeba použít locale. Jenomže to už je pro perl nebezpečná operace, a musíme tedy použít untrusted perl. Což může vadit v systémech, kde se tvůrci databází netěší až tak velké důvěře: webhostingy, školy atd. Untrusted plperl nejenže nemá žádná omezení v přístupu k lokálním zdrojům, ale běží pod uživatelem postgres. Není problém si například smazat databázi.

-- Pokud se jedna o Prahu, Brno, Liberec, Ostravu,
-- Plzen nebo Karvinou, tj. jednoslovne nazvy, da
-- se predpokladat, ze dalsim slovem bude identifikace
-- casti, napr. Praha Bohnice -> Praha - Bohnice

CREATE OR REPLACE FUNCTION checkname(varchar) RETURNS varchar AS '
  use locale;
  my ($source) = @_;
  if (! defined $source) {return undef;}

  if ($source =~ m#[a-zA-Z]+[[:space:]]+[a-zA-Z]+#i) {
    if (index($source, "-") == -1 && index($source, ",") && index($source, "+")) {
      $source =~ s/^[[:space:]]*(Praha|Brno|Liberec|Ostrava|Plzeň|Karviná) {1}[[:space:]]/$1 - /i;
    }
  }
  return uc($source); ' LANGUAGE plperlu; 

(Pozn. ed.: mezera za Karvinou být nemá, ústupek sazbě –Johanka)

davame_internetu_obsah
       

Nejtvrdším omezením plperl je nemožnost přímo volat funkce PostgreSQL. Jakékoliv hodnoty se při převodu z Perlu do PostgreSQL konvertují do řetězců: čísla, texty, ale i pole. plperl podporuje typ record, hodnoty jsou opět textové a uložené v hash tabulce. Pro přístup k funkcím PostgreSQL musíme použít rozhraní DBD::PgSPI. Bohužel toto rozhraní již tři roky nebylo aktualizováno a jeho dokumentace také není nejlepší.

CREATE OR REPLACE FUNCTION foospi() RETURNS VARCHAR AS '
  use DBD::PgSPI;
  my @ar=$pg_dbh->selectrow_array("SELECT CURRENT_USER");
  return $ar[0]; ' LANGUAGE plperlu; 

Když už nám nezbude nic jiného než použít untrusted plperl, nemusíme se bránit používání existující další (nejen db relevantní knihovny) Perlu. S trochou nadsázky by se dalo říci, že o něco podobného se snaží v tuto chvíli Microsoft se svou integrací .NET frameworku do MsSQL.

CREATE OR REPLACE FUNCTION foo() RETURNS text AS '
  use Mail::Sendmail;
  %mail = ( To   =>  q(you@yourname.com),
            From =>  q(me@here.com),
            Message => "This is very short message"
          );
  sendmail(%mail) or die $Mail::Sendmail::error;
  return "Ok. Log says:\n", $Mail::Sendmail::log;
' LANGUAGE plperlu; 

Pavel Stěhule

Pavel Stěhule

Pavel Stěhule je odborníkem na relační databázový systém PostgreSQL, který v současnosti pracuje jako vývojář ve společnosti GoodData.

Školení: Návrh a používání MySQL databáze

 

Naučte se používat jednu z nejrozšířenějších databází. Dozvíte se vše potřebné od návrhu až po samotné využití MySQL v projektech.

Školení pro všechny, kteří se chtějí naučit efektivně pracovat s MySQL nebo se v práci s touto databází zlepšit.

Přihláška a podrobné informace

Ohodnoťte jako ve škole:
Průměrná známka 2,77

Přehled názorů

ach ty preklady :(
znouza 17. 3. 2004 10:24
Nový
├ 
Re: ach ty preklady :(
Ondra 'Kepi' Kudlík 17. 3. 2004 10:40
Nový
├ 
Re: ach ty preklady :(
Bubak 17. 3. 2004 13:24
Nový
├ 
Re: ach ty preklady :(
pajout 17. 3. 2004 13:58
Nový
│
└ 
Re: ach ty preklady :(
Jakub Hegenbart 17. 3. 2004 18:14
Nový
└ 
Re: ach ty preklady :(
kolisko 17. 3. 2004 18:16
Nový
 
├ 
Re: ach ty preklady :(
Pavel 18. 3. 2004 06:21
Nový
 
└ 
Re: ach ty preklady :(
andrej 18. 3. 2004 09:41
Nový
pro koho jste to psal?
Viktor Matys 17. 3. 2004 12:42
Nový
├ 
Re: pro koho jste to psal?
brano 17. 3. 2004 14:51
Nový
└ 
Re: pro koho jste to psal?
Pavel 18. 3. 2004 06:47
Nový
 
└ 
Re: pro koho jste to psal?
P.Dvořák 22. 3. 2004 17:25
Nový
Stabilita Perlu v MT aplikacich
Ivan 17. 3. 2004 15:46
Nový
└ 
Re: Stabilita Perlu v MT aplikacich
kciii 17. 3. 2004 17:19
Nový
 
└ 
Re: Stabilita Perlu v MT aplikacich
Dan 18. 3. 2004 07:07
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem