J'ai un petit souci avec des critères optionnels. (spip branche 2.0)
J'ai déclaré une jointure sur une nouvelle table : $interface['tables_jointures']['spip_auteurs'][] = 'grappes_liens';
Où spip_grappes_liens contient : id_grappe, objet, id_objet. (Comme la table spip_documents_liens)
Premiers problème (peu important), indiquer un id_grappe fait perdre l'affichage d'uniquement les auteurs qui ont écrit un article. Tous les auteurs (liés à la grappe 3) apparaîssent, qu'ils aient publié ou non des articles. Exemple :
<BOUCLE_(AUTEURS){id_grappe=3}>#NOM<br /><BOUCLE_>
Second couac, c'est celui là qui m'interpelle : si l'on met un critère conditionnel {id_grappe ?} et que ce critère est absent de l'environnement, il y a tout de même une jointure de réalisée entre les tables auteurs et grappes_liens, tel qu'apparaissent tous les auteurs qui appartiennent au moins à une grappe. Ainsi :
<BOUCLE_(AUTEURS){id_grappe ?}>#NOM<br /></BOUCLE_> provoque en absence de id_grappe la requête :
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur )
WHERE (auteurs.statut != '5poubelle')
AND (L1.objet = 'auteur')
GROUP BY auteurs.id_auteur
Est-ce que cette jointure est "normale" ?
En allant un peu plus loin, lorsque le paramètre transmis commence par "id_" (exception de id_article), une jointure se réalise sur la table spip_grappes_liens...
<BOUCLE_(AUTEURS){id_grappe ?}{id_rubrique ?}{id_bidule ?}{id_chose ?}>#NOM<br /></BOUCLE_> Provoque la belle requête :
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L4 ON ( L4.id_objet = auteurs.id_auteur )
INNER JOIN spip_grappes_liens AS L3 ON ( L3.id_objet = auteurs.id_auteur )
INNER JOIN spip_grappes_liens AS L2 ON ( L2.id_objet = auteurs.id_auteur )
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur )
WHERE (auteurs.statut != '5poubelle')
AND (L1.objet = 'auteur')
AND (L2.objet = 'auteur')
AND (L3.objet = 'auteur')
AND (L4.objet = 'auteur')
GROUP BY auteurs.id_auteur
J'ai un petit souci avec des critères optionnels. (spip branche 2.0)
Si quelqu'un peut m'expliquer ce qui se passe ?
Je continue mon exploration.
Il semble que la relation id_chose=8 => objet='chose', id_objet=8 ne se passe pas toujours bien comme il le faudrait.
Plutôt donc que de partir avec une table en plus (grappes) je teste avec directement les documents (et donc la liaison spip_documents_liens).
La boucle :
<BOUCLE(ARTICLES){id_document=2}> crée une requête correcte.
<BOUCLE(ARTICLES){id_document ?}> se plante (comme grappes précedemment) avec :
SELECT articles.titre, articles.lang
FROM spip_articles AS `articles`
INNER JOIN spip_documents_liens AS L1 ON ( L1.id_objet = articles.id_article )
WHERE (articles.statut = 'publie')
AND (L1.objet = 'article')
GROUP BY articles.id_article
Donnant tous les articles possédant au moins un document joint ce qui correspondrait plutot à une demande comme : <BOUCLE(ARTICLES){id_document>=0}>#TITRE<br /></BOUCLE>
Le commentaire ligne 534 de composer.php, déjà là en 1.9.2, dit qu'on cherche à retirer les jointures finalement inutiles suite à un critère conditionnel absent. Il faudrait voir si ça marchait bien en 1.9.2 (il me semble que oui), et trouver quand ça a divergé pour corriger.
Je pense que j'ai oublié le cas conditionnel sur la jointure decomposee en id_article => (id_objet,objet=article)
SI SQL permet d'ecrire de maniere fiable
ON (L1.id_objet = articles.id_article AND L1.objet = 'article')
alors cela resoudrait la question, et la jointure serait eliminee lors de l'optimisation.
J'ai constaté que cela marchait en mysql, mais je n'ai pas vérifié si cette ecriture est standard et autorisée par sql.
Si tu peux verifier ce point, mathieu, je veux bien faire ensuite le correctif
OK, c'est en grande partie corrigé effectivement...
Mais il me semble qu'il reste un problème. Est-on d'accord que la syntaxe : {!id_mot} affiche "tout sauf ce qui lié à ce mot" ?
Si c'est le cas, {!id_groupe} ne répond pas à ce critère, mais donne : "tout ce qui est lié à un groupe, mais pas au groupe id_groupe". Par exemple en envoyant id_grappe=3 sur cette boucle
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur AND L1.objet='auteur')
WHERE (auteurs.statut != '5poubelle')
AND NOT((L1.id_grappe = 3))
GROUP BY auteurs.id_auteur
Le "AND L1.objet='auteur'" dans ce cas là devrait être dans le NOT me semble-t-il :
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur )
WHERE (auteurs.statut != '5poubelle')
AND NOT((L1.id_grappe = 3 AND L1.objet='auteur'))
GROUP BY auteurs.id_auteur
OK, c'est en grande partie corrigé effectivement...
Mais il me semble qu'il reste un problème. Est-on d'accord que la syntaxe : {!id_mot} affiche "tout sauf ce qui lié à ce mot" ?
Si c'est le cas, {!id_groupe} ne répond pas à ce critère, mais donne : "tout ce qui est lié à un groupe, mais pas au groupe id_groupe". Par exemple en envoyant id_grappe=3 sur cette boucle
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur AND L1.objet='auteur')
WHERE (auteurs.statut != '5poubelle')
AND NOT((L1.id_grappe = 3))
GROUP BY auteurs.id_auteur
Le "AND L1.objet='auteur'" dans ce cas là devrait être dans le NOT me semble-t-il :
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur )
WHERE (auteurs.statut != '5poubelle')
AND NOT((L1.id_grappe = 3 AND L1.objet='auteur'))
GROUP BY auteurs.id_auteur
OK, c'est en grande partie corrigé effectivement...
Mais il me semble qu'il reste un problème. Est-on d'accord que la syntaxe : {!id_mot} affiche "tout sauf ce qui lié à ce mot" ?
Si c'est le cas, {!id_groupe} ne répond pas à ce critère, mais donne : "tout ce qui est lié à un groupe, mais pas au groupe id_groupe". Par exemple en envoyant id_grappe=3 sur cette boucle
SELECT auteurs.nom
FROM spip_auteurs AS `auteurs`
INNER JOIN spip_grappes_liens AS L1 ON ( L1.id_objet = auteurs.id_auteur AND L1.objet='auteur')
WHERE (auteurs.statut != '5poubelle')
AND NOT((L1.id_grappe = 3))
GROUP BY auteurs.id_auteur
Le "AND L1.objet='auteur'" dans ce cas là devrait être dans le NOT me semble-t-il :
Ah non, pardon, j'ai faux là... c'est plutot un LEFT JOIN qu'il faut à la place du INNER JOIN ? enfin, je sais plus tiens !...
Il me semble que dans un soucis de compatibilité ascendante avec les écritures existantes
{!id_mot} reste traduit comme {id_mot!=n} (ie son interprétation n'a pas été modifiée)
et non comme {!id_mot=n} (écriture qui n'était pas possible auparavant)
Il me semble que dans un soucis de compatibilité ascendante avec les écritures existantes
{!id_mot} reste traduit comme {id_mot!=n} (ie son interprétation n'a pas été modifiée)
et non comme {!id_mot=n} (écriture qui n'était pas possible auparavant)
Ok pour ça.
1 question : {!id_mot=n?} aurait-il un sens alors (si n est null) ?
génère :
SELECT articles.date, articles.titre, articles.lang
FROM spip_articles AS `articles`
WHERE (articles.statut = 'publie')
AND NOT((articles.id_article IN (
SELECT L1.id_objet, L1.id_objet AS id_article
FROM `mu_naya`.spip_documents_liens AS `L1`
WHERE (L1.id_document = 4))))
GROUP BY articles.id_article
ORDER BY articles.date DESC
LIMIT 0,10
Or la selection : SELECT L1.id_objet, L1.id_objet AS id_article
FROM `mu_naya`.spip_documents_liens AS `L1`
WHERE (L1.id_document = 4)
Récupère des id_objets qui n'ont aucun liens avec des articles (comme des documents de rubriques). Il faudrait bien ici :
WHERE (L1.id_document = 4 AND objet = 'article')