31.6. Catégories de volatibilité des fonctions

Chaque fonction a une classification volatility comprenant VOLATILE, STABLE ou IMMUTABLE. VOLATILE est la valeur par défaut si la commande CREATE FUNCTION ne spécifie pas de catégorie. La catégorie de volatibilité est une promesse à l'optimiseur sur le comportement de la fonction :

Pour une meilleure optimisation des résultats, vous devez mettre un label sur les fonctions avec la catégorie la plus volatile valide pour elles.

Toute fonction avec des effets de bord doit être indiquée comme VOLATILE, de façon à ce que les appels ne puissent pas être optimisés. Même une fonction sans effets de bord doit être indiquée comme VOLATILE si sa valeur peut changer à l'intérieur d'une seule requête ; quelques exemples sont random(), currval(), timeofday().

Il y a relativement peu de différences entre les catégories STABLE et IMMUTABLE en considérant les requêtes interactives qui sont planifiées et immédiatement exécutées : il importe peu que la fonction soit exécutée une fois lors de la planification ou une fois au lancement de l'exécution de la requête mais cela fait une grosse différence si le plan est sauvegardé et utilisé plus tard. Placer un label IMMUTABLE sur une fonction quand elle ne l'est pas vraiment pourrait avoir comme conséquence de la considérer prématurément comme une constante lors de la planification et résulterait en une valeur erronée lors d'une utilisation ultérieure de ce plan d'exécution. C'est un danger qui arrive lors de l'utilisattion d'instructions préparées ou avec l'utilisation de langages de fonctions mettant les plans d'exécutions en cache (comme PL/pgSQL).

À cause du comportement à base d'images de MVCC (voir le Chapitre 12), une fonction contenant seulement des commandes SELECT peut être indiquée STABLE en toute sécurité même s'il sélectionne des données à partir de tables qui pourraient avoir subi des modifications entre temps par des requêtes concurrentes. PostgreSQL exécutera une fonction STABLE en utilisant l'image établie par la requête appelante et n'aura qu'une vision figée de la base de données au cours de la requête. Notez aussi que la famille de fonctions current_timestamp est qualifiée de stable car leurs valeurs ne changent pas dans une transaction.

Ce même comportement d'images est utilisé pour les commandes SELECT à l'intérieur de fonctions IMMUTABLE. Il est généralement déconseillé de sélectionner des tables de la base de données à l'intérieur de fonctions IMMUTABLE car l'immutabilité sera rompue si le contenu de la table change. Néanmoins, PostgreSQL ne vous force pas à ne pas le faire.

Une erreur commune est de placer un label sur une fonction IMMUTABLE quand son résultat dépend d'un paramètre de configuration. Par exemple, une fonction qui manipule des types date/heure pourrait bien avoir des résultats dépendant du paramètre timezone. Pour être sécurisées, de telles fonctions devraient avoir le label STABLE à la place.

Note : Avant PostgreSQL version 8.0, le prérequis que les fonctions STABLE et IMMUTABLE ne pouvaient pas modifier la base de données n'était pas contraint par le système. La version 8.0 le contraint en réclamant que les fonctions SQL et les fonctions de langages de procédures de ces catégories ne contiennent pas de commandes SQL autre que SELECT (ceci n'a pas été complètement testé car de telles fonctions pourraient toujours appeler des fonctions VOLATILE qui modifient la base de données. Si vous le faites, vous trouverez que la fonction STABLE ou IMMUTABLE n'est pas au courant des modifications effectuées sur la base de données par la fonction appelée).