📄 ibdatabase.pas
字号:
if FTRParamsChanged then
begin
FTRParamsChanged := False;
GenerateTPB(FTRParams, TPB, FTPBLength);
if FTPBLength > 0 then
begin
IBAlloc(FTPB, 0, FTPBLength);
Move(TPB[1], FTPB[0], FTPBLength);
end;
end;
pteb := nil;
IBAlloc(pteb, 0, DatabaseCount * SizeOf(TISC_TEB));
try
for i := 0 to DatabaseCount - 1 do if Databases[i] <> nil then
begin
pteb^[i].db_handle := @(Databases[i].Handle);
pteb^[i].tpb_length := FTPBLength;
pteb^[i].tpb_address := FTPB;
end;
if Call(isc_start_multiple(StatusVector, @FHandle,
DatabaseCount, PISC_TEB(pteb)), False) > 0 then
begin
FHandle := nil;
IBDataBaseError;
end;
if not (csDesigning in ComponentState) then
MonitorHook.TRStart(Self);
finally
FreeMem(pteb);
end;
end;
procedure TIBTransaction.TimeoutTransaction(Sender: TObject);
begin
if InTransaction then
begin
if FCanTimeout then
begin
EndTransaction(FDefaultAction, True);
FCanTimeout := True;
if Assigned(FOnIdleTimer) then
FOnIdleTimer(Self);
end
else
FCanTimeout := True;
end;
end;
procedure TIBTransaction.TRParamsChange(Sender: TObject);
begin
FTRParamsChanged := True;
end;
procedure TIBTransaction.TRParamsChanging(Sender: TObject);
begin
EnsureNotInTransaction;
CheckNotInTransaction;
end;
{ TIBBase }
constructor TIBBase.Create(AOwner: TObject);
begin
FOwner := AOwner;
end;
destructor TIBBase.Destroy;
begin
SetDatabase(nil);
SetTransaction(nil);
inherited Destroy;
end;
procedure TIBBase.CheckDatabase;
begin
if (FDatabase = nil) then
IBError(ibxeDatabaseNotAssigned, [nil]);
FDatabase.CheckActive;
end;
procedure TIBBase.CheckTransaction;
begin
if FTransaction = nil then
IBError(ibxeTransactionNotAssigned, [nil]);
FTransaction.CheckInTransaction;
end;
function TIBBase.GetDBHandle: PISC_DB_HANDLE;
begin
CheckDatabase;
result := @FDatabase.Handle;
end;
function TIBBase.GetTRHandle: PISC_TR_HANDLE;
begin
CheckTransaction;
result := @FTransaction.Handle;
end;
procedure TIBBase.DoBeforeDatabaseDisconnect;
begin
if Assigned(BeforeDatabaseDisconnect) then
BeforeDatabaseDisconnect(Self);
end;
procedure TIBBase.DoAfterDatabaseDisconnect;
begin
if Assigned(AfterDatabaseDisconnect) then
AfterDatabaseDisconnect(Self);
end;
procedure TIBBase.DoDatabaseFree;
begin
if Assigned(OnDatabaseFree) then
OnDatabaseFree(Self);
SetDatabase(nil);
SetTransaction(nil);
end;
procedure TIBBase.DoBeforeTransactionEnd;
begin
if Assigned(BeforeTransactionEnd) then
BeforeTransactionEnd(Self);
end;
procedure TIBBase.DoAfterTransactionEnd;
begin
if Assigned(AfterTransactionEnd) then
AfterTransactionEnd(Self);
end;
procedure TIBBase.DoTransactionFree;
begin
if Assigned(OnTransactionFree) then
OnTransactionFree(Self);
FTransaction := nil;
end;
procedure TIBBase.SetDatabase(Value: TIBDatabase);
begin
if (FDatabase <> nil) then
FDatabase.RemoveSQLObject(FIndexInDatabase);
FDatabase := Value;
if (FDatabase <> nil) then
begin
FIndexInDatabase := FDatabase.AddSQLObject(Self);
if (FTransaction = nil) then
Transaction := FDatabase.FindDefaultTransaction;
end;
end;
procedure TIBBase.SetTransaction(Value: TIBTransaction);
begin
if (FTransaction <> nil) then
FTransaction.RemoveSQLObject(FIndexInTransaction);
FTransaction := Value;
if (FTransaction <> nil) then
begin
FIndexInTransaction := FTransaction.AddSQLObject(Self);
if (FDatabase = nil) then
Database := FTransaction.FindDefaultDatabase;
end;
end;
{ GenerateDPB -
Given a string containing a textual representation
of the database parameters, generate a database
parameter buffer, and return it and its length
in DPB and DPBLength, respectively. }
procedure GenerateDPB(sl: TStrings; var DPB: string; var DPBLength: Short);
var
i, j, pval: Integer;
DPBVal: UShort;
ParamName, ParamValue: string;
begin
{ The DPB is initially empty, with the exception that
the DPB version must be the first byte of the string. }
DPBLength := 1;
DPB := Char(isc_dpb_version1);
{Iterate through the textual database parameters, constructing
a DPB on-the-fly }
for i := 0 to sl.Count - 1 do
begin
{ Get the parameter's name and value from the list,
and make sure that the name is all lowercase with
no leading 'isc_dpb_' prefix
}
if (Trim(sl.Names[i]) = '') then
continue;
ParamName := LowerCase(sl.Names[i]); {mbcs ok}
ParamValue := Copy(sl[i], Pos('=', sl[i]) + 1, Length(sl[i])); {mbcs ok}
if (Pos(DPBPrefix, ParamName) = 1) then {mbcs ok}
Delete(ParamName, 1, Length(DPBPrefix));
{ We want to translate the parameter name to some Integer
value. We do this by scanning through a list of known
database parameter names (DPBConstantNames, defined above) }
DPBVal := 0;
{ Find the parameter }
for j := 1 to isc_dpb_last_dpb_constant do
if (ParamName = DPBConstantNames[j]) then
begin
DPBVal := j;
break;
end;
{ A database parameter either contains a string value (case 1)
or an Integer value (case 2)
or no value at all (case 3)
or an error needs to be generated (case else) }
case DPBVal of
isc_dpb_user_name, isc_dpb_password, isc_dpb_password_enc,
isc_dpb_sys_user_name, isc_dpb_license, isc_dpb_encrypt_key,
isc_dpb_lc_messages, isc_dpb_lc_ctype,
isc_dpb_sql_role_name, isc_dpb_sql_dialect:
begin
if DPBVal = isc_dpb_sql_dialect then
ParamValue[1] := Char(Ord(ParamValue[1]) - 48);
DPB := DPB +
Char(DPBVal) +
Char(Length(ParamValue)) +
ParamValue;
Inc(DPBLength, 2 + Length(ParamValue));
end;
isc_dpb_num_buffers, isc_dpb_dbkey_scope, isc_dpb_force_write,
isc_dpb_no_reserve, isc_dpb_damaged, isc_dpb_verify:
begin
DPB := DPB +
Char(DPBVal) +
#1 +
Char(StrToInt(ParamValue));
Inc(DPBLength, 3);
end;
isc_dpb_sweep:
begin
DPB := DPB +
Char(DPBVal) +
#1 +
Char(isc_dpb_records);
Inc(DPBLength, 3);
end;
isc_dpb_sweep_interval:
begin
pval := StrToInt(ParamValue);
DPB := DPB +
Char(DPBVal) +
#4 +
PChar(@pval)[0] +
PChar(@pval)[1] +
PChar(@pval)[2] +
PChar(@pval)[3];
Inc(DPBLength, 6);
end;
isc_dpb_activate_shadow, isc_dpb_delete_shadow, isc_dpb_begin_log,
isc_dpb_quit_log:
begin
DPB := DPB +
Char(DPBVal) +
#1 + #0;
Inc(DPBLength, 3);
end;
else
begin
if (DPBVal > 0) and
(DPBVal <= isc_dpb_last_dpb_constant) then
IBError(ibxeDPBConstantNotSupported, [DPBConstantNames[DPBVal]])
else
IBError(ibxeDPBConstantUnknownEx, [sl.Names[i]]);
end;
end;
end;
end;
{ GenerateTPB -
Given a string containing a textual representation
of the transaction parameters, generate a transaction
parameter buffer, and return it and its length in
TPB and TPBLength, respectively. }
procedure GenerateTPB(sl: TStrings; var TPB: string; var TPBLength: Short);
var
i, j, TPBVal, ParamLength: Integer;
ParamName, ParamValue: string;
begin
TPB := '';
if (sl.Count = 0) then
TPBLength := 0
else
begin
TPBLength := sl.Count + 1;
TPB := TPB + Char(isc_tpb_version3);
end;
for i := 0 to sl.Count - 1 do
begin
if (Trim(sl[i]) = '') then
begin
Dec(TPBLength);
Continue;
end;
if (Pos('=', sl[i]) = 0) then {mbcs ok}
ParamName := LowerCase(sl[i]) {mbcs ok}
else
begin
ParamName := LowerCase(sl.Names[i]); {mbcs ok}
ParamValue := Copy(sl[i], Pos('=', sl[i]) + 1, Length(sl[i])); {mbcs ok}
end;
if (Pos(TPBPrefix, ParamName) = 1) then {mbcs ok}
Delete(ParamName, 1, Length(TPBPrefix));
TPBVal := 0;
{ Find the parameter }
for j := 1 to isc_tpb_last_tpb_constant do
if (ParamName = TPBConstantNames[j]) then
begin
TPBVal := j;
break;
end;
{ Now act on it }
case TPBVal of
isc_tpb_consistency, isc_tpb_exclusive, isc_tpb_protected,
isc_tpb_concurrency, isc_tpb_shared, isc_tpb_wait, isc_tpb_nowait,
isc_tpb_read, isc_tpb_write, isc_tpb_ignore_limbo,
isc_tpb_read_committed, isc_tpb_rec_version, isc_tpb_no_rec_version:
TPB := TPB + Char(TPBVal);
isc_tpb_lock_read, isc_tpb_lock_write:
begin
TPB := TPB + Char(TPBVal);
{ Now set the string parameter }
ParamLength := Length(ParamValue);
Inc(TPBLength, ParamLength + 1);
TPB := TPB + Char(ParamLength) + ParamValue;
end;
else
begin
if (TPBVal > 0) and
(TPBVal <= isc_tpb_last_tpb_constant) then
IBError(ibxeTPBConstantNotSupported, [TPBConstantNames[TPBVal]])
else
IBError(ibxeTPBConstantUnknownEx, [sl.Names[i]]);
end;
end;
end;
end;
{$IFDEF MSWINDOWS}
{ TTimer }
constructor TIBTimer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := True;
FInterval := 1000;
FWindowHandle := AllocateHWnd(WndProc);
end;
destructor TIBTimer.Destroy;
begin
FEnabled := False;
UpdateTimer;
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;
procedure TIBTimer.WndProc(var Msg: TMessage);
begin
with Msg do
if Msg = WM_TIMER then
try
Timer;
except
if Assigned(ApplicationHandleException) then
ApplicationHandleException(Self);
end
else
Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;
procedure TIBTimer.UpdateTimer;
begin
KillTimer(FWindowHandle, 1);
if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
raise EOutOfResources.Create(SNoTimers);
end;
procedure TIBTimer.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
UpdateTimer;
end;
end;
procedure TIBTimer.SetInterval(Value: Cardinal);
begin
if Value <> FInterval then
begin
FInterval := Value;
UpdateTimer;
end;
end;
procedure TIBTimer.SetOnTimer(Value: TNotifyEvent);
begin
FOnTimer := Value;
UpdateTimer;
end;
procedure TIBTimer.Timer;
begin
if Assigned(FOnTimer) then FOnTimer(Self);
end;
{$ENDIF}
{ TSchema }
function TSchema.Add_Node(Relation, Field : String) : TFieldNode;
var
FField : TFieldNode;
FFieldList : TStringList;
DidActivate : Boolean;
begin
FFieldList := TStringList.Create;
FRelations.AddObject(Relation, FFieldList);
Result := nil;
DidActivate := not FQuery.Database.InternalTransaction.InTransaction;
if DidActivate then
FQuery.Database.InternalTransaction.StartTransaction;
FQuery.Params[0].AsString := Relation;
FQuery.ExecQuery;
while not FQuery.Eof do
begin
FField := TFieldNode.Create;
FField.FieldName := FQuery.Fields[2].AsTrimString;
FField.DEFAULT_VALUE := not FQuery.Fields[1].IsNull;
FField.COMPUTED_BLR := not FQuery.Fields[0].IsNull;
FFieldList.AddObject(FField.FieldName, FField);
if FField.FieldName = Field then
Result := FField;
FQuery.Next;
end;
FQuery.Close;
if DidActivate then
FQuery.Database.InternalTransaction.Commit;
end;
constructor TSchema.Create(ADatabase : TIBDatabase);
const
DefaultSQL = 'Select F.RDB$COMPUTED_BLR, ' + {do not localize}
'F.RDB$DEFAULT_VALUE, R.RDB$FIELD_NAME ' + {do not localize}
'from RDB$RELATION_FIELDS R, RDB$FIELDS F ' + {do not localize}
'where R.RDB$RELATION_NAME = :RELATION ' + {do not localize}
'and R.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME '+ {do not localize}
'and ((not F.RDB$COMPUTED_BLR is NULL) or ' + {do not localize}
' (not F.RDB$DEFAULT_VALUE is NULL)) '; {do not localize}
begin
FRelations := TStringList.Create;
FQuery := TIBSQL.Create(ADatabase);
FQuery.Transaction := ADatabase.Internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -