Re: Modification de la compilation de jointures en 3.1 ?

Cédric Morin <[email protected]>
Newsgroups gmane.comp.web.spip.devel
Message-ID <[email protected]>
Hello,

plusieurs remarques sur ton mail.

1/ il y a incomprehension de la notion de jointure explicite. Tu dis "le 
compilateur DOIT l'ajouter". Non, ce n'est pas comme ça que ça marche. 
Cela doit se comprendre en "si le compilateur a besoin de champs 
supplémentaires, il doit regarder dans ces tables"
C'est une nuance de taille.

2/ oui il manque des tests unitaires sur la compilation des boucles, oui 
il faut les formaliser et les écrire, mais cela dit on sait qu'on a 
changé le comportement de certaines jointures un peu exotiques qui 
marchaient par chance en 3.0

3/ oui le commit en cause est très certainement
https://core.spip.net/projects/spip/repository/revisions/21875
qui fait un bugfix sur certains cas où le compilateur doublonnait des 
jointures car il piochait dans la jointure explicite sans verifier que 
le champ cherché existait déjà dans les jointures posées

4/ le critère {auteurs_liens.id_auteur?} ne veut pas dire que le 
compilateur ajoute la jointure uniquement si il y a un id_auteur dans le 
env, ça ne serait pas possible : la jointure est créer lors de la 
compilation, le env est connu a l'execution.
En pratique le compilateur ajoute la jointure dans la construction de la 
boucle (elle est donc toujours là), le critère where est lui ajouté de 
façon facultative en fonction du env, et l'executeur de requete se 
charge in fine de nettoyer les jointures et autres critères inutiles.

5/ on ne peut pas debug ta boucle car il faut connaitre son contenu, qui 
déclenche ou non les jointures. Je présume que ta boucle contient des 
#OBJET et #ID_OBJET

6/ si tu as bien suivi tu comprends ce qui se passe :
- le compilateur crée la boucle avec jointure sur spip_auteurs
- il voit un #ID_OBJET dans le corps de la boucle
- il cherche le champ dans la requete SQL et le trouve sur la table 
auteurs_liens
- lors de l'execution sans id_auteur dans le env, la jointure 
auteurs_liens est conservée car elle sert pour le champ #ID_OBJET

En 3.0 on avait
- le compilateur crée la boucle avec jointure sur spip_auteurs
- il voit un #ID_OBJET dans le corps de la boucle
- il cherche le champ dans les jointures explicites
- il ajoute la jointure sur selections_liens
- lors de l'execution sans id_auteur dans le env, la jointure 
auteurs_liens est supprimée

C'est pur coup de chance que ta boucle ait marché en 3.0 car il y a 
ambiguité sur le sens de #ID_OBJET qui peut venir aussi bien de 
selections_liens que de auteurs_liens, les deux jointures étant 
explicites dans ta boucle

Peut-être que la solution serait de modifier le sens des jointures 
explicites pour lui donner celui que tu suppose : une jointure que l'on 
force, explicitement, avant toute autre analyse de la boucle, quitte à 
ce qu'elle soit optimisée ensuite si elle ne sert pas.
Mais c'est une modification non mineure a tester en 3.2-dev

Par ailleurs il ne me parait pas judicieux de revenir sur le r21875 car 
celui ci corrige un vrai bug.

Je vais reflechir aux possibilités, côté compilateur, mais en attendant 
je vois deux solutions :
1/ faire une première boucle de selection avec un {id_auteur?} et un 
{doublons} et ensuite une boucle d'utilisation
2/ centrer ta boucle sur selections_liens avec les jointures explicites 
sur selections et auteurs_liens, mais je ne suis pas certain que 
id_auteur sera bien interprété dans ce cas, je crains qu'on ait une 
jointure directe selections_liens - auteurs_liens


-- 
Cédric



RastaPopoulos a écrit :
>
> Cas concret, une boucle dans le plugin Sélections éditoriales *qui n'a
> pas bougé* :
>
> (SELECTIONS selections_liens){!orphelins}{auteurs_liens.id_auteur?}
>
> Cette boucle contient *une jointure explicite* demandée. Le compilateur
> DOIT l'ajouter normalement, ce n'est pas facultatif, on la demande
> explicitement.
>
> La seconde différence *hors* compilateur qui a changé aussi, c'est que
> Cédric à modifier {orphelins} pour ajouter une "subquery". Mais ce point
> n'est pas censé être lié à la jointure, c'est dans une des conditions du
> "where".
>
>
> Voici sur les deux versions :
>
>
> ## En SPIP 3.0
>
> SELECT selections.id_selection, 0 AS points, '', L2.id_objet, L2.objet,
> selections.titre AS titre_rang, selections.titre
> FROM spip_selections AS 'selections'
> INNER JOIN spip_selections_liens AS L2 ON ( L2.id_selection =
> selections.id_selection )
> WHERE selections.id_selection IN (
> SELECT DISTINCT id_selection
> FROM spip_selections_liens AS oooo)
> GROUP BY selections.id_selection
> ORDER BY 0+selections.titre, id_objet
>
> ## En SPIP 3.1
>
> SELECT selections.id_selection, 0 AS points, '', L1.id_objet, L1.objet,
> selections.titre AS titre_rang, selections.titre
> FROM spip_selections AS `selections`
> INNER JOIN spip_auteurs_liens AS L1 ON ( L1.id_objet =
> ctions.id_selection AND L1.objet='selection')
> WHERE selections.id_selection IN (SELECT * FROM(
> SELECT DISTINCT id_selection
> FROM spip_selections_liens AS oooo) AS subquery)
> GROUP BY selections.id_selection
> ORDER BY 0+selections.titre, id_objet
>
>
> En 3.1, quand on vire {auteurs_liens.id_auteur?}, alors ça remet la
> bonne jointure "spip_selections_liens". Mais en 3.0 ça marche direct
> sans rien changer.
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.