--- ibx/branches/udr/client/FBAttachment.pas 2022/01/05 14:59:15 370 +++ ibx/branches/udr/client/FBAttachment.pas 2022/01/05 15:21:22 371 @@ -16,7 +16,7 @@ * * The Initial Developer of the Original Code is Tony Whyman. * - * The Original Code is (C) 2016 Tony Whyman, MWA Software + * The Original Code is (C) 2016-2021 Tony Whyman, MWA Software * (http://www.mwasoftware.co.uk). * * All Rights Reserved. @@ -69,22 +69,22 @@ type Syntax: Transaction Start: - *S:,,,:,:, + *S:,,,,:,:, Transaction Commit: - *C:,, + *C:,,, Transaction Commit retaining : - *c:,, + *c:,,, Transaction Rollback: - *R:,, + *R:,,, Transaction Rollback retaining: - *r:,, + *r:,,, Update/Insert/Delete - *Q:,,,: + *Q:,,,,: } @@ -93,12 +93,12 @@ type TFBJournaling = class(TActivityHandler, IJournallingHook) private {Logfile} - const sQueryJournal = '*Q:''%s'',%d,%d,%d:%s' + LineEnding; - const sTransStartJnl = '*S:''%s'',%d,%d,%d:%s,%d:%s,%d' + LineEnding; - const sTransCommitJnl = '*C:''%s'',%d,%d' + LineEnding; - const sTransCommitRetJnl = '*c:''%s'',%d,%d,%d' + LineEnding; - const sTransRollBackJnl = '*R:''%s'',%d,%d' + LineEnding; - const sTransRollBackRetJnl = '*r:''%s'',%d,%d,%d' + LineEnding; + const sQueryJournal = '*Q:''%s'',%d,%d,%d,%d:%s' + LineEnding; + const sTransStartJnl = '*S:''%s'',%d,%d,%d,%d:%s,%d:%s,%d' + LineEnding; + const sTransCommitJnl = '*C:''%s'',%d,%d,%d' + LineEnding; + const sTransCommitRetJnl = '*c:''%s'',%d,%d,%d,%d' + LineEnding; + const sTransRollBackJnl = '*R:''%s'',%d,%d,%d' + LineEnding; + const sTransRollBackRetJnl = '*r:''%s'',%d,%d,%d,%d' + LineEnding; private FOptions: TJournalOptions; FJournalFilePath: string; @@ -125,6 +125,7 @@ type function GetJournalOptions: TJournalOptions; function StartJournaling(aJournalLogFile: AnsiString): integer; overload; function StartJournaling(aJournalLogFile: AnsiString; Options: TJournalOptions): integer; overload; + function StartJournaling(S: TStream; Options: TJournalOptions): integer; overload; procedure StopJournaling(RetainJournal: boolean); end; @@ -139,6 +140,7 @@ type FUserCharSetMap: array of TCharSetMap; FSecDatabase: AnsiString; FInlineBlobLimit: integer; + FAttachmentID: integer; protected FDatabaseName: AnsiString; FRaiseExceptionOnConnectError: boolean; @@ -217,6 +219,7 @@ type function GetEventHandler(Event: AnsiString): IEvents; overload; function GetSQLDialect: integer; + function GetAttachmentID: integer; function CreateBlob(transaction: ITransaction; RelationName, ColumnName: AnsiString; BPB: IBPB=nil): IBlob; overload; function CreateBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BPB: IBPB=nil): IBlob; overload; virtual; abstract; function OpenBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB=nil): IBlob; overload; virtual; abstract; @@ -233,18 +236,20 @@ type function GetDBInformation(Requests: array of byte): IDBInformation; overload; function GetDBInformation(Request: byte): IDBInformation; overload; function GetDBInformation(Requests: IDIRB): IDBInformation; overload; - function GetAttachmentID: integer; function GetConnectString: AnsiString; function GetRemoteProtocol: AnsiString; function GetAuthenticationMethod: AnsiString; function GetSecurityDatabase: AnsiString; function GetODSMajorVersion: integer; function GetODSMinorVersion: integer; + function GetCharSetID: integer; function HasDecFloatSupport: boolean; virtual; function GetInlineBlobLimit: integer; procedure SetInlineBlobLimit(limit: integer); function HasBatchMode: boolean; virtual; function HasTable(aTableName: AnsiString): boolean; + function HasFunction(aFunctionName: AnsiString): boolean; + function HasProcedure(aProcName: AnsiString): boolean; public {Character Sets} @@ -610,10 +615,10 @@ end; procedure TFBJournaling.EndSession(RetainJournal: boolean); begin - if JournalingActive then + if JournalingActive and (FJournalFilePath <> '') then begin FreeAndNil(FJournalFileStream); - if not RetainJournal then + if not (joNoServerTable in FOptions) and not RetainJournal then try GetAttachment.ExecuteSQL([isc_tpb_write,isc_tpb_wait,isc_tpb_consistency], sqlCleanUpSession,[FSessionID]); @@ -638,6 +643,7 @@ var LogEntry: AnsiString; TPBText: AnsiString; begin FDoNotJournal := true; + if not (joNoServerTable in FOptions) then try GetAttachment.ExecuteSQL(Tr,sqlRecordJournalEntry,[FSessionID,Tr.GetTransactionID,NULL]); finally @@ -645,6 +651,7 @@ begin end; TPBText := Tr.getTPB.AsText; LogEntry := Format(sTransStartJnl,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, FSessionID, Tr.GetTransactionID, Length(Tr.TransactionName), @@ -664,12 +671,16 @@ begin case Action of TARollback: begin - LogEntry := Format(sTransRollbackJnl,[FBFormatDateTime(GetDateTimeFmt,Now),FSessionID,TransactionID]); + LogEntry := Format(sTransRollbackJnl,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, + FSessionID,TransactionID]); Result := true; end; TACommit: begin - LogEntry := Format(sTransCommitJnl,[FBFormatDateTime(GetDateTimeFmt,Now),FSessionID,TransactionID]); + LogEntry := Format(sTransCommitJnl,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, + FSessionID,TransactionID]); Result := true; end; end; @@ -684,15 +695,18 @@ begin case Action of TACommitRetaining: LogEntry := Format(sTransCommitRetJnl,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, FSessionID,Tr.GetTransactionID,OldTransactionID]); TARollbackRetaining: LogEntry := Format(sTransRollbackRetJnl,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, FSessionID,Tr.GetTransactionID,OldTransactionID]); end; if assigned(FJournalFileStream) then FJournalFileStream.Write(LogEntry[1],Length(LogEntry)); FDoNotJournal := true; + if not (joNoServerTable in FOptions) then try GetAttachment.ExecuteSQL(Tr,sqlRecordJournalEntry,[FSessionID,Tr.GetTransactionID,OldTransactionID]); finally @@ -706,6 +720,7 @@ var SQL: AnsiString; begin SQL := TQueryProcessor.Execute(Stmt); LogEntry := Format(sQueryJournal,[FBFormatDateTime(GetDateTimeFmt,Now), + GetAttachment.GetAttachmentID, FSessionID, Stmt.GetTransaction.GetTransactionID, Length(SQL),SQL]); @@ -731,18 +746,28 @@ end; function TFBJournaling.StartJournaling(aJournalLogFile: AnsiString; Options: TJournalOptions): integer; begin + try + StartJournaling(TFileStream.Create(aJournalLogFile,fmCreate),Options); + finally + FJournalFilePath := aJournalLogFile; + end; +end; + +function TFBJournaling.StartJournaling(S: TStream; Options: TJournalOptions + ): integer; +begin FOptions := Options; + if not (joNoServerTable in FOptions) then with GetAttachment do begin - if not HasTable(sJournalTableName) then + if not HasTable(sJournalTableName) then begin ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_consistency],sqlCreateJournalTable); ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_consistency],sqlCreateSequence); end; FSessionID := OpenCursorAtStart(sqlGetNextSessionID)[0].AsInteger; end; - FJournalFilePath := aJournalLogFile; - FJournalFileStream := TFileStream.Create(FJournalFilePath,fmCreate); + FJournalFileStream := S; Result := FSessionID; end; @@ -765,7 +790,7 @@ var DBInfo: IDBInformation; begin if not IsConnected then Exit; DBInfo := GetDBInformation([isc_info_db_id,isc_info_ods_version,isc_info_ods_minor_version, - isc_info_db_SQL_Dialect]); + isc_info_db_SQL_Dialect, isc_info_attachment_id]); for i := 0 to DBInfo.GetCount - 1 do with DBInfo[i] do case getItemType of @@ -775,6 +800,8 @@ begin FODSMajorVersion := getAsInteger; isc_info_db_SQL_Dialect: FSQLDialect := getAsInteger; + isc_info_attachment_id: + FAttachmentID := getAsInteger; end; FCharSetID := 0; @@ -831,12 +858,12 @@ begin FFirebirdAPI := api.GetAPI; {Keep reference to interface} FSQLDialect := 3; FDatabaseName := DatabaseName; - FDPB := DPB; SetLength(FUserCharSetMap,0); - FRaiseExceptionOnConnectError := RaiseExceptionOnConnectError; FODSMajorVersion := 0; FODSMinorVersion := 0; FInlineBlobLimit := DefaultMaxInlineBlobLimit; + FDPB := DPB; + FRaiseExceptionOnConnectError := RaiseExceptionOnConnectError; end; function TFBAttachment.GenerateCreateDatabaseSQL(DatabaseName: AnsiString; aDPB: IDPB): AnsiString; @@ -1181,6 +1208,11 @@ begin Result := FSQLDialect; end; +function TFBAttachment.GetAttachmentID: integer; +begin + Result := FAttachmentID; +end; + function TFBAttachment.CreateBlob(transaction: ITransaction; RelationName, ColumnName: AnsiString; BPB: IBPB): IBlob; begin @@ -1250,16 +1282,6 @@ begin Result := GetDBInfo(getBuffer,getDataLength); end; -function TFBAttachment.GetAttachmentID: integer; -var Info: IDBInformation; -begin - Info := GetDBInformation(isc_info_attachment_id); - if (Info.Count > 0) and (Info[0].getItemType = isc_info_attachment_id) then - Result := Info[0].getAsInteger - else - Result := -1; -end; - function TFBAttachment.GetConnectString: AnsiString; begin Result := FDatabaseName; @@ -1290,6 +1312,11 @@ begin Result := FODSMinorVersion; end; +function TFBAttachment.GetCharSetID: integer; +begin + Result := FCharSetID; +end; + function TFBAttachment.HasDecFloatSupport: boolean; begin Result := false; @@ -1320,6 +1347,20 @@ begin [aTableName])[0].AsInteger > 0; end; +function TFBAttachment.HasFunction(aFunctionName: AnsiString): boolean; +begin + Result := OpenCursorAtStart( + 'Select count(*) From RDB$FUNCTIONS Where RDB$FUNCTION_NAME = ?', + [aFunctionName])[0].AsInteger > 0; +end; + +function TFBAttachment.HasProcedure(aProcName: AnsiString): boolean; +begin + Result := OpenCursorAtStart( + 'Select count(*) From RDB$PROCEDURES Where RDB$PROCEDURE_NAME = ?', + [aProcName])[0].AsInteger > 0; +end; + function TFBAttachment.HasDefaultCharSet: boolean; begin Result := FHasDefaultCharSet