- base: added new TDataSetState: dsRefreshFields used in refreshing field between local TBufDataSet and remote DB during process of applying updates.
- mssql: implemented RefreshLastInsertID + test

git-svn-id: trunk@29443 -
This commit is contained in:
lacak 2015-01-12 09:00:37 +00:00
parent 8ae9752530
commit 9fba59b3bc
5 changed files with 35 additions and 14 deletions

View File

@ -2106,6 +2106,7 @@ begin
case State of
dsFilter: Result := FFilterBuffer;
dsCalcFields: Result := CalcBuffer;
dsRefreshFields: Result := FCurrentIndex.CurrentBuffer
else Result := ActiveBuffer;
end;
end;
@ -2155,7 +2156,7 @@ begin
begin
Inc(CurrBuff, GetRecordSize + Field.Offset);
Result := Boolean(CurrBuff^);
if result and assigned(Buffer) then
if Result and assigned(Buffer) then
begin
inc(CurrBuff);
Move(CurrBuff^, Buffer^, Field.DataSize);
@ -2180,7 +2181,7 @@ begin
CurrBuff := GetCurrentBuffer;
If Field.FieldNo > 0 then // If =-1, then calculated/lookup field or =0 unbound field
begin
if Field.ReadOnly and not (State in [dsSetKey, dsFilter]) then
if Field.ReadOnly and not (State in [dsSetKey, dsFilter, dsRefreshFields]) then
DatabaseErrorFmt(SReadOnlyField, [Field.DisplayName]);
if State in [dsEdit, dsInsert, dsNewValue] then
Field.Validate(Buffer);

View File

@ -48,7 +48,7 @@ type
TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey,
dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead,
dsInternalCalc, dsOpening);
dsInternalCalc, dsOpening, dsRefreshFields);
TDataEvent = (deFieldChange, deRecordChange, deDataSetChange,
deDataSetScroll, deLayoutChange, deUpdateRecord, deUpdateState,
@ -2157,7 +2157,7 @@ const
dsEditModes = [dsEdit, dsInsert, dsSetKey];
dsWriteModes = [dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter,
dsNewValue, dsInternalCalc];
dsNewValue, dsInternalCalc, dsRefreshFields];
// Correct list of all field types that are BLOB types.
// Please use this instead of checking TBlobType which will give
// incorrect results

View File

@ -96,6 +96,7 @@ type
// - Statement execution
procedure Execute(cursor:TSQLCursor; ATransaction:TSQLTransaction; AParams:TParams); override;
function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
function RefreshLastInsertID(Query : TCustomSQLQuery; Field : TField): boolean; override;
// - Result retrieving
procedure AddFieldDefs(cursor:TSQLCursor; FieldDefs:TFieldDefs); override;
function Fetch(cursor:TSQLCursor):boolean; override;
@ -315,7 +316,7 @@ end;
constructor TMSSQLConnection.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FConnOptions := FConnOptions + [sqSupportEmptyDatabaseName, sqEscapeRepeat];
FConnOptions := [sqSupportEmptyDatabaseName, sqEscapeRepeat, sqImplicitTransaction, sqLastInsertID];
//FieldNameQuoteChars:=DoubleQuotes; //default
Ftds := DBTDS_UNKNOWN;
end;
@ -659,6 +660,21 @@ begin
Result := inherited RowsAffected(cursor);
end;
function TMSSQLConnection.RefreshLastInsertID(Query: TCustomSQLQuery; Field: TField): boolean;
var Identity: int64;
begin
// global variable @@IDENTITY is NUMERIC(38,0)
Result:=False;
if dbcmd(FDBProc, 'SELECT @@IDENTITY') = FAIL then Exit;
if dbsqlexec(FDBProc) = FAIL then Exit;
if dbresults(FDBProc) = FAIL then Exit;
if dbnextrow(FDBProc) = FAIL then Exit;
if dbconvert(FDBProc, dbcoltype(FDBProc,1), dbdata(FDBProc,1), -1, SYBINT8, @Identity, sizeof(Identity)) = -1 then Exit;
// by default identity columns are ReadOnly
Field.AsLargeInt := Identity;
Result:=True;
end;
function TMSSQLConnection.TranslateFldType(SQLDataType: integer): TFieldType;
begin
case SQLDataType of

View File

@ -2644,7 +2644,9 @@ begin
DoRefresh:=(UpdateKind in [ukModify,ukInsert]) and NeedRefreshRecord(UpdateKind);
if assigned(LastIDField) or DoRefresh then
begin
S:=SetTempState(dsNewValue);
// updates fields directly in record buffer of TBufDataSet
// TDataSet buffers are resynchronized at end of ApplyUpdates process
S:=SetTempState(dsRefreshFields);
try
RecordRefreshed:=False;
if assigned(LastIDField) then
@ -2656,7 +2658,7 @@ begin
end;
if RecordRefreshed then
// Active buffer is updated, move to record.
ActiveBufferToRecord;
//ActiveBufferToRecord;
end;
end;

View File

@ -574,6 +574,8 @@ begin
case SQLServerType of
ssMySQL:
datatype := 'integer auto_increment';
ssMSSQL, ssSybase:
datatype := 'integer identity';
ssSQLite:
datatype := 'integer';
else
@ -590,18 +592,18 @@ begin
Open;
Insert;
FieldByName('f').AsString:='a';
Post;
Post; // #1 record
Append;
FieldByName('f').AsString:='b';
Post;
Post; // #2 record
AssertTrue('ID field is not null after Post', FieldByName('id').IsNull);
First;
First; // #1 record
ApplyUpdates(0);
AssertTrue('ID field is still null after ApplyUpdates', Not FieldByName('id').IsNull);
// Should be 1 after the table was created, but this is not guaranteed... So we just test positive values.
id := FieldByName('id').AsLargeInt;
AssertTrue('ID field has not positive value', id>0);
Next;
Next; // #2 record
AssertTrue('Next ID value is not greater than previous', FieldByName('id').AsLargeInt>id);
end;
end;