[spip-dev] Spip tables supplementaires et jointures

Bonjour

Suite à un premier post sur la liste "user", je tente ma chance ici.
Malgrè mes recherches et essais ainsi que la lecture de différents
messages sur ce groupe, je coince.

Pour ajouter des renseignements dans les rubriques (sous-titre par
exemple) puisque les champs texte et description servent à autre chose,
j'ai choisi de créer une table supplémentaire "rubriques_plus". (le
plugin champs homonymes alterant les structures des tables existantes,
je l'ai écarté, mais ce n'est pas définitif). Cette table est gérée avec
Table_data.

CREATE TABLE rubriques_plus (
  id_rub_plus bigint(21) NOT NULL auto_increment,
  id_rubrique bigint(21) NOT NULL default '0',
  sous_titre text NOT NULL,
  PRIMARY KEY (id_rub_plus),
  KEY id_rubrique (id_rubrique)
)

Toutes les rubriques n'ayant pas un sous-titre, la table rubrique_plus
comporte une clef primaire et une clé étrangère (l'id de la rubrique
auquel se rapporte le sous-titre).

la boucle avec jointure :
<BOUCLE_rubriques(RUBRIQUES rubriques_plus){tout}>
        #TITRE - #SOUS_TITRE<br />
</BOUCLE_rubriques>

produit une erreur :
1 SELECT rubriques.titre, J0.sous_titre, rubriques.lang
2 FROM rubriques_plus AS `J0`, spip_rubriques AS `rubriques`
3 WHERE (rubriques.id_rub_plus = J0.id_rub_plus)

car spip tente de faire la jointure sur la clé primaire de la table
"rubriques_plus" et le champ homonyme de la table "rubriques" qui
n'existe pas.

remarque au passage : spip fait les jointures dans la clause where,
plutot que par "join..."

Si je déclare dans rubriques_plus le champ id_rubrique comme clé
primaire tout fonctionne, mais c'est table_data qui refuse de
fonctionner car la clé primaire n'est plus auto-incrément et ce n'est
pas très correct de procéder ainsi pour l'intégrité des tables.

Bien sûr on peut s'en sortir par :
<BOUCLE_rubriques(RUBRIQUES){tout}>

<BOUCLE_rubriques_plus(RUBRIQUES_PLUS){id_rubrique=#ID_RUBRIQUE}>
        #TITRE - #SOUS_TITRE<br />
        </BOUCLE_rubriques_plus>
</BOUCLE_rubriques>

Pas très propre d'un point de vue optimisation des requètes puisque si
on a N rubriques on fait N+1 requètes alors qu'avec la jointure on n'en
fait qu'une seule

Autre tentative
declarer dans "mes_fonctions.php" :

global $tables_principales;
$tables_principales['rubriques_plus']['field'] = array(
        'id_rub_plus' => 'bigint(21) NOT NULL auto_increment',
        'id_rubrique' => 'bigint(21) NOT NULL default \'0\'',
        'sous_titre' => 'text NOT NULL');
$tables_principales['rubriques_plus']['key'] = array(
        'PRIMARY KEY id_rub_plus' => 'id_rub_plus',
        'KEY id_rubrique' => 'id_rubrique');
         
global $tables_jointures;
$tables_jointures['spip_rubriques'][] ='rubriques_plus';

et la boucle
<BOUCLE_rubriques(RUBRIQUES){tout}>
        #TITRE - #SOUS_TITRE<br />
</BOUCLE_rubriques>

mais seul le titre s'affiche.
Mais peut-être dans ce cas là ai-je oublié qqchose ? Si qqun pouvait me
valider ce bout de code, cela léverai une hypthèse.

Remarques :
Le résultat est identique avec la 1.9.2 officielle ou la dernière
révision SPIP 1.9.3 dev [8932]

Cette dernière intègre pourtant la correction :
"ne pas s'interdire les jointures sur les cles secondaires, meme si la
cle primaire est prioritaire !" ?
http://trac.rezo.net/trac/spip/changeset/8919

Si on ajoute le critère pour forcer la jointure sur les bons champs :

<BOUCLE_rubriques(RUBRIQUES rubriques_plus)
{id_rubrique=rubrique_plus.id_rubrique}>
        #TITRE - #SOUS_TITRE<br />
</BOUCLE_rubriques>

celle-ci est bien produite dans la requète, mais comme celle sur la clef
primaire est toujours présente, cela produit l'échec.
SELECT rubriques.titre, J0.sous_titre, rubriques.lang
FROM rubriques_plus AS `J0`, `spip192`.spip_rubriques AS `rubriques`
WHERE (rubriques.id_rubrique = 'rubrique_plus.id_rubrique')
AND (rubriques.id_rub_plus = J0.id_rub_plus)
AND (rubriques.statut = "publie")

Il faudrait qu'à partir du moment où la jointure est donnée dans les
critères, spip n'ajoute rien comme autres critères de jointure (encore
que là il me semble que les quote autour de 'rubrique_plus.id_rubrique'
sont de trop. Ou alors un critère "jointure" {jointure id_rubrique
id_rubrique} explicite pour les boucles (sans ajout alors d'autres
critères)

Reste toujours la solution des boucles imbriquées mais bon...
Il faudrait alors préciser aussi dans la doc que spip ne fait des
jointures avec les tables supplémentaires que sur les clefs primaires
(ce qui a son importance).

Merci

Dominique wrote: ...

Le résultat est identique avec la 1.9.2 officielle ou la dernière
révision SPIP 1.9.3 dev [8932]

Il faudrait qu'à partir du moment où la jointure est donnée dans les
critères, spip n'ajoute rien comme autres critères de jointure (encore
que là il me semble que les quote autour de 'rubrique_plus.id_rubrique'
sont de trop. Ou alors un critère "jointure" {jointure id_rubrique
id_rubrique} explicite pour les boucles (sans ajout alors d'autres
critères)

As-tu testé la nouvelle modif récente http://trac.rezo.net/trac/spip/changeset/8937 ?

JLuc

As-tu testé la nouvelle modif récente
http://trac.rezo.net/trac/spip/changeset/8937 ?

Non mais dès que j'aurais un peu de temps.
Cela m'a l'air très interessant.
Mais : comment déclare-t-on les champs de jointure ?
apparemment dans la global $tables_auxiliaires;

mais alors à quoi sert $tables_jointures ???

JLuc

Merci des tuyaux

Mais je viens de découvrir que :
<BOUCLE_rubriques(RUBRIQUES_PLUS rubriques){tout}>
        #TITRE - #SOUS_TITRE<br />
</BOUCLE_rubriques>

fonctionne elle parfaitement ???
le code produit :
1 SELECT J0.titre, rubriques_plus.sous_titre
2 FROM `spip19`.spip_rubriques AS `J0`, rubriques_plus AS
`rubriques_plus`
3 WHERE (rubriques_plus.id_rubrique = J0.id_rubrique)

je pense que le sens de l'analyse des champs doit y être pour quelque
chose.