Hi *,
I have 2 questions, which I divide into 2 emails.
1st is about TField.OldValue and Delphi compatibility. Please look at
small attached program (for SQLite3).
In Delphi (with TClientDataSet and dbExpress) outputs:
1. Field.OnValidate: OldValue=N; Value=N; NewValue=N
2. Field.OnChange: OldValue=O; Value=N; NewValue=N
3. BeforePost: OldValue=O; Value=N; NewValue=N
4. AfterPost: OldValue=O; Value=N; NewValue=N
5. Before ApplyUpdates: OldValue=O; Value=N; NewValue=N
6. After ApplyUpdates: OldValue=N; Value=N; NewValue=N
In FPC:
1. Field.OnValidate: OldValue=N; Value=N; NewValue=N
2. Field.OnChange: OldValue=null; Value=N; NewValue=N
3. BeforePost: OldValue=null; Value=N; NewValue=N
4. AfterPost: OldValue=O; Value=N; NewValue=N
5. Before ApplyUpdates: OldValue=O; Value=N; NewValue=N
6. After ApplyUpdates: OldValue=null; Value=N; NewValue=N
As you can see, there are differences in 2,3,6, where in FPC OldValue is
NULL but in Delphi is it "old value".
Dou you think, that it is bug ? (at least it makes impossible compare
OldValue and Value in BeforePost event handler and take some action when
some field changes)
TIA
L.
program testOldValue;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils, CustApp,
db, sqlite3conn, sqldb, variants;
type
{ TtestOldValue }
TtestOldValue = class(TCustomApplication)
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure WriteHelp; virtual;
private
Forder: integer;
procedure Show(Msg: string; Field: TField);
procedure QfieldValidate(Sender: TField);
procedure QfieldChange(Sender: TField);
procedure QBeforePost(DataSet: TDataSet);
procedure QAfterPost(DataSet: TDataSet);
end;
{ SQLite3Test }
procedure TtestOldValue.DoRun;
var
ErrorMsg: String;
Conn: TSQLite3Connection;
Tran: TSQLTransaction;
s: string;
Q: TSQLQuery;
begin
// quick check parameters
ErrorMsg:=CheckOptions('h','help');
if ErrorMsg<>'' then begin
ShowException(Exception.Create(ErrorMsg));
Terminate;
Exit;
end;
// parse parameters
if HasOption('h','help') then begin
WriteHelp;
Terminate;
Exit;
end;
Conn:=TSQlite3Connection.Create(Self);
Conn.DatabaseName:='test.db';
Tran:=TSQLTransaction.Create(Self);
Tran.DataBase:=Conn;
Conn.Open;
Conn.ExecuteDirect('CREATE TEMPORARY TABLE t (int_field INTEGER PRIMARY KEY,
str_field varchar(1))');
Conn.ExecuteDirect('INSERT INTO t VALUES(1, ''O'')');
Q:=TSQLQuery.Create(Self);
Q.Name:='SQLQuery1';
Q.DataBase:=Conn;
Q.Transaction:=Tran;
Q.BeforePost:=@QBeforePost;
Q.AfterPost:=@QAfterPost;
Q.SQL.Text:='SELECT * FROM t';
Q.Open;
Q.Fields[1].OnValidate:=@QfieldValidate;
Q.Fields[1].OnChange :=@QfieldChange;
Forder:=1;
{Q.AppendRecord([1,'O']);
Show('Before ApplyUpdates', Q.Fields[1]);
Q.ApplyUpdates;
Show('After ApplyUpdates', Q.Fields[1]);
Tran.CommitRetaining;
}
Forder:=1;
Q.Edit;
Q.Fields[1].Value:='N';
Q.Post;
Show('Before ApplyUpdates', Q.Fields[1]);
Q.ApplyUpdates;
Show('After ApplyUpdates', Q.Fields[1]);
Tran.CommitRetaining;
Q.Close;
Tran.Commit;
Conn.Close;
Q.Free;
Tran.Free;
Conn.Free;
readln;
// stop program loop
Terminate;
end;
constructor TtestOldValue.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
StopOnException:=true;
end;
destructor TtestOldValue.Destroy;
begin
inherited Destroy;
end;
procedure TtestOldValue.WriteHelp;
begin
{ add your help code here }
writeln('Usage: ',ExeName,' -h');
end;
procedure TtestOldValue.Show(Msg: string; Field: TField);
function VarToStr2(v:variant):string;
begin
if VarIsNull(v) then Result:='null'
else Result:=VarToStr(v);
end;
begin
writeln( format('%d. %s: OldValue=%s; Value=%s; NewValue=%s',
[Forder, Msg, VarToStr2(Field.OldValue),
VarToStr2(Field.Value), VarToStr2(Field.NewValue)])
);
{ writeln( format('%d. %s: DataSet=%s; Field=%s; OldValue=%s; Value=%s;
NewValue=%s',
[Forder, Msg, Field.DataSet.Name, Field.FieldName,
VarToStr(Field.OldValue), VarToStr(Field.Value), VarToStr(Field.NewValue)])
);
}
inc(Forder);
end;
procedure TtestOldValue.QfieldValidate(Sender: TField);
begin
Show('Field.OnValidate', Sender);
end;
procedure TtestOldValue.QfieldChange(Sender: TField);
begin
Show('Field.OnChange', Sender);
end;
procedure TtestOldValue.QBeforePost(DataSet: TDataSet);
begin
Show('BeforePost', DataSet.Fields[1]);
end;
procedure TtestOldValue.QAfterPost(DataSet: TDataSet);
begin
Show('AfterPost', DataSet.Fields[1]);
end;
var
Application: TtestOldValue;
{$R *.res}
begin
Application:=TtestOldValue.Create(nil);
Application.Run;
Application.Free;
end.
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel