Jointure entre tables et champs homonymes #5203

Closed
opened 3 months ago by tofulm · 4 comments
tofulm commented 3 months ago
Collaborator

dans cet exemple :

<BOUCLE_billetteries(BILLETTERIES spip_evenements)>
    #TITRE
</BOUCLE_billetteries>

les tables spip_billetteries et spip_evenements ont un champ titre. SPIP va donc prendre en compte, je site la doc : "table première de la requête", donc dans mon exemple le champ titre de spip_billetteries.
https://www.spip.net/fr_article4254.html

De la meme manière que l'on peut appeller une balise en la prefixant par le nom de la boucle #_billetterie:TITRE, on pourrait avoir une ecriture equivalente en spécifiant le nom de la table.

dans cet exemple : ```html <BOUCLE_billetteries(BILLETTERIES spip_evenements)> #TITRE </BOUCLE_billetteries> ``` les tables spip_billetteries et spip_evenements ont un champ titre. SPIP va donc prendre en compte, je site la doc : "table première de la requête", donc dans mon exemple le champ titre de spip_billetteries. https://www.spip.net/fr_article4254.html De la meme manière que l'on peut appeller une balise en la prefixant par le nom de la boucle `#_billetterie:TITRE`, on pourrait avoir une ecriture equivalente en spécifiant le nom de la table.

Je pense que l'écriture #CHAMP_SQL{evenements.titre} devrait utiliser l'alias et faire la correspondance avec le vrai alias final généré dans le SQL, comme dans les critères qui génère les where.

Par ex là, si la table spip_evenements est mise dans JOIN spip_evenements as L3 alors avec cette balise ça devrait détecter et générer SELECT L3.titre.

SPIP sait forcément déjà le faire puisque c'est exactement ce qui est fait dans les critères : si dans cette boucle BILLETTERIES on met {evenements.date_debut > 2019-02} dans le SQL ça génère déjà un L3.date_debut > "2019-02".

Je pense que l'écriture `#CHAMP_SQL{evenements.titre}` devrait utiliser l'alias et faire la correspondance avec le vrai alias final généré dans le SQL, comme dans les critères qui génère les where. Par ex là, si la table spip_evenements est mise dans `JOIN spip_evenements as L3` alors avec cette balise ça devrait détecter et générer `SELECT L3.titre`. SPIP sait forcément déjà le faire puisque c'est exactement ce qui est fait dans les critères : si dans cette boucle BILLETTERIES on met `{evenements.date_debut > 2019-02}` dans le SQL ça génère déjà un `L3.date_debut > "2019-02"`.
b_b added the
amélioration
label 2 months ago
b_b added this to the 4.2 milestone 2 months ago

Y aurait il une combinaison de tables moins exotiques qui permettent de tester la situation ?

Et pourquoi #CHAMP_SQL{L2.titre} ou #CHAMP_SQL{L1.titre} ne marchent ils pas ?

Y aurait il une combinaison de tables moins exotiques qui permettent de tester la situation ? Et pourquoi `#CHAMP_SQL{L2.titre}` ou `#CHAMP_SQL{L1.titre}` ne marchent ils pas ?
Poster
Collaborator

dans mon exemple, il faudrait utiliser L2.titre car L1 est c'est l'alias de la table de liens spip_billetteries_liens, mais la n'est pas la question.
je pense qu'il serait plus lisible d'ecrire : #CHAMP_SQL{evenements.titre}

dans mon exemple, il faudrait utiliser `L2.titre` car `L1` est c'est l'alias de la table de liens spip_billetteries_liens, mais la n'est pas la question. je pense qu'il serait plus lisible d'ecrire : `#CHAMP_SQL{evenements.titre}`
Owner

La balise #CHAMP_SQL tente déjà de réaliser une jointure, mais seulement si le nom du champ n’existe pas déjà dans la table.

  • #CHAMP_SQL appelle
  • champ_sql()
  • index_pile()
  • index_tables_en_pile()

Qui indique par ailleurs

 * @todo
 *     Ici la recherche de jointure sur l'absence d'un champ ne cherche
 *     une jointure que si des jointures explicites sont demandées,
 *     et non comme à d'autres endroits sur toutes les jointures possibles.
 *     Il faut homogénéiser cela.

