Vue locale (langage)
(→Opérateur portant sur un type numérique) |
(→Vue avec jointures liées) |
||
Ligne 393 : | Ligne 393 : | ||
* La coincidence des deux jointures est réalisée par le clause where (aId1=aId2) | * La coincidence des deux jointures est réalisée par le clause where (aId1=aId2) | ||
* gcv est une jointure sur le tuple défini par vp1 et vp2 | * gcv est une jointure sur le tuple défini par vp1 et vp2 | ||
+ | |||
+ | ====Vue avec sous requêtes==== | ||
+ | |||
+ | {{version11}} | ||
+ | |||
+ | Il est possible de générer une sous requête liée à la requête principale en utilisant la méthode SELECT d'un sélecteur. | ||
+ | |||
+ | La sous requêtes doit être liée à la requête principale en utilisant l'opérateur self dans la clause Where du SELECT. | ||
+ | |||
+ | Une sous requêtes peut être utilisée soit dans la liste des colonnes, soit dans la clause Where du selecteur. | ||
+ | |||
+ | '''Utilisation dans les colonnes :''' | ||
+ | <source lang="delphi"> | ||
+ | Type | ||
+ | Vue1 = viewOf(MyClass) | ||
+ | sub1:TMoney = sum(...); | ||
+ | id1:TOID = ....; | ||
+ | .... | ||
+ | end; | ||
+ | |||
+ | Vue2 = viewOf(MyClass) | ||
+ | sum1:TMoney = sum(...); | ||
+ | sum2:TMoney = Vue1.Select('sub1','(id1=self.id2)','',true,[]); | ||
+ | id2:TOID = ...; | ||
+ | .... | ||
+ | end; | ||
+ | |||
+ | var sel:TSelector; | ||
+ | begin | ||
+ | sel := Vue2.CreateSelector('','',true,[]); | ||
+ | // | ||
+ | ... | ||
+ | end; | ||
+ | </source> | ||
+ | |||
+ | '''Utilisation dans la clause Where :''' | ||
+ | <source lang="delphi"> | ||
+ | Type | ||
+ | Vue1 = viewOf(MyClass) | ||
+ | sub1:TMoney = sum(...); | ||
+ | id1:TOID = ....; | ||
+ | .... | ||
+ | end; | ||
+ | |||
+ | Vue2 = viewOf(MyClass) | ||
+ | sum1:TMoney = sum(...); | ||
+ | id2:TOID = ...; | ||
+ | .... | ||
+ | end; | ||
+ | |||
+ | var sel:TSelector; | ||
+ | begin | ||
+ | sel := Vue2.CreateSelector('(sum1>%1)','',true,[ | ||
+ | Vue1.Select('sub1','(id1=self.id2)','',true,[]) | ||
+ | ]); | ||
+ | // | ||
+ | ... | ||
+ | end; | ||
+ | </source> | ||
+ | |||
+ | ====Vue utilisant une CTE (Commun table expression)==== | ||
+ | |||
+ | {{version11}} | ||
+ | |||
+ | Il est possible de générer une requête CTE : | ||
+ | * En utilisant une directive "over" dans la définition d'une colonne | ||
+ | * En positionant la propriété useCTE sur le sélecteur. | ||
+ | |||
+ | Le code SQL généré sera | ||
+ | |||
+ | <pre> | ||
+ | With CTE AS ( | ||
+ | ) | ||
+ | SELECT * from CTE | ||
+ | </pre> | ||
+ | |||
+ | Lorsqu'une CTE est utilisée la clause Where du sélecteur s'applique sur résultat de la CTE. | ||
+ | |||
+ | <source lang="delphi"> | ||
+ | Type | ||
+ | Vue1 = viewOf(MyClass) | ||
+ | sub1:TMoney = sum(...); | ||
+ | id1:TOID = ....; | ||
+ | .... | ||
+ | end; | ||
+ | |||
+ | Vue2 = viewOf(MyClass) | ||
+ | sum1:TMoney = sum(...); | ||
+ | sum2:TMoney = Vue1.Select('sub1','(id1=self.id2)','',true,[]); | ||
+ | id2:TOID = ...: | ||
+ | end; | ||
+ | |||
+ | var sel:TSelector; | ||
+ | begin | ||
+ | sel := Vue2.CreateSelector('(sum1 > sum2)','',true,[]); | ||
+ | sel.UseCTE := True; | ||
+ | // | ||
+ | ... | ||
+ | end; | ||
+ | </source> | ||
===Opérateurs=== | ===Opérateurs=== |
Version du 15 mai 2023 à 08:56
Les vues locales sont des type de données vues déclarées localement à l'intérieur d'une opération.
Par exemple le code suivant déclare une vue MyView et effectue une recherche sur cette vue :
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCode:string = unCodeA; unEntier:Integer = refB.unEntierB; end; var inst:MyView; begin inst := MyView.Find('unCode=%1','',true,['B1']); if Assigned(inst) then begin ... end; end
Le périmètre du type est limité à la procédure, il n'est donc pas possible de passer les objets de la vue en paramètre à d'autres fonctions (pour cela utilisez une vue globale).
La syntaxe pour définir une vue locale :
BNF style grammar : <nom_vue> ::= ViewOf(<class_dec>) [<attributes>] end <class_dec> ::= <class_names> | <class_name> <class_dec> <class_names> ::= <class_name>| [<class_name> ,] <class_name> ::= identifier <class_dec> ::= distinct <attributes> ::= <attribute_def> | <attribute_def> <where_def> <attribute_def> ::= <simple_attribute_def> | <simple_attribute_def> <attribute_directive> <simple_attribute_def> ::= <attribute_dec> | <attribute_dec> = <attribute_ref> <attribute_dec> ::= <attribute_name> : <type_name> <attribute_ref> ::= <main_class_attribute_name> | <operator>(<main_class_attribute_name>) <operator> ::= <aggregate_operator> | <date_operator> | <join_operator> <aggregate_operator> ::= count|sum|max|min <date_operator> ::= year|month|quarter|week|day|dayofyear|dayofweek|hour|minute|second <join_operator> ::= join <attribute_directive> ::= primary | orderby | orderby desc <where_def> ::= [ <expression> ] Type NomDeVue = ViewOf(NomDeClassePrincipale) Attribut : Type; Attribut : Type = AliasDe; Attribut : Type = operator(AliasDe); Attribut : Type = AliasDe primary; Attribut : Type = AliasDe orderby; Attribut : Type = AliasDe orderby desc; [ expression ] end;
Les vues peuvent utiles pour effectuer des traitement sur des classes complexes, par exemples :
Exemples
Curseur sur une classe vue
function foo(const S:string):Integer; Type MyView = viewof(ClassA) newCode:string; unCode:string = unCodeA; unEntier:Integer = refB.unEntierB; end; var inst:MyView; cursor:MyViewCursor begin Result := 0; cursor := MyView.CreateCursorWhere(''unCode=%1'','''',true,[S]); foreach inst in cursor do begin Result := Result + inst.unEntier; end; end;
Vue avec jointure externe
function ViewExternalJoin(const S:string):Boolean; Type MyView = viewof(ClassA) newCode:string; unCodeAA:string = unCodeA; unCodeBB:string = refB+unCodeB; end; var inst:MyView; begin inst := MyView.Find('unCodeAA=%1','',true,[S]); if Assigned(inst) and (inst.unCodeAA=S) then Result := True else Result := False; end;
Vue sur une interface
function foo(const S:string):Integer; Type MyView = viewof(InterfaceA, ClassA1, ClassA2) unCode:string = unCodeA primary; .... end; begin ... end;
Vue sur des combinaisons uniques d'attributs
function foo(const S:string):Integer; Type MyView = viewof(ClassA distinct) unCode:string = unCodeA primary; unEntier:Integer = refB.unEntierB; end; begin ... end;
Vue avec agrégats
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCode:string = unCodeA primary; unEntier:Integer = sum(unEntier); end; begin ... end;
Vue avec agrégats sur un montant
Type myView = viewof(WFClasseX) mysum:TMoney = sum(credit) orderby; end; var sel:TSelector; inst:MyView; S,stag:string; begin sel := MyView.CreateSelector('','',true,[]); S := ''; stag := ''; foreach inst in Sel.AsCursor do begin S := S+stag+Formatfloat('0.00',inst.mysum.Value); stag := ','; end; showmessage(S); Result := FALSE; end;
select sum(t0.credit) "mysum",t0.credit_CodeDevise "mysum_CodeDevise" from dbo.WFCLASSEX t0 group by t0.credit_CodeDevise order by sum(t0.credit)
Vue avec agrégats sur un attribut enfant
Type myView = viewof(WFClasseX) mysum:TMoney = sum(credit:TCValue) orderby; end; begin ... end;
select sum(t0.credit_TCValue) "mysum" from dbo.WFCLASSEX t0 order by sum(t0.credit_TCValue)
Vue avec un opérateur de date
function foo(const S:string):Integer; Type MyView = viewof(ClassC distinct) unCode:string = unCodeC primary; unMois:Integer = month(uneDate); end; begin ... end;
Vue avec un opérateur de date (diff)
function foo(iDayDiff):string; Type MyView = viewof(ClassC distinct) unCode:string = unCodeC primary; DayDiff:Integer = DayDiff(uneDateStart,uneDateEnd); end; begin inst := MyView.Find('DayDiff >= %1','',true,[iDayDiff]); if Assigned(inst) then Result := inst.unCode else Result := 'Not found'; end;
Vue avec référence
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCodeAA:string = unCodeA; refB:reference = refB; end; begin ... end;
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCodeAA:string = unCodeA; refB:ClassB = refB; end; begin ... end;
Vue avec variable référence
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCodeAA:string = unCodeA; refB:ClassB; end; begin ... end;
Vue avec filtre
function foo(const S:string):Integer; Type MyView = viewof(ClassA) unCodeAA:string = unCodeA; unCodeBB:string = refB.unCodeB; [ unCodeA='A1' ] end; begin ... end;
Vue avec traversée de liste
function _Concat(const S:string):string; Type MyView = viewof(ClassF) unCodeF:string = unCodeF; unCodeG:string = refFG.unCodeG; unCodeH:string = refFG.listH.unCodeH; end; var ls:MyViewList; stag:string; idx:integer; begin ls := MyView.CreateListWhere('unCodeG=%1','','unCodeH',true,-1,[S]); Result := ''; stag := ''; for idx:=0 to ls.Count-1 do begin Result := Result+stag+ls.Refs[idx].unCodeH; stag := ','; end; end;
Vue avec jointure
//Procedure expensePendings(req:Tjson; var res:TObject); Type ExpenseView = viewOf(TNoteFrais) vp: TValideurPossible = join(ValidationEtat.EtatPossible.EtatMetier, EtatNF); aManager:string = vp.ContactEtablissement.oidutilisateur; // aDate:TDatetime = nDate; aRef:string = referencePiece; aReason:string = Caption; aAmountOrg:TMoney = MontantTTC; aAmountAct:TMoney = MontantRetenu; aQuantity:TQuantity = Quantite; aUser:string = Salarie.Operateur.oidutilisateur; aType:string = FraisSalarie.Caption; aMode:Integer = FraisSalarie.modeRemboursement; aAmountMax:TMoney = FraisSalarie.montantPlafond; aStatus:Integer = Statut; end; var json:TJson; ls:TSelector; indx,ctn:Integer; inst:ExpenseView; AWhere,AOrder:string; Args:Array[0..5] of variant; begin json := TJson.Create(''); res := json; // AWhere := '(aManager=%1) and (aStatus=%2)'; Args[0] := GlbUserName; Args[1] := StatutNF_AValider; AOrder := 'aUser,-aDate'; indx := 0; ctn := 0; ls := ExpenseView.CreateSelector(AWhere,AOrder,true,Args); foreachP inst in ls.AsCursor do begin . . . end; end;
Dans cet exemple le modèle est celui-ci :
La classe TEtatMetier est atteinte par deux chemins différents, un issu de la classe TValideurPossible et un issu de la classe TNoteFrais. La jointure est réalisée sur l'objet TEtatMetier.
vp: TValideurPossible = join(ValidationEtat.EtatPossible.EtatMetier, EtatNF);
- TValideurPossible est la classe qui va être jointe
- vp défini un alias sur cette classe qui peut être ensuite utilisé dans la définition de la vue.
- ValidationEtat.EtatPossible.EtatMetier est le chemin issu de la classe jointe
- EtatNF est le chemin issu de la classe de la vue.
Vue avec jointures liées
Type VueValideur = viewOf(TPieceTaxable) vp1: TValideurPossible = join(ValidationEtat.EtatPossible.EtatMetier,EtatMetier); vp2: TValideurPossible = join(ValidationEtat.RegleValidation,RegleValidation); gcv: TGroupeContactValidation = leftjoin(TGroupeValidation,vp2.ContactEtablissement); aId1:TOID = vp1.oid; aId2:TOID = vp2.oid; // ... [ (aId1=aId2) and ... ] end;
Dans cet exemple :
- vp1 et vp2 sont deux jointures qui coincident sur le même tuple.
- La coincidence des deux jointures est réalisée par le clause where (aId1=aId2)
- gcv est une jointure sur le tuple défini par vp1 et vp2
Vue avec sous requêtes
Il est possible de générer une sous requête liée à la requête principale en utilisant la méthode SELECT d'un sélecteur.
La sous requêtes doit être liée à la requête principale en utilisant l'opérateur self dans la clause Where du SELECT.
Une sous requêtes peut être utilisée soit dans la liste des colonnes, soit dans la clause Where du selecteur.
Utilisation dans les colonnes :
Type Vue1 = viewOf(MyClass) sub1:TMoney = sum(...); id1:TOID = ....; .... end; Vue2 = viewOf(MyClass) sum1:TMoney = sum(...); sum2:TMoney = Vue1.Select('sub1','(id1=self.id2)','',true,[]); id2:TOID = ...; .... end; var sel:TSelector; begin sel := Vue2.CreateSelector('','',true,[]); // ... end;
Utilisation dans la clause Where :
Type Vue1 = viewOf(MyClass) sub1:TMoney = sum(...); id1:TOID = ....; .... end; Vue2 = viewOf(MyClass) sum1:TMoney = sum(...); id2:TOID = ...; .... end; var sel:TSelector; begin sel := Vue2.CreateSelector('(sum1>%1)','',true,[ Vue1.Select('sub1','(id1=self.id2)','',true,[]) ]); // ... end;
Vue utilisant une CTE (Commun table expression)
Il est possible de générer une requête CTE :
- En utilisant une directive "over" dans la définition d'une colonne
- En positionant la propriété useCTE sur le sélecteur.
Le code SQL généré sera
With CTE AS ( ) SELECT * from CTE
Lorsqu'une CTE est utilisée la clause Where du sélecteur s'applique sur résultat de la CTE.
Type Vue1 = viewOf(MyClass) sub1:TMoney = sum(...); id1:TOID = ....; .... end; Vue2 = viewOf(MyClass) sum1:TMoney = sum(...); sum2:TMoney = Vue1.Select('sub1','(id1=self.id2)','',true,[]); id2:TOID = ...: end; var sel:TSelector; begin sel := Vue2.CreateSelector('(sum1 > sum2)','',true,[]); sel.UseCTE := True; // ... end;
Opérateurs
Opérateur portant sur une colonne
Opérateur | Arguments | Action |
---|---|---|
isNull | 2 | Retourne la valeur de la colonne 2 si la valeur de la colonne 1 est nulle |
Exemple d'utilisation de isNull
Type VueValideur = viewOf(TPieceTaxable) vp1: TValideurPossible = join(ValidationEtat.EtatPossible.EtatMetier,EtatMetier); vp2: TValideurPossible = join(ValidationEtat.RegleValidation,RegleValidation); gcv: TGroupeContactValidation = leftjoin(TGroupeValidation,vp2.ContactEtablissement); aId1:TOID = vp1.oid; aId2:TOID = vp2.oid; aIdVP:TOID = vp2.oidValideurPrecedent; aIdDV:TOID = oiddernierValideur; aIdCV:TOID = vp2.oidContactEtablissement; // contact établissement valideur, peut être membre du groupe de validation ou le valideur défini par la règle aIdCE:TOID = ISNULL(gcv.oidTContactEtablissement,vp2.oidContactEtablissement); // personne Mail:string = ISNULL(gcv.TContactEtablissement+eMail,vp2.ContactEtablissement.eMail); // [ (aId1=aId2) ... ] end;
Opérateur portant sur un type numérique
Opérateur | Arguments | Action |
---|---|---|
sum | 1 | Effectue la somme de l'attribut |
min | 1 | Effectue la somme de l'attribut |
max | 1 | Retourne le max de l'attribut |
add | 2 | Retourne la somme de deux attributs |
sub | 2 | Retourne la différence entre deux attributs |
sumdiff | 2 | Retourne la somme de la différence entre deux attributs |
mindiff | 2 | Retourne le min de la différence entre deux attributs |
maxdiff | 2 | Retourne le max de la différence entre deux attributs |
sumconcat | 2 | Retourne la somme de la somme entre deux attributs |
minconcat | 2 | Retourne la min de la somme entre deux attributs |
maxconcat | 2 | Retourne le max de la somme entre deux attributs |
count | 1 | Compte le nombre d'attribut |
Opérateur | Arguments | Action |
---|---|---|
sumDiffP | 2 | Retourne la somme de la différence si elle positive et 0 sinon. |
sumDiffA | 2 | Retourne la valeur absolue de la différence. |
sumDiffS | 2 | Retourne le signe de la différence |
Opérateur | Arguments | Action | Operation |
---|---|---|---|
sum | 1,2,3 | Effectue la somme des attributs | sum(A), sum(A+B),sum(A+B+C) |
sumCase | 3 | Somme de l'attribut suivant une condition | Sum(case B=C then A else 0) |
sumSign | 3 | Somme signée de l'attribut suivant une condition | Sum(case B=C then A else -A) |
sumSens | 3 | Somme suivant le sens comptable (A=Credit, B=Débit, C=Sens, Sens=1=Débit) | case C=1 then B-A else A-B) |
Opérateur portant sur OID
Opérateur | Arguments | Action |
---|---|---|
count | 1 | Compte les éléments de la vue |
Opérateur portant sur une date
Ces opérateur prennent une date comme argument.
Opérateur | Arguments | Action |
---|---|---|
year | 1 | Retourne l'année de la date |
quarter | 1 | Retourne le trimestre de la date |
month | 1 | Retourne le mois de la date |
dayofyear | 1 | Retourne le jour de l'année de la date |
dayofweek | 1 | Retourne le jour de la semaine de la date |
hour | 1 | Retourne le nombre d'heures de la date |
minute | 1 | Retourne le nombre de minutes de la date |
second | 1 | Retourne le nombre de secondes de la date |
millisecond | 1 | Retourne le nombre de millisecondes de la date |
daydiff | 2 | Retourne le nombre de jour entre deux dates |
Opérateur portant sur une référence
Opérateur | Arguments | Action |
---|---|---|
join | 2 | Réalise une jointure sur une référence |
Agrégat portant sur un montant
C'est le type de l'attribut défini dans la vue qui détermine le résultat de l'agrégation.
Les opération d'agrégation effectuent un groupement par devise et agrègent les valeurs de montant (en devise, tenue de compte et reporting). Les chaînes de conversion sont à vides et la date de cours est la date du jour.
Type Source | Type Vue | Opération |
---|---|---|
source:Money | vue:Money = sum(source) | sum(Value) group by CodeDevise |
source:MoneyDT | vue:Money = sum(source) | sum(Value) group by CodeDevise |
source:Money | vue:MoneyDT = sum(source) | ** ERREUR ** |
source:MoneyDT | vue:MoneyDT = sum(source) | sum(Value) group by CodeDevise |
source:Money | vue:Currency = sum(source) | sum (Value) |
source:MoneyDT | vue:Currency = sum(source) | sum (Value) |
source:MoneyDT | vue:Currency = sum(source:TCValue) | sum (TCValue) |
source:MoneyDT | vue:Currency = sum(source:RPValue) | sum (RPValue) |
source:Currency | vue:Currency = sum(source) | sum (Value) |
Voir aussi :