PL/Perl est un langage de procédures chargeable qui vous permet
d'écrire des fonctions PostgreSQL™ dans le
langage de programmation Perl
.
L'avantage habituellement cité quant à l'utilisation de Perl est que
cela permet l'utilisation des nombreux opérateurs et fonctions de
« gestion de chaînes »
disponibles grâce à Perl dans des procédures stockées. L'analyse de
chaînes complexes se trouve facilité par l'utilisation de Perl et des
fonctions et structures de contrôles fournies dans PL/pgSQL.
Pour installer PL/Perl dans une base de données spécifique, utilisez
la commande createlang plperl
nom_base
.
39.1. Fonctions et arguments PL/Perl
Pour créer une fonction dans le langage PL/Perl, utilisez la
syntaxe standard CREATE FUNCTION :
CREATE FUNCTION nom_fonction (types-arguments) RETURNS
type-retour AS $$
# Corps de la fonction PL/Perl
$$ LANGUAGE plperl;
Le corps de la fonction est du code Perl normal. En fait, le code
supplémentaire PL/Perl l'emballe dans une sous-routine Perl. Une
fonction PL/Perl doit toujours renvoyer une valeur scalaire. Vous
pouvez renvoyer des structures plus complexes (tableaux,
enregistrements et ensembles) en renvoyant une référence comme
indiqué ci-dessous. Ne renvoyez jamais une liste.
Note
L'utilisation de sous-routines nommées est dangereux en Perl,
spécialement si elles font références à des variables lexicales
dans la partie englobante. Comme une fonction PL/Perl est
englobée dans une sous-routine, toute sous-routine nommée que
vous créez sera englobée. En général, il est bien plus sûr de
créer des sous-routines anonymes que vous appelerez via un
« coderef ». Voir la page
man de perldiag pour les détails.
La syntaxe de la commande
CREATE
FUNCTION
requiert que le corps de la fonction soit
écrit comme une constante de type chaîne. Il est habituellement
plus agréable d'utiliser les guillemets dollar (voir la Section 4.1.2.2,
« Constantes de chaînes avec guillemet dollar ») pour
cette constante. Si vous choisissez d'utiliser la syntaxe
d'échappement des chaînes E'', vous devez
doubler les marques de guillemets simples (') et les antislashs (\)
utilisés dans le corps de la fonction (voir la Section 4.1.2.1,
« Constantes de chaînes »).
Les arguments et les résultats sont manipulés comme dans n'importe
quel routine Perl : les arguments sont passés au tableau @_ et une valeur de retour est indiquée par
return ou par la dernière expression
évaluée dans la fonction.
Par exemple, une fonction retournant le plus grand de deux entiers
peut être définie comme suit :
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
if ($_[0] > $_[1]) { return $_[0]; }
return $_[1];
$$ LANGUAGE plperl;
Si une valeur NULL en SQL est passée à une fonction, cet argument
apparaîtra comme « undefined »
en Perl. La fonction définie ci-dessus ne se comportera pas
correctement avec des arguments NULL (en fait, tout se passera
comme s'ils avaient été des zéros). Nous aurions pu ajouter
STRICT à la définition de la fonction pour
forcer PostgreSQL™ à faire
quelque chose de plus raisonnable : si une valeur NULL est passée
en argument, la fonction ne sera pas du tout appelée mais
retournera automatiquement un résultat NULL. D'une autre façon,
nous aurions pu vérifier dans le corps de la fonction la présence
d'arguments NULL. Par exemple, supposons que nous voulions que
perl_max avec un argument NULL et un
autre non NULL retourne une valeur non NULL plutôt qu'une valeur
NULL, on aurait écrit :
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
my ($x,$y) = @_;
if (! defined $x) {
if (! defined $y) { return undef; }
return $y;
}
if (! defined $y) { return $x; }
if ($x > $y) { return $x; }
return $y;
$$ LANGUAGE plperl;
Comme le montre l'exemple ci-dessus, passer une valeur NULL en SQL
à une fonction en PL/Perl retourne une valeur non définie. Et ceci,
que la fonction soit déclarée stricte ou non.
Perl peut renvoyer des tableaux PostgreSQL™ comme référence à des
tableaux Perl. Voici un exemple :
CREATE OR REPLACE function renvoit_tableau()
RETURNS text[][] AS $$
return [['a"b','c,d'],['e\\f','g']];
$$ LANGUAGE plperl;
select renvoit_tableau();
Les arguments de type composite sont passés à la fonction en tant
que références d'un tableau de découpage, les clés du tableau de
découpage étant les noms des attributs du type composé. Voici un
exemple :
CREATE TABLE employe (
nom text,
basesalaire integer,
bonus integer
);
CREATE FUNCTION empcomp(employe) RETURNS integer AS $$
my ($emp) = @_;
return $emp->{basesalaire} + $emp->{bonus};
$$ LANGUAGE plperl;
SELECT nom, empcomp(employe.*) FROM employe;
Une fonction PL/Perl peut renvoyer un résultat de type composite en
utilisant la même approche : renvoyer une référence à un hachage
qui a les attributs requis. Par exemple,
CREATE TYPE testligneperl AS (f1 integer, f2 text, f3 text);
CREATE OR REPLACE FUNCTION perl_ligne() RETURNS test_ligne_perl AS $$
return {f2 => 'hello', f1 => 1, f3 => 'world'};
$$ LANGUAGE plperl;
SELECT * FROM perl_row();
Toute colonne dans le type de données déclaré du résultat qui n'est
pas présente dans le hachage sera renvoyée NULL.
Les fonctions PL/Perl peuvent aussi renvoyer des ensembles de types
scalaires ou composites. Habituellement, vous voulez renvoyer une
ligne à la fois, à la fois pour améliorer le temps de démarrage et
pour éviter d'allonger la queue de l'ensemble des résultats en
mémoire. Vous pouvez faire ceci avec return_next comme indiqué ci-dessous. Notez
qu'après le dernier return_next, vous
devez placer soit return soit (encore
mieux) return undef.
CREATE OR REPLACE FUNCTION perl_set_int(int)
RETURNS SETOF INTEGER AS $$
foreach (0..$_[0]) {
return_next($_);
}
return undef;
$$ LANGUAGE plperl;
SELECT * FROM perl_set_int(5);
CREATE OR REPLACE FUNCTION perl_set()
RETURNS SETOF test_ligne_perl AS $$
return_next({ f1 => 1, f2 => 'Hello', f3 => 'World' });
return_next({ f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' });
return_next({ f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' });
return undef;
$$ LANGUAGE plperl;
Pour les petits ensembles de résultats, vous pouvez renvoyer une
référence à un tableau contenant soit des scalaires, soit des
références à des tableaux soit des références à des hachages de
types simples, de types tableaux ou de types composites. Voici
quelques exemples simples pour renvoyer l'ensemble complet du
résultant en tant que référence de tableau :
CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
return [0..$_[0]];
$$ LANGUAGE plperl;
SELECT * FROM perl_set_int(5);
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testligneperl AS $$
return [
{ f1 => 1, f2 => 'Bonjour', f3 => 'Monde' },
{ f1 => 2, f2 => 'Bonjour', f3 => 'PostgreSQL' },
{ f1 => 3, f2 => 'Bonjour', f3 => 'PL/Perl' }
];
$$ LANGUAGE plperl;
SELECT * FROM perl_set();
Si vous souhaitez utiliser le pragma strict dans votre code, la façon la plus simple de
le faire est de configurer (
SET
) plperl.use_strict à true. Ce paramètre affecte les
compilations suivantes de fonctions PL/Perl, mais pas les fonctions déjà compilées
dans la session en cours. Pour configurer le paramètre avant que
PL/Perl ne soit chargé, il est
nécessaire d'avoir ajouté «
plperl
» dans la liste custom_variable_classes
de postgresql.conf.
Une autre façon d'utiliser le pragma strict est de placer
use strict;
dans le corps de la fonction. Mais ceci fonctionne uniquement dans
les fonctions PL/PerlU car
use n'est pas une opération de confiance.
Dans les fonctions PL/Perl, vous
pouvez utiliser à la place :
BEGIN { strict->import(); }