* fixes Mantis #14730 dealing with oldvalue=null

git-svn-id: trunk@19267 -
This commit is contained in:
marco 2011-09-28 16:27:32 +00:00
parent 08c97e81bf
commit 448e3db450
4 changed files with 170 additions and 41 deletions

1
.gitattributes vendored
View File

@ -2006,6 +2006,7 @@ packages/fcl-db/tests/testsqlfiles.lpr svneol=native#text/plain
packages/fcl-db/tests/testsqlscanner.lpi svneol=native#text/plain
packages/fcl-db/tests/testsqlscanner.lpr svneol=native#text/plain
packages/fcl-db/tests/testsqlscript.pas svneol=native#text/plain
packages/fcl-db/tests/testwherenull.lpr svneol=native#text/plain
packages/fcl-db/tests/toolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/xmlxsdexporttestcase1.pas svneol=native#text/plain
packages/fcl-extra/Makefile svneol=native#text/plain

View File

@ -1544,17 +1544,17 @@ Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
var FieldNamesQuoteChars : TQuoteChars;
procedure InitialiseModifyQuery(var qry : TCustomSQLQuery; aSQL: String);
function InitialiseModifyQuery(var qry : TCustomSQLQuery): TCustomSQLQuery;
begin
qry := TCustomSQLQuery.Create(nil);
with qry do
begin
ParseSQL := False;
DataBase := Self.DataBase;
Transaction := Self.Transaction;
SQL.text := aSQL;
end;
if not assigned(qry) then
begin
qry := TCustomSQLQuery.Create(nil);
qry.ParseSQL := False;
qry.DataBase := Self.DataBase;
qry.Transaction := Self.Transaction;
end;
Result:=qry;
end;
procedure UpdateWherePart(var sql_where : string;x : integer);
@ -1562,8 +1562,11 @@ var FieldNamesQuoteChars : TQuoteChars;
begin
if (pfInKey in Fields[x].ProviderFlags) or
((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
sql_where := sql_where + '(' + FieldNamesQuoteChars[0] + fields[x].FieldName + FieldNamesQuoteChars[1] + '= :"' + 'OLD_' + fields[x].FieldName + '") and ';
((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (Fields[x].Value <> Fields[x].OldValue)) then
if Fields[x].OldValue = NULL then
sql_where := sql_where + FieldNamesQuoteChars[0] + Fields[x].FieldName + FieldNamesQuoteChars[1] + ' is null and '
else
sql_where := sql_where + '(' + FieldNamesQuoteChars[0] + Fields[x].FieldName + FieldNamesQuoteChars[1] + '= :"' + 'OLD_' + Fields[x].FieldName + '") and ';
end;
function ModifyRecQuery : string;
@ -1632,6 +1635,7 @@ var FieldNamesQuoteChars : TQuoteChars;
end;
var qry : TCustomSQLQuery;
s : string;
x : integer;
Fld : TField;
@ -1639,37 +1643,25 @@ begin
FieldNamesQuoteChars := TSQLConnection(DataBase).FieldNameQuoteChars;
case UpdateKind of
ukModify : begin
if not assigned(FUpdateQry) then
begin
if (trim(FUpdateSQL.Text)<> '') then
InitialiseModifyQuery(FUpdateQry,FUpdateSQL.Text)
else
InitialiseModifyQuery(FUpdateQry,ModifyRecQuery);
end;
qry := FUpdateQry;
end;
ukInsert : begin
if not assigned(FInsertQry) then
begin
if (trim(FInsertSQL.Text)<> '') then
InitialiseModifyQuery(FInsertQry,FInsertSQL.Text)
else
InitialiseModifyQuery(FInsertQry,InsertRecQuery);
end;
qry := FInsertQry;
s := trim(FInsertSQL.Text);
if s = '' then s := InsertRecQuery;
qry := InitialiseModifyQuery(FInsertQry);
end;
ukModify : begin
s := trim(FUpdateSQL.Text);
if (s='') and (not assigned(FUpdateQry) or (UpdateMode<>upWhereKeyOnly)) then //first time or dynamic where part
s := ModifyRecQuery;
qry := InitialiseModifyQuery(FUpdateQry);
end;
ukDelete : begin
if not assigned(FDeleteQry) then
begin
if (trim(FDeleteSQL.Text)<> '') then
InitialiseModifyQuery(FDeleteQry,FDeleteSQL.Text)
else
InitialiseModifyQuery(FDeleteQry,DeleteRecQuery);
end;
qry := FDeleteQry;
s := trim(FDeleteSQL.Text);
if (s='') and (not assigned(FDeleteQry) or (UpdateMode<>upWhereKeyOnly)) then
s := DeleteRecQuery;
qry := InitialiseModifyQuery(FDeleteQry);
end;
end;
if (qry.SQL.Text<>s) and (s<>'') then qry.SQL.Text:=s; //assign only when changed, to avoid UnPrepare/Prepare
assert(qry.sql.Text<>'');
with qry do
begin

View File

@ -32,6 +32,8 @@ type
procedure SeveralEditsChange(ADataset: TCustomBufDataset);
procedure DeleteAllChange(ADataset: TCustomBufDataset);
procedure DeleteAllInsertChange(ADataset: TCustomBufDataset);
procedure NullInsertChange(ADataset: TCustomBufDataset);
procedure NullEditChange(ADataset: TCustomBufDataset);
protected
procedure SetUp; override;
procedure TearDown; override;
@ -53,6 +55,7 @@ type
procedure SeveralEditsApplUpd;
procedure DeleteAllApplUpd;
procedure DeleteAllInsertApplUpd;
procedure NullInsertUpdateApplUpd;
procedure TestBasicsXML;
procedure TestSimpleEditXML;
@ -99,6 +102,7 @@ begin
if Inserts then
begin
ChangedDs := TSQLDBConnector(DBConnector).Query;
ChangedDs.Close;
TSQLQuery(ChangedDS).SQL.Text:='SELECT * FROM FPDEV WHERE (ID < 16) or (ID>100) ORDER BY ID';
OrgDs.IndexFieldNames:='ID';
@ -274,14 +278,43 @@ begin
end;
end;
procedure TTestBufDatasetStreams.SetUp;
procedure TTestBufDatasetStreams.NullInsertChange(ADataset: TCustomBufDataset);
begin
DBConnector.StartTest;
with ADataset do
begin
AssertTrue(Locate('ID',11,[]));
Delete; //11
Delete; //12
Delete; //13
Delete; //14
Append;
FieldByName('ID').AsInteger:=11;
//FieldByName('NAME').Clear;
Post;
AppendRecord([12,'AfterNull']);
AppendRecord([13,null]);
AppendRecord([14,'AfterNull']);
//Append; Post;
end;
end;
procedure TTestBufDatasetStreams.TearDown;
procedure TTestBufDatasetStreams.NullEditChange(ADataset: TCustomBufDataset);
var i: integer;
begin
DBConnector.StopTest;
//depends on procedure TTestBufDatasetStreams.NullInsertChange
if ADataSet is TSQLQuery then
with ADataset as TSQLQuery do
begin
AssertTrue(Locate('ID',11,[]));
for i:=11 to 14 do
begin
Edit;
FieldByName('NAME').AsString:='TestName'+inttostr(i);
Post;
Next;
end;
UpdateMode:=upWhereAll; //test when also null fields will be in where
end;
end;
procedure TTestBufDatasetStreams.TestSimpleEditCancelUpd;
@ -459,6 +492,24 @@ begin
TestChangesApplyUpdates(@DeleteAllInsertChange, False);
end;
procedure TTestBufDatasetStreams.NullInsertUpdateApplUpd;
begin
TestChangesApplyUpdates(@NullInsertChange, True);
TestChangesApplyUpdates(@NullEditChange, True);
end;
procedure TTestBufDatasetStreams.SetUp;
begin
DBConnector.StartTest;
end;
procedure TTestBufDatasetStreams.TearDown;
begin
DBConnector.StopTest;
end;
initialization
if uppercase(dbconnectorname)='SQL' then
RegisterTestDecorator(TDBBasicsTestSetup, TTestBufDatasetStreams);

View File

@ -0,0 +1,85 @@
program testWhereNULL;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils,
db, sqldb, sqlite3conn, variants;
var
Conn: TSQLite3Connection;
Tran: TSQLTransaction;
Q: TSQLQuery;
sql: string;
i: integer;
begin
Conn:=TSQLite3Connection.Create(nil);
Conn.DatabaseName:='test.db';
Tran:=TSQLTransaction.Create(nil);
Tran.DataBase:=Conn;
Q:=TSQLQuery.Create(nil);
Q.DataBase:=Conn;
Conn.Open;
writeln('Connected');
Conn.ExecuteDirect('CREATE TEMPORARY TABLE t (int_field INT, string_field VARCHAR(30))');
writeln('Temporary table created');
Q.SQL.Text:='SELECT * FROM t';
Q.UpdateMode:=upWhereAll; // <-- UpdateMode is upWhereAll or upWhereCahnged
Q.Open;
Q.AppendRecord([NULL,'a']);
Q.AppendRecord([2,'c']);
Q.ApplyUpdates;
Q.Close;
writeln('1. Bug: second row has instead of 2 in first column NULL');
Q.Open;
Q.Next;
writeln('Value of ', Q.Fields[0].FieldName,' is: ', Q.Fields[0].AsString, ' expected: 2');
Q.Close;
writeln;
writeln('2. Case update of record, where some value is null (upWhereAll or upWhereChanged)');
Q.Open;
Q.Edit;
Q.Fields[1].AsString:='b';
Q.Post;
Q.ApplyUpdates;
Q.Close;
Q.Open;
writeln('Value of ', Q.Fields[1].FieldName,' is: ', Q.Fields[1].AsString,' expected: b');
Q.Close;
writeln;
writeln('3. Case delete of record, where some value is null (upWhereAll or upWhereChanged)');
Q.Open;
Q.Delete;
Q.ApplyUpdates;
Q.Close;
Q.Open;
writeln('Number of rows: ', Q.RecordCount, ' expected: 1');
Q.Close;
//END
Tran.Commit;
Conn.Close;
Q.Free;
Tran.Free;
Conn.Free;
writeln('End. Press any key');
readln;
end.