ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBDatabase.pas
(Generate patch)

Comparing ibx/trunk/runtime/IBDatabase.pas (file contents):
Revision 13 by tony, Thu Nov 22 22:53:40 2012 UTC vs.
Revision 33 by tony, Sat Jul 18 12:30:52 2015 UTC

# Line 43 | Line 43 | uses
43   {$ELSE}
44    unix,
45   {$ENDIF}
46 <  Dialogs, Controls, StdCtrls, SysUtils, Classes, Forms, ExtCtrls, IBHeader, IBExternals, DB,
47 <  IB, DBLoginDlg;
46 >  SysUtils, Classes, FPTimer, IBHeader, IBExternals, DB,
47 >  IB, CustApp;
48  
49   const
50    DPBPrefix = 'isc_dpb_';
# Line 159 | Line 159 | type
159      FHiddenPassword: string;
160      FIBLoaded: Boolean;
161      FOnLogin: TIBDatabaseLoginEvent;
162 +    FSQLHourGlass: Boolean;
163      FTraceFlags: TTraceFlags;
164      FDBSQLDialect: Integer;
165      FSQLDialect: Integer;
# Line 177 | Line 178 | type
178      FDefaultTransaction: TIBTransaction;
179      FInternalTransaction: TIBTransaction;
180      FStreamedConnected: Boolean;
181 <    FTimer: TTimer;
181 >    FTimer: TFPTimer;
182      FUserNames: TStringList;
183      FDataSets: TList;
184      FLoginCalled: boolean;
185 +    FCharSetSizes: array of integer;
186      procedure EnsureInactive;
187      function GetDBSQLDialect: Integer;
188      function GetSQLDialect: Integer;
# Line 195 | Line 197 | type
197      function GetTransaction(Index: Integer): TIBTransaction;
198      function GetTransactionCount: Integer;
199      function Login: Boolean;
200 +    procedure LoadCharSetInfo;
201      procedure SetDatabaseName(const Value: TIBFileName);
202      procedure SetDBParamByDPB(const Idx: Integer; Value: String);
203      procedure SetDBParams(Value: TStrings);
# Line 212 | Line 215 | type
215      procedure DoDisconnect; override;
216      function GetConnected: Boolean; override;
217      procedure CheckStreamConnect;
218 +    procedure HandleException(Sender: TObject);
219      procedure Notification( AComponent: TComponent; Operation: TOperation); override;
220      function GetDataset(Index : longint) : TDataset; override;
221      function GetDataSetCount : Longint; override;
# Line 262 | Line 266 | type
266                                                   write SetDefaultTransaction;
267      property IdleTimer: Integer read GetIdleTimer write SetIdleTimer;
268      property SQLDialect : Integer read GetSQLDialect write SetSQLDialect default 3;
269 +    property SQLHourGlass: Boolean read FSQLHourGlass write FSQLHourGlass default true;
270      property DBSQLDialect : Integer read FDBSQLDialect;
271      property TraceFlags: TTraceFlags read FTraceFlags write FTraceFlags;
272      property AfterConnect;
# Line 279 | Line 284 | type
284  
285    TIBTransaction = class(TComponent)
286    private
287 +    FAfterDelete: TNotifyEvent;
288 +    FAfterEdit: TNotifyEvent;
289 +    FAfterExecQuery: TNotifyEvent;
290 +    FAfterInsert: TNotifyEvent;
291 +    FAfterPost: TNotifyEvent;
292 +    FAfterTransactionEnd: TNotifyEvent;
293 +    FBeforeTransactionEnd: TNotifyEvent;
294      FIBLoaded: Boolean;
295      FCanTimeout         : Boolean;
296      FDatabases          : TList;
297 +    FOnStartTransaction: TNotifyEvent;
298      FSQLObjects         : TList;
299      FDefaultDatabase    : TIBDatabase;
300      FHandle             : TISC_TR_HANDLE;
# Line 290 | Line 303 | type
303      FStreamedActive     : Boolean;
304      FTPB                : PChar;
305      FTPBLength          : Short;
306 <    FTimer              : TTimer;
306 >    FTimer              : TFPTimer;
307      FDefaultAction      : TTransactionAction;
308      FTRParams           : TStrings;
309      FTRParamsChanged    : Boolean;
310      FInEndTransaction   : boolean;
311 +    FEndAction          : TTransactionAction;
312 +    procedure DoBeforeTransactionEnd;
313 +    procedure DoAfterTransactionEnd;
314 +    procedure DoOnStartTransaction;
315 +    procedure DoAfterExecQuery(Sender: TObject);
316 +    procedure DoAfterEdit(Sender: TObject);
317 +    procedure DoAfterDelete(Sender: TObject);
318 +    procedure DoAfterInsert(Sender: TObject);
319 +    procedure DoAfterPost(Sender: TObject);
320      procedure EnsureNotInTransaction;
321      procedure EndTransaction(Action: TTransactionAction; Force: Boolean);
322      function GetDatabase(Index: Integer): TIBDatabase;
# Line 336 | Line 358 | type
358      function AddDatabase(db: TIBDatabase): Integer;
359      function FindDatabase(db: TIBDatabase): Integer;
360      function FindDefaultDatabase: TIBDatabase;
361 +    function GetEndAction: TTransactionAction;
362      procedure RemoveDatabase(Idx: Integer);
363      procedure RemoveDatabases;
364      procedure CheckDatabasesInList;
# Line 357 | Line 380 | type
380      property DefaultAction: TTransactionAction read FDefaultAction write SetDefaultAction default taCommit;
381      property Params: TStrings read FTRParams write SetTRParams;
382      property OnIdleTimer: TNotifyEvent read FOnIdleTimer write FOnIdleTimer;
383 <  end;
383 >    property BeforeTransactionEnd: TNotifyEvent read FBeforeTransactionEnd
384 >                                             write FBeforeTransactionEnd;
385 >    property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd
386 >                                            write FAfterTransactionEnd;
387 >    property OnStartTransaction: TNotifyEvent read FOnStartTransaction
388 >                                              write FOnStartTransaction;
389 >    property AfterExecQuery: TNotifyEvent read FAfterExecQuery
390 >                                              write FAfterExecQuery;
391 >    property AfterEdit: TNotifyEvent read FAfterEdit write FAfterEdit;
392 >    property AfterDelete: TNotifyEvent read FAfterDelete write FAfterDelete;
393 >    property AfterInsert: TNotifyEvent read FAfterInsert write FAfterInsert;
394 >    property AfterPost: TNotifyEvent read FAfterPost write FAfterPost;
395 >  end;
396 >
397 >  TTransactionEndEvent = procedure(Sender:TObject; Action: TTransactionAction) of object;
398 >  TBeforeDatabaseConnectEvent = procedure (Sender: TObject; DBParams: TStrings;
399 >                              var DBName: string) of object;
400  
401    { TIBBase }
402  
# Line 366 | Line 405 | type
405      connections. }
406    TIBBase = class(TObject)
407    protected
408 +    FBeforeDatabaseConnect: TBeforeDatabaseConnectEvent;
409      FDatabase: TIBDatabase;
410      FIndexInDatabase: Integer;
411      FTransaction: TIBTransaction;
# Line 375 | Line 415 | type
415      FAfterDatabaseDisconnect: TNotifyEvent;
416      FAfterDatabaseConnect: TNotifyEvent;
417      FOnDatabaseFree: TNotifyEvent;
418 <    FBeforeTransactionEnd: TNotifyEvent;
418 >    FBeforeTransactionEnd: TTransactionEndEvent;
419      FAfterTransactionEnd: TNotifyEvent;
420      FOnTransactionFree: TNotifyEvent;
421  
422 +    procedure DoBeforeDatabaseConnect(DBParams: TStrings;
423 +                              var DBName: string); virtual;
424      procedure DoAfterDatabaseConnect; virtual;
425      procedure DoBeforeDatabaseDisconnect; virtual;
426      procedure DoAfterDatabaseDisconnect; virtual;
427      procedure DoDatabaseFree; virtual;
428 <    procedure DoBeforeTransactionEnd; virtual;
428 >    procedure DoBeforeTransactionEnd(Action: TTransactionAction); virtual;
429      procedure DoAfterTransactionEnd; virtual;
430      procedure DoTransactionFree; virtual;
431      function GetDBHandle: PISC_DB_HANDLE; virtual;
# Line 395 | Line 437 | type
437      destructor Destroy; override;
438      procedure CheckDatabase; virtual;
439      procedure CheckTransaction; virtual;
440 +    procedure DoAfterExecQuery(Sender: TObject); virtual;
441 +    procedure DoAfterEdit(Sender: TObject); virtual;
442 +    procedure DoAfterDelete(Sender: TObject); virtual;
443 +    procedure DoAfterInsert(Sender: TObject); virtual;
444 +    procedure DoAfterPost(Sender: TObject); virtual;
445 +    function GetCharSetSize(CharSetID: integer): integer;
446 +    procedure HandleException(Sender: TObject);
447 +    procedure SetCursor;
448 +    procedure RestoreCursor;
449    public
450 +    property BeforeDatabaseConnect: TBeforeDatabaseConnectEvent read FBeforeDatabaseConnect
451 +                                                 write FBeforeDatabaseConnect;
452      property AfterDatabaseConnect: TNotifyEvent read FAfterDatabaseConnect
453                                                  write FAfterDatabaseConnect;
454      property BeforeDatabaseDisconnect: TNotifyEvent read FBeforeDatabaseDisconnect
# Line 403 | Line 456 | type
456      property AfterDatabaseDisconnect: TNotifyEvent read FAfterDatabaseDisconnect
457                                                    write FAfterDatabaseDisconnect;
458      property OnDatabaseFree: TNotifyEvent read FOnDatabaseFree write FOnDatabaseFree;
459 <    property BeforeTransactionEnd: TNotifyEvent read FBeforeTransactionEnd write FBeforeTransactionEnd;
459 >    property BeforeTransactionEnd: TTransactionEndEvent read FBeforeTransactionEnd write FBeforeTransactionEnd;
460      property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd write FAfterTransactionEnd;
461      property OnTransactionFree: TNotifyEvent read FOnTransactionFree write FOnTransactionFree;
462      property Database: TIBDatabase read FDatabase
# Line 426 | Line 479 | uses IBIntf, IBSQLMonitor, IBCustomDataS
479  
480   { TIBDatabase }
481  
482 < constructor TIBDatabase.Create(AOwner: TComponent);
482 > constructor TIBDataBase.Create(AOwner: TComponent);
483   {$ifdef WINDOWS}
484   var acp: uint;
485   {$endif}
# Line 440 | Line 493 | begin
493    FTransactions := TList.Create;
494    FDBName := '';
495    FDBParams := TStringList.Create;
496 +  FSQLHourGlass := true;
497 +  if (AOwner <> nil) and
498 +     (AOwner is TCustomApplication) and
499 +     TCustomApplication(AOWner).ConsoleApplication then
500 +    LoginPrompt := false;
501    {$ifdef UNIX}
502    if csDesigning in ComponentState then
503 <    FDBParams.Add('lc_ctype=UTF-8');
503 >    FDBParams.Add('lc_ctype=UTF8');
504    {$else}
505    {$ifdef WINDOWS}
506    if csDesigning in ComponentState then
# Line 461 | Line 519 | begin
519    FUserNames := nil;
520    FInternalTransaction := TIBTransaction.Create(self);
521    FInternalTransaction.DefaultDatabase := Self;
522 <  FTimer := TTimer.Create(Self);
522 >  FTimer := TFPTimer.Create(Self);
523    FTimer.Enabled := False;
524    FTimer.Interval := 0;
525    FTimer.OnTimer := TimeoutConnection;
# Line 472 | Line 530 | begin
530    CheckStreamConnect;
531   end;
532  
533 < destructor TIBDatabase.Destroy;
533 > destructor TIBDataBase.Destroy;
534   var
535    i: Integer;
536   begin
# Line 498 | Line 556 | begin
556    inherited Destroy;
557   end;
558  
559 < function TIBDatabase.Call(ErrCode: ISC_STATUS;
560 <  RaiseError: Boolean): ISC_STATUS;
559 > function TIBDataBase.Call(ErrCode: ISC_STATUS; RaiseError: Boolean
560 >   ): ISC_STATUS;
561   begin
562    result := ErrCode;
563    FCanTimeout := False;
# Line 507 | Line 565 | begin
565      IBDataBaseError;
566   end;
567  
568 < procedure TIBDatabase.CheckActive;
568 > procedure TIBDataBase.CheckActive;
569   begin
570    if StreamedConnected and (not Connected) then
571      Loaded;
# Line 515 | Line 573 | begin
573      IBError(ibxeDatabaseClosed, [nil]);
574   end;
575  
576 < procedure TIBDatabase.EnsureInactive;
576 > procedure TIBDataBase.EnsureInactive;
577   begin
578    if csDesigning in ComponentState then
579    begin
# Line 524 | Line 582 | begin
582    end
583   end;
584  
585 < procedure TIBDatabase.CheckInactive;
585 > procedure TIBDataBase.CheckInactive;
586   begin
587    if FHandle <> nil then
588      IBError(ibxeDatabaseOpen, [nil]);
589   end;
590  
591 < procedure TIBDatabase.CheckDatabaseName;
591 > procedure TIBDataBase.CheckDatabaseName;
592   begin
593    if (FDBName = '') then
594      IBError(ibxeDatabaseNameMissing, [nil]);
595   end;
596  
597 < function TIBDatabase.AddSQLObject(ds: TIBBase): Integer;
597 > function TIBDataBase.AddSQLObject(ds: TIBBase): Integer;
598   begin
599    result := 0;
600    if (ds.Owner is TIBCustomDataSet) then
# Line 549 | Line 607 | begin
607      FSQLObjects[result] := ds;
608   end;
609  
610 < function TIBDatabase.AddTransaction(TR: TIBTransaction): Integer;
610 > function TIBDataBase.AddTransaction(TR: TIBTransaction): Integer;
611   begin
612    result := FindTransaction(TR);
613    if result <> -1 then
# Line 566 | Line 624 | begin
624      FTransactions[result] := TR;
625   end;
626  
627 < procedure TIBDatabase.DoDisconnect;
627 > procedure TIBDataBase.DoDisconnect;
628   begin
629    if Connected then
630      InternalClose(False);
631    FDBSQLDialect := 1;
632 +  SetLength(FCharSetSizes,0);
633   end;
634  
635 < procedure TIBDatabase.CreateDatabase;
635 > procedure TIBDataBase.CreateDatabase;
636   var
637    tr_handle: TISC_TR_HANDLE;
638   begin
# Line 586 | Line 645 | begin
645      True);
646   end;
647  
648 < procedure TIBDatabase.DropDatabase;
648 > procedure TIBDataBase.DropDatabase;
649   begin
650    CheckActive;
651    Call(isc_drop_database(StatusVector, @FHandle), True);
652   end;
653  
654 < procedure TIBDatabase.DBParamsChange(Sender: TObject);
654 > procedure TIBDataBase.DBParamsChange(Sender: TObject);
655   begin
656    FDBParamsChanged := True;
657   end;
658  
659 < procedure TIBDatabase.DBParamsChanging(Sender: TObject);
659 > procedure TIBDataBase.DBParamsChanging(Sender: TObject);
660   begin
661    EnsureInactive;
662    CheckInactive;
663   end;
664  
665 < function TIBDatabase.FindTransaction(TR: TIBTransaction): Integer;
665 > function TIBDataBase.FindTransaction(TR: TIBTransaction): Integer;
666   var
667    i: Integer;
668   begin
# Line 616 | Line 675 | begin
675      end;
676   end;
677  
678 < function TIBDatabase.FindDefaultTransaction(): TIBTransaction;
678 > function TIBDataBase.FindDefaultTransaction: TIBTransaction;
679   var
680    i: Integer;
681   begin
# Line 634 | Line 693 | begin
693    end;
694   end;
695  
696 < procedure TIBDatabase.ForceClose;
696 > procedure TIBDataBase.ForceClose;
697   begin
698    if Connected then
699      InternalClose(True);
700   end;
701  
702 < function TIBDatabase.GetConnected: Boolean;
702 > function TIBDataBase.GetConnected: Boolean;
703   begin
704    result := FHandle <> nil;
705   end;
706  
707 < function TIBDatabase.GetSQLObject(Index: Integer): TIBBase;
707 > function TIBDataBase.GetSQLObject(Index: Integer): TIBBase;
708   begin
709    result := FSQLObjects[Index];
710   end;
711  
712 < function TIBDatabase.GetSQLObjectCount: Integer;
712 > function TIBDataBase.GetSQLObjectCount: Integer;
713   var
714    i: Integer;
715   begin
# Line 659 | Line 718 | begin
718      Inc(result);
719   end;
720  
721 < function TIBDatabase.GetDBParamByDPB(const Idx: Integer): String;
721 > function TIBDataBase.GetDBParamByDPB( const Idx: Integer): String;
722   var
723    ConstIdx, EqualsIdx: Integer;
724   begin
# Line 682 | Line 741 | begin
741      result := '';
742   end;
743  
744 < function TIBDatabase.GetIdleTimer: Integer;
744 > function TIBDataBase.GetIdleTimer: Integer;
745   begin
746    result := FTimer.Interval;
747   end;
748  
749 < function TIBDatabase.GetTransaction(Index: Integer): TIBTransaction;
749 > function TIBDataBase.GetTransaction(Index: Integer): TIBTransaction;
750   begin
751    result := FTransactions[Index];
752   end;
753  
754 < function TIBDatabase.GetTransactionCount: Integer;
754 > function TIBDataBase.GetTransactionCount: Integer;
755   var
756    i: Integer;
757   begin
# Line 702 | Line 761 | begin
761        Inc(result);
762   end;
763  
764 < function TIBDatabase.IndexOfDBConst(st: String): Integer;
764 > function TIBDataBase.IndexOfDBConst(st: String): Integer;
765   var
766    i, pos_of_str: Integer;
767   begin
# Line 718 | Line 777 | begin
777    end;
778   end;
779  
780 < procedure TIBDatabase.InternalClose(Force: Boolean);
780 > procedure TIBDataBase.InternalClose(Force: Boolean);
781   var
782    i: Integer;
783   begin
# Line 765 | Line 824 | begin
824        SQLObjects[i].DoAfterDatabaseDisconnect;
825   end;
826  
827 + procedure TIBDataBase.LoadCharSetInfo;
828 + var Query: TIBSQL;
829 +    i: integer;
830 + begin
831 +  if not FInternalTransaction.Active then
832 +    FInternalTransaction.StartTransaction;
833 +  Query := TIBSQL.Create(self);
834 +  try
835 +    Query.Database := Self;
836 +    Query.Transaction := FInternalTransaction;
837 +    Query.SQL.Text := 'Select RDB$CHARACTER_SET_ID, RDB$BYTES_PER_CHARACTER ' +
838 +                      'From RDB$CHARACTER_SETS Order by 1 DESC'; {do not localize}
839 +    Query.Prepare;
840 +    Query.ExecQuery;
841 +    if not Query.EOF then
842 +    begin
843 +      SetLength(FCharSetSizes,Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger + 1);
844 +      for i := 0 to Length(FCharSetSizes) - 1 do FCharSetSizes[i] := 1;
845 +      repeat
846 +        FCharSetSizes[Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger] :=
847 +                 Query.FieldByName('RDB$BYTES_PER_CHARACTER').AsInteger;
848 +        Query.Next;
849 +      until Query.EOF;
850 +    end;
851 +  finally
852 +    Query.free;
853 +    FInternalTransaction.Commit;
854 +  end;
855 + end;
856 +
857   procedure TIBDataBase.CheckStreamConnect;
858   var
859    i: integer;
# Line 791 | Line 880 | begin
880      end;
881    except
882      if csDesigning in ComponentState then
883 <      Application.HandleException(Self)
883 >      HandleException(Self)
884      else
885        raise;
886    end;
887   end;
888  
889 < procedure TIBDatabase.Notification( AComponent: TComponent;
890 <                                        Operation: TOperation);
889 > procedure TIBDataBase.HandleException(Sender: TObject);
890 > var aParent: TComponent;
891 > begin
892 >  aParent := Owner;
893 >  while aParent <> nil do
894 >  begin
895 >    if aParent is TCustomApplication then
896 >    begin
897 >      TCustomApplication(aParent).HandleException(Sender);
898 >      Exit;
899 >    end;
900 >    aParent := aParent.Owner;
901 >  end;
902 >  SysUtils.ShowException(ExceptObject,ExceptAddr);
903 > end;
904 >
905 > procedure TIBDataBase.Notification(AComponent: TComponent;
906 >   Operation: TOperation);
907   var
908    i: Integer;
909   begin
# Line 812 | Line 917 | begin
917    end;
918   end;
919  
920 < function TIBDatabase.Login: Boolean;
920 > function TIBDataBase.Login: Boolean;
921   var
922    IndexOfUser, IndexOfPassword: Integer;
923    Username, Password, OldPassword: String;
# Line 854 | Line 959 | begin
959      end;
960    end
961    else
962 +  if assigned(IBGUIInterface) then
963    begin
964      IndexOfUser := IndexOfDBConst(DPBConstantNames[isc_dpb_user_name]);
965      if IndexOfUser <> -1 then
# Line 868 | Line 974 | begin
974                                           Length(Params[IndexOfPassword]));
975        OldPassword := password;
976      end;
977 <    result := LoginDialogEx(DatabaseName, Username, Password, False);
977 >    result := IBGUIInterface.LoginDialogEx(DatabaseName, Username, Password, False);
978      if result then
979      begin
980        if IndexOfUser = -1 then
# Line 885 | Line 991 | begin
991            HidePassword;
992        end;
993      end;
994 <  end;
994 >  end
995 >  else
996 >  if LoginPrompt then
997 >     IBError(ibxeNoLoginDialog,[]);
998    finally
999      FLoginCalled := false
1000    end;
1001   end;
1002  
1003 < procedure TIBDatabase.DoConnect;
1003 > procedure TIBDataBase.DoConnect;
1004   var
1005    DPB: String;
1006    TempDBParams: TStrings;
1007    I: integer;
1008 <
1008 >  aDBName: string;
1009   begin
1010    CheckInactive;
1011    CheckDatabaseName;
# Line 908 | Line 1017 | begin
1017    { Use builtin login prompt if requested }
1018    if (LoginPrompt or (csDesigning in ComponentState)) and not Login then
1019      IBError(ibxeOperationCancelled, [nil]);
1020 <  { Generate a new DPB if necessary }
1021 <  if (FDBParamsChanged) then
1022 <  begin
1023 <    FDBParamsChanged := False;
1024 <    if (not LoginPrompt and not (csDesigning in ComponentState)) or (FHiddenPassword = '') then
1025 <      GenerateDPB(FDBParams, DPB, FDPBLength)
1026 <    else
1027 <    begin
1028 <      TempDBParams := TStringList.Create;
1029 <      try
1030 <       TempDBParams.Assign(FDBParams);
1031 <       TempDBParams.Add('password=' + FHiddenPassword);
1032 <       GenerateDPB(TempDBParams, DPB, FDPBLength);
1033 <      finally
1034 <       TempDBParams.Free;
1035 <      end;
1036 <    end;
1037 <    IBAlloc(FDPB, 0, FDPBLength);
1038 <    Move(DPB[1], FDPB[0], FDPBLength);
1020 >
1021 >  TempDBParams := TStringList.Create;
1022 >  try
1023 >   TempDBParams.Assign(FDBParams);
1024 >   aDBName := FDBName;
1025 >   {Opportuning to override defaults}
1026 >   for i := 0 to FSQLObjects.Count - 1 do
1027 >   begin
1028 >       if FSQLObjects[i] <> nil then
1029 >         SQLObjects[i].DoBeforeDatabaseConnect(TempDBParams,aDBName);
1030 >   end;
1031 >
1032 >   { Generate a new DPB if necessary }
1033 >   if (FDBParamsChanged or (TempDBParams.Text <> FDBParams.Text)) then
1034 >   begin
1035 >     FDBParamsChanged := False;
1036 >     if (not LoginPrompt and not (csDesigning in ComponentState)) or (FHiddenPassword = '') then
1037 >       GenerateDPB(TempDBParams, DPB, FDPBLength)
1038 >     else
1039 >     begin
1040 >        TempDBParams.Add('password=' + FHiddenPassword);
1041 >        GenerateDPB(TempDBParams, DPB, FDPBLength);
1042 >     end;
1043 >     IBAlloc(FDPB, 0, FDPBLength);
1044 >     Move(DPB[1], FDPB[0], FDPBLength);
1045 >   end;
1046 >  finally
1047 >   TempDBParams.Free;
1048    end;
1049 <  if Call(isc_attach_database(StatusVector, Length(FDBName),
1050 <                         PChar(FDBName), @FHandle,
1049 >  if Call(isc_attach_database(StatusVector, Length(aDBName),
1050 >                         PChar(aDBName), @FHandle,
1051                           FDPBLength, FDPB), False) > 0 then
1052    begin
1053      FHandle := nil;
1054      IBDataBaseError;
1055    end;
1056 +  if not (csDesigning in ComponentState) then
1057 +    FDBName := aDBName; {Synchronise at run time}
1058    FDBSQLDialect := GetDBSQLDialect;
1059    ValidateClientSQLDialect;
1060    for i := 0 to FSQLObjects.Count - 1 do
# Line 944 | Line 1064 | begin
1064    end;
1065    if not (csDesigning in ComponentState) then
1066      MonitorHook.DBConnect(Self);
1067 +  LoadCharSetInfo;
1068   end;
1069  
1070 < procedure TIBDatabase.RemoveSQLObject(Idx: Integer);
1070 > procedure TIBDataBase.RemoveSQLObject(Idx: Integer);
1071   var
1072    ds: TIBBase;
1073   begin
# Line 960 | Line 1081 | begin
1081    end;
1082   end;
1083  
1084 < procedure TIBDatabase.RemoveSQLObjects;
1084 > procedure TIBDataBase.RemoveSQLObjects;
1085   var
1086    i: Integer;
1087   begin
# Line 972 | Line 1093 | begin
1093    end;
1094   end;
1095  
1096 < procedure TIBDatabase.RemoveTransaction(Idx: Integer);
1096 > procedure TIBDataBase.RemoveTransaction(Idx: Integer);
1097   var
1098    TR: TIBTransaction;
1099   begin
# Line 986 | Line 1107 | begin
1107    end;
1108   end;
1109  
1110 < procedure TIBDatabase.RemoveTransactions;
1110 > procedure TIBDataBase.RemoveTransactions;
1111   var
1112    i: Integer;
1113   begin
# Line 994 | Line 1115 | begin
1115      RemoveTransaction(i);
1116   end;
1117  
1118 < procedure TIBDatabase.SetDatabaseName(const Value: TIBFileName);
1118 > procedure TIBDataBase.SetDatabaseName( const Value: TIBFileName);
1119   begin
1120    if FDBName <> Value then
1121    begin
# Line 1004 | Line 1125 | begin
1125    end;
1126   end;
1127  
1128 < procedure TIBDatabase.SetDBParamByDPB(const Idx: Integer; Value: String);
1128 > procedure TIBDataBase.SetDBParamByDPB( const Idx: Integer; Value: String);
1129   var
1130    ConstIdx: Integer;
1131   begin
# Line 1023 | Line 1144 | begin
1144    end;
1145   end;
1146  
1147 < procedure TIBDatabase.SetDBParams(Value: TStrings);
1147 > procedure TIBDataBase.SetDBParams(Value: TStrings);
1148   begin
1149    FDBParams.Assign(Value);
1150   end;
1151  
1152 < procedure TIBDatabase.SetDefaultTransaction(Value: TIBTransaction);
1152 > procedure TIBDataBase.SetDefaultTransaction(Value: TIBTransaction);
1153   var
1154    i: Integer;
1155   begin
# Line 1046 | Line 1167 | begin
1167    FDefaultTransaction := Value;
1168   end;
1169  
1170 < procedure TIBDatabase.SetHandle(Value: TISC_DB_HANDLE);
1170 > procedure TIBDataBase.SetHandle(Value: TISC_DB_HANDLE);
1171   begin
1172    if HandleIsShared then
1173      Close
# Line 1056 | Line 1177 | begin
1177    FHandleIsShared := (Value <> nil);
1178   end;
1179  
1180 < procedure TIBDatabase.SetIdleTimer(Value: Integer);
1180 > procedure TIBDataBase.SetIdleTimer(Value: Integer);
1181   begin
1182    if Value < 0 then
1183      IBError(ibxeTimeoutNegative, [nil])
# Line 1075 | Line 1196 | begin
1196        end;
1197   end;
1198  
1199 < function TIBDatabase.TestConnected: Boolean;
1199 > function TIBDataBase.TestConnected: Boolean;
1200   var
1201    DatabaseInfo: TIBDatabaseInfo;
1202   begin
# Line 1096 | Line 1217 | begin
1217    end;
1218   end;
1219  
1220 < procedure TIBDatabase.TimeoutConnection(Sender: TObject);
1220 > procedure TIBDataBase.TimeoutConnection(Sender: TObject);
1221   begin
1222    if Connected then
1223    begin
# Line 1111 | Line 1232 | begin
1232    end;
1233   end;
1234  
1235 < function TIBDatabase.GetIsReadOnly: Boolean;
1235 > function TIBDataBase.GetIsReadOnly: Boolean;
1236   var
1237    DatabaseInfo: TIBDatabaseInfo;
1238   begin
# Line 1129 | Line 1250 | begin
1250    DatabaseInfo.Free;
1251   end;
1252  
1253 < function TIBDatabase.GetSQLDialect: Integer;
1253 > function TIBDataBase.GetSQLDialect: Integer;
1254   begin
1255    Result := FSQLDialect;
1256   end;
1257  
1258  
1259 < procedure TIBDatabase.SetSQLDialect(const Value: Integer);
1259 > procedure TIBDataBase.SetSQLDialect( const Value: Integer);
1260   begin
1261    if (Value < 1) then IBError(ibxeSQLDialectInvalid, [nil]);
1262    if ((FHandle = nil) or (Value <= FDBSQLDialect))  then
# Line 1144 | Line 1265 | begin
1265      IBError(ibxeSQLDialectInvalid, [nil]);
1266   end;
1267  
1268 < function TIBDatabase.GetDBSQLDialect: Integer;
1268 > function TIBDataBase.GetDBSQLDialect: Integer;
1269   var
1270    DatabaseInfo: TIBDatabaseInfo;
1271   begin
# Line 1154 | Line 1275 | begin
1275    DatabaseInfo.Free;
1276   end;
1277  
1278 < procedure TIBDatabase.ValidateClientSQLDialect;
1278 > procedure TIBDataBase.ValidateClientSQLDialect;
1279   begin
1280    if (FDBSQLDialect < FSQLDialect) then
1281    begin
# Line 1164 | Line 1285 | begin
1285    end;
1286   end;
1287  
1288 < procedure TIBDatabase.ApplyUpdates(const DataSets: array of TDataSet);
1288 > procedure TIBDataBase.ApplyUpdates( const DataSets: array of TDataSet);
1289   var
1290    I: Integer;
1291    DS: TIBCustomDataSet;
# Line 1190 | Line 1311 | begin
1311    TR.CommitRetaining;
1312   end;
1313  
1314 < procedure TIBDatabase.CloseDataSets;
1314 > procedure TIBDataBase.CloseDataSets;
1315   var
1316    i: Integer;
1317   begin
# Line 1199 | Line 1320 | begin
1320        DataSets[i].close;
1321   end;
1322  
1323 < function TIBDatabase.GetDataset(Index : longint) : TDataset;
1323 > function TIBDataBase.GetDataset(Index: longint): TDataset;
1324   begin
1325    if (Index >= 0) and (Index < FDataSets.Count) then
1326      Result := TDataSet(FDataSets[Index])
# Line 1207 | Line 1328 | begin
1328      raise Exception.Create('Invalid Index to DataSets');
1329   end;
1330  
1331 < function TIBDatabase.GetDataSetCount : Longint;
1331 > function TIBDataBase.GetDataSetCount: Longint;
1332   begin
1333    Result := FDataSets.Count;
1334   end;
# Line 1228 | Line 1349 | begin
1349    inherited SetConnected(Value);
1350   end;
1351  
1352 < procedure TIBDatabase.GetFieldNames(const TableName: string; List: TStrings);
1352 > procedure TIBDataBase.GetFieldNames( const TableName: string; List: TStrings);
1353   var
1354    Query: TIBSQL;
1355   begin
# Line 1269 | Line 1390 | begin
1390    end;
1391   end;
1392  
1393 < procedure TIBDatabase.GetTableNames(List: TStrings; SystemTables: Boolean);
1393 > procedure TIBDataBase.GetTableNames(List: TStrings; SystemTables: Boolean);
1394   var
1395    Query : TIBSQL;
1396   begin
# Line 1328 | Line 1449 | begin
1449    FTRParamsChanged := True;
1450    TStringList(FTRParams).OnChange := TRParamsChange;
1451    TStringList(FTRParams).OnChanging := TRParamsChanging;
1452 <  FTimer := TTimer.Create(Self);
1452 >  FTimer := TFPTimer.Create(Self);
1453    FTimer.Enabled := False;
1454    FTimer.Interval := 0;
1455    FTimer.OnTimer := TimeoutTransaction;
# Line 1384 | Line 1505 | begin
1505      IBError(ibxeNotInTransaction, [nil]);
1506   end;
1507  
1508 + procedure TIBTransaction.DoBeforeTransactionEnd;
1509 + begin
1510 +  if Assigned(FBeforeTransactionEnd) then
1511 +    FBeforeTransactionEnd(self);
1512 + end;
1513 +
1514 + procedure TIBTransaction.DoAfterTransactionEnd;
1515 + begin
1516 +  if Assigned(FAfterTransactionEnd) then
1517 +    FAfterTransactionEnd(self);
1518 + end;
1519 +
1520 + procedure TIBTransaction.DoOnStartTransaction;
1521 + begin
1522 +  if assigned(FOnStartTransaction) then
1523 +    OnStartTransaction(self);
1524 + end;
1525 +
1526 + procedure TIBTransaction.DoAfterExecQuery(Sender: TObject);
1527 + begin
1528 +  if assigned(FAfterExecQuery) then
1529 +    AfterExecQuery(Sender);
1530 + end;
1531 +
1532 + procedure TIBTransaction.DoAfterEdit(Sender: TObject);
1533 + begin
1534 +  if assigned(FAfterEdit) then
1535 +    AfterEdit(Sender);
1536 + end;
1537 +
1538 + procedure TIBTransaction.DoAfterDelete(Sender: TObject);
1539 + begin
1540 +  if assigned(FAfterDelete) then
1541 +    AfterDelete(Sender);
1542 + end;
1543 +
1544 + procedure TIBTransaction.DoAfterInsert(Sender: TObject);
1545 + begin
1546 +  if assigned(FAfterInsert) then
1547 +    AfterInsert(Sender);
1548 + end;
1549 +
1550 + procedure TIBTransaction.DoAfterPost(Sender: TObject);
1551 + begin
1552 +  if assigned(FAfterPost) then
1553 +    AfterPost(Sender);
1554 + end;
1555 +
1556   procedure TIBTransaction.EnsureNotInTransaction;
1557   begin
1558    if csDesigning in ComponentState then
# Line 1460 | Line 1629 | begin
1629    CheckInTransaction;
1630    if FInEndTransaction then Exit;
1631    FInEndTransaction := true;
1632 +  FEndAction := Action;
1633    try
1634    case Action of
1635      TARollback, TACommit:
# Line 1468 | Line 1638 | begin
1638           (Action <> FDefaultAction) and
1639           (not Force) then
1640          IBError(ibxeCantEndSharedTransaction, [nil]);
1641 +      DoBeforeTransactionEnd;
1642        for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then
1643 <        SQLObjects[i].DoBeforeTransactionEnd;
1643 >        SQLObjects[i].DoBeforeTransactionEnd(Action);
1644        if InTransaction then
1645        begin
1646          if HandleIsShared then
# Line 1492 | Line 1663 | begin
1663              IBDataBaseError;
1664          for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then
1665            SQLObjects[i].DoAfterTransactionEnd;
1666 +        DoAfterTransactionEnd;
1667        end;
1668      end;
1669      TACommitRetaining:
# Line 1582 | Line 1754 | begin
1754    end;
1755   end;
1756  
1757 + function TIBTransaction.GetEndAction: TTransactionAction;
1758 + begin
1759 +  if FInEndTransaction then
1760 +     Result := FEndAction
1761 +  else
1762 +     IBError(ibxeIB60feature, [nil])
1763 + end;
1764 +
1765  
1766   function TIBTransaction.GetIdleTimer: Integer;
1767   begin
# Line 1687 | Line 1867 | begin
1867      for i := 0 to FSQLObjects.Count - 1 do
1868        if (FSQLObjects[i] <> nil) and
1869           (TIBBase(FSQLObjects[i]).Database = nil) then
1870 <        SetOrdProp(TIBBase(FSQLObjects[i]).Owner, 'Database', Integer(Value));
1870 >         SetObjectProp(TIBBase(FSQLObjects[i]).Owner, 'Database', Value);
1871    end;
1872    FDefaultDatabase := Value;
1873   end;
# Line 1793 | Line 1973 | begin
1973    finally
1974      FreeMem(pteb);
1975    end;
1976 +  DoOnStartTransaction;
1977   end;
1978  
1979   procedure TIBTransaction.TimeoutTransaction(Sender: TObject);
# Line 1834 | Line 2015 | begin
2015    inherited Destroy;
2016   end;
2017  
2018 + function TIBBase.GetCharSetSize(CharSetID: integer): integer;
2019 + begin
2020 +  if (CharSetID >= 0) and (CharSetID < Length(Database.FCharSetSizes)) then
2021 +    Result := Database.FCharSetSizes[CharSetID]
2022 +  else
2023 +    Result := 1; {Unknown character set}
2024 + end;
2025 +
2026 + procedure TIBBase.HandleException(Sender: TObject);
2027 + begin
2028 +  if assigned(Database) then
2029 +     Database.HandleException(Sender)
2030 +  else
2031 +     SysUtils.ShowException(ExceptObject,ExceptAddr);
2032 + end;
2033 +
2034 + procedure TIBBase.SetCursor;
2035 + begin
2036 +  if Assigned(Database) and not Database.SQLHourGlass then
2037 +     Exit;
2038 +  if assigned(IBGUIInterface) then
2039 +     IBGUIInterface.SetCursor;
2040 + end;
2041 +
2042 + procedure TIBBase.RestoreCursor;
2043 + begin
2044 +  if Assigned(Database) and not Database.SQLHourGlass then
2045 +     Exit;
2046 +  if assigned(IBGUIInterface) then
2047 +     IBGUIInterface.RestoreCursor;
2048 + end;
2049 +
2050   procedure TIBBase.CheckDatabase;
2051   begin
2052    if (FDatabase = nil) then
# Line 1860 | Line 2073 | begin
2073    result := @FTransaction.Handle;
2074   end;
2075  
2076 + procedure TIBBase.DoBeforeDatabaseConnect(DBParams: TStrings; var DBName: string
2077 +  );
2078 + begin
2079 +  if assigned(FBeforeDatabaseConnect) then
2080 +    BeforeDatabaseConnect(self,DBParams,DBName);
2081 + end;
2082 +
2083   procedure TIBBase.DoAfterDatabaseConnect;
2084   begin
2085    if assigned(FAfterDatabaseConnect) then
# Line 1886 | Line 2106 | begin
2106    SetTransaction(nil);
2107   end;
2108  
2109 < procedure TIBBase.DoBeforeTransactionEnd;
2109 > procedure TIBBase.DoBeforeTransactionEnd(Action: TTransactionAction);
2110   begin
2111    if Assigned(BeforeTransactionEnd) then
2112 <    BeforeTransactionEnd(Self);
2112 >    BeforeTransactionEnd(Self,Action);
2113   end;
2114  
2115   procedure TIBBase.DoAfterTransactionEnd;
# Line 1905 | Line 2125 | begin
2125    FTransaction := nil;
2126   end;
2127  
2128 + procedure TIBBase.DoAfterExecQuery(Sender: TObject);
2129 + begin
2130 +  if FTransaction <> nil then
2131 +    FTransaction.DoAfterExecQuery(Sender);
2132 + end;
2133 +
2134 + procedure TIBBase.DoAfterEdit(Sender: TObject);
2135 + begin
2136 +  if FTransaction <> nil then
2137 +    FTransaction.DoAfterEdit(Sender);
2138 + end;
2139 +
2140 + procedure TIBBase.DoAfterDelete(Sender: TObject);
2141 + begin
2142 +  if FTransaction <> nil then
2143 +    FTransaction.DoAfterDelete(Sender);
2144 + end;
2145 +
2146 + procedure TIBBase.DoAfterInsert(Sender: TObject);
2147 + begin
2148 +  if FTransaction <> nil then
2149 +    FTransaction.DoAfterInsert(Sender);
2150 + end;
2151 +
2152 + procedure TIBBase.DoAfterPost(Sender: TObject);
2153 + begin
2154 +  if FTransaction <> nil then
2155 +    FTransaction.DoAfterPost(Sender);
2156 + end;
2157 +
2158   procedure TIBBase.SetDatabase(Value: TIBDatabase);
2159   begin
2160    if (FDatabase <> nil) then

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines