IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

BIRT Discussion :

Passer un paramètre via le before Open sur une requête sql


Sujet :

BIRT

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut Passer un paramètre via le before Open sur une requête sql
    Bonjour,

    Je cherche à faire un remplacement de texte dans mon dataset. Ce remplacement de texte doit me permettre de modifier la table requêtée.

    Voilà comment je procède mais sans réussir pour l'instant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var xxx = this.queryText="select echelon_sup FROM birt_echelon_sup WHERE echelon ='" + params["Nom_Table"].value + "'"; 
    this.queryText=this.queryText.replaceAll('tete', xxx);

    J'ai une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Caused by: org.eclipse.birt.report.data.adapter.api.AdapterException: An exception occurred during processing. Please see the following message for details:
    Failed to prepare the query execution for the data set: tab
    Cannot set the integer value (100) to parameter 1.
        org.eclipse.birt.report.data.oda.jdbc.JDBCException: Cannot set preparedStatement parameter int value.
    SQL error #1:L'indice de la colonne est hors limite*: 1, nombre de colonnes*: 0.
     ;
        org.postgresql.util.PSQLException: L'indice de la colonne est hors limite*: 1, nombre de colonnes*: 0
    La requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    SELECT a.tao_id_taxon, 
    row_number() over(ORDER BY (CASE 
    	WHEN e.sta_nom_statut ilike 'RE%' THEN '8' 
    	WHEN e.sta_nom_statut ilike 'CR%' THEN '7'
    	WHEN e.sta_nom_statut ilike 'EN%' THEN '6'  
    	WHEN e.sta_nom_statut ilike 'VU%' THEN '5' 
    	END) DESC, gta_nom_groupe_taxonomique ASC),
     gta_nom_groupe_taxonomique,
     tax_nom_vern,tax_nom_complet,
     sta_nom_statut,
     array_to_string(array_agg(distinct(tae_article)),' - ') as tae_article,
     tae_intitule,tae_url,
     MAX(SUBSTRING(ota_date_debut FOR 4)) as date_max
    ,(CASE 
    	WHEN e.sta_nom_statut ilike 'RE%' THEN '8' 
    	WHEN sta_nom_statut ilike 'CR%' THEN '7'
    	WHEN sta_nom_statut ilike 'EN%' THEN '6'  
    	WHEN sta_nom_statut ilike 'VU%' THEN '5'
    	END 
    ) AS toto 
     
    FROM t_taxon_observe a
    JOIN tr_groupe_taxonomique b ON a.gta_id_groupe_taxonomique = b.gta_id_groupe_taxonomique
    JOIN tv_taxon_observe_commune c ON a.tao_id_taxon = c.tao_id_taxon
    JOIN t_taxref d ON a.tao_id_taxon = d.tax_id_taxref
    JOIN tv_taxon_menace e ON a.tao_id_taxon = e.tao_id_taxon
    JOIN tj_taxref_protection f ON d.tax_id_taxref = f.tax_id_taxref
    JOIN t_taxref_reglementation g ON f.tae_cd_protection = g.tae_cd_protection
     
    WHERE gez_id_geom_zonage IN 
    (
    	SELECT b.gez_id_geom_zonage 
    	FROM tv_geom_zonages_commune a,tete b
    	WHERE ST_INTERSECTS(a.gez_geometry, b.gez_geometry)
    	AND a.gez_id_geom_zonage = ?
    )
    AND a.tao_id_taxon NOT IN
    (
    	SELECT b.tao_id_taxon
    	FROM tv_taxon_observe_commune b
    	WHERE gez_id_geom_zonage = ?
    )
     
    AND (tae_niveau = 'national'  OR tae_niveau = 'international' OR tae_niveau = 'communautaire')
    AND (sta_nom_statut ilike 'RE%' OR sta_nom_statut ilike 'EN%' OR sta_nom_statut ilike 'CR%' OR sta_nom_statut ilike 'VU%')
    OR (tae_niveau = 'regional' AND f.tae_cd_protection = 'RV43' AND ( sta_nom_statut ilike 'RE%' OR sta_nom_statut ilike 'EN%' OR sta_nom_statut ilike 'CR%' OR sta_nom_statut ilike 'VU%') )
     
     
    GROUP BY gta_nom_groupe_taxonomique,tax_nom_vern,tax_nom_complet,sta_nom_statut,tae_url,tae_arrete,a.tao_id_taxon,tae_intitule
    ORDER BY toto DESC, gta_nom_groupe_taxonomique ASC

    Merci de votre aide.

  2. #2
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Salut,

    C'est la première ligne qui embrouille les choses, il n'est pas nécessaire de passer par une variable.

    Essaie comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.queryText=this.queryText.replaceAll('tete', params["Nom_Table"].value);
    Par contre sans vouloir alarmer cela ouvre les possibilités d'injection SQL, selon la destination du rapport je conseille de tester dans le script si la valeur du paramètre "Nom_table" ressemble en gros à ce qui est attendu avant de faire le "replace". Par exemple si on peut comparer la valeur du paramètre à une liste de tables possibles c'est parfait.

    EDIT: j'ai peut être mal compris ce que tu souhaitais faire, pourquoi il y a une double affectation sur la première ligne?

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Citation Envoyé par donino Voir le message
    Salut,

    C'est la première ligne qui embrouille les choses, il n'est pas nécessaire de passer par une variable.

    Essaie comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.queryText=this.queryText.replaceAll('tete', params["Nom_Table"].value);
    Par contre sans vouloir alarmer cela ouvre les possibilités d'injection SQL, selon la destination du rapport je conseille de tester dans le script si la valeur du paramètre "Nom_table" ressemble en gros à ce qui est attendu avant de faire le "replace". Par exemple si on peut comparer la valeur du paramètre à une liste de tables possibles c'est parfait.

    EDIT: j'ai peut être mal compris ce que tu souhaitais faire, pourquoi il y a une double affectation sur la première ligne?

    Merci pour la réponse !

    Le truc c'est que j'ai besoin de la première ligne car je dois aller chercher un nom de table à partir du nom de table du paramètre.

    Pour tout expliquer, je vais chercher l'échelon géographique supérieur. Exemple je suis dans une commune et l'échelon supérieur est la communauté de commune.

    Ainsi, je souhaite récupérer la table de l'échelon supérieur avant l’exécution du projet Birt.

    Pour le côté sécurité, je regarderais cela après mais merci pou ton alerte. On est de toute façon dans une application sécurisée par un mot de passe.

  4. #4
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Ok je pense que j'ai compris. La problématique principale étant qu'on ne peut en effet pas définir de paramètre SQL dans la clause 'from' d'une requête.

    Il n'est pas possible d' invoquer dynamiquement du SQL comme tente de le faire la première ligne de ton script, il faut procéder autrement et c'est un peu sioux.

    Il faut d'abord créer un dataset séparé avec cette requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select echelon_sup FROM birt_echelon_sup WHERE echelon =?
    • Le paramètre '?' étant donc le nom de l'échelon, si j'ai bien compris cette requête ne retourne qu'une ligne.
    • Récupérer echelon_sup dans une variable globale, par exemple dans le script "onFetch" du nouveau dataset
    • Lier ce nouveau dataset à un élément caché tout en haut du rapport, pour être certain qu'il soit déclenché avant le dataset principal.

      utiliser la variable globale dans le script beforeOpen du dataset principal, comme tu l'as fait avec la variable xxx mais cette fois sans la première ligne.


    Voilà, c'est un peu compliqué mais je pense que c'est la seule méthode pour ce type de problème. En plus le paramètre d'entrée étant cette fois utilisé comme un vrai paramètre '?', les injections SQL sont impossibles

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Citation Envoyé par donino Voir le message
    Ok je pense que j'ai compris. La problématique principale étant qu'on ne peut en effet pas définir de paramètre SQL dans la clause 'from' d'une requête.

    Il n'est pas possible d' invoquer dynamiquement du SQL comme tente de le faire la première ligne de ton script, il faut procéder autrement et c'est un peu sioux.

    Il faut d'abord créer un dataset séparé avec cette requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select echelon_sup FROM birt_echelon_sup WHERE echelon =?
    • Le paramètre '?' étant donc le nom de l'échelon, si j'ai bien compris cette requête ne retourne qu'une ligne.
    • Récupérer echelon_sup dans une variable globale, par exemple dans le script "onFetch" du nouveau dataset
    • Lier ce nouveau dataset à un élément caché tout en haut du rapport, pour être certain qu'il soit déclenché avant le dataset principal.

      utiliser la variable globale dans le script beforeOpen du dataset principal, comme tu l'as fait avec la variable xxx mais cette fois sans la première ligne.


    Voilà, c'est un peu compliqué mais je pense que c'est la seule méthode pour ce type de problème. En plus le paramètre d'entrée étant cette fois utilisé comme un vrai paramètre '?', les injections SQL sont impossibles
    Merci pour ta réponse.


    Peux tu me dire comment faire :

    -Récupérer echelon_sup dans une variable globale, par exemple dans le script "onFetch" du nouveau dataset

    -Lier ce nouveau dataset à un élément caché tout en haut du rapport, pour être certain qu'il soit déclenché avant le dataset principal.


    Un grand merci.

  6. #6
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Lier ce nouveau dataset à un élément caché tout en haut du rapport, pour être certain qu'il soit déclenché avant le dataset principal.
    Par exemple il suffit de faire un glisser-déplacer de la colonne du dataset vers le rapport, il va automatiquement créer un élément lié qui affichera le fameux echelon_sup. Il suffit ensuite de le cacher (propriété "visibility").

    Récupérer echelon_sup dans une variable globale, par exemple dans le script "onFetch" du nouveau dataset
    Les variables globales sont des variables sans le mot "var" devant. Donc on peut faire dans le script onFetch du dataset
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ECHELON_SUP=row["echelon_sup"]
    puis dans ton beforeOpen:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.queryText=this.queryText.replaceAll('tete', ECHELON_SUP);

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Bonjour,

    De retour du week-end et bien motivé de réussir cette astuce, je te remercie pour ton message explicatif.

    Malheureusement, j'ai encore un message d'erreur malgré cela :

    1) Faire glisser échelon_sup tout en haut de la feuille et cacher sa visibilité

    2) Faire le ECHELON_SUP=row["echelon_sup"]; dans le OnFetch() du DataSet principal

    3) Faire le remplacement du texte grâce à this.queryText=this.queryText.replaceAll('tete', ECHELON_SUP); dans le beforeOpen du dataset principal


    Erreur : ECHELON_SUP n'est pas défini. (cf. pj).

    Merci encore une fois pour tes lumières.
    Images attachées Images attachées  

  8. #8
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    il doit y avoir une erreur de syntaxe quelquepart ou une erreur de nom de colonne dans le onfetch. Il faut faire un peu de débuggage classique: afficher le champs echelon_sup en haut pour voir si il est bien renseigné, afficher un texte dynamique juste aprés pour vérifier si la variable a été correctement renseignée, avec une expression genre "Echelon sup="+ECHELON_SUP

    Dans le script "initialize" du rapport mets une valeur par défaut cela aidera à trouver l'origine du problème.
    ECHELON_SUP="default";

    etc.

  9. #9
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Salut,

    Un 'echelon sup ='+ ECHELON_SUP dans un texte dynamique après l'affichage de l'échelon sup provenant de la requête ne fonctionne pas.

    Par contre, le champ "echelon_sup" provenant de la requête affiche bien l'échelon supérieur.

    Edit : Si je met le ECHELON_SUP="default"; dans le initialize, cela m'affiche default

    Edit : Ca fonctionne avec dataSetRow["echelon_sup"]

  10. #10
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Comment être en mesure maintenant de gérer le fait que parfois, il n'y a pas d'échelon supérieur.

    Peut-mettre un message à la place du message d'erreur que cela risque de générer ?

    Merci !

  11. #11
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Je suis content que ça fonctionne!

    Habituellement pour gérer l'absence de données on crée un élément label avec dedans le message qui va bien, et on met une visibilité conditionnelle dessus, avec la propriété "visibility". Par exemple dans ton cas la condition pour cacher ce label serait probablement:

    De la même manière on peut cacher des éléments quand il n'y a pas de données avec l'expression inverse:


  12. #12
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Salut,

    Moi aussi je suis content !

    j'ai appliqué les conditions dans visibility. Si je passe une table qui n'a pas d'échelon supérieur, j'ai un message d'erreur.

    Une idée d'où cela peu provenir ?

    visible en PJ.

    Merci !
    Images attachées Images attachées  

  13. #13
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Et oui c pas facile La requête plante sans doute si la table 'tete' est remplacée par une table qui n'existe pas, en plus 'default' est aussi à priori un mot réservé en SQL. Donc pour résoudre le problème je pense qu' il faut tester ECHELON_SUP avant d'effectuer le remplacement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (ECHELON_SUP!="default"){
      this.queryText=this.queryText.replaceAll('tete', ECHELON_SUP);
    }else{
     
    }
    Quoi mettre dans le "else"? A priori en ne mettant rien ça ira si les éléments sont cachés quand ECHELON_SUP est égal à la valeur par défaut, mais ça va générer une requête sur la table 'tete' et donc sans doute des données pour rien. On peut ajouter un filtre de dataset pour exclure les données quand ECHELON_SUP est à la valeur par défaut. On peut aussi remplacer ici la valeur d'un paramètre d'entrée par une valeur qui ne retournera rien.

    Enfin, une alternative serait de déplacer le problème dans la base de données en créant une procédure stockée qui s'occupe de tout ça

  14. #14
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Bonjour,

    J'ai ajouté la condition dans le BeforeOpen. On reste sur une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Table (id = 876): 
    + Cannot get the result set metadata.
        org.eclipse.birt.report.data.oda.jdbc.JDBCException: SQL statement does not return a ResultSet object.
    SQL error #1:ERROR: relation "tv_taxon_observe_epci1" does not exist
     ;
        org.postgresql.util.PSQLException: ERROR: relation "tv_taxon_observe_epci1" does not exist (Element ID:876)

  15. #15
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    Cette fois le message est clair, "tv_taxon_observe_epci1" ne fait pas partie de la requête initiale d'où vient il

  16. #16
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 660
    Points : 331
    Points
    331
    Par défaut
    Arf oui, une erreur sur la table.

    Mais lorsque je passe une table qui n'est pas dans la table des échelons supérieur, voilà l'erreur affichée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Table (id = 876): 
    + Cannot get the result set metadata.
        org.eclipse.birt.report.data.oda.jdbc.JDBCException: SQL statement does not return a ResultSet object.
    SQL error #1:ERROR: relation "tv_taxon_observe_undefined" does not exist
     ;
        org.postgresql.util.PSQLException: ERROR: relation "tv_taxon_observe_undefined" does not exist (Element ID:876)
    A noter que je modifie deux autres tables sur le Before soit en tout :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var sArr = params["Nom_Table"].value.split("_");this.queryText=this.queryText.replaceAll('param_table', 'tv_taxon_observe_'+sArr[3]); 
    var sArr2 = params["Nom_Table"].value.split("_");this.queryText=this.queryText.replaceAll('geom_a', 'tv_geom_zonages_'+sArr2[3]);
    var sArr3 = ECHELON_SUP.split("_");if (ECHELON_SUP!="default"){this.queryText=this.queryText.replaceAll('tete', ECHELON_SUP);}else{};
    this.queryText=this.queryText.replaceAll('titi', 'tv_taxon_observe_'+sArr3[3]);

  17. #17
    Membre éclairé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2009
    Messages
    529
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2009
    Messages : 529
    Points : 836
    Points
    836
    Par défaut
    ça se complique mais normal que ECHELON_SUP.split("_") retourne "undefined" puisque il n'y a pas de underscore dans la valeur par défaut. En fait pour faire simple il ne faut traiter la requête que si ECHELON_SUP n'est pas à la valeur par défaut, donc englober tous les "replace" dans le if (ECHELON_SUP!="default"){...}

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/03/2012, 10h50
  2. aide sur une requête sql
    Par sanach dans le forum Développement
    Réponses: 9
    Dernier message: 17/10/2007, 20h42
  3. Problème de SUM sur une requête SQL
    Par Lapicure dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 12/06/2007, 11h51
  4. Barre de progression sur une requète SQL
    Par Wilco dans le forum Bases de données
    Réponses: 4
    Dernier message: 28/04/2005, 14h20
  5. Pb sur une requête SQL (de champ vide)
    Par Marion dans le forum Langage SQL
    Réponses: 3
    Dernier message: 01/07/2004, 11h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo