Jeudi dernier, comme dorénavant les prochains jeudis sur sa chaine tv, Patrick Prémartin (pprem) nous a présenté durant sa session une gestion de comptes personnelle.
Lors de sa création de base (SQLite) il a fait deux choix personnels qui m'ont légèrement fait tiquer : une date sous la forme d'un texte AAAAMMJJ et un sens d'écriture indiqué par les valeurs '+' ou '-'. Du coup, pour le programme des champs calculés ont du être mis en place et ça, ne lui en déplaise, cela m'a vraiment interpellé.
Cette fin de semaine j'ai donc voulu voir s'il était possible de faire autrement.
J'ai tout de suite pensé aux fonctions qu'il était possible d'ajouter au moteur SQLite mais ce vendredi je suis tombé sur un os, au runtime mes fonctions retournaient des widestrings et ce malgré ma codification en asDate ou asCurrency pour le retour de mes fonctions. Au niveau du designtime, impossible de créer des liens corrects, la déclarations de champs posait soucis !
Pour boucler un programme FMX similaire je suis donc passé par, livebindings obligent, des CustomFormats. Lors de la session en live j'avais déjà indiqué que le montant pouvait être traité ainsi
CustomFormat IfThen(Dataset.sens.asString='+',%s,Dataset.Montant.Value*1)
ou, mieux encore
CustomFormat IfThen(Dataset.sens.asString='+',Format('%%m',Dataset.Montant.asCurrency*1),Format('%%m',Dataset.Montant.asCurrency*-1))
Pour la colonne Date on pouvait écrire
CustomFormat SubString(DataSet.Date.Text,6,2)+'/'+SubString(DataSet.Date.Text,4,2)+'/'+SubString(DataSet.Date.Text,2,2)
Bien que cette solution soit possible, elle me laissait un goût de non achevé. Le pourquoi de mon échec pour les fonctions, c'est Dmitry Arefiev qui me l'a soufflé
SQLite est une base de données vraiment sans type. Lorsque vous utilisez AOutput.AsCurrency, FireDAC le mappe à SQLITE_TEXT (pour conserver la précision) et AOutput.AsFloat à SQLITE_FLOAT. Pour 'remapper' une expression dans la liste SELECT vers un type spécifique Delphi, vous devez utiliser une construction spéciale dans la liste SELECT:
<expression> AS "<alias>::<type>"
voir
http://docwiki.embarcadero.com/RADSt...ireDAC_Mapping
C'est sur ce remappage que je bloquais au niveau du design time.
Et, voilà donc, cet après-midi, un programme de démonstration qui montre comment procéder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| procedure TForm11.FDPhysSQLiteDriverLink1DriverCreated(Sender: TObject);
begin
FDSQLiteFunctionToMontant.Active:=True;
FDSQLiteFunctionToDate.Active:=True;
end;
procedure TForm11.FDSQLiteFunctionToDateCalculate(
AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs;
AOutput: TSQLiteOutput; var AUserData: TObject);
var AA,MM,JJ : Word;
begin
AA:=AInputs[0].AsString.Substring(1, 4).ToInteger;
MM := AInputs[0].AsString.Substring(5, 2).ToInteger;
JJ := AInputs[0].AsString.Substring(7, 2).ToInteger;
try
AOutput.AsDate := EncodeDate(AA, MM, JJ);
except
AOutput.AsDate := Date;
end;
end;
procedure TForm11.FDSQLiteFunctionToMontantCalculate(
AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs;
AOutput: TSQLiteOutput; var AUserData: TObject);
begin
if AInputs[0].AsString = '+' then
AOutput.AsCurrency := AInputs[1].AsCurrency
else
AOutput.AsCurrency := AInputs[1].AsCurrency * -1;
end;
procedure TForm11.FormCreate(Sender: TObject);
begin
fdQuery1.Open;
// c'est ceci qui amène une cerise sur un super gateau
Total.Text:=FDConnection1.ExecSQLScalar('SELECT SUM(ToMontant(sens,Montant)) FROM ECRITURES');
end; |
En PJ le source et la base test