Show Menu
SUJETS×

Ajout d'autres fonctions SQL

Introduction

Adobe Campaign permet à l'utilisateur de définir ses propres fonctions , qui peuvent accéder aux fonctions SQL offertes par la base de données, et qui ne seraient pas déjà disponibles dans la console. Ce mécanisme est utile par exemple dans le cas de fonctions d'agrégats (moyenne, maximum, somme) qui ne peuvent être calculées que sur le serveur ou bien quand la base de données offre un moyen plus facile d'implémenter certaines fonctions, plutôt que d'écrire l'expression "à la main" dans la console (par ex. gestion de dates).
Ce mécanisme peut aussi servir dans le cas où l'on souhaiterait utiliser une fonction SQL récente, ou rare, d'un moteur de base de données, et qui ne serait pas encore offerte par la console Adobe Campaign.
Une fois ces fonctions ajoutées, elles apparaissent dans l'éditeur d'expressions, au même titre que les fonctions prédéfinies.
Les appels de fonctions SQL dans la console ne sont plus naturellement transmis au serveur. Le mécanisme décrit ici devient donc le seul moyen d'appeler sur le serveur des fonctions SQL non prévues initialement.

Installation

La ou les fonctions à ajouter se présentent sous la forme d'un fichier "package" au format XML , dont la structure est décrite au paragraphe suivant.
Pour l'installer, depuis la console, sélectionner les options de menu Tools/Advanced/Import package , puis le bouton Installer depuis un fichier , et suivre les instructions de l’assistant d’import.
Attention, même si la liste des fonctions importées apparaît tout de suite dans l'éditeur de fonctions, elles ne seront pas utilisables tant que le serveur Adobe Campaign n'aura pas été redémarré.

Structure générale du package à importer

La ou les fonctions à ajouter se présentent sous la forme d'un fichier "package" au format XML dont voici un exemple :
<?xml version="1.0" encoding='ISO-8859-1' ?>
<!-- ===========================================================================
  Additional SQL functions for Adobe Campaign
  ========================================================================== -->
<package
  namespace   = "nms"
  name        = "package-additional-funclist"
  label       = "Additional functions"
  buildVersion= "6.1"
  buildNumber = "10000">

  <entities schema="xtk:funcList">
    <funcList name="myList" namespace="cus">
      <group name="date" label="Personalized date">
        <function name="relativeMaturity" type="long" args="(<Âge>)" help="Returns the difference between a date and 18 years"
                  minArgs="1" maxArgs="1" display="Relative maturity of the person born on the date $1">
          <providerPart provider="MSSQL,Sybase,PostgreSQL" body="extract(year from age($1))-18"/>
        </function>
      </group>
    </funcList>
  </entities>
</package>

  • Les champs nom , espace de nommage , et description du package ("name", "namespace" et "label") sont essentiellement indicatifs. Ils permettent de voir le package récapitulé dans la liste des packages installés (Explorateur/Administration/Gestion des packages/Packages installés).
  • Les champs buildVersion et buildNumber sont obligatoires. Ils doivent correspondre à la version du serveur auquel la console est connectée. Cette information est disponible dans la boîte de dialogue "Aide/À propos".
  • Les blocs suivants, entities et funclist , sont obligatoires. Dans funcList, les champs "name" et "namespace" sont obligatoires, mais leur nom est laissé au choix de l'utilisateur, et il désignent la liste de fonctions de manière unique.
    Cela signifie que si l'on importe plus tard une autre liste de fonctions avec le même couple namespace/name (ici "cus::maListe"), les fonctions précédemment importées seront effacées. Inversement, si l'on change ce couple namespace/name, la nouvelle série de fonctions importées s'ajoutera à la précédente.
  • L'élément group permet de définir visuellement dans quel groupe de fonctions la ou les fonctions importées apparaîtront dans l'éditeur de fonction. L'attribut @name peut, soit être un nom déjà existant (auquel cas les fonctions s'ajouteront au groupe considéré), soit un nouveau nom, qui apparaîtra sous forme d'un nouveau groupe.
  • Pour mémoire, les valeurs possibles pour l’attribut @name dans l’élément <group> sont :
      name="aggregate"      ( label="Aggregates"         )
      name="string"             ( label="String"           )
      name="date"               ( label="Date"             )
      name="numeric"          ( label="Numeric"        )
      name="geomarketing" ( label="Geomarketing"     )
      name="other"              ( label="Others"           )
      name="window"          ( label="Windowing functions" )
    
    
