📄 ibcustomdataset.pas
字号:
end;
procedure TIBCustomDataSet.DoBeforeTransactionEnd(Sender: TObject);
begin
if Active then
Active := False;
if FQSelect <> nil then
FQSelect.FreeHandle;
if FQDelete <> nil then
FQDelete.FreeHandle;
if FQInsert <> nil then
FQInsert.FreeHandle;
if FQModify <> nil then
FQModify.FreeHandle;
if FQRefresh <> nil then
FQRefresh.FreeHandle;
FInternalPrepared := false;
if Assigned(FBeforeTransactionEnd) then
FBeforeTransactionEnd(Sender);
end;
procedure TIBCustomDataSet.DoAfterTransactionEnd(Sender: TObject);
begin
if Assigned(FAfterTransactionEnd) then
FAfterTransactionEnd(Sender);
end;
procedure TIBCustomDataSet.DoTransactionFree(Sender: TObject);
begin
if Assigned(FTransactionFree) then
FTransactionFree(Sender);
end;
{ Read the record from FQSelect.Current into the record buffer
Then write the buffer to in memory cache }
procedure TIBCustomDataSet.FetchCurrentRecordToBuffer(Qry: TIBSQL;
RecordNumber: Integer; Buffer: PChar);
var
p: PRecordData;
pbd: PBlobDataArray;
i, j: Integer;
LocalData: Pointer;
LocalDate, LocalDouble: Double;
LocalInt: Integer;
LocalInt64: Int64;
LocalCurrency: Currency;
FieldsLoaded: Integer;
begin
p := PRecordData(Buffer);
{ Make sure blob cache is empty }
pbd := PBlobDataArray(Buffer + FBlobCacheOffset);
if RecordNumber > -1 then
for i := 0 to BlobFieldCount - 1 do
pbd^[i] := nil;
{ Get record information }
p^.rdBookmarkFlag := bfCurrent;
p^.rdFieldCount := Qry.Current.Count;
p^.rdRecordNumber := RecordNumber;
p^.rdUpdateStatus := usUnmodified;
p^.rdCachedUpdateStatus := cusUnmodified;
p^.rdSavedOffset := $FFFFFFFF;
{ Load up the fields }
FieldsLoaded := FQSelect.Current.Count;
j := 1;
for i := 0 to Qry.Current.Count - 1 do
begin
if (Qry = FQSelect) then
j := i + 1
else begin
if FieldsLoaded = 0 then
break;
j := FQSelect.FieldIndex[Qry.Current[i].Name] + 1;
if j < 1 then
continue
else
Dec(FieldsLoaded);
end;
with FQSelect.Current[j - 1].Data^ do
if aliasname = 'IBX_INTERNAL_DBKEY' then {do not localize}
begin
if sqllen <= 8 then
p^.rdDBKey := PIBDBKEY(Qry.Current[i].AsPointer)^;
continue;
end;
if j > 0 then with p^ do
begin
rdFields[j].fdDataType :=
Qry.Current[i].Data^.sqltype and (not 1);
rdFields[j].fdDataScale :=
Qry.Current[i].Data^.sqlscale;
rdFields[j].fdNullable :=
(Qry.Current[i].Data^.sqltype and 1 = 1);
rdFields[j].fdIsNull :=
(rdFields[j].fdNullable and (Qry.Current[i].Data^.sqlind^ = -1));
LocalData := Qry.Current[i].Data^.sqldata;
case rdFields[j].fdDataType of
SQL_TIMESTAMP:
begin
rdFields[j].fdDataSize := SizeOf(TDateTime);
if RecordNumber >= 0 then
LocalDate := TimeStampToMSecs(DateTimeToTimeStamp(Qry.Current[i].AsDateTime));
LocalData := PChar(@LocalDate);
end;
SQL_TYPE_DATE:
begin
rdFields[j].fdDataSize := SizeOf(TDateTime);
if RecordNumber >= 0 then
LocalInt := DateTimeToTimeStamp(Qry.Current[i].AsDateTime).Date;
LocalData := PChar(@LocalInt);
end;
SQL_TYPE_TIME:
begin
rdFields[j].fdDataSize := SizeOf(TDateTime);
if RecordNumber >= 0 then
LocalInt := DateTimeToTimeStamp(Qry.Current[i].AsDateTime).Time;
LocalData := PChar(@LocalInt);
end;
SQL_SHORT, SQL_LONG:
begin
if (rdFields[j].fdDataScale = 0) then
begin
rdFields[j].fdDataSize := SizeOf(Integer);
if RecordNumber >= 0 then
LocalInt := Qry.Current[i].AsLong;
LocalData := PChar(@LocalInt);
end
else if (rdFields[j].fdDataScale >= (-4)) then
begin
rdFields[j].fdDataSize := SizeOf(Currency);
if RecordNumber >= 0 then
LocalCurrency := Qry.Current[i].AsCurrency;
LocalData := PChar(@LocalCurrency);
end
else begin
rdFields[j].fdDataSize := SizeOf(Double);
if RecordNumber >= 0 then
LocalDouble := Qry.Current[i].AsDouble;
LocalData := PChar(@LocalDouble);
end;
end;
SQL_INT64:
begin
if (rdFields[j].fdDataScale = 0) then
begin
rdFields[j].fdDataSize := SizeOf(Int64);
if RecordNumber >= 0 then
LocalInt64 := Qry.Current[i].AsInt64;
LocalData := PChar(@LocalInt64);
end
else if (rdFields[j].fdDataScale >= (-4)) then
begin
rdFields[j].fdDataSize := SizeOf(Currency);
if RecordNumber >= 0 then
LocalCurrency := Qry.Current[i].AsCurrency;
LocalData := PChar(@LocalCurrency);
end
else begin
rdFields[j].fdDataSize := SizeOf(Double);
if RecordNumber >= 0 then
LocalDouble := Qry.Current[i].AsDouble;
LocalData := PChar(@LocalDouble);
end
end;
SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
begin
rdFields[j].fdDataSize := SizeOf(Double);
if RecordNumber >= 0 then
LocalDouble := Qry.Current[i].AsDouble;
LocalData := PChar(@LocalDouble);
end;
SQL_VARYING:
begin
rdFields[j].fdDataSize := Qry.Current[i].Data^.sqllen;
rdFields[j].fdDataLength := isc_vax_integer(Qry.Current[i].Data^.sqldata, 2);
if RecordNumber >= 0 then
begin
if (rdFields[j].fdDataLength = 0) then
LocalData := nil
else
LocalData := @Qry.Current[i].Data^.sqldata[2];
end;
end;
else { SQL_TEXT, SQL_BLOB, SQL_ARRAY, SQL_QUAD }
begin
rdFields[j].fdDataSize := Qry.Current[i].Data^.sqllen;
if (rdFields[j].fdDataType = SQL_TEXT) then
rdFields[j].fdDataLength := rdFields[j].fdDataSize;
end;
end;
if RecordNumber < 0 then
begin
rdFields[j].fdIsNull := True;
rdFields[j].fdDataOfs := FRecordSize;
Inc(FRecordSize, rdFields[j].fdDataSize);
end
else begin
if rdFields[j].fdDataType = SQL_VARYING then
begin
if LocalData <> nil then
Move(LocalData^, Buffer[rdFields[j].fdDataOfs], rdFields[j].fdDataLength)
end
else
Move(LocalData^, Buffer[rdFields[j].fdDataOfs], rdFields[j].fdDataSize)
end;
end;
end;
WriteRecordCache(RecordNumber, PChar(p));
end;
function TIBCustomDataSet.GetActiveBuf: PChar;
begin
case State of
dsBrowse:
if IsEmpty then
result := nil
else
result := ActiveBuffer;
dsEdit, dsInsert:
result := ActiveBuffer;
dsCalcFields:
result := CalcBuffer;
dsFilter:
result := FFilterBuffer;
dsNewValue:
result := ActiveBuffer;
dsOldValue:
if (PRecordData(ActiveBuffer)^.rdRecordNumber =
PRecordData(FOldBuffer)^.rdRecordNumber) then
result := FOldBuffer
else
result := ActiveBuffer;
else if not FOpen then
result := nil
else
result := ActiveBuffer;
end;
end;
function TIBCustomDataSet.CachedUpdateStatus: TCachedUpdateStatus;
begin
if Active then
result := PRecordData(GetActiveBuf)^.rdCachedUpdateStatus
else
result := cusUnmodified;
end;
function TIBCustomDataSet.GetDatabase: TIBDatabase;
begin
result := FBase.Database;
end;
function TIBCustomDataSet.GetDBHandle: PISC_DB_HANDLE;
begin
result := FBase.DBHandle;
end;
function TIBCustomDataSet.GetDeleteSQL: TStrings;
begin
result := FQDelete.SQL;
end;
function TIBCustomDataSet.GetInsertSQL: TStrings;
begin
result := FQInsert.SQL;
end;
function TIBCustomDataSet.GetSQLParams: TIBXSQLDA;
begin
if not FInternalPrepared then
InternalPrepare;
result := FQSelect.Params;
end;
function TIBCustomDataSet.GetRefreshSQL: TStrings;
begin
result := FQRefresh.SQL;
end;
function TIBCustomDataSet.GetSelectSQL: TStrings;
begin
result := FQSelect.SQL;
end;
function TIBCustomDataSet.GetStatementType: TIBSQLTypes;
begin
result := FQSelect.SQLType;
end;
function TIBCustomDataSet.GetModifySQL: TStrings;
begin
result := FQModify.SQL;
end;
function TIBCustomDataSet.GetTransaction: TIBTransaction;
begin
result := FBase.Transaction;
end;
function TIBCustomDataSet.GetTRHandle: PISC_TR_HANDLE;
begin
result := FBase.TRHandle;
end;
procedure TIBCustomDataSet.InternalDeleteRecord(Qry: TIBSQL; Buff: Pointer);
begin
if (Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukDelete).Text <> '')) then
FUpdateObject.Apply(ukDelete)
else
begin
SetInternalSQLParams(FQDelete, Buff);
FQDelete.ExecQuery;
FRowsAffected := FQDelete.RowsAffected;
end;
with PRecordData(Buff)^ do
begin
rdUpdateStatus := usDeleted;
rdCachedUpdateStatus := cusUnmodified;
end;
WriteRecordCache(PRecordData(Buff)^.rdRecordNumber, Buff);
end;
function TIBCustomDataSet.InternalLocate(const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions): Boolean;
var
fl: TList;
CurBookmark: string;
fld : Variant;
val : Array of Variant;
i, fld_cnt: Integer;
fld_str : String;
begin
fl := TList.Create;
try
GetFieldList(fl, KeyFields);
fld_cnt := fl.Count;
CurBookmark := Bookmark;
result := False;
SetLength(val, fld_cnt);
if not Eof then
for i := 0 to fld_cnt - 1 do
begin
if VarIsArray(KeyValues) then
val[i] := KeyValues[i]
else
val[i] := KeyValues;
if (TField(fl[i]).DataType = ftString) and
not VarIsNull(val[i]) then
begin
if (loCaseInsensitive in Options) then
val[i] := AnsiUpperCase(val[i]);
val[i] := TrimRight(string(val[i]));
end;
end;
while ((not result) and (not EOF)) do
begin
i := 0;
result := True;
while (result and (i < fld_cnt)) do
begin
fld := TField(fl[i]).Value;
if VarIsNull(fld) then
result := result and VarIsNull(val[i])
else
begin
// We know the Field is not null so if the passed value is null we are
// done with this record
result := result and not VarIsNull(val[i]);
if result then
begin
try
fld := VarAsType(fld, VarType(val[i]));
except
on E: EVariantError do result := False;
end;
if TField(fl[i]).DataType = ftString then
begin
fld_str := TField(fl[i]).AsString;
fld_str := TrimRight(fld_str);
if (loCaseInsensitive in Options) then
fld_str := AnsiUpperCase(fld_str);
if (loPartialKey in Options) then
result := result and (AnsiPos(val[i], fld_str) = 1)
else
result := result and (fld_str = val[i]);
end
else
result := result and (val[i] = fld);
end;
end;
Inc(i);
end;
if not result then
Next;
end;
if not result then
Bookmark := CurBookmark
else
CursorPosChanged;
finally
fl.Free;
val := nil;
end;
end;
procedure TIBCustomDataSet.InternalPostRecord(Qry: TIBSQL; Buff: Pointer);
var
i, j, k: Integer;
pbd: PBlobDataArray;
begin
pbd := PBlobDataArray(PChar(Buff) + FBlobCacheOffset);
j := 0;
for i := 0 to FieldCount - 1 do
if Fields[i].IsBlob then
begin
k := FMappedFieldPosition[Fields[i].FieldNo -1];
if pbd^[j] <> nil then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -