📄 ibdatabase.pas
字号:
typInfo, IBXConst;
type
TFieldNode = class(TObject)
public
FieldName : String;
COMPUTED_BLR : Boolean;
DEFAULT_VALUE : boolean;
end;
TSchema = class(TIBSchema)
private
FRelations : TStringList;
FQuery : TIBSQL;
function Add_Node(Relation, Field : String) : TFieldNode;
public
constructor Create(ADatabase : TIBDatabase);
destructor Destroy; override;
procedure FreeNodes; override;
function Has_DEFAULT_VALUE(Relation, Field : String) : Boolean; override;
function Has_COMPUTED_BLR(Relation, Field : String) : Boolean; override;
end;
{ TIBDatabase }
constructor TIBDatabase.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FIBLoaded := False;
CheckIBLoaded;
FIBLoaded := True;
LoginPrompt := True;
FSQLObjects := TList.Create;
FTransactions := TList.Create;
FDBName := '';
FDBParams := TStringList.Create;
FDBParamsChanged := True;
TStringList(FDBParams).OnChange := DBParamsChange;
TStringList(FDBParams).OnChanging := DBParamsChanging;
FDPB := nil;
FHandle := nil;
FUserNames := nil;
FInternalTransaction := TIBTransaction.Create(self);
FInternalTransaction.DefaultDatabase := Self;
FTimer := TIBTimer.Create(Self);
FTimer.Enabled := False;
FTimer.Interval := 0;
FTimer.OnTimer := TimeoutConnection;
FDBSQLDialect := 3;
FSQLDialect := 3;
FTraceFlags := [];
FEventNotifiers := TList.Create;
FAllowStreamedConnected := true;
FSchema := TSchema.Create(self);
end;
destructor TIBDatabase.Destroy;
var
i: Integer;
begin
if FIBLoaded then
begin
IdleTimer := 0;
if FHandle <> nil then
ForceClose;
for i := 0 to FSQLObjects.Count - 1 do
if FSQLObjects[i] <> nil then
SQLObjects[i].DoDatabaseFree;
RemoveSQLObjects;
RemoveTransactions;
FInternalTransaction.Free;
FreeMem(FDPB);
FDPB := nil;
FDBParams.Free;
FSQLObjects.Free;
FUserNames.Free;
FTransactions.Free;
FEventNotifiers.Free;
FSchema.Free;
end;
inherited Destroy;
end;
function TIBDatabase.Call(ErrCode: ISC_STATUS;
RaiseError: Boolean): ISC_STATUS;
begin
result := ErrCode;
FCanTimeout := False;
if RaiseError and (ErrCode > 0) then
IBDataBaseError;
end;
procedure TIBDatabase.CheckActive;
begin
if StreamedConnected and (not Connected) then
Loaded;
if FHandle = nil then
IBError(ibxeDatabaseClosed, [nil]);
end;
procedure TIBDatabase.EnsureInactive;
begin
if csDesigning in ComponentState then
begin
if FHandle <> nil then
Close;
end
end;
procedure TIBDatabase.CheckInactive;
begin
if FHandle <> nil then
IBError(ibxeDatabaseOpen, [nil]);
end;
procedure TIBDatabase.CheckDatabaseName;
begin
if (FDBName = '') then
IBError(ibxeDatabaseNameMissing, [nil]);
end;
function TIBDatabase.AddSQLObject(ds: TIBBase): Integer;
begin
result := 0;
if (ds.Owner is TIBCustomDataSet) then
RegisterClient(TDataSet(ds.Owner));
while (result < FSQLObjects.Count) and (FSQLObjects[result] <> nil) do
Inc(result);
if (result = FSQLObjects.Count) then
FSQLObjects.Add(ds)
else
FSQLObjects[result] := ds;
end;
function TIBDatabase.AddTransaction(TR: TIBTransaction): Integer;
begin
result := FindTransaction(TR);
if result <> -1 then
begin
result := -1;
exit;
end;
result := 0;
while (result < FTransactions.Count) and (FTransactions[result] <> nil) do
Inc(result);
if (result = FTransactions.Count) then
FTransactions.Add(TR)
else
FTransactions[result] := TR;
end;
procedure TIBDatabase.DoDisconnect;
var
i : Integer;
begin
for i := 0 to FEventNotifiers.Count - 1 do
IIBEventNotifier(FEventNotifiers[i]).UnRegisterEvents;
if Connected then
InternalClose(False);
FDBSQLDialect := 1;
end;
procedure TIBDatabase.CreateDatabase;
var
tr_handle: TISC_TR_HANDLE;
begin
CheckInactive;
tr_handle := nil;
Call(
isc_dsql_execute_immediate(StatusVector, @FHandle, @tr_handle, 0,
PChar('CREATE DATABASE ''' + FDBName + ''' ' + {do not localize}
Params.Text), SQLDialect, nil),
True);
end;
procedure TIBDatabase.DropDatabase;
begin
CheckActive;
Call(isc_drop_database(StatusVector, @FHandle), True);
end;
procedure TIBDatabase.DBParamsChange(Sender: TObject);
begin
FDBParamsChanged := True;
end;
procedure TIBDatabase.DBParamsChanging(Sender: TObject);
begin
EnsureInactive;
CheckInactive;
end;
function TIBDatabase.FindTransaction(TR: TIBTransaction): Integer;
var
i: Integer;
begin
result := -1;
for i := 0 to FTransactions.Count - 1 do
if TR = Transactions[i] then
begin
result := i;
break;
end;
end;
function TIBDatabase.FindDefaultTransaction(): TIBTransaction;
var
i: Integer;
begin
result := FDefaultTransaction;
if result = nil then
begin
for i := 0 to FTransactions.Count - 1 do
if (Transactions[i] <> nil) and
(TIBTransaction(Transactions[i]).DefaultDatabase = self) and
(TIBTransaction(Transactions[i]) <> FInternalTransaction) then
begin
result := TIBTransaction(Transactions[i]);
break;
end;
end;
end;
procedure TIBDatabase.ForceClose;
begin
if Connected then
begin
if Assigned(BeforeDisconnect) then
BeforeDisconnect(Self);
InternalClose(True);
if Assigned(AfterDisconnect) then
AfterDisconnect(Self);
end;
end;
function TIBDatabase.GetConnected: Boolean;
begin
result := FHandle <> nil;
end;
function TIBDatabase.GetSQLObject(Index: Integer): TIBBase;
begin
result := FSQLObjects[Index];
end;
function TIBDatabase.GetSQLObjectCount: Integer;
var
i: Integer;
begin
result := 0;
for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then
Inc(result);
end;
function TIBDatabase.GetDBParamByDPB(const Idx: Integer): String;
var
ConstIdx, EqualsIdx: Integer;
begin
if (Idx > 0) and (Idx <= isc_dpb_last_dpb_constant) then
begin
ConstIdx := IndexOfDBConst(DPBConstantNames[Idx]);
if ConstIdx = -1 then
result := ''
else
begin
result := Params[ConstIdx];
EqualsIdx := Pos('=', result); {mbcs ok}
if EqualsIdx = 0 then
result := ''
else
result := Copy(result, EqualsIdx + 1, Length(result));
end;
end
else
result := '';
end;
function TIBDatabase.GetIdleTimer: Integer;
begin
result := FTimer.Interval;
end;
function TIBDatabase.GetTransaction(Index: Integer): TIBTransaction;
begin
result := FTransactions[Index];
end;
function TIBDatabase.GetTransactionCount: Integer;
var
i: Integer;
begin
result := 0;
for i := 0 to FTransactions.Count - 1 do
if FTransactions[i] <> nil then
Inc(result);
end;
function TIBDatabase.IndexOfDBConst(st: String): Integer;
var
i, pos_of_str: Integer;
begin
result := -1;
for i := 0 to Params.Count - 1 do
begin
pos_of_str := Pos(st, AnsiLowerCase(Params[i])); {mbcs ok}
if (pos_of_str = 1) or (pos_of_str = Length(DPBPrefix) + 1) then
begin
result := i;
break;
end;
end;
end;
procedure TIBDatabase.InternalClose(Force: Boolean);
var
i: Integer;
begin
CheckActive;
{ Tell all connected transactions that we're disconnecting.
This is so transactions can commit/rollback, accordingly
}
for i := 0 to FTransactions.Count - 1 do
begin
try
if FTransactions[i] <> nil then
Transactions[i].BeforeDatabaseDisconnect(Self);
except
if not Force then
raise;
end;
end;
for i := 0 to FSQLObjects.Count - 1 do
begin
try
if FSQLObjects[i] <> nil then
SQLObjects[i].DoBeforeDatabaseDisconnect;
except
if not Force then
raise;
end;
end;
if (not HandleIsShared) and
(Call(isc_detach_database(StatusVector, @FHandle), False) > 0) and
(not Force) then
IBDataBaseError
else
begin
FHandle := nil;
FHandleIsShared := False;
end;
if not (csDesigning in ComponentState) then
MonitorHook.DBDisconnect(Self);
for i := 0 to FSQLObjects.Count - 1 do
if FSQLObjects[i] <> nil then
SQLObjects[i].DoAfterDatabaseDisconnect;
end;
procedure TIBDatabase.Loaded;
var
i: integer;
begin
try
If (not FAllowStreamedConnected) and
(not (csDesigning in ComponentState)) then
begin
StreamedConnected := false;
for i := 0 to FTransactions.Count - 1 do
if FTransactions[i] <> nil then
with TIBTransaction(FTransactions[i]) do
FStreamedActive := False;
end;
if StreamedConnected and (not Connected) then
begin
inherited Loaded;
for i := 0 to FTransactions.Count - 1 do
if FTransactions[i] <> nil then
begin
with TIBTransaction(FTransactions[i]) do
if not Active then
if FStreamedActive and not InTransaction then
begin
StartTransaction;
FStreamedActive := False;
end;
end;
if (FDefaultTransaction <> nil) and
(FDefaultTransaction.FStreamedActive) and
(not FDefaultTransaction.InTransaction) then
FDefaultTransaction.StartTransaction;
StreamedConnected := False;
end;
except
if csDesigning in ComponentState then
if Assigned(ApplicationHandleException) then
ApplicationHandleException(Self)
else
raise;
end;
end;
procedure TIBDatabase.Notification( AComponent: TComponent;
Operation: TOperation);
var
i: Integer;
begin
inherited Notification( AComponent, Operation);
if (Operation = opRemove) and (AComponent = FDefaultTransaction) then
begin
i := FindTransaction(FDefaultTransaction);
if (i <> -1) then
RemoveTransaction(i);
FDefaultTransaction := nil;
end;
end;
function TIBDatabase.Login: Boolean;
var
IndexOfUser, IndexOfPassword: Integer;
Username, Password, OldPassword: String;
LoginParams: TStrings;
procedure HidePassword;
var
I: Integer;
IndexAt: Integer;
begin
IndexAt := 0;
for I := 0 to Params.Count -1 do
if Pos('password', LowerCase(Trim(Params.Names[i]))) = 1 then {mbcs ok}
begin
FHiddenPassword := Params.Values[Params.Names[i]];
IndexAt := I;
break;
end;
if IndexAt <> 0 then
Params.Delete(IndexAt);
end;
begin
if Assigned(FOnLogin) then
begin
result := True;
LoginParams := TStringList.Create;
try
LoginParams.Assign(Params);
FOnLogin(Self, LoginParams);
Params.Assign (LoginParams);
HidePassword;
finally
LoginParams.Free;
end;
end
else
begin
IndexOfUser := IndexOfDBConst(DPBConstantNames[isc_dpb_user_name]);
if IndexOfUser <> -1 then
Username := Copy(Params[IndexOfUser],
Pos('=', Params[IndexOfUser]) + 1, {mbcs ok}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -