Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
Pages : 1
#1 24/02/2017 16:05:09
- linuxprocess
- Membre
Bug ou feature ?
Bonjour,
Je en sais pas trop quoi penser de cette observation qui est faite ...
Je suspecte tout de même une forme de bug, parce que ca ne me semble pas optimal du tout ...
Pour résumer : dans le cas de figure qui suit, la fonction est appelée deux fois par le moteur, alors que la requête ne l'appelle qu'une fois.
Le POC, beaucoup plus clair que les explications :
CREATE OR REPLACE FUNCTION testnext(OUT a bigint, OUT b bigint)
RETURNS record
LANGUAGE sql
IMMUTABLE STRICT
AS $function$
select nextval('lieu_id_seq'::regclass) as a, nextval('lieu_id_seq'::regclass) as b
$function$
select now(),testnext();
Retourne le résultat attendu :
now |testnext |
--------------------|----------|
2017-02-24 15:01:17 |(263,264) |
263 et 264 se suivent, tout est ok ...
select now(),(testnext()).*;
Retourne ce résultat :
now |a |b |
--------------------|----|----|
2017-02-24 15:02:06 |265 |268 |
265 et 268 sont retournés ...
266 et 267 sont perdus, ca correspond tout à fait au fait que comme il y a deux résultats, alors la fonction a été appelée 2 fois.
Avec trois éléments retournés, on retrouve le même problème : la fonction est appelée 3 fois.
Qu'en pensez vous ?
Voyez vous une autre façon de faire qui n'appellerait pas la fonction plusieurs fois ?
Merci
Dernière modification par linuxprocess (24/02/2017 16:05:49)
Hors ligne
#2 24/02/2017 16:26:08
- Marc Cousin
- Membre
Re : Bug ou feature ?
On peut s'en sortir avec un CTE:
with next as (select testnext())
select now(),(next).* from next;
Ce n'est pas vraiment un bug, c'est l'optimiseur qui choisit d'appeler la fonction une fois par colonne produite, c'est un artefact de sa façon de travailler. Par contre, c'est une limitation peu pratique de l'optimiseur, il y a du travail pour éviter ces exécutions inutiles.
Avec la CTE on lui force la main.
Par contre, au passage, cette fonction ne devrait pas être immutable, vu qu'elle modifie le contenu de la base. Elle devrait être volatile.
Marc.
Hors ligne
#3 24/02/2017 17:11:40
- linuxprocess
- Membre
Re : Bug ou feature ?
Merci pour ton retour et tes explications.
cependant, je n'obtient pas le résultat attendu avec ta proposition :
with next as (select testnext())
select now(),(next).* from next;
now |testnext |
--------------------|--------------|
2017-02-24 16:09:45 |(302,303,304) |
et la syntaxe suivante est en erreur :
with next as (select testnext())
select now(),((next).*).* from next;
Hors ligne
#4 24/02/2017 17:25:39
- Marc Cousin
- Membre
Re : Bug ou feature ?
Répondu trop vite désolé
with next as (select testnext())
select now(),(next).testnext.* from next;
Marc.
Hors ligne
#5 24/02/2017 17:33:06
- linuxprocess
- Membre
Re : Bug ou feature ?
super !
merci
Hors ligne
Pages : 1