La fonction spécifique référencée par un appel de fonction est déterminée selon les étapes suivantes.
Résolution de types pour les fonctions
Sélectionner les fonctions à examiner depuis le catalogue système
pg_proc
. Si un nom non-qualifié de fonction
était utilisé, les fonctions examinées sont celles avec un nom et un
nombre d'arguments corrects et qui sont visibles dans le chemin de
recherche courant (voir la Section 5.8.3). Si
un nom qualifié de fonctions a été donné, seules les fonctions dans le
schéma spécifique sont examinées.
Si un chemin de recherche trouve de nombreuses fonctions avec des types d'arguments identiques, seule celle apparaissant le plus tôt dans le chemin sera examinée. Mais les fonctions avec des types d'arguments différents sont examinées sur une base d'égalité indépendamment de leur position dans le chemin de recherche.
Si une fonction est déclarée avec un paramètre VARIADIC
et
que l'appel n'utilise pas le mot clé VARIADIC
, alors la
fonction est traitée comme si le paramètre tableau était remplacé par une ou
plusieurs occurrences de son type élémentaire, autant que nécessaire pour
correspondre à l'appel. Après cette expansion, la fonction pourrait avoir
des types d'arguments identiques à certaines fonctions non variadic. Dans ce
cas, la fonction apparaissant plus tôt dans le chemin de recherche est utilisée
ou, si les deux fonctions sont dans le même schéma, celle qui n'est pas VARIADIC
est préférée.
Les fonctions qui ont des valeurs par défaut pour les paramètres sont considérés comme correspondant à un appel qui omet zéro ou plus des paramètres ayant des valeurs par défaut. Si plus d'une fonction de ce type correspondent à un appel, celui apparaissant en premier dans le chemin des schémas est utilisé. S'il existe deux ou plus de ces fonctions dans le même schémas avec les même types de paramètres pour les paramètres sans valeur par défaut (ce qui est possible s'ils ont des ensembles différents de paramètres par défaut), le système ne sera pas capable de déterminer laquelle sélectionnée, ce qui résultera en une erreur « ambiguous function call ».
Vérifier que la fonction accepte le type exact des arguments en entrée.
Si une fonction existe (il peut en avoir uniquement une qui correspond
exactement dans tout l'ensemble des fonctions considérées), utiliser cette
fonction. Le manque d'une correspondance exacte crée un risque de sécurité
lors de l'appel, via un nom qualifié[9], d'une fonction trouvé dans un schéma
permettant à des utilisateurs sans confiance de créer des objets. Dans de
telles situations, convertissez les arguments pour forcer une
correspondance exacte. (Les cas impliquant le type unknown
ne
trouveront jamais de correspondance à cette étape).
Si aucune correspondance n'est trouvée, vérifier si l'appel à la
fonction apparaît être une requête spéciale de conversion de types.
Cela arrive si l'appel à la fonction a juste un argument et si le nom
de la fonction est le même que le nom (interne) de certains types de
données. De plus, l'argument de la fonction doit être soit un type
inconnu soit un type qui a une compatibilité binaire avec le type de
données nommés, soit un type qui peut être converti dans le type de données
indiqué en appliquant les fonctions d'entrées/sorties du type (c'est-à-dire
que la conversion est vers ou à partir d'un type standard de chaîne). Quand
ces conditions sont rencontrées, l'appel de la fonction est traité sous la
forme d'une spécification CAST
.
[10]
Regarder pour la meilleure correspondance.
Se débarrasser des fonctions candidates pour lesquelles les types en
entrée ne correspondent pas et qui ne peuvent pas être convertis (en
utilisant une conversion implicite) pour correspondre. Le type
unknown
est supposé être convertible vers n'importe quoi.
Si un seul candidat reste, utiliser le ; sinon, aller à la prochaine
étape.
Si tout argument en entrée est un type domaine, le traiter comme son type de base pour toutes les étapes suivantes. Ceci nous assure que les domaines agissent comme leur types de base pour la résolution des fonctions ambigues.
Parcourir tous les candidats et garder ceux avec la correspondance la plus exacte par rapport aux types en entrée. Garder tous les candidats si aucun n'a de correspondance exacte. Si un seul candidat reste, utiliser le ; sinon, aller à la prochaine étape.
Parcourir tous les candidats et garder ceux qui acceptent les types préférés (de la catégorie des types de données en entrée) aux positions où la conversion de types aurait été requise. Garder tous les candidats si aucun n'accepte les types préférés. Si un seul candidat reste, utiliser le ; sinon, aller à la prochaine étape.
Si des arguments en entrée sont unknown
, vérifier les
catégories de types acceptées à la position de ces arguments par les
candidats restants. À chaque position, sélectionner la catégorie
chaîne de caractères
si un des candidats accepte cette
catégorie (cette préférence envers les chaînes de caractères est
appropriée depuis que le terme type-inconnu ressemble à une chaîne de
caractères). Dans le cas contraire, si tous les candidats restants
acceptent la même catégorie de types, sélectionner cette catégorie.
Dans le cas contraire, échouer car le choix correct ne peut pas être
déduit sans plus d'indices. Se débarrasser maintenant des candidats qui
n'acceptent pas la catégorie sélectionnée. De plus, si des candidats
acceptent un type préféré dans cette catégorie, se débarrasser des
candidats qui acceptent, pour cet argument, les types qui ne sont pas
préférés.
Garder tous les candidats si aucun ne survit à ces tests. Si un seul
candidat reste, utilisez-le. Sinon continuez avec l'étape suivante.
S'il y a des arguments à fois unkown
et connus, et que tous
les arguments de type connu ont le même type, supposer que les arguments
unkown
sont de ce même type, et vérifier les candidats
qui acceptent ce type aux positions des arguments de type unknown
.
Si un seul candidat réussit ce test, utilisez-le. Sinon, échec.
Notez que les règles de « correspondance optimale » sont identiques pour la résolution de types concernant les opérateurs et les fonctions. Quelques exemples suivent.
Exemple 10.6. Résolution de types pour les arguments de la fonction arrondie
Il n'existe qu'une seule fonction round
avec deux arguments (le premier est de type numeric
, le
second est de type integer
). Ainsi, la requête suivante
convertie automatiquement le type du premier argument de
integer
vers numeric
.
SELECT round(4, 4); round -------- 4.0000 (1 row)
La requête est en fait transformée par l'analyseur en
SELECT round(CAST (4 AS numeric), 4);
Puisque le type numeric
est initialement assigné aux
constantes numériques avec un point décimal, la requête suivante ne
requièrera pas une conversion de types et pourra par conséquent être
un peu plus efficace :
SELECT round(4.0, 4);
Exemple 10.7. Résolution de types pour les fonctions retournant un segment de chaîne
Il existe plusieurs fonctions substr
, une d'entre
elles prend les types text
et integer
. Si
cette fonction est appelée avec une constante de chaînes d'un type
inconnu, le système choisi la fonction candidate qui accepte un
argument issu de la catégorie préférée string
(c'est-à-dire de type text
).
SELECT substr('1234', 3); substr -------- 34 (1 row)
Si la chaîne de caractères est déclarée comme étant du type
varchar
(chaîne de caractères de longueur variable), ce
qui peut être le cas si elle vient d'une table, alors l'analyseur
essayera de la convertir en text
:
SELECT substr(varchar '1234', 3); substr -------- 34 (1 row)
Ceci est transformé par l'analyseur en
SELECT substr(CAST (varchar '1234' AS text), 3);
L'analyseur apprend depuis le catalogue pg_cast
que les
types text
et varchar
ont une compatibilité
binaire, ce qui veut dire que l'un peut être passé à une fonction qui
accepte l'autre sans avoir à faire aucune conversion physique. Par
conséquent, aucun appel de conversion de types n'est
réellement inséré dans ce cas.
Et si la fonction est appelée avec un argument de type
integer
, l'analyseur essaie de le convertir en
text
:
SELECT substr(1234, 3); ERROR: function substr(integer, integer) does not exist HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Ceci ne fonctionne pas car integer
n'a pas de conversion
implicite vers text
. Néanmoins, une conversion explicite
fonctionnera :
SELECT substr(CAST (1234 AS text), 3); substr -------- 34 (1 row)
[10] La raison de cette étape est le support des spécifications de conversion au format fonction pour les cas où la vraie fonction de conversion n'existe pas. S'il existe une fonction de conversion, elle est habituellement nommée suivant le nom du type en sortie et donc il n'est pas nécessaire d'avoir un cas spécial. Pour plus d'informations, voir CREATE CAST.