Il semble possible de modifier index_tables_en_pile() pour obtenir ce qui est souhaité

<h1>#SQUELETTE</h1>

<BOUCLE_art(ARTICLES){par num titre}{0,5}>
	- #TITRE<br />
	- #CHAMP_SQL{titre}<br />
	- #CHAMP_SQL{rubriques.titre}<br />
	----<br />
</BOUCLE_art>
diff --git a/ecrire/public/references.php b/ecrire/public/references.php
index 997edf2a0..6d5dbf726 100644
--- a/ecrire/public/references.php
+++ b/ecrire/public/references.php
@@ -281,6 +281,20 @@ function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) {
                // tenter via une jointure...
                else {
                        $joker = false; // indiquer a l'appelant
+                       // la table de jointure est explicitement indiquée {truc.muche}
+                       if (preg_match('/^([^,]*)\.(.*)$/', $nom_champ, $r)) {
+                               [, $_table, $_nom_champ] = $r;
+                               if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) {
+                                       $_alias = $cle . '_' . $_nom_champ;
+                                       $x = index_exception(
+                                               $boucles[$idb],
+                                               $desc,
+                                               $_alias,
+                                               [$_table, $_nom_champ]
+                                       );
+                                       return $x;
+                               }
+                       } else {
                                // regarder si le champ est deja dans une jointure existante
                                // sinon, si il y a des joitures explicites, la construire
                                if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) {
@@ -294,6 +308,7 @@ function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) {
                                                }
                                        }
                                }
+                       }
                        if ($t) {
                                // si on a trouvé une jointure possible, on fait comme
                                // si c'était une exception pour le champ demandé

Le code est peut être pas placé au meilleur endroit ici cela dit.
En tout cas ça répond au besoin.

La balise `#CHAMP_SQL` tente déjà de réaliser une jointure, mais seulement si le nom du champ n’existe pas déjà dans la table. - `#CHAMP_SQL` appelle - `champ_sql()` - `index_pile()` - `index_tables_en_pile()` Qui indique par ailleurs ``` * @todo * Ici la recherche de jointure sur l'absence d'un champ ne cherche * une jointure que si des jointures explicites sont demandées, * et non comme à d'autres endroits sur toutes les jointures possibles. * Il faut homogénéiser cela. ``` Il semble possible de modifier `index_tables_en_pile()` pour obtenir ce qui est souhaité ```html <h1>#SQUELETTE</h1> <BOUCLE_art(ARTICLES){par num titre}{0,5}> - #TITRE<br /> - #CHAMP_SQL{titre}<br /> - #CHAMP_SQL{rubriques.titre}<br /> ----<br /> </BOUCLE_art> ``` ```diff diff --git a/ecrire/public/references.php b/ecrire/public/references.php index 997edf2a0..6d5dbf726 100644 --- a/ecrire/public/references.php +++ b/ecrire/public/references.php @@ -281,6 +281,20 @@ function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) { // tenter via une jointure... else { $joker = false; // indiquer a l'appelant + // la table de jointure est explicitement indiquée {truc.muche} + if (preg_match('/^([^,]*)\.(.*)$/', $nom_champ, $r)) { + [, $_table, $_nom_champ] = $r; + if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) { + $_alias = $cle . '_' . $_nom_champ; + $x = index_exception( + $boucles[$idb], + $desc, + $_alias, + [$_table, $_nom_champ] + ); + return $x; + } + } else { // regarder si le champ est deja dans une jointure existante // sinon, si il y a des joitures explicites, la construire if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) { @@ -294,6 +308,7 @@ function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) { } } } + } if ($t) { // si on a trouvé une jointure possible, on fait comme // si c'était une exception pour le champ demandé ``` Le code est peut être pas placé au meilleur endroit ici cela dit. En tout cas ça répond au besoin.
marcimat referenced this issue from a commit 2 months ago
marcimat referenced this issue from a commit 2 months ago
marcimat closed this issue 2 months ago
Sign in to join this conversation.
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.