Attention à bien remplir l'attribut @label : c'est le nom qui sera affiché dans la liste des fonctions disponibles. Si vous ne mettez rien, le groupe n'aura pas de nom, par contre si vous mettez un autre nom que le nom existant, c'est le tout le groupe qui changera de nom.
Si vous souhaitez ajouter des fonctions dans plusieurs groupes différents, il est possible de faire se suivre plusieurs éléments <group> dans la même liste.
Enfin, un élément <group> peut contenir la définition d’une ou de plusieurs fonctions, c’est-à-dire l’objectif du fichier de package. L’élément <function> est présenté dans le paragraphe ci-après.

Descripteur de fonction <function></function>

Le cas présenté ici est le cas général, où l'on souhaite fournir l'implémentation de la fonction .
Ci-dessous l'exemple d'une fonction de "pseudo-maturité", qui, à partir d'un âge, indique depuis combien d'années la personne est majeure.
 <function name="relativeMaturity" type="long" args="(<Âge>)" help="Returns the difference between a date and 18 years"
              minArgs="1" maxArgs="1" display="Relative maturity of the person born on the date $1">
       <providerPart provider="PostgreSQL" body="extract(year from age($1))-18"/>
       <providerPart provider="MSSQL,Sybase,Teradata" body="[Other implementation]"/>
    </function>

Le champ @name fait référence au nom de la fonction et « args » correspond à la liste des paramètres qui s’affichera dans la description. Dans ce cas, la fonction apparaît sous la forme « relativeMaturity ( <age> ) » dans la fenêtre de sélection de fonction.
  • @help est le champ qui est affiché en bas de la fenêtre d'édition d'expressions.
  • @display est informatif.
    Dans les attributs @help et @display, la chaîne "$1" représente le nom qui a été donné au premier paramètre de la fonction (ici, "Âge"). $2, $3... représenteraient les paramètres suivants. Dans l'attribut @body décrit ci-après, $1 désigne la valeur de l'argument passé à la fonction lors de l'appel.
    La description doit être une chaîne de caractères valide au sens XML : noter l'utilisation de '<' et '>' au lieu de < et >.
  • @type est le type de retour de la fonction, il peut prendre les valeurs habituelles (long, string, byte, datetime...). S'il est omis, le serveur détermine le type au mieux d'après les types intervenant dans l'expression implémentant la fonction.
  • @minArgs et maxArgs désignent le nombre de paramètres (minimum et maximum) de la fonction. Par exemple, dans le cas d'une fonction à 2 paramètres, minArgs et maxArgs vaudront 2 et 2. Dans le cas de 3 paramètres, plus 1 optionnel, ils vaudront 3 et 4 respectivement.
  • Enfin, l'élément providerPart fournit l'implémentation de la fonction.
    • L'attribut @provider est obligatoire, il indique pour quels systèmes de bases de données l'implémentation est fournie. Comme le montre l'exemple, on peut fournir des implémentations différentes selon la base de données, quand les syntaxes des expressions ou fonctions sous-jacentes diffèrent.
    • Et l'attribut @body contient l'implémentation de la fonction. Noter que cette implémentation doit être une expression, au sens du langage de la base de données (pas de bloc de code). Selon les bases, les expressions peuvent être des sous-requêtes ("(select column from table where...)") ne retournant qu'une seule valeur. C'est par exemple le cas sous Oracle (la requête doit être parenthésée).
    Si seules une ou deux bases de données sont susceptibles d'être interrogées par la fonction que l'on définit, on peut bien sûr ne fournir que les définitions correspondant à ces bases.

Le descripteur de fonction 'pass-through'

Un descripteur de fonction spéciale est le bloc « pass-through » avec un système de base de données « provider » non spécifié. Dans ce cas, l’implémentation « body » ne peut contenir qu’un seul appel de fonction avec une syntaxe qui ne dépend pas de la base de données utilisée. Pendant ce temps, le bloc « ProviderPart » est unique.
    <function name="CountAll" args="()" help="Counts the values returned (all fields together)"
              type="long" minArgs="0" maxArgs="0">
      <providerPart body="Count(*)"/>
    </function>

Dans ce cas, l'ajout d'une fonction sert uniquement à rendre visible pour le client une fonction de la base de données qui n'aurait pas été rendue disponible par défaut.

Exemples

D’autres exemples de fonctions sont disponibles dans le package prédéfini « xtkdatakitfuncList.xml ».