Carnet Wiki

Difficultés avec jointures et solutions

Version 10 — Octobre 2022 JLuc

Champs homonymes, alias et LEFT JOIN

Thème : alias et type de join - Auteur : John Livingston et JMT19 - Source : https://code.globenet.org/attacfr/campagnodon/-/commit/d2b516b1e3e05fc4598973ae037cf868843b736d - Autre réf : ticket https://git.spip.net/spip/spip/issues/5203#issuecomment-37646 + PR https://git.spip.net/spip/spip/pulls/5205

Les 2 tables <code class=« mysql »>campagnodon_transactions</code code>CAMPAGNODON_TRANSACTIONS</code > et <code class=« mysql »>transactions</code code>transactions</code > ont toutes 2 un champ <code class=« mysql »>mode</code code>mode</code >.
Dans une jointure <code class=« spip »><BOUCLE_liste_campagnodon_transactions(CAMPAGNODON_TRANSACTIONS code><BOUCLE_liste_campagnodon_transactions(CAMPAGNODON_TRANSACTIONS transactions) on ne peut accéder qu’au <code class=« spip »>#MODE</code code>#MODE</code > de la 1re table : <code class=« mysql » >campagnodon_transactions</code CAMPAGNODON_TRANSACTIONS</code >

De plus, on souhaite que la jointure soit de type <code class=« mysql »>LEFT code>LEFT JOIN alors que SPIP fait par défaut des <code class=« mysql »>INNER code>INNER JOIN.

Soluce

On y parvient au moyen du critère suivant, qui déclare la jointure au lieu que ça soit la boucle, la déclare de type LEFT JOIN et crée un alias sur le champ. La balise qui suit permet ensuite d’y accéder.

function critere_campagnodon_jointure_transactions_dist($idb, &$boucles, $crit) {
  $boucle = &$boucles[$idb];
  $boucle->from['transactions'] = 'spip_transactions';
  $boucle->from_type['transactions'] = 'LEFT';
  // le format de join est :
  // array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
  $boucle->join['transactions'] = array("'campagnodon_transactions'", "'id_transaction'", "'id_transaction'");
  $boucle->select[] = 'transactions.mode AS transaction_mode'; // ce champ a un homonyme dans campagnodon_transactions, on contourne.
}


function balise_TRANSACTION_MODE_dist($p) {
    return rindex_pile($p, 'transaction_mode', 'campagnodon_jointure_transactions');
}

Usage

<BOUCLE_liste_campagnodon_transactions(CAMPAGNODON_TRANSACTIONS)
    {campagnodon_jointure_transactions}
    {statut_synchronisation?=#ENV{statut_synchronisation}}
    {tri #ENV{par,id_campagnodon_transaction},#GET{defaut_tri}}
    {pagination #ENV{nb,10}}
            title="<:info_numero_abbreviation|attribut_html:> #ID_TRANSACTION">#ID_TRANSACTION</a>
        </td>
        <td class="statut">[(#STATUT|match{echec|ok|rembourse}|et{#MESSAGE|trim|strlen}|?{[<abbr title="[(#MESSAGE|attribut_html)[ - (#ERREUR|attribut_html)]]">(#STATUT)</abbr>],#STATUT})]</td>
        <td class="transaction_mode">[(#TRANSACTION_MODE|bank_afficher_mode)]</td>
        <td class="montant">[(#MONTANT|bank_affiche_montant)]</td>
        <td class="mode">#MODE</td>
...
</BOUCLE_liste_campagnodon_transactions>

Alternative

JMT19 : une simple déclaration suffit dans le pipeline table interface :
$interfaces['exceptions_des_tables']['spip_transactions']['transaction_mode'] = array('campagnodon_transaction', 'mode');

#TRANSACTION_MODE doit alors fonctionner nickel, ainsi que les critères des tris.

À tester et confirmer !

Jointure conditionnelle avec critère conditionnel

Auteur Stéphane Santon - ref https://discuter.spip.net/t/erreur-sql-sur-boucle/164214

La boucle suivante

&lt;BOUCLE_rubs(ARTICLES){id_mot ?IN #ENV**{sections}}{0,12 }>
     ENV**{sections}}{0 ,  #ENV{limit,12 }}>
     #SET{etabs, #GET{etabs}|push{#ID_RUBRIQUE}}
</BOUCLE_rubs>

provoque l’erreur suivante quand il y a une valeur de sections dans l’environnement :

Unknown column 'L1.id_mot' in 'order clause'
SELECT articles.id_rubrique, articles.lang, articles.titre FROM spip_articles AS <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span> WHERE (articles.statut = 'publie') GROUP BY articles.id_article ORDER BY FIELD(L1.id_mot,5) LIMIT 0,12

Solution
L’erreur n’apparaît pas si le corps de la boucle utilise #ID_MOT car alors SPIP comprend bien qu’il a besoin de cette jointure.
Une soluce est donc d’y insérer [(#ID_MOT|oui)] pour forcer le compilateur SPIP à inclure la jointure même avec un critère conditionnel .