Overblog
Suivre ce blog
Editer la page Administration Créer mon blog
/ / /

Vous voulez agréger vos données de manière stupide et irrationnelle ?

Pour vous, l'ODCIAggregate ! (Et pour moi, un pense-bête de la syntaxe barbare du truc...)

1) La démarche

 

L'agrégation personnalisée sous Oracle s'appuie sur la création d'un objet regroupant les variables et les routines d'agrégations
On peut alors créer une fonction utilisant cette structure pour calculer le résultat voulu dans un GROUP BY.

Ensuite, lors de l'exécution :
- On appelle la fonction d'agrégation dans la requête
- Pour chaque groupe, la fonction définie :
    - Instancie un objet (et donc un contexte) d'aggrégation pour chaque process de lecture parallèle
    - Sur chacune de ces instances parallèles, la fonction d'itération est appelée sur chaque ligne
    - Les différentes instances parallèles sont mergées itérativement (deux à deux) par appel de la fonction de fusion
    - La fonction terminate renvoie le résultat définit pour le groupe traité

2) La syntaxe !

a. Spécification

CREATE TYPE MonObjAgg AS OBJECT

(

-- Définition des variables de contexte qui permettront de calculer des trucs itérativement

  MaVariable1 NUMBER,

  MaVariable2 NUMBER,

 

-- La fonction statique d'initialisation: elle retourne une instance (sous forme de paramètre out)

  STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT MonObjAgg)

    RETURN NUMBER,

 

-- La fonction d'itération : c'est le calcul à définir

-- L'instance en paramètre in out est mise à jour. Le deuxième paramètre est la valeur donnée à la fonction d'aggrégation

  MEMBER FUNCTION ODCIAggregateIterate(self IN OUT MonObjAgg,

    value IN NUMBER) RETURN NUMBER,

 

-- La fonction qui fusionne deux instances parallèles fournies en argument (à vrai dire, elle fusionne la deuxième dans la première)

  MEMBER FUNCTION ODCIAggregateMerge(self IN OUT MonObjAgg,

    ctx2 IN MonObjAgg) RETURN NUMBER,

 

-- La fonction qui renvoie le résultat final pour le GROUP BY

-- Premier paramètre : l'instance résultant du process d'aggrégation / merge

-- Second paramètre : La valeur qui sera retournée par la fonction d'agrégation dans la requête GROUP BY

-- Troisième paramètre : Euh un truc compliqué auquel je m'intéresserais peut être un autre jour

  MEMBER FUNCTION ODCIAggregateTerminate(self IN MonObjAgg,

    returnValue OUT NUMBER,flags IN NUMBER) RETURN NUMBER

);

/


b. Implémentation

Ben ouais, comme pour les packages, faut définir le corps maintenant...

 

CREATE OR REPLACE TYPE BODY MonObjAgg is

STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT MonObjAgg)

RETURN NUMBER is

begin

  sctx := MonObjAgg(1, 1); -- Créer une instance de l'objet, en initialisant ses variable

  RETURN ODCIConst.Success;

end;

 

MEMBER FUNCTION ODCIAggregateIterate(self IN OUT MonObjAgg, value IN NUMBER) RETURN NUMBER is

begin

--Ici, on définit vraiment l'itération... en stockant les résultats itératifs dans les variables (propriétés) de l'objet

--Par exemple :

self.MaVariable1 := value * self.MaVariable1;

--...

 

  RETURN ODCIConst.Success;

end;

 

MEMBER FUNCTION ODCIAggregateMerge(self IN OUT MonObjAgg, ctx2 IN MonObjAgg) RETURN NUMBER is

begin

-- Merger ctx2 dans self... par exemple juste sommer les variables :

self.MaVariable1 := self.MaVariable1 + ctx2.MaVariable1;

self.MaVariable2 := self.MaVariable1 + ctx2.MaVariable2;

 

  RETURN ODCIConst.Success;

end;

 

MEMBER FUNCTION ODCIAggregateTerminate(self IN MonObjAgg,

    returnValue OUT NUMBER,flags IN NUMBER) RETURN NUMBER is

begin

-- Ben faut retourner le résultat. On peut faire une dernière manip genre tests, opérations en tous genre...

  returnValue := self.MaVariable1 + MaVariable2; -- Mon exemple est complètement idiot, certes

 

  RETURN ODCIConst.Success;

end;

 

end;

/


c. Créer le type !

 

CREATE OR REPLACE FUNCTION MonAgg (input NUMBER) RETURN NUMBER

 PARALLEL_ENABLE AGGREGATE USING MonObjAgg;


Et si vous ne voulez pas que ça puisse paralléliser... omettez la clause PARALLEL_ENABLE ! (Sûrement évident pour vous, mais c'est un pense-bête pour moi qui suis pas toujours très lucide :D)


Voilà voilà...

Partager cette page

Published by