Vue locale (langage)

De Wiki1000

{{#images:version650-32x32.png|stock}}

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 :

<source lang="delphi"> 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 </source>

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 | over | notInSelect
  <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

<source lang="delphi"> 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; </source>

Vue avec jointure externe

<source lang="delphi"> 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;

</source>

Vue sur une interface

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(InterfaceA, ClassA1, ClassA2)
   unCode:string = unCodeA primary;
   ....
 end;

begin

 ...

end; </source>

Vue sur des combinaisons uniques d'attributs

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA distinct)
   unCode:string = unCodeA primary;
   unEntier:Integer = refB.unEntierB;
 end;

begin

 ...

end; </source>

Vue avec agrégats

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA)
   unCode:string = unCodeA primary;
   unEntier:Integer = sum(unEntier);
 end;

begin

 ...

end; </source>

Vue avec agrégats sur un montant

<source lang="delphi"> 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; </source>

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

<source lang="delphi"> Type

 myView = viewof(WFClasseX)
  mysum:TMoney = sum(credit:TCValue) orderby;
 end;

begin

 ...

end; </source>

select sum(t0.credit_TCValue) "mysum" from dbo.WFCLASSEX t0
order by sum(t0.credit_TCValue)

Vue avec un opérateur de date

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassC distinct)
   unCode:string = unCodeC primary;
   unMois:Integer = month(uneDate);
 end;

begin

 ...

end; </source>

Vue avec un opérateur de date (diff)

<source lang="delphi"> 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; </source>

Vue avec référence

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA)
   unCodeAA:string = unCodeA;
   refB:reference = refB;
 end;

begin

 ...

end; </source>

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA)
   unCodeAA:string = unCodeA;
   refB:ClassB = refB;
 end;

begin

 ...

end; </source>

Vue avec variable référence

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA)
   unCodeAA:string = unCodeA;
   refB:ClassB;
 end;

begin

 ...

end; </source>

Vue avec filtre

<source lang="delphi"> function foo(const S:string):Integer; Type

 MyView = viewof(ClassA)
   unCodeAA:string = unCodeA;
   unCodeBB:string = refB.unCodeB;
   [ unCodeA='A1' ]
 end;

begin

 ...

end; </source>

Vue avec traversée de liste

<source lang="delphi"> 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; </source>

Vue avec jointure

Type
  myView = class(myClass)
    vp1:joinClass1 = join(A,B);
    vp2:JoinClass2 = join(A,B,W);
    vp3:JoinClass3 = join(W);
    ....
  end;
Paramètre Usage
A Attribut de la classe join (joinClass)
B Chemin à partir de la classe base (myView)
W Clause Where sur la classe join

La clause Where peut être exprimé avec les préfixes :

self Préfixe de la classe de base
? Préfixe de la classe Join


<source lang="delphi"> //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; </source>

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

<source lang="delphi">

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;

</source>

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 : <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 avec interface (Union)

Il est possible d'utiliser une interface pour générer une union de plusieurs vues locales supportant cette interface

Exemple :

<source lang="delphi"> Type

 ISoldeCompte = interface
   credit:Currency;
   debit:Currency; 
   typeLot:Integer;
   codeCompte:string;
   captionCompte:string;
   sensCompte:Integer;
   norme:string;
 end; 
 VueSoldeComptePeriode = viewOf(TCumulPeriodeCompte,ISoldeCompte)
   credit:Currency = creditTenue;
   debit:Currency = debitTenue;
   typeLot:Integer = typeLot; 
   codeCompte:string = compteGeneral.codeCompte;
   captionCompte:string = compteGeneral.Caption;
   sensCompte:Integer = compteGeneral.sensPrivilegie; 
   norme:string = normeComptable.code; 
   dateFin:Tdatetime = Periode.dateFin notInSelect;
   [dateFin < GetDate] 
 end; 
 VueSoldeEcriture = viewOf(TEcriture,VueSoldeComptePeriode)
   credit:Currency = credit:TCValue;
   debit:Currency = debit:TCValue;
   typeLot:Integer = piece.lot.typeLot; 
   codeCompte:string = compteGeneral.codeCompte;
   captionCompte:string = compteGeneral.Caption; 
   sensCompte:Integer = compteGeneral.sensPrivilegie; 
   norme:string = piece.normeComptable.code; 
   eDate:Tdatetime = eDate notInSelect; 
   [eDate >= GetValue('begin Result := TFacadeInitGeneral.GetPreviousPeriodEndDate(Date); end;')] 
 end; 
 VueSoldeCompte = viewOf(ISoldeCompte,VueSoldeComptePeriode,VueSoldeEcriture)
   solde:Currency = sumSens(credit,debit,sensCompte);
   typeLot:Integer = typeLot;
   codeCompte:string= codeCompte;
   captionCompte:string = captionCompte; 
   sensCompte:Integer = sensCompte; 
   norme:string= norme notInSelect;
 end;   

var ls:TSelector; inst:VueSoldeCompte; doc:TxmlhtmlMailDocument; Table:ThtmlTable; ANorme1,ANorme2:string; begin

 ls := VueSoldeCompte.CreateSelector('(codeCompte like %1) and (typeLot=%2) and ((norme=%3)or(norme=%4))',,true,[
   _StrLike(prefixeCompte),
   typeLot.Value,
   ANorme1,
   ANorme2 
   ]);
 ...

end; </source>


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.

<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>

Directive d'attribut

Directive Action
notInSelect L'attribut ne sera pas généré dans clause select
over L'attribut est généré par rapport à la requête CTE

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

<source lang="delphi">

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;

</source>

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 de lignes

{{#images:version900-32x32.png|stock}}

Opérateur Arguments Action Opération
sumDiffP 2 Retourne la somme de la différence si elle positive et 0 sinon. case sum(A-B)>0 then sum(A-B) else 0
sumDiffA 2 Retourne la valeur absolue de la différence. ABS(sum(A-B))
sumDiffS 2 Retourne le signe de la différence case sum(A-B)>0 then 1 else 0

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 chaine

Opérateur Arguments Action
concat 2 Concaténation de deux attributs chaîne

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 :