Chapitre 37. PL/Perl - Langage de procédures Perl

Table des matières
37.1. Fonctions et arguments PL/Perl
37.2. Accès à la base de données depuis PL/Perl
37.3. Valeurs des données dans PL/Perl
37.4. Valeurs globales dans PL/Perl
37.5. Niveaux de confiance de PL/Perl
37.6. Déclencheurs PL/Perl
37.7. Limitations et fonctionnalités absentes

PL/Perl est un langage de procédures chargeable qui vous permet d'écrire des fonctions PostgreSQL dans le langage de programmation Perl.

Pour installer PL/Perl dans une base de données spécifique, utilisez la commande createlang plperl nom_base.

Astuce : Si un langage est installé dans template1, toutes les bases de données créées ultérieurement disposeront automatiquement de ce langage.

Note : Les utilisateurs des paquetages sources doivent explicitement autoriser la construction de PL/Perl pendant le processus d'installation (se référer à la Section 14.1 pour plus d'informations). Les utilisateurs des paquetages binaires peuvent trouver PL/Perl dans un sous-paquetage séparé.

37.1. Fonctions et arguments PL/Perl

Pour créer une fonction dans le langage PL/Perl, utilisez la syntaxe standard :

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.

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) pour cette constante. Si vous choisissez d'utiliser la syntaxe à base de guillemets simples, vous devez faire un échappement des marques de guillemets simples (') et des antislashs (\) utilisés dans le corps de la fonction, typiquement en les doublant (voir la Section 4.1.2.1).

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 ($a,$b) = @_;
    if (! defined $a) {
        if (! defined $b) { return undef; }
        return $b;
    }
    if (! defined $b) { return $a; }
    if ($a > $b) { return $a; }
    return $b;
$$ 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.

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 testligneperl 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. Pour cela, renvoyez une référence à un tableau contenant respectivement soit des scalaires soit des références à des hachages. Voici quelques exemples simples :

      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();
    

Notez qu'en faisant ceci, Perl devra construire le tableau entier en mémoire ; du coup, la technique n'est pas utilisable pour des ensembles de résultats très importants.

PL/Perl n'a actuellement pas de support complet pour les types domaine : il traite un domaine de la même façon qu'un type scalaire sous-jacent. Ceci signifie que les contraintes associées au domaine ne seront pas forcées. Ceci n'est pas un problème pour les arguments d'une fonction mais c'est hasardeux de déclarer une fonction PL/Perl renvoyant un type domaine.