Utilitaires
Scripts
Divers
Jeux
Rechercher
Quillevere.net
Réflexions informatiques

Talend : injection de variables dans une requête SQL (bind variables)

19/07/2022

Problématique

Sur Talend, il n'y a pas de composant SQL permettant de faire une requête de sélection préparée avec du binding de variables, comme sur un éditeur SQL (tel que dBeaver). Il serait en effet intéressant de pouvoir faire une requête comme ci-dessous, en injectant la valeur saisie depuis des variables globales :

SELECT champ1, champ2 FROM maTable WHERE champ3 = :valeurChamp3

Proposition

Voici un exemple de job Talend permettant de s'en approcher, avec seulement 2 composants qui vont varier en contenu selon la requête :

  • Un composant tSetGlobalVar pour affecter les différentes valeurs à injecter sur la requête
  • Un composant tFixedFlowInput pour affecter le contenu de la requête elle-même, avec comme avantage de pouvoir être repris facilement, par copier-coller dans un requêteur SQL.

Description du traitement, étape par étape

Ajoutez un tSetGlobalVar

Ce composant va contenir vos variables à injecter.
Il est important de préfixer les clés par ":" car la liste des variables sera analysée en Java.
Le type est également important : les chaînes seront entre guillemets (avec "%" si on utilise LIKE) et les nombres directement saisis.

Ajoutez un tFixedFlowInput

Spécifiez les attributs suivants :
- Mode "Utiliser du contenu aligné"
- Séparateur de lignes = ";"
- Séparateur de champs = ";"
En lieu et place du contenu, collez votre requête avec les champs à injecter.

- Schéma avec une seule variable, nommée "sql" et de type String

Ajoutez un tJavaRow

Ce composant va effectuer les remplacements grâce au code suivant, à copier-coller sans adaptation.
// Injection des variables SQL

// -- Requête SQL sur une seule ligne (pour l'affichage en log)
String sSQL=input_row.sql.replace("\r", "").replace("\n", " ");

// -- Parcours les variables globales
java.util.Iterator<String> it = globalMap.keySet().iterator();
while(it.hasNext())
    {
    String key = it.next().toString();
    if (key.startsWith(":") && sSQL.contains(key))
        {
        Object value = globalMap.get(key);
       
        if (value==null)
            sSQL=sSQL.replace(key, "NULL");
        else
            {
            // Détermine le type de la variable
            if (value instanceof String)
                {
                // Echappement chaîne
                sSQL=sSQL.replace(key, "'" + value.toString().replace("'", "''") + "'");           
               
                }
               
            else
                {
                // Autre : pas d'échappement
                sSQL=sSQL.replace(key, value.toString());
               
                }
            }
       
       
        log.debug(" - Champ {} affecté à {}", key, value);   
        }
    }

log.info("Requête : {}", sSQL);
output_row.sql = sSQL;

Ajoutez un tFlowToIterate

Ajoutez un tDBInput

Ce composant va traiter la requête construite à l'étape précédente, en reprenant la variable globale.

Vous pouvez tester la bonne exécution en ajoutant un tLogRow.

Avantages et inconvénients

Comme avantage principal, on a la possibilité de copier-coller directement la requête dans un éditeur SQL et de tester différentes variables.

Il est également possible d'écrire des requêtes variant selon les données en entrée, comme pour une API acceptant différents types de recherche, comme par exemple :

SELECT champ3 FROM maTable WHERE (:valeur1 IS NULL OR champ1=:valeur1) AND (:valeur2 IS NULL OR champ2=:valeur2)

L'inconvénient majeur de cette technique est de ne plus pouvoir utiliser directement la fonction "Guess Schema" du composant tDBInput, qui ne connait plus la requête qu'au moment de l'exécution (mais une requête utilisant des variables n'aurait de toute façon pas pu être analysée en mode conception par un Guess Schema).

Dernière modification le 23/07/2022 - Quillevere.net

Rechercher sur le site

fr en rss RSS info Informations