PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#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;



hmm

Hors ligne

#4 24/02/2017 17:25:39

Marc Cousin
Membre

Re : Bug ou feature ?

Répondu trop vite désolé smile

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

Pied de page des forums