--- ibx/trunk/runtime/IBDatabase.pas 2015/03/14 10:44:03 26 +++ ibx/trunk/runtime/IBDatabase.pas 2015/04/14 13:10:23 27 @@ -182,6 +182,7 @@ type FUserNames: TStringList; FDataSets: TList; FLoginCalled: boolean; + FCharSetSizes: array of integer; procedure EnsureInactive; function GetDBSQLDialect: Integer; function GetSQLDialect: Integer; @@ -196,6 +197,7 @@ type function GetTransaction(Index: Integer): TIBTransaction; function GetTransactionCount: Integer; function Login: Boolean; + procedure LoadCharSetInfo; procedure SetDatabaseName(const Value: TIBFileName); procedure SetDBParamByDPB(const Idx: Integer; Value: String); procedure SetDBParams(Value: TStrings); @@ -281,11 +283,17 @@ type TIBTransaction = class(TComponent) private + FAfterDelete: TNotifyEvent; + FAfterEdit: TNotifyEvent; + FAfterExecQuery: TNotifyEvent; + FAfterInsert: TNotifyEvent; + FAfterPost: TNotifyEvent; FAfterTransactionEnd: TNotifyEvent; FBeforeTransactionEnd: TNotifyEvent; FIBLoaded: Boolean; FCanTimeout : Boolean; FDatabases : TList; + FOnStartTransaction: TNotifyEvent; FSQLObjects : TList; FDefaultDatabase : TIBDatabase; FHandle : TISC_TR_HANDLE; @@ -302,6 +310,12 @@ type FEndAction : TTransactionAction; procedure DoBeforeTransactionEnd; procedure DoAfterTransactionEnd; + procedure DoOnStartTransaction; + procedure DoAfterExecQuery(Sender: TObject); + procedure DoAfterEdit(Sender: TObject); + procedure DoAfterDelete(Sender: TObject); + procedure DoAfterInsert(Sender: TObject); + procedure DoAfterPost(Sender: TObject); procedure EnsureNotInTransaction; procedure EndTransaction(Action: TTransactionAction; Force: Boolean); function GetDatabase(Index: Integer): TIBDatabase; @@ -369,8 +383,18 @@ type write FBeforeTransactionEnd; property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd write FAfterTransactionEnd; + property OnStartTransaction: TNotifyEvent read FOnStartTransaction + write FOnStartTransaction; + property AfterExecQuery: TNotifyEvent read FAfterExecQuery + write FAfterExecQuery; + property AfterEdit: TNotifyEvent read FAfterEdit write FAfterEdit; + property AfterDelete: TNotifyEvent read FAfterDelete write FAfterDelete; + property AfterInsert: TNotifyEvent read FAfterInsert write FAfterInsert; + property AfterPost: TNotifyEvent read FAfterPost write FAfterPost; end; + TTransactionEndEvent = procedure(Sender:TObject; Action: TTransactionAction) of object; + { TIBBase } { Virtually all components in IB are "descendents" of TIBBase. @@ -387,7 +411,7 @@ type FAfterDatabaseDisconnect: TNotifyEvent; FAfterDatabaseConnect: TNotifyEvent; FOnDatabaseFree: TNotifyEvent; - FBeforeTransactionEnd: TNotifyEvent; + FBeforeTransactionEnd: TTransactionEndEvent; FAfterTransactionEnd: TNotifyEvent; FOnTransactionFree: TNotifyEvent; @@ -395,7 +419,7 @@ type procedure DoBeforeDatabaseDisconnect; virtual; procedure DoAfterDatabaseDisconnect; virtual; procedure DoDatabaseFree; virtual; - procedure DoBeforeTransactionEnd; virtual; + procedure DoBeforeTransactionEnd(Action: TTransactionAction); virtual; procedure DoAfterTransactionEnd; virtual; procedure DoTransactionFree; virtual; function GetDBHandle: PISC_DB_HANDLE; virtual; @@ -407,6 +431,12 @@ type destructor Destroy; override; procedure CheckDatabase; virtual; procedure CheckTransaction; virtual; + procedure DoAfterExecQuery(Sender: TObject); virtual; + procedure DoAfterEdit(Sender: TObject); virtual; + procedure DoAfterDelete(Sender: TObject); virtual; + procedure DoAfterInsert(Sender: TObject); virtual; + procedure DoAfterPost(Sender: TObject); virtual; + function GetCharSetSize(CharSetID: integer): integer; public property AfterDatabaseConnect: TNotifyEvent read FAfterDatabaseConnect write FAfterDatabaseConnect; @@ -415,7 +445,7 @@ type property AfterDatabaseDisconnect: TNotifyEvent read FAfterDatabaseDisconnect write FAfterDatabaseDisconnect; property OnDatabaseFree: TNotifyEvent read FOnDatabaseFree write FOnDatabaseFree; - property BeforeTransactionEnd: TNotifyEvent read FBeforeTransactionEnd write FBeforeTransactionEnd; + property BeforeTransactionEnd: TTransactionEndEvent read FBeforeTransactionEnd write FBeforeTransactionEnd; property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd write FAfterTransactionEnd; property OnTransactionFree: TNotifyEvent read FOnTransactionFree write FOnTransactionFree; property Database: TIBDatabase read FDatabase @@ -584,6 +614,7 @@ begin if Connected then InternalClose(False); FDBSQLDialect := 1; + SetLength(FCharSetSizes,0); end; procedure TIBDataBase.CreateDatabase; @@ -778,6 +809,36 @@ begin SQLObjects[i].DoAfterDatabaseDisconnect; end; +procedure TIBDataBase.LoadCharSetInfo; +var Query: TIBSQL; + i: integer; +begin + if not FInternalTransaction.Active then + FInternalTransaction.StartTransaction; + Query := TIBSQL.Create(self); + try + Query.Database := Self; + Query.Transaction := FInternalTransaction; + Query.SQL.Text := 'Select RDB$CHARACTER_SET_ID, RDB$BYTES_PER_CHARACTER ' + + 'From RDB$CHARACTER_SETS Order by 1 DESC'; {do not localize} + Query.Prepare; + Query.ExecQuery; + if not Query.EOF then + begin + SetLength(FCharSetSizes,Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger + 1); + for i := 0 to Length(FCharSetSizes) - 1 do FCharSetSizes[i] := 1; + repeat + FCharSetSizes[Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger] := + Query.FieldByName('RDB$BYTES_PER_CHARACTER').AsInteger; + Query.Next; + until Query.EOF; + end; + finally + Query.free; + FInternalTransaction.Commit; + end; +end; + procedure TIBDataBase.CheckStreamConnect; var i: integer; @@ -957,6 +1018,7 @@ begin end; if not (csDesigning in ComponentState) then MonitorHook.DBConnect(Self); + LoadCharSetInfo; end; procedure TIBDataBase.RemoveSQLObject(Idx: Integer); @@ -1409,6 +1471,42 @@ begin FAfterTransactionEnd(self); end; +procedure TIBTransaction.DoOnStartTransaction; +begin + if assigned(FOnStartTransaction) then + OnStartTransaction(self); +end; + +procedure TIBTransaction.DoAfterExecQuery(Sender: TObject); +begin + if assigned(FAfterExecQuery) then + AfterExecQuery(Sender); +end; + +procedure TIBTransaction.DoAfterEdit(Sender: TObject); +begin + if assigned(FAfterEdit) then + AfterEdit(Sender); +end; + +procedure TIBTransaction.DoAfterDelete(Sender: TObject); +begin + if assigned(FAfterDelete) then + AfterDelete(Sender); +end; + +procedure TIBTransaction.DoAfterInsert(Sender: TObject); +begin + if assigned(FAfterInsert) then + AfterInsert(Sender); +end; + +procedure TIBTransaction.DoAfterPost(Sender: TObject); +begin + if assigned(FAfterPost) then + AfterPost(Sender); +end; + procedure TIBTransaction.EnsureNotInTransaction; begin if csDesigning in ComponentState then @@ -1496,7 +1594,7 @@ begin IBError(ibxeCantEndSharedTransaction, [nil]); DoBeforeTransactionEnd; for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then - SQLObjects[i].DoBeforeTransactionEnd; + SQLObjects[i].DoBeforeTransactionEnd(Action); if InTransaction then begin if HandleIsShared then @@ -1829,6 +1927,7 @@ begin finally FreeMem(pteb); end; + DoOnStartTransaction; end; procedure TIBTransaction.TimeoutTransaction(Sender: TObject); @@ -1870,6 +1969,14 @@ begin inherited Destroy; end; +function TIBBase.GetCharSetSize(CharSetID: integer): integer; +begin + if (CharSetID >= 0) and (CharSetID < Length(Database.FCharSetSizes)) then + Result := Database.FCharSetSizes[CharSetID] + else + Result := 1; {Unknown character set} +end; + procedure TIBBase.CheckDatabase; begin if (FDatabase = nil) then @@ -1922,10 +2029,10 @@ begin SetTransaction(nil); end; -procedure TIBBase.DoBeforeTransactionEnd; +procedure TIBBase.DoBeforeTransactionEnd(Action: TTransactionAction); begin if Assigned(BeforeTransactionEnd) then - BeforeTransactionEnd(Self); + BeforeTransactionEnd(Self,Action); end; procedure TIBBase.DoAfterTransactionEnd; @@ -1941,6 +2048,36 @@ begin FTransaction := nil; end; +procedure TIBBase.DoAfterExecQuery(Sender: TObject); +begin + if FTransaction <> nil then + FTransaction.DoAfterExecQuery(Sender); +end; + +procedure TIBBase.DoAfterEdit(Sender: TObject); +begin + if FTransaction <> nil then + FTransaction.DoAfterEdit(Sender); +end; + +procedure TIBBase.DoAfterDelete(Sender: TObject); +begin + if FTransaction <> nil then + FTransaction.DoAfterDelete(Sender); +end; + +procedure TIBBase.DoAfterInsert(Sender: TObject); +begin + if FTransaction <> nil then + FTransaction.DoAfterInsert(Sender); +end; + +procedure TIBBase.DoAfterPost(Sender: TObject); +begin + if FTransaction <> nil then + FTransaction.DoAfterPost(Sender); +end; + procedure TIBBase.SetDatabase(Value: TIBDatabase); begin if (FDatabase <> nil) then @@ -2150,4 +2287,4 @@ end. - \ No newline at end of file +