Test

De Wiki1000

version650-32x32.png

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

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 sur une classe

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ée avec les préfixes :

self Préfixe de la classe de base
? Préfixe de la classe Join
xx alias d'une jointure de classe
Tip : Il est possible de créer un produit cartésien entre deux classes en utilisant une jointure avec une clause where toujours vraie.
Tip : Les jointures seront générées dans l'ordre de leur déclaration dans la vue.
//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.


Exemple, vue locale avec produit cartésien, jointure par clause where et sous requêtes

//procedure RubriqueParExerciceDetail;
Type
  vueSolde = viewof(TCumulPeriodeCompte)
   codeCompte:string = CompteGeneral.codeCompte;
   datePeriode:TDatetime = Periode.dateDebut;
   value:Currency = sumDiff(debitTenue,creditTenue); 
   oidExercice:TOID = Periode.oidexercice; 
   [(typeLot=1)] 
  end;

  vueSelection = viewOf(TSelectionCompte) 
   vc:TCompteGeneral = join('(codeCompte>=self.compteInferieur) and (codeCompte<=self.compteSuperieur)');
   vp:TPeriode = join('(1=1)'); 
   ve:TExercice = join(oid,vp.oidexercice); 
   ve1:TExercice = join('(?.dateDebut = DateAdd(dpyear,ve.dateDebut,-1))');
  // 
   idCompteGeneral:TOID = vc.oid primary; 
   idRubrique:TOID = oidRubriqueCompte primary; 
   idPeriode:TOID = vp.oid primary;
   idExercice:TOID = vp.oidexercice; 
   idExerciceN1:TOID = ve1.oid;
   // 
   codeRubrique:string = RubriqueCompte.code orderby; 
   libelleRubrique:string = RubriqueCompte.Caption; 
   codeCompte:string = vc.codeCompte orderby;
   libelleCompte:string = vc.Caption; 
   libellePeriode:string = vp.Caption; 
   // 
   datePeriode:TDatetime = vp.dateDebut orderby desc;
   year:Integer = year(vp.dateDebut);
   month:Integer = month(vp.dateDebut);
   valueN0:currency = VueSolde.select('value','(oidExercice=self.idExercice) and  (codeCompte=self.codeCompte) and (datePeriode<=self.datePeriode)','',true,[]); 
   valueN1:currency = VueSolde.select('value','(oidExercice=self.idExerciceN1) and  (codeCompte=self.codeCompte) and (datePeriode<=DateAdd(dpYear,self.datePeriode,-1))','',true,[]); 
 end; 

var Sel:TSelector; inst:vueSelection; S,stag:string;
begin
  Sel   := vueSelection.CreateSelector('(codeRubrique=%1) and (year=2022) and (month=3)','',True,['SIG.L02']);

  S := ''; stag := ''; 
  forEach inst in Sel.AsCursor do
   begin
     S := S+stag+inst.codeCompte;
     stag := ','; 
   end; 
  showMessage(S); 
end;
Tip : Notez l'opérateur SQL DateAdd() qui peut être utilisé dans la partie littérale d'une expression

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


Voir aussi :