Voici un bug bien caché que je ne suis pas du tout arrivé à suivre dans les méandres de criteres.php et composer.php.
Avec un SPIP 2.3.0 le critère {!id_mot ID 1,5} n’arrive pas à fabriquer la bonne sous-requête SQL, il renvoie:
<BOUCLE_artmot(ARTICLES){!id_mot IN 1,5}> :
[…]
AND NOT((articles.id_article IN (
SELECT L1.id_objet, L1.id_objet AS id_article
FROM spip_mots_liens AS L1
WHERE ((L1.id_mot IN (1,5))))))
[…]
Le problème vient du fait que les liens des mots sont maintenant dans une table objet,id_objet.
Mais ce n’est pas un bug nouveau; un SPIP 2.1.2 a déjà du mal avec une boucle:
<BOUCLE_artdoc(ARTICLES){!id_document IN 1,5}> :
[…]
AND NOT((articles.id_article IN (
SELECT L1.id_objet, L1.id_objet AS id_article
FROM spip_documents_liens AS L1
WHERE ((L1.id_document IN (1,5))))))
[…]
J’attendrai plutôt une requête :
[…]
AND NOT((articles.id_article IN (
SELECT L1.id_objet AS id_article
FROM spip_documents_liens AS L1
WHERE ((L1.id_document IN (1,5))
AND (L1.objet=‘article’)))))
[…]
=> 1 seul SELECT : mysql renvoie l’erreur : Erreur SQL 1241 Operand should contain 1 column(s).
=> un WHERE qui réduit les réponses à l’objet de la table principale de la boucle.
Voici un bug bien caché que je ne suis pas du tout arrivé à suivre dans les méandres de criteres.php et composer.php.
Avec un SPIP 2.3.0 le critère {!id_mot ID 1,5} n'arrive pas à fabriquer la bonne sous-requête SQL, il renvoie:
Et bien non, ce n'est pas la même chose:
- la première boucle donne les articles qui n'ont le mot-clefs 1 ou 5
- la deuxième boucle uniquement les articles ayant au moins un mot clef qui n'est pas 1 ou 5.
Au niveau SQL:
- la première crée une sous-requête qui sera intégré dans le WHERE sous forme de NOT IN (...)
- la deuxième crée une jointure INNER JOIN (ce qui fait que seul les articles possédant au moins un mot clef seront listés)
C'est un vrai bug introduit par [11469]
qui ne devrait pas introduire 2 fois la même valeur sous 2 noms différents dans un Select.
Ce patach semble marcher:
Ce correctif corrige effectivement un des problèmes. Mais pas les 2 : l'autre étant qu'il manque «and objet='article'» dans la sous-requête pour filtrer uniquement sur ces liaisons là.
C'est un vrai bug introduit par [11469]
qui ne devrait pas introduire 2 fois la même valeur sous 2 noms différents dans un Select.
Ce patach semble marcher:
..
mais je ne suis pas sûr que ça ne pose pas d'autres pbs.
Cédric ?
Ce correctif corrige effectivement un des problèmes. Mais pas les 2 : l'autre étant qu'il manque «and objet='article'» dans la sous-requête pour filtrer uniquement sur ces liaisons là.
Oui bien vu. Mais en dernière analyse qqch ne va pas dans tout ça.
SELECT articles.id_article, articles.lang, articles.titre
FROM SLR_articles AS `articles`
INNER JOIN SLR_documents_liens AS L1 ON ( L1.id_objet = articles.id_article AND L1.objet='article')
WHERE (articles.statut = 'publie')
AND (articles.date < '2138-01-01 00:00:00')
AND ((L1.id_document NOT IN (1,5)))
GROUP BY articles.id_article
produit une requêté complètement différente, et de surcroit buggé.
Je ne comprends pas fondamenetalement pas pourquoi ces 2 écritures ne sont pas considérées comme équivalentes,
c'est complètement contre-intuitif.
Oui... en fait, l'écriture avec le ! devant est arrivé je ne sais quand pour répondre à un besoin précis.
{id_mot != 3} est différent de {!id_mot = 3} :
- le premier prend tous les mots qui ne sont pas 3 MAIS il y a au moins un mot (c'est ce que faisait naturellement SPIP)
- le second dit qu'on ne veut pas le mot 3, mais qu'il peut y avoir d'autres mots, ou aucun mot : la jointure n'est pas la même.
produit une requêté complètement différente, et de surcroit buggé.
Je ne comprends pas fondamenetalement pas pourquoi ces 2 écritures ne sont pas considérées comme équivalentes,
c'est complètement contre-intuitif.
En vérité c'est SQL qui induit des choses contre-intuitives. On parle
de tous ceux qui voulaient "tous les articles sauf ceux liés au mot
numéro 2" et tentaient intuitivement {id_mot!=2}, ce qui signifie en
bonne logique "lié à un mot dont l'id est différent de 2".
En introduisant {!id_mot=2} on pouvait enfin énoncer "n'est pas (lié
au mot 2)", à lire donc plutôt comme suit : {!(id_mot=2)} .