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 21 by tony, Thu Feb 26 10:33:34 2015 UTC vs.
Revision 29 by tony, Sat May 9 11:37:49 2015 UTC

# 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 181 | Line 182 | type
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 262 | Line 265 | type
265                                                   write SetDefaultTransaction;
266      property IdleTimer: Integer read GetIdleTimer write SetIdleTimer;
267      property SQLDialect : Integer read GetSQLDialect write SetSQLDialect default 3;
268 +    property SQLHourGlass: Boolean read FSQLHourGlass write FSQLHourGlass default true;
269      property DBSQLDialect : Integer read FDBSQLDialect;
270      property TraceFlags: TTraceFlags read FTraceFlags write FTraceFlags;
271      property AfterConnect;
# Line 279 | Line 283 | type
283  
284    TIBTransaction = class(TComponent)
285    private
286 +    FAfterDelete: TNotifyEvent;
287 +    FAfterEdit: TNotifyEvent;
288 +    FAfterExecQuery: TNotifyEvent;
289 +    FAfterInsert: TNotifyEvent;
290 +    FAfterPost: TNotifyEvent;
291      FAfterTransactionEnd: TNotifyEvent;
292      FBeforeTransactionEnd: TNotifyEvent;
293      FIBLoaded: Boolean;
294      FCanTimeout         : Boolean;
295      FDatabases          : TList;
296 +    FOnStartTransaction: TNotifyEvent;
297      FSQLObjects         : TList;
298      FDefaultDatabase    : TIBDatabase;
299      FHandle             : TISC_TR_HANDLE;
# Line 300 | Line 310 | type
310      FEndAction          : TTransactionAction;
311      procedure DoBeforeTransactionEnd;
312      procedure DoAfterTransactionEnd;
313 +    procedure DoOnStartTransaction;
314 +    procedure DoAfterExecQuery(Sender: TObject);
315 +    procedure DoAfterEdit(Sender: TObject);
316 +    procedure DoAfterDelete(Sender: TObject);
317 +    procedure DoAfterInsert(Sender: TObject);
318 +    procedure DoAfterPost(Sender: TObject);
319      procedure EnsureNotInTransaction;
320      procedure EndTransaction(Action: TTransactionAction; Force: Boolean);
321      function GetDatabase(Index: Integer): TIBDatabase;
# Line 367 | Line 383 | type
383                                               write FBeforeTransactionEnd;
384      property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd
385                                              write FAfterTransactionEnd;
386 +    property OnStartTransaction: TNotifyEvent read FOnStartTransaction
387 +                                              write FOnStartTransaction;
388 +    property AfterExecQuery: TNotifyEvent read FAfterExecQuery
389 +                                              write FAfterExecQuery;
390 +    property AfterEdit: TNotifyEvent read FAfterEdit write FAfterEdit;
391 +    property AfterDelete: TNotifyEvent read FAfterDelete write FAfterDelete;
392 +    property AfterInsert: TNotifyEvent read FAfterInsert write FAfterInsert;
393 +    property AfterPost: TNotifyEvent read FAfterPost write FAfterPost;
394    end;
395  
396 +  TTransactionEndEvent = procedure(Sender:TObject; Action: TTransactionAction) of object;
397 +  TBeforeDatabaseConnectEvent = procedure (Sender: TObject; DBParams: TStrings;
398 +                              var DBName: string) of object;
399 +
400    { TIBBase }
401  
402    { Virtually all components in IB are "descendents" of TIBBase.
# Line 376 | Line 404 | type
404      connections. }
405    TIBBase = class(TObject)
406    protected
407 +    FBeforeDatabaseConnect: TBeforeDatabaseConnectEvent;
408      FDatabase: TIBDatabase;
409      FIndexInDatabase: Integer;
410      FTransaction: TIBTransaction;
# Line 385 | Line 414 | type
414      FAfterDatabaseDisconnect: TNotifyEvent;
415      FAfterDatabaseConnect: TNotifyEvent;
416      FOnDatabaseFree: TNotifyEvent;
417 <    FBeforeTransactionEnd: TNotifyEvent;
417 >    FBeforeTransactionEnd: TTransactionEndEvent;
418      FAfterTransactionEnd: TNotifyEvent;
419      FOnTransactionFree: TNotifyEvent;
420  
421 +    procedure DoBeforeDatabaseConnect(DBParams: TStrings;
422 +                              var DBName: string); virtual;
423      procedure DoAfterDatabaseConnect; virtual;
424      procedure DoBeforeDatabaseDisconnect; virtual;
425      procedure DoAfterDatabaseDisconnect; virtual;
426      procedure DoDatabaseFree; virtual;
427 <    procedure DoBeforeTransactionEnd; virtual;
427 >    procedure DoBeforeTransactionEnd(Action: TTransactionAction); virtual;
428      procedure DoAfterTransactionEnd; virtual;
429      procedure DoTransactionFree; virtual;
430      function GetDBHandle: PISC_DB_HANDLE; virtual;
# Line 405 | Line 436 | type
436      destructor Destroy; override;
437      procedure CheckDatabase; virtual;
438      procedure CheckTransaction; virtual;
439 +    procedure DoAfterExecQuery(Sender: TObject); virtual;
440 +    procedure DoAfterEdit(Sender: TObject); virtual;
441 +    procedure DoAfterDelete(Sender: TObject); virtual;
442 +    procedure DoAfterInsert(Sender: TObject); virtual;
443 +    procedure DoAfterPost(Sender: TObject); virtual;
444 +    function GetCharSetSize(CharSetID: integer): integer;
445    public
446 +    property BeforeDatabaseConnect: TBeforeDatabaseConnectEvent read FBeforeDatabaseConnect
447 +                                                 write FBeforeDatabaseConnect;
448      property AfterDatabaseConnect: TNotifyEvent read FAfterDatabaseConnect
449                                                  write FAfterDatabaseConnect;
450      property BeforeDatabaseDisconnect: TNotifyEvent read FBeforeDatabaseDisconnect
# Line 413 | Line 452 | type
452      property AfterDatabaseDisconnect: TNotifyEvent read FAfterDatabaseDisconnect
453                                                    write FAfterDatabaseDisconnect;
454      property OnDatabaseFree: TNotifyEvent read FOnDatabaseFree write FOnDatabaseFree;
455 <    property BeforeTransactionEnd: TNotifyEvent read FBeforeTransactionEnd write FBeforeTransactionEnd;
455 >    property BeforeTransactionEnd: TTransactionEndEvent read FBeforeTransactionEnd write FBeforeTransactionEnd;
456      property AfterTransactionEnd: TNotifyEvent read FAfterTransactionEnd write FAfterTransactionEnd;
457      property OnTransactionFree: TNotifyEvent read FOnTransactionFree write FOnTransactionFree;
458      property Database: TIBDatabase read FDatabase
# Line 450 | Line 489 | begin
489    FTransactions := TList.Create;
490    FDBName := '';
491    FDBParams := TStringList.Create;
492 +  FSQLHourGlass := true;
493    {$ifdef UNIX}
494    if csDesigning in ComponentState then
495      FDBParams.Add('lc_ctype=UTF-8');
# Line 581 | Line 621 | begin
621    if Connected then
622      InternalClose(False);
623    FDBSQLDialect := 1;
624 +  SetLength(FCharSetSizes,0);
625   end;
626  
627   procedure TIBDataBase.CreateDatabase;
# Line 775 | Line 816 | begin
816        SQLObjects[i].DoAfterDatabaseDisconnect;
817   end;
818  
819 + procedure TIBDataBase.LoadCharSetInfo;
820 + var Query: TIBSQL;
821 +    i: integer;
822 + begin
823 +  if not FInternalTransaction.Active then
824 +    FInternalTransaction.StartTransaction;
825 +  Query := TIBSQL.Create(self);
826 +  try
827 +    Query.Database := Self;
828 +    Query.Transaction := FInternalTransaction;
829 +    Query.SQL.Text := 'Select RDB$CHARACTER_SET_ID, RDB$BYTES_PER_CHARACTER ' +
830 +                      'From RDB$CHARACTER_SETS Order by 1 DESC'; {do not localize}
831 +    Query.Prepare;
832 +    Query.ExecQuery;
833 +    if not Query.EOF then
834 +    begin
835 +      SetLength(FCharSetSizes,Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger + 1);
836 +      for i := 0 to Length(FCharSetSizes) - 1 do FCharSetSizes[i] := 1;
837 +      repeat
838 +        FCharSetSizes[Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger] :=
839 +                 Query.FieldByName('RDB$BYTES_PER_CHARACTER').AsInteger;
840 +        Query.Next;
841 +      until Query.EOF;
842 +    end;
843 +  finally
844 +    Query.free;
845 +    FInternalTransaction.Commit;
846 +  end;
847 + end;
848 +
849   procedure TIBDataBase.CheckStreamConnect;
850   var
851    i: integer;
# Line 906 | Line 977 | var
977    DPB: String;
978    TempDBParams: TStrings;
979    I: integer;
980 <
980 >  aDBName: string;
981   begin
982    CheckInactive;
983    CheckDatabaseName;
# Line 918 | Line 989 | begin
989    { Use builtin login prompt if requested }
990    if (LoginPrompt or (csDesigning in ComponentState)) and not Login then
991      IBError(ibxeOperationCancelled, [nil]);
992 <  { Generate a new DPB if necessary }
993 <  if (FDBParamsChanged) then
994 <  begin
995 <    FDBParamsChanged := False;
996 <    if (not LoginPrompt and not (csDesigning in ComponentState)) or (FHiddenPassword = '') then
997 <      GenerateDPB(FDBParams, DPB, FDPBLength)
998 <    else
999 <    begin
1000 <      TempDBParams := TStringList.Create;
1001 <      try
1002 <       TempDBParams.Assign(FDBParams);
1003 <       TempDBParams.Add('password=' + FHiddenPassword);
1004 <       GenerateDPB(TempDBParams, DPB, FDPBLength);
1005 <      finally
1006 <       TempDBParams.Free;
1007 <      end;
1008 <    end;
1009 <    IBAlloc(FDPB, 0, FDPBLength);
1010 <    Move(DPB[1], FDPB[0], FDPBLength);
992 >
993 >  TempDBParams := TStringList.Create;
994 >  try
995 >   TempDBParams.Assign(FDBParams);
996 >   aDBName := FDBName;
997 >   {Opportuning to override defaults}
998 >   for i := 0 to FSQLObjects.Count - 1 do
999 >   begin
1000 >       if FSQLObjects[i] <> nil then
1001 >         SQLObjects[i].DoBeforeDatabaseConnect(TempDBParams,aDBName);
1002 >   end;
1003 >
1004 >   { Generate a new DPB if necessary }
1005 >   if (FDBParamsChanged or (TempDBParams.Text <> FDBParams.Text)) then
1006 >   begin
1007 >     FDBParamsChanged := False;
1008 >     if (not LoginPrompt and not (csDesigning in ComponentState)) or (FHiddenPassword = '') then
1009 >       GenerateDPB(TempDBParams, DPB, FDPBLength)
1010 >     else
1011 >     begin
1012 >        TempDBParams.Add('password=' + FHiddenPassword);
1013 >        GenerateDPB(TempDBParams, DPB, FDPBLength);
1014 >     end;
1015 >     IBAlloc(FDPB, 0, FDPBLength);
1016 >     Move(DPB[1], FDPB[0], FDPBLength);
1017 >   end;
1018 >  finally
1019 >   TempDBParams.Free;
1020    end;
1021 <  if Call(isc_attach_database(StatusVector, Length(FDBName),
1022 <                         PChar(FDBName), @FHandle,
1021 >  if Call(isc_attach_database(StatusVector, Length(aDBName),
1022 >                         PChar(aDBName), @FHandle,
1023                           FDPBLength, FDPB), False) > 0 then
1024    begin
1025      FHandle := nil;
1026      IBDataBaseError;
1027    end;
1028 +  if not (csDesigning in ComponentState) then
1029 +    FDBName := aDBName; {Synchronise at run time}
1030    FDBSQLDialect := GetDBSQLDialect;
1031    ValidateClientSQLDialect;
1032    for i := 0 to FSQLObjects.Count - 1 do
# Line 954 | Line 1036 | begin
1036    end;
1037    if not (csDesigning in ComponentState) then
1038      MonitorHook.DBConnect(Self);
1039 +  LoadCharSetInfo;
1040   end;
1041  
1042   procedure TIBDataBase.RemoveSQLObject(Idx: Integer);
# Line 1406 | Line 1489 | begin
1489      FAfterTransactionEnd(self);
1490   end;
1491  
1492 + procedure TIBTransaction.DoOnStartTransaction;
1493 + begin
1494 +  if assigned(FOnStartTransaction) then
1495 +    OnStartTransaction(self);
1496 + end;
1497 +
1498 + procedure TIBTransaction.DoAfterExecQuery(Sender: TObject);
1499 + begin
1500 +  if assigned(FAfterExecQuery) then
1501 +    AfterExecQuery(Sender);
1502 + end;
1503 +
1504 + procedure TIBTransaction.DoAfterEdit(Sender: TObject);
1505 + begin
1506 +  if assigned(FAfterEdit) then
1507 +    AfterEdit(Sender);
1508 + end;
1509 +
1510 + procedure TIBTransaction.DoAfterDelete(Sender: TObject);
1511 + begin
1512 +  if assigned(FAfterDelete) then
1513 +    AfterDelete(Sender);
1514 + end;
1515 +
1516 + procedure TIBTransaction.DoAfterInsert(Sender: TObject);
1517 + begin
1518 +  if assigned(FAfterInsert) then
1519 +    AfterInsert(Sender);
1520 + end;
1521 +
1522 + procedure TIBTransaction.DoAfterPost(Sender: TObject);
1523 + begin
1524 +  if assigned(FAfterPost) then
1525 +    AfterPost(Sender);
1526 + end;
1527 +
1528   procedure TIBTransaction.EnsureNotInTransaction;
1529   begin
1530    if csDesigning in ComponentState then
# Line 1493 | Line 1612 | begin
1612          IBError(ibxeCantEndSharedTransaction, [nil]);
1613        DoBeforeTransactionEnd;
1614        for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then
1615 <        SQLObjects[i].DoBeforeTransactionEnd;
1615 >        SQLObjects[i].DoBeforeTransactionEnd(Action);
1616        if InTransaction then
1617        begin
1618          if HandleIsShared then
# Line 1826 | Line 1945 | begin
1945    finally
1946      FreeMem(pteb);
1947    end;
1948 +  DoOnStartTransaction;
1949   end;
1950  
1951   procedure TIBTransaction.TimeoutTransaction(Sender: TObject);
# Line 1867 | Line 1987 | begin
1987    inherited Destroy;
1988   end;
1989  
1990 + function TIBBase.GetCharSetSize(CharSetID: integer): integer;
1991 + begin
1992 +  if (CharSetID >= 0) and (CharSetID < Length(Database.FCharSetSizes)) then
1993 +    Result := Database.FCharSetSizes[CharSetID]
1994 +  else
1995 +    Result := 1; {Unknown character set}
1996 + end;
1997 +
1998   procedure TIBBase.CheckDatabase;
1999   begin
2000    if (FDatabase = nil) then
# Line 1893 | Line 2021 | begin
2021    result := @FTransaction.Handle;
2022   end;
2023  
2024 + procedure TIBBase.DoBeforeDatabaseConnect(DBParams: TStrings; var DBName: string
2025 +  );
2026 + begin
2027 +  if assigned(FBeforeDatabaseConnect) then
2028 +    BeforeDatabaseConnect(self,DBParams,DBName);
2029 + end;
2030 +
2031   procedure TIBBase.DoAfterDatabaseConnect;
2032   begin
2033    if assigned(FAfterDatabaseConnect) then
# Line 1919 | Line 2054 | begin
2054    SetTransaction(nil);
2055   end;
2056  
2057 < procedure TIBBase.DoBeforeTransactionEnd;
2057 > procedure TIBBase.DoBeforeTransactionEnd(Action: TTransactionAction);
2058   begin
2059    if Assigned(BeforeTransactionEnd) then
2060 <    BeforeTransactionEnd(Self);
2060 >    BeforeTransactionEnd(Self,Action);
2061   end;
2062  
2063   procedure TIBBase.DoAfterTransactionEnd;
# Line 1938 | Line 2073 | begin
2073    FTransaction := nil;
2074   end;
2075  
2076 + procedure TIBBase.DoAfterExecQuery(Sender: TObject);
2077 + begin
2078 +  if FTransaction <> nil then
2079 +    FTransaction.DoAfterExecQuery(Sender);
2080 + end;
2081 +
2082 + procedure TIBBase.DoAfterEdit(Sender: TObject);
2083 + begin
2084 +  if FTransaction <> nil then
2085 +    FTransaction.DoAfterEdit(Sender);
2086 + end;
2087 +
2088 + procedure TIBBase.DoAfterDelete(Sender: TObject);
2089 + begin
2090 +  if FTransaction <> nil then
2091 +    FTransaction.DoAfterDelete(Sender);
2092 + end;
2093 +
2094 + procedure TIBBase.DoAfterInsert(Sender: TObject);
2095 + begin
2096 +  if FTransaction <> nil then
2097 +    FTransaction.DoAfterInsert(Sender);
2098 + end;
2099 +
2100 + procedure TIBBase.DoAfterPost(Sender: TObject);
2101 + begin
2102 +  if FTransaction <> nil then
2103 +    FTransaction.DoAfterPost(Sender);
2104 + end;
2105 +
2106   procedure TIBBase.SetDatabase(Value: TIBDatabase);
2107   begin
2108    if (FDatabase <> nil) then
# Line 2147 | Line 2312 | end.
2312  
2313  
2314  
2315 <
2315 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines