35 |
|
|
36 |
|
{$Mode Delphi} |
37 |
|
|
38 |
+ |
{$IF FPC_FULLVERSION >= 20700 } |
39 |
+ |
{$codepage UTF8} |
40 |
+ |
{$DEFINE HAS_ANSISTRING_CODEPAGE} |
41 |
+ |
{$ENDIF} |
42 |
+ |
|
43 |
|
interface |
44 |
|
|
45 |
|
uses |
187 |
|
FUserNames: TStringList; |
188 |
|
FDataSets: TList; |
189 |
|
FLoginCalled: boolean; |
190 |
< |
FCharSetSizes: array of integer; |
191 |
< |
FCharSetNames: array of string; |
190 |
> |
FDefaultCharSetName: RawByteString; |
191 |
> |
FDefaultCharSetID: integer; |
192 |
> |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
193 |
> |
FDefaultCodePage: TSystemCodePage; |
194 |
> |
{$ENDIF} |
195 |
> |
FUseDefaultSystemCodePage: boolean; |
196 |
|
procedure EnsureInactive; |
197 |
|
function GetDBSQLDialect: Integer; |
198 |
|
function GetSQLDialect: Integer; |
206 |
|
function GetIdleTimer: Integer; |
207 |
|
function GetTransaction(Index: Integer): TIBTransaction; |
208 |
|
function GetTransactionCount: Integer; |
209 |
< |
function Login: Boolean; |
201 |
< |
procedure LoadCharSetInfo; |
209 |
> |
function Login(var aDatabaseName: string): Boolean; |
210 |
|
procedure SetDatabaseName(const Value: TIBFileName); |
211 |
|
procedure SetDBParamByDPB(const Idx: Integer; Value: String); |
212 |
|
procedure SetDBParams(Value: TStrings); |
263 |
|
property TransactionCount: Integer read GetTransactionCount; |
264 |
|
property Transactions[Index: Integer]: TIBTransaction read GetTransaction; |
265 |
|
property InternalTransaction: TIBTransaction read FInternalTransaction; |
266 |
+ |
property DefaultCharSetName: RawByteString read FDefaultCharSetName; |
267 |
+ |
property DefaultCharSetID: integer read FDefaultCharSetID; |
268 |
+ |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
269 |
+ |
property DefaultCodePage: TSystemCodePage read FDefaultCodePage; |
270 |
+ |
{$ENDIF} |
271 |
|
|
272 |
|
published |
273 |
|
property Connected; |
283 |
|
property SQLHourGlass: Boolean read FSQLHourGlass write FSQLHourGlass default true; |
284 |
|
property DBSQLDialect : Integer read FDBSQLDialect; |
285 |
|
property TraceFlags: TTraceFlags read FTraceFlags write FTraceFlags; |
286 |
+ |
property UseDefaultSystemCodePage: boolean read FUseDefaultSystemCodePage |
287 |
+ |
write FUseDefaultSystemCodePage; |
288 |
|
property AfterConnect; |
289 |
|
property AfterDisconnect; |
290 |
|
property BeforeConnect; |
458 |
|
procedure DoAfterDelete(Sender: TObject); virtual; |
459 |
|
procedure DoAfterInsert(Sender: TObject); virtual; |
460 |
|
procedure DoAfterPost(Sender: TObject); virtual; |
461 |
< |
function GetCharSetSize(CharSetID: integer): integer; |
462 |
< |
function GetDefaultCharSetSize: integer; |
448 |
< |
function GetCharSetName(CharSetID: integer): string; |
449 |
< |
function GetDefaultCharSetName: string; |
461 |
> |
function GetDefaultCharSetName: RawByteString; |
462 |
> |
function GetDefaultCharSetID: cardinal; |
463 |
|
procedure HandleException(Sender: TObject); |
464 |
|
procedure SetCursor; |
465 |
|
procedure RestoreCursor; |
492 |
|
implementation |
493 |
|
|
494 |
|
uses IBIntf, IBSQLMonitor, IBCustomDataSet, IBDatabaseInfo, IBSQL, IBUtils, |
495 |
< |
typInfo; |
495 |
> |
typInfo, IBCodePage; |
496 |
|
|
497 |
|
{ TIBDatabase } |
498 |
|
|
499 |
< |
constructor TIBDataBase.Create(AOwner: TComponent); |
487 |
< |
{$ifdef WINDOWS} |
488 |
< |
var acp: uint; |
489 |
< |
{$endif} |
499 |
> |
constructor TIBDataBase.Create(AOwner: TComponent); |
500 |
|
begin |
501 |
|
inherited Create(AOwner); |
502 |
|
FIBLoaded := False; |
512 |
|
(AOwner is TCustomApplication) and |
513 |
|
TCustomApplication(AOWner).ConsoleApplication then |
514 |
|
LoginPrompt := false; |
515 |
< |
{$ifdef UNIX} |
516 |
< |
if csDesigning in ComponentState then |
517 |
< |
FDBParams.Add('lc_ctype=UTF8'); |
508 |
< |
{$else} |
509 |
< |
{$ifdef WINDOWS} |
510 |
< |
if csDesigning in ComponentState then |
511 |
< |
begin |
512 |
< |
acp := GetACP; |
513 |
< |
if (acp >= 1250) and (acp <= 1254) then |
514 |
< |
FDBParams.Values['lc_ctype'] := Format('WIN%d',[acp]); |
515 |
< |
end; |
516 |
< |
{$endif} |
517 |
< |
{$endif} |
515 |
> |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
516 |
> |
FDefaultCodePage := CP_NONE; |
517 |
> |
{$ENDIF} |
518 |
|
FDBParamsChanged := True; |
519 |
|
TStringList(FDBParams).OnChange := DBParamsChange; |
520 |
|
TStringList(FDBParams).OnChanging := DBParamsChanging; |
633 |
|
if Connected then |
634 |
|
InternalClose(False); |
635 |
|
FDBSQLDialect := 1; |
636 |
< |
SetLength(FCharSetSizes,0); |
637 |
< |
SetLength(FCharSetNames,0); |
636 |
> |
FDefaultCharSetName := ''; |
637 |
> |
FDefaultCharSetID := 0; |
638 |
> |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
639 |
> |
FDefaultCodePage := CP_NONE; |
640 |
> |
{$ENDIF} |
641 |
|
end; |
642 |
|
|
643 |
|
procedure TIBDataBase.CreateDatabase; |
832 |
|
SQLObjects[i].DoAfterDatabaseDisconnect; |
833 |
|
end; |
834 |
|
|
832 |
– |
procedure TIBDataBase.LoadCharSetInfo; |
833 |
– |
var Query: TIBSQL; |
834 |
– |
i: integer; |
835 |
– |
begin |
836 |
– |
if not FInternalTransaction.Active then |
837 |
– |
FInternalTransaction.StartTransaction; |
838 |
– |
Query := TIBSQL.Create(self); |
839 |
– |
try |
840 |
– |
Query.Database := Self; |
841 |
– |
Query.Transaction := FInternalTransaction; |
842 |
– |
Query.SQL.Text := 'Select RDB$CHARACTER_SET_ID, RDB$BYTES_PER_CHARACTER, RDB$CHARACTER_SET_NAME ' + |
843 |
– |
'From RDB$CHARACTER_SETS Order by 1 DESC'; {do not localize} |
844 |
– |
Query.Prepare; |
845 |
– |
Query.ExecQuery; |
846 |
– |
if not Query.EOF then |
847 |
– |
begin |
848 |
– |
SetLength(FCharSetSizes,Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger + 1); |
849 |
– |
SetLength(FCharSetNames,Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger + 1); |
850 |
– |
for i := 0 to Length(FCharSetSizes) - 1 do FCharSetSizes[i] := 1; |
851 |
– |
repeat |
852 |
– |
FCharSetSizes[Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger] := |
853 |
– |
Query.FieldByName('RDB$BYTES_PER_CHARACTER').AsInteger; |
854 |
– |
FCharSetNames[Query.FieldByName('RDB$CHARACTER_SET_ID').AsInteger] := |
855 |
– |
Query.FieldByName('RDB$CHARACTER_SET_NAME').AsString; |
856 |
– |
Query.Next; |
857 |
– |
until Query.EOF; |
858 |
– |
end; |
859 |
– |
finally |
860 |
– |
Query.free; |
861 |
– |
FInternalTransaction.Commit; |
862 |
– |
end; |
863 |
– |
end; |
864 |
– |
|
835 |
|
procedure TIBDataBase.CheckStreamConnect; |
836 |
|
var |
837 |
|
i: integer; |
895 |
|
end; |
896 |
|
end; |
897 |
|
|
898 |
< |
function TIBDataBase.Login: Boolean; |
898 |
> |
function TIBDataBase.Login(var aDatabaseName: string): Boolean; |
899 |
|
var |
900 |
|
IndexOfUser, IndexOfPassword: Integer; |
901 |
|
Username, Password, OldPassword: String; |
931 |
|
LoginParams.Assign(Params); |
932 |
|
FOnLogin(Self, LoginParams); |
933 |
|
Params.Assign (LoginParams); |
934 |
+ |
aDatabaseName := FDBName; |
935 |
|
HidePassword; |
936 |
|
finally |
937 |
|
LoginParams.Free; |
953 |
|
Length(Params[IndexOfPassword])); |
954 |
|
OldPassword := password; |
955 |
|
end; |
956 |
< |
result := IBGUIInterface.LoginDialogEx(DatabaseName, Username, Password, False); |
956 |
> |
result := IBGUIInterface.LoginDialogEx(aDatabaseName, Username, Password, False); |
957 |
|
if result then |
958 |
|
begin |
959 |
|
if IndexOfUser = -1 then |
990 |
|
sqlcode: Long; |
991 |
|
IBErrorCode: Long; |
992 |
|
status_vector: PISC_STATUS; |
993 |
+ |
CharSetID: integer; |
994 |
|
begin |
995 |
|
CheckInactive; |
996 |
|
CheckDatabaseName; |
1000 |
|
FDBParamsChanged := True; |
1001 |
|
end; |
1002 |
|
{ Use builtin login prompt if requested } |
1003 |
< |
if (LoginPrompt or (csDesigning in ComponentState)) and not Login then |
1003 |
> |
aDBName := FDBName; |
1004 |
> |
if (LoginPrompt or (csDesigning in ComponentState)) and not Login(aDBName) then |
1005 |
|
IBError(ibxeOperationCancelled, [nil]); |
1006 |
|
|
1007 |
|
TempDBParams := TStringList.Create; |
1008 |
|
try |
1009 |
|
TempDBParams.Assign(FDBParams); |
1010 |
< |
aDBName := FDBName; |
1010 |
> |
if UseDefaultSystemCodePage then |
1011 |
> |
begin |
1012 |
> |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
1013 |
> |
{$ifdef WINDOWS} |
1014 |
> |
if TFirebirdCharacterSets.CodePage2CharSetID(GetACP,CharSetID) then |
1015 |
> |
TempDBParams.Values['lc_ctype'] := TFirebirdCharacterSets.GetCharsetName(CharSetID) |
1016 |
> |
else |
1017 |
> |
{$else} |
1018 |
> |
if TFirebirdCharacterSets.CodePage2CharSetID(DefaultSystemCodePage,CharSetID) then |
1019 |
> |
TempDBParams.Values['lc_ctype'] := TFirebirdCharacterSets.GetCharsetName(CharSetID) |
1020 |
> |
else |
1021 |
> |
{$endif} |
1022 |
> |
{$ENDIF} |
1023 |
> |
TempDBParams.Values['lc_ctype'] :='UTF8'; |
1024 |
> |
end; |
1025 |
|
{Opportunity 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 |
< |
|
1031 |
> |
FDefaultCharSetName := AnsiUpperCase(TempDBParams.Values['lc_ctype']); |
1032 |
> |
if FDefaultCharSetName <> '' then |
1033 |
> |
TFirebirdCharacterSets.CharSetName2CharSetID(FDefaultCharSetName,FDefaultCharSetID); |
1034 |
> |
{$IFDEF HAS_ANSISTRING_CODEPAGE} |
1035 |
> |
TFirebirdCharacterSets.CharSetID2CodePage(FDefaultCharSetID,FDefaultCodePage); |
1036 |
> |
{$ENDIF} |
1037 |
|
{ Generate a new DPB if necessary } |
1038 |
|
if (FDBParamsChanged or (TempDBParams.Text <> FDBParams.Text)) then |
1039 |
|
begin |
1088 |
|
end; |
1089 |
|
if not (csDesigning in ComponentState) then |
1090 |
|
MonitorHook.DBConnect(Self); |
1099 |
– |
LoadCharSetInfo; |
1091 |
|
end; |
1092 |
|
|
1093 |
|
procedure TIBDataBase.RemoveSQLObject(Idx: Integer); |
2038 |
|
inherited Destroy; |
2039 |
|
end; |
2040 |
|
|
2041 |
< |
function TIBBase.GetCharSetSize(CharSetID: integer): integer; |
2041 |
> |
function TIBBase.GetDefaultCharSetName: RawByteString; |
2042 |
|
begin |
2043 |
< |
if (CharSetID >= 0) and (CharSetID < Length(Database.FCharSetSizes)) then |
2053 |
< |
Result := Database.FCharSetSizes[CharSetID] |
2054 |
< |
else |
2055 |
< |
Result := 1; {Unknown character set} |
2056 |
< |
end; |
2057 |
< |
|
2058 |
< |
function TIBBase.GetDefaultCharSetSize: integer; |
2059 |
< |
var DefaultCharSetName: string; |
2060 |
< |
i: integer; |
2061 |
< |
begin |
2062 |
< |
DefaultCharSetName := GetDefaultCharSetName; |
2063 |
< |
Result := 4; {worse case} |
2064 |
< |
for i := 0 to Length(Database.FCharSetSizes) - 1 do |
2065 |
< |
if Database.FCharSetNames[i] = DefaultCharSetName then |
2066 |
< |
begin |
2067 |
< |
Result := Database.FCharSetSizes[i]; |
2068 |
< |
break; |
2069 |
< |
end; |
2070 |
< |
end; |
2071 |
< |
|
2072 |
< |
function TIBBase.GetCharSetName(CharSetID: integer): string; |
2073 |
< |
begin |
2074 |
< |
if (CharSetID >= 0) and (CharSetID < Length(Database.FCharSetNames)) then |
2075 |
< |
Result := Database.FCharSetNames[CharSetID] |
2076 |
< |
else |
2077 |
< |
Result := ''; {Unknown character set} |
2043 |
> |
Result := Database.FDefaultCharSetName; |
2044 |
|
end; |
2045 |
|
|
2046 |
< |
function TIBBase.GetDefaultCharSetName: string; |
2046 |
> |
function TIBBase.GetDefaultCharSetID: cardinal; |
2047 |
|
begin |
2048 |
< |
Result := AnsiUpperCase(Database.Params.Values['lc_ctype']); |
2048 |
> |
Result := Database.DefaultCharSetID; |
2049 |
|
end; |
2050 |
|
|
2051 |
|
procedure TIBBase.HandleException(Sender: TObject); |