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.
>