ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/udr/source/FBUDRUtils.pas
Revision: 402
Committed: Mon Aug 1 10:07:24 2022 UTC (2 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 27423 byte(s)
Log Message:
IBX Release 2.5.0

File Contents

# User Rev Content
1 tony 402 (*
2     * Firebird UDR Support (fbudr). The fbudr components provide a set of
3     * Pascal language bindings for the Firebird API in support of server
4     * side User Defined Routines (UDRs). The fbudr package is an extension
5     * to the Firebird Pascal API.
6     *
7     * The contents of this file are subject to the Initial Developer's
8     * Public License Version 1.0 (the "License"); you may not use this
9     * file except in compliance with the License. You may obtain a copy
10     * of the License here:
11     *
12     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
13     *
14     * Software distributed under the License is distributed on an "AS
15     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16     * implied. See the License for the specific language governing rights
17     * and limitations under the License.
18     *
19     * The Initial Developer of the Original Code is Tony Whyman.
20     *
21     * The Original Code is (C) 2021 Tony Whyman, MWA Software
22     * (http://www.mwasoftware.co.uk).
23     *
24     * All Rights Reserved.
25     *
26     * Contributor(s): ______________________________________.
27     *
28     *)
29     unit FBUDRUtils;
30    
31     {$IFDEF MSWINDOWS}
32     {$DEFINE WINDOWS}
33     {$ENDIF}
34    
35     {$IFDEF FPC}
36     {$mode delphi}
37     {$codepage UTF8}
38     {$interfaces COM}
39     {$ENDIF}
40    
41     interface
42    
43     uses
44     Classes, SysUtils, Firebird, FBActivityMonitor, IB, FBUDRController, FBUDRIntf;
45    
46     const
47     {$IFDEF WINDOWS}
48     NewLineTAB = #$0D#$0A' ';
49     {$ELSE}
50     NewLineTAB = #$0A' ';
51     {$ENDIF}
52     {$if not declared(LineEnding)}
53     LineEnding = #$0D#$0A;
54     {$ifend}
55    
56     type
57    
58     { TFBUDRObject }
59    
60     TFBUDRObject = class(TFBInterfacedObject)
61     private
62     FFirebirdAPI: IFirebirdAPI;
63     FController: TFBUDRController;
64     procedure SetFirebirdAPI(AValue: IFirebirdAPI);
65     protected
66     FStatus: Firebird.IStatus;
67     public
68     constructor Create(aController: TFBUDRController);
69     destructor Destroy; override;
70     procedure Clear; {IStatus}
71     procedure CheckStatus;
72     function getStatus: Firebird.IStatus;
73     property FirebirdAPI: IFirebirdAPI read FFirebirdAPI write SetFirebirdAPI;
74     property Controller: TFBUDRController read FController;
75     end;
76    
77     {An External Context is provided when a factory object or an instance of an
78     external function, procedure or trigger is called}
79    
80     { TFBUDRExternalContext }
81    
82     TFBUDRExternalContext = class(TFBUDRObject, IFBUDRExternalContext)
83     private
84     FContext: Firebird.IExternalContext;
85     FAttachment: IAttachment;
86     FTransaction: ITransaction;
87     public
88     constructor Create(aController: TFBUDRController; context: Firebird.IExternalContext);
89     function AsText: AnsiString;
90     public
91     {IFBUDRExternalContext}
92     function GetFirebirdAPI: IFirebirdAPI;
93     function GetAttachment: IAttachment;
94     function GetTransaction: ITransaction;
95     function GetUserName: AnsiString;
96     function GetDatabaseName: AnsiString;
97     function GetClientCharSet: AnsiString;
98     function obtainInfoCode: Integer;
99     function getInfo(code: Integer): Pointer;
100     function setInfo(code: Integer; value: Pointer): Pointer;
101     function cloneAttachment: IAttachment;
102     function GetServiceManager: IServiceManager;
103     function HasConfigFile: boolean;
104     function ReadConfigString(Section, Ident, DefaultValue: AnsiString): AnsiString;
105     function ReadConfigInteger(Section, Ident: AnsiString; DefaultValue: integer): integer;
106     function ReadConfigBool(Section, Ident: AnsiString; DefaultValue: boolean): boolean;
107     procedure WriteToLog(Msg: AnsiString);
108     end;
109    
110     { The Routine metadata is provided when a factory object or an instance of an
111     external function, procedure or trigger is called and provides the input
112     and output metadata}
113    
114     { TFBUDRRoutineMetadata }
115    
116     TFBUDRRoutineMetadata = class(TFBUDRObject,IFBUDRRoutineMetadata,IFBUDRProcMetadata,IFBUDRTriggerMetaData)
117     private
118     FRoutineMetadata: firebird.IRoutineMetadata;
119     FInputMetadata: firebird.IMessageMetadata;
120     FOutputMetadata: firebird.IMessageMetadata;
121     FTriggerMetadata: firebird.IMessageMetadata;
122     FContext: IFBUDRExternalContext;
123     FFBInputMetadata: IFBUDRMessageMetadata;
124     FFBOutputMetadata: IFBUDRMessageMetadata;
125     FFBTriggerMetadata: IFBUDRMessageMetadata;
126     FModuleName: AnsiString;
127     FRoutineName: AnsiString;
128     FInfo: AnsiString;
129     public
130     constructor Create(context: IFBUDRExternalContext; routineMetadata: firebird.IRoutineMetadata);
131     destructor Destroy; override;
132     function AsText: AnsiString;
133     function getInputMetadata: firebird.IMessageMetadata;
134     function getOutputMetadata: firebird.IMessageMetadata;
135     function getTriggerMetadata: firebird.IMessageMetadata;
136     class procedure ParseEntryPoint(aEntryPoint: AnsiString; var aModuleName, aRoutineName, aInfo: AnsiString);
137     public
138     {IFBUDRRoutineMetadata}
139     function getPackage: AnsiString;
140     function getName: AnsiString;
141     function getEntryPoint: AnsiString;
142     function getModuleName: AnsiString;
143     function getRoutineName: AnsiString;
144     function getInfo: AnsiString;
145     function getBody: AnsiString;
146     function HasInputMetadata: boolean;
147     function HasOutputMetadata: boolean;
148     function HasTriggerMetadata: boolean;
149     function getFBInputMetadata: IFBUDRMessageMetadata;
150     function getFBOutputMetadata: IFBUDRMessageMetadata;
151     function getFBTriggerMetadata: IFBUDRMessageMetadata;
152     function getTriggerTable: AnsiString;
153     function getTriggerType: TFBUDRTriggerType;
154     end;
155    
156     { TFBUDRMetadataBuilder }
157    
158     TFBUDRMetadataBuilder = class(TFBUDRObject,IFBUDRMetadataBuilder)
159     private
160     FMetadataBuilder: Firebird.IMetadataBuilder;
161     public
162     constructor Create(context: IFBUDRExternalContext;
163     metadataBuilder: Firebird.IMetadataBuilder);
164     destructor Destroy; override;
165     property Builder: Firebird.IMetadataBuilder read FMetadataBuilder;
166     public
167     {IFBUDRMetadataBuilder}
168     procedure setType(index: Cardinal; type_: Cardinal);
169     procedure setSubType(index: Cardinal; subType: Integer);
170     procedure setLength(index: Cardinal; length: Cardinal);
171     procedure setCharSet(index: Cardinal; charSet: Cardinal);
172     procedure setScale(index: Cardinal; scale: Integer);
173     procedure truncate(count: Cardinal);
174     procedure moveNameToIndex(name: AnsiString; index: Cardinal);
175     procedure remove(index: Cardinal);
176     function addField:Cardinal;
177     procedure setField(index: Cardinal; field: AnsiString);
178     procedure setRelation(index: Cardinal; relation: AnsiString);
179     procedure setOwner(index: Cardinal; owner: AnsiString);
180     procedure setAlias(index: Cardinal; alias: AnsiString);
181     end;
182    
183     { TFBUDRMessageMetadata }
184    
185     TFBUDRMessageMetadata = class(TFBUDRObject,IFBUDRMessageMetadata)
186     private
187     FMetadata: Firebird.IMessageMetadata;
188     FContext: IFBUDRExternalContext;
189     public
190     constructor Create(context: IFBUDRExternalContext;
191     metadata: Firebird.IMessageMetadata);
192     destructor Destroy; override;
193     function AsText: AnsiString;
194     public
195     function getCount: Cardinal;
196     function getField(index: Cardinal): AnsiString;
197     function getRelation(index: Cardinal): AnsiString;
198     function getOwner(index: Cardinal): AnsiString;
199     function getAlias(index: Cardinal): AnsiString;
200     function getType(index: Cardinal): Cardinal;
201     function isNullable(index: Cardinal): Boolean;
202     function getSubType(index: Cardinal): Integer;
203     function getLength(index: Cardinal): Cardinal;
204     function getScale(index: Cardinal): Integer;
205     function getCharSet(index: Cardinal): Cardinal;
206     function getOffset(index: Cardinal): Cardinal;
207     function getNullOffset(index: Cardinal): Cardinal;
208     function getBuilder: IFBUDRMetadataBuilder;
209     function getMessageLength: Cardinal;
210     function getAlignment: Cardinal;
211     function getAlignedLength: Cardinal;
212     end;
213    
214     { EFBUDRException }
215    
216     EFBUDRException = class(Exception)
217     private
218     FStatus: Firebird.IStatus;
219     public
220     constructor Create(aStatus: Firebird.IStatus);
221     destructor Destroy; override;
222     property Status: Firebird.IStatus read FStatus;
223     end;
224    
225     {$IFDEF MSWINDOWS}
226     function GetTempDir: AnsiString;
227     {$ENDIF}
228    
229     function BooleanToStr(boolValue: boolean; ValTrue, ValFalse: AnsiString): AnsiString;
230    
231     implementation
232    
233     uses FBClientLib, FBClientAPI, FB30ClientAPI, FB30Attachment, FB30Transaction,
234     FBUDRMessage, FBSQLData {$IFDEF MSWINDOWS}, Windows{$ENDIF};
235    
236     {$IFDEF MSWINDOWS}
237     function GetTempDir: AnsiString;
238     var
239     tempFolder: array[0..MAX_PATH] of Char;
240     begin
241     GetTempPath(MAX_PATH, @tempFolder);
242     result := StrPas(tempFolder);
243     end;
244     {$ENDIF}
245    
246     function BooleanToStr(boolValue: boolean; ValTrue, ValFalse: AnsiString): AnsiString;
247     begin
248     if boolValue then
249     Result := ValTrue
250     else
251     Result := ValFalse;
252     end;
253    
254     { TFBUDRMessageMetadata }
255    
256     constructor TFBUDRMessageMetadata.Create(context: IFBUDRExternalContext;
257     metadata: Firebird.IMessageMetadata);
258     begin
259     inherited Create((context as TFBUDRExternalContext).Controller);
260     FirebirdAPI := context.GetFirebirdAPI;
261     FContext := context;
262     FMetadata := metadata;
263     FMetadata.addRef;
264     end;
265    
266     destructor TFBUDRMessageMetadata.Destroy;
267     begin
268     if FMetadata <> nil then
269     FMetadata.release;
270     inherited Destroy;
271     end;
272    
273     function TFBUDRMessageMetadata.AsText: AnsiString;
274    
275     function CharsetIDToText(id: integer): AnsiString;
276     begin
277     if FContext.GetAttachment <> nil then
278     Result := FContext.GetAttachment.GetCharsetName(id)
279     else
280     Result := IntToStr(id);
281     end;
282    
283     var i: integer;
284     begin
285     Result := Format('Field Count = %d' + NewLineTAB,[getCount]);
286     if FMetadata.vTable.version >= 4 then
287     begin
288     Result := Result + Format('Alignment = %d' + NewLineTAB,[getAlignment]) +
289     Format('Aligned Length = %d' + NewLineTAB,[getAlignedLength]);
290     end;
291     for i := 0 to getCount - 1 do
292     begin
293     Result := Result +
294     Format('Field No. %d' + NewLineTAB,[i]) +
295     Format('Field Name = %s' + NewLineTAB,[getField(i)]) +
296     Format('Relation Name = %s' + NewLineTAB,[getRelation(i)]) +
297     Format('Alias Name = %s' + NewLineTAB,[getAlias(i)]) +
298     Format('SQLType = %s' + NewLineTAB,[TSQLDataItem.GetSQLTypeName(getType(i))]) +
299     Format('IsNullable = %s' + NewLineTAB,[BooleanToStr(isNullable(i),'yes','no')]) +
300     Format('SubType = %d' + NewLineTAB,[getSubType(i)]) +
301     Format('Length = %d' + NewLineTAB,[getLength(i)]) +
302     Format('Scale = %d' + NewLineTAB,[getScale(i)]) +
303     Format('Offset = %d' + NewLineTAB,[getOffset(i)]) +
304     Format('Null Offset = %d' + NewLineTAB,[getNullOffset(i)]) +
305     Format('Message Length = %d' + NewLineTAB,[getLength(i)]);
306     end;
307     end;
308    
309     function TFBUDRMessageMetadata.getCount: Cardinal;
310     begin
311     Result := FMetadata.getCount(FStatus);
312     CheckStatus;
313     end;
314    
315     function TFBUDRMessageMetadata.getField(index: Cardinal): AnsiString;
316     begin
317     Result := strpas(FMetadata.getField(FStatus,index));
318     CheckStatus;
319     end;
320    
321     function TFBUDRMessageMetadata.getRelation(index: Cardinal): AnsiString;
322     begin
323     Result := strpas(FMetadata.getRelation(FStatus,index));
324     CheckStatus;
325     end;
326    
327     function TFBUDRMessageMetadata.getOwner(index: Cardinal): AnsiString;
328     begin
329     Result := strpas(FMetadata.getOwner(FStatus,index));
330     CheckStatus;
331     end;
332    
333     function TFBUDRMessageMetadata.getAlias(index: Cardinal): AnsiString;
334     begin
335     Result := strpas(FMetadata.getAlias(FStatus,index));
336     CheckStatus;
337     end;
338    
339     function TFBUDRMessageMetadata.getType(index: Cardinal): Cardinal;
340     begin
341     Result := FMetadata.getType(FStatus,index);
342     CheckStatus;
343     end;
344    
345     function TFBUDRMessageMetadata.isNullable(index: Cardinal): Boolean;
346     begin
347     Result := FMetadata.isNullable(FStatus,index);
348     CheckStatus;
349     end;
350    
351     function TFBUDRMessageMetadata.getSubType(index: Cardinal): Integer;
352     begin
353     Result := FMetadata.getSubType(FStatus,index);
354     CheckStatus;
355     end;
356    
357     function TFBUDRMessageMetadata.getLength(index: Cardinal): Cardinal;
358     begin
359     Result := FMetadata.getLength(FStatus,index);
360     CheckStatus;
361     end;
362    
363     function TFBUDRMessageMetadata.getScale(index: Cardinal): Integer;
364     begin
365     Result := FMetadata.getScale(FStatus,index);
366     CheckStatus;
367     end;
368    
369     function TFBUDRMessageMetadata.getCharSet(index: Cardinal): Cardinal;
370     begin
371     Result := FMetadata.getCharSet(FStatus,index);
372     CheckStatus;
373     end;
374    
375     function TFBUDRMessageMetadata.getOffset(index: Cardinal): Cardinal;
376     begin
377     Result := FMetadata.getOffset(FStatus,index);
378     CheckStatus;
379     end;
380    
381     function TFBUDRMessageMetadata.getNullOffset(index: Cardinal): Cardinal;
382     begin
383     Result := FMetadata.getNullOffset(FStatus,index);
384     CheckStatus;
385     end;
386    
387     function TFBUDRMessageMetadata.getBuilder: IFBUDRMetadataBuilder;
388     var builder: Firebird.IMetadataBuilder;
389     begin
390     builder := FMetadata.getBuilder(FStatus);
391     try
392     CheckStatus;
393     Result := TFBUDRMetadataBuilder.Create(FContext,builder);
394     finally
395     builder.release;
396     end;
397     end;
398    
399     function TFBUDRMessageMetadata.getMessageLength: Cardinal;
400     begin
401     Result := FMetadata.getMessageLength(FStatus);
402     CheckStatus;
403     end;
404    
405     function TFBUDRMessageMetadata.getAlignment: Cardinal;
406     begin
407     Result := FMetadata.getAlignment(FStatus);
408     CheckStatus;
409     end;
410    
411     function TFBUDRMessageMetadata.getAlignedLength: Cardinal;
412     begin
413     Result := FMetadata.getAlignedLength(FStatus);
414     CheckStatus;
415     end;
416    
417     { TFBUDRMetadataBuilder }
418    
419     constructor TFBUDRMetadataBuilder.Create(context: IFBUDRExternalContext;
420     metadataBuilder: Firebird.IMetadataBuilder);
421     begin
422     inherited Create((context as TFBUDRExternalContext).Controller);
423     FirebirdAPI := context.GetFirebirdAPI;
424     FMetadataBuilder := metadataBuilder;
425     FMetadataBuilder.addRef;
426     end;
427    
428     destructor TFBUDRMetadataBuilder.Destroy;
429     begin
430     if FMetadataBuilder <> nil then
431     FMetadataBuilder.release;
432     inherited Destroy;
433     end;
434    
435     procedure TFBUDRMetadataBuilder.setType(index: Cardinal; type_: Cardinal);
436     begin
437     FMetadataBuilder.setType(FStatus,index,type_);
438     CheckStatus;
439     end;
440    
441     procedure TFBUDRMetadataBuilder.setSubType(index: Cardinal; subType: Integer);
442     begin
443     FMetadataBuilder.setSubType(FStatus,index,subType);
444     CheckStatus;
445     end;
446    
447     procedure TFBUDRMetadataBuilder.setLength(index: Cardinal; length: Cardinal);
448     begin
449     FMetadataBuilder.setLength(FStatus,index,Length);
450     CheckStatus;
451     end;
452    
453     procedure TFBUDRMetadataBuilder.setCharSet(index: Cardinal; charSet: Cardinal);
454     begin
455     FMetadataBuilder.setCharSet(FStatus,index,charSet);
456     CheckStatus;
457     end;
458    
459     procedure TFBUDRMetadataBuilder.setScale(index: Cardinal; scale: Integer);
460     begin
461     FMetadataBuilder.SetScale(FStatus,index,scale);
462     CheckStatus;
463     end;
464    
465     procedure TFBUDRMetadataBuilder.truncate(count: Cardinal);
466     begin
467     FMetadataBuilder.truncate(FStatus,count);
468     CheckStatus;
469     end;
470    
471     procedure TFBUDRMetadataBuilder.moveNameToIndex(name: AnsiString; index: Cardinal);
472     begin
473     FMetadataBuilder.moveNameToIndex(FStatus,PAnsiChar(name),index);
474     CheckStatus;
475     end;
476    
477     procedure TFBUDRMetadataBuilder.remove(index: Cardinal);
478     begin
479     FMetadataBuilder.remove(FStatus,index);
480     CheckStatus;
481     end;
482    
483     function TFBUDRMetadataBuilder.addField: Cardinal;
484     begin
485     Result := FMetadataBuilder.addField(FStatus);
486     CheckStatus;
487     end;
488    
489     procedure TFBUDRMetadataBuilder.setField(index: Cardinal; field: AnsiString);
490     begin
491     FMetadataBuilder.setField(FStatus,index,PAnsiChar(field));
492     CheckStatus;
493     end;
494    
495     procedure TFBUDRMetadataBuilder.setRelation(index: Cardinal; relation: AnsiString);
496     begin
497     FMetadataBuilder.setRelation(FStatus,index,PAnsiChar(relation));
498     CheckStatus;
499     end;
500    
501     procedure TFBUDRMetadataBuilder.setOwner(index: Cardinal; owner: AnsiString);
502     begin
503     FMetadataBuilder.setOwner(FStatus,index,PAnsiChar(owner));
504     CheckStatus;
505     end;
506    
507     procedure TFBUDRMetadataBuilder.setAlias(index: Cardinal; alias: AnsiString);
508     begin
509     FMetadataBuilder.setAlias(FStatus,index,PAnsiChar(alias));
510     end;
511    
512     { TFBUDRObject }
513    
514     procedure TFBUDRObject.SetFirebirdAPI(AValue: IFirebirdAPI);
515     var MasterProvider: IFBIMasterProvider;
516     begin
517     if FFirebirdAPI = AValue then Exit;
518     FFirebirdAPI := AValue;
519     if (FStatus = nil) and
520     FirebirdAPI.HasMasterIntf and (FirebirdAPI.QueryInterface(IFBIMasterProvider,MasterProvider) = S_OK) then
521     FStatus := MasterProvider.GetIMasterIntf.getStatus;
522     end;
523    
524     procedure TFBUDRObject.CheckStatus;
525     begin
526     with FStatus do
527     if (getState and STATE_ERRORS) <> 0 then
528     raise EFBUDRException.Create(FStatus);
529     end;
530    
531     function TFBUDRObject.getStatus: Firebird.IStatus;
532     begin
533     Result := FStatus;
534     end;
535    
536     constructor TFBUDRObject.Create(aController: TFBUDRController);
537     begin
538     inherited Create;
539     FController := aController;
540     end;
541    
542     destructor TFBUDRObject.Destroy;
543     begin
544     if FStatus <> nil then
545     FStatus.dispose;
546     inherited Destroy;
547     end;
548    
549     procedure TFBUDRObject.Clear;
550     begin
551     if FStatus <> nil then
552     FStatus.Init;
553     end;
554    
555     { TFBUDRExternalContext }
556    
557     constructor TFBUDRExternalContext.Create(aController: TFBUDRController;
558     context: Firebird.IExternalContext);
559     begin
560     inherited Create(aController);
561     FContext := context;
562     FirebirdAPI := TFB30ClientAPI.Create(context.getMaster);
563     aController.StartJournaling(self);
564     end;
565    
566     function TFBUDRExternalContext.AsText: AnsiString;
567     begin
568     Result := 'External Context: ' + NewLineTAB +
569     Format('Attachment ID = %d' + NewLineTAB,[GetAttachment.GetAttachmentID]) +
570     Format('Transaction ID = %d' + NewLineTAB,[GetTransaction.GetTransactionID]) +
571     Format('User Name = %s' + NewLineTAB,[GetUserName]) +
572     Format('Database Name = %s' + NewLineTAB,[GetDatabaseName]) +
573     Format('Client Character Set = %s' + NewLineTAB,[GetClientCharSet]);
574     end;
575    
576     function TFBUDRExternalContext.GetFirebirdAPI: IFirebirdAPI;
577     begin
578     Result := FirebirdAPI;
579     end;
580    
581     function TFBUDRExternalContext.GetAttachment: IAttachment;
582     var att: Firebird.IAttachment;
583     begin
584     if FAttachment = nil then
585     begin
586     att := FContext.getAttachment(FStatus);
587     CheckStatus;
588     FAttachment := TFB30Attachment.Create(FirebirdAPI as TFB30ClientAPI,
589     att,
590     GetDatabaseName);
591     end;
592     Result := FAttachment;
593     end;
594    
595     function TFBUDRExternalContext.GetTransaction: ITransaction;
596     var tr: Firebird.ITransaction;
597     begin
598     Result := nil;
599     if FTransaction = nil then
600     begin
601     tr := FContext.getTransaction(FStatus);
602     CheckStatus;
603     FTransaction := TFB30Transaction.Create(FirebirdAPI as TFB30ClientAPI,GetAttachment,tr);
604     end;
605     Result := FTransaction;
606     end;
607    
608     function TFBUDRExternalContext.GetUserName: AnsiString;
609     begin
610     Result := strpas(FContext.getUserName);
611     end;
612    
613     function TFBUDRExternalContext.GetDatabaseName: AnsiString;
614     begin
615     Result := strpas(FContext.getDatabaseName);
616     end;
617    
618     function TFBUDRExternalContext.GetClientCharSet: AnsiString;
619     begin
620     Result := strpas(FContext.getClientCharSet);
621     end;
622    
623     function TFBUDRExternalContext.obtainInfoCode: Integer;
624     begin
625     Result := FContext.obtainInfoCode;
626     end;
627    
628     function TFBUDRExternalContext.getInfo(code: Integer): Pointer;
629     begin
630     Result := FContext.getInfo(code);
631     end;
632    
633     function TFBUDRExternalContext.setInfo(code: Integer; value: Pointer): Pointer;
634     begin
635     Result := FContext.setInfo(code,value);
636     end;
637    
638     function TFBUDRExternalContext.cloneAttachment: IAttachment;
639     var DPB: IDPB;
640     begin
641     DPB := GetFirebirdAPI.AllocateDPB;
642     DPB.Add(isc_dpb_user_name).setAsString(GetUserName);
643     DPB.Add(isc_dpb_lc_ctype).setAsString(GetClientCharSet);
644     Result := GetFirebirdAPI.OpenDatabase(GetDatabaseName,DPB);
645     end;
646    
647     function TFBUDRExternalContext.GetServiceManager: IServiceManager;
648     var SPB: ISPB;
649     begin
650     SPB := FirebirdAPI.AllocateSPB;
651     SPB.Add(isc_spb_user_name).setAsString(GetUserName);
652     Result := GetFirebirdAPI.GetServiceManager('',Local,SPB);
653     end;
654    
655     function TFBUDRExternalContext.HasConfigFile: boolean;
656     begin
657     Result := Controller.HasConfigFile;
658     end;
659    
660     function TFBUDRExternalContext.ReadConfigString(Section, Ident,
661     DefaultValue: AnsiString): AnsiString;
662     begin
663     Result := Controller.ReadConfigString(Section, Ident, DefaultValue);
664     end;
665    
666     function TFBUDRExternalContext.ReadConfigInteger(Section, Ident: AnsiString;
667     DefaultValue: integer): integer;
668     begin
669     Result := Controller.ReadConfigInteger(Section, Ident, DefaultValue);
670     end;
671    
672     function TFBUDRExternalContext.ReadConfigBool(Section, Ident: AnsiString;
673     DefaultValue: boolean): boolean;
674     begin
675     Result := Controller.ReadConfigBool(Section, Ident, DefaultValue);
676     end;
677    
678     procedure TFBUDRExternalContext.WriteToLog(Msg: AnsiString);
679     begin
680     Controller.WriteToLog(Msg);
681     end;
682    
683    
684     { TFBUDRRoutineMetadata }
685    
686     class procedure TFBUDRRoutineMetadata.ParseEntryPoint(aEntryPoint: AnsiString;
687     var aModuleName, aRoutineName, aInfo: AnsiString);
688     var p1,p2: integer;
689     begin
690     aModuleName := '';
691     aRoutineName := '';
692     aInfo := '';
693     p1 := 1;
694     P2 := 1;
695     while (p2 < length(aEntryPoint)) and (aEntryPoint[p2] <> '!') do
696     Inc(p2);
697     if p2 = length(aEntryPoint) then
698     begin
699     aModuleName := aEntryPoint;
700     Exit;
701     end;
702     aModuleName := system.copy(aEntryPoint,1,p2-1);
703     Inc(p2);
704     p1 := p2;
705     while (p2 < length(aEntryPoint)) and (aEntryPoint[p2] <> '!') do
706     Inc(p2);
707     if p2 = length(aEntryPoint) then
708     begin
709     aRoutineName := system.copy(aEntryPoint,p1,maxint);
710     Exit;
711     end;
712     aRoutineName := system.copy(aEntryPoint,p1,p2-p1);
713     aInfo := system.copy(aEntryPoint,p2+1,maxint);
714     end;
715    
716     constructor TFBUDRRoutineMetadata.Create(context: IFBUDRExternalContext;
717     routineMetadata: firebird.IRoutineMetadata);
718     var TriggerType: cardinal;
719     begin
720     inherited Create((context as TFBUDRExternalContext).Controller);
721     FirebirdAPI := context.GetFirebirdAPI;
722     FContext := context;
723     FRoutineMetadata := routineMetadata;
724    
725     TriggerType := FRoutineMetadata.getTriggerType(FStatus);
726     CheckStatus;
727    
728     if TriggerType = 0 then
729     begin
730     FInputMetadata := FRoutineMetadata.getInputMetadata(FStatus);
731     CheckStatus;
732     if FInputMetadata <> nil then
733     FInputMetadata.addRef;
734    
735     FOutputMetadata := FRoutineMetadata.getOutputMetadata(FStatus);
736     CheckStatus;
737     if FOutputMetadata <> nil then
738     FOutputMetadata.addRef;
739     end
740     else
741     begin
742     FTriggerMetadata := FRoutineMetadata.getTriggerMetadata(FStatus);
743     CheckStatus;
744     if FTriggerMetadata <> nil then
745     FTriggerMetadata.addRef;
746     end;
747     ParseEntryPoint(getEntryPoint,FModuleName,FRoutineName,FInfo);
748     end;
749    
750     destructor TFBUDRRoutineMetadata.Destroy;
751     begin
752     if FInputMetadata <> nil then
753     FInputMetadata.release;
754     if FOutputMetadata <> nil then
755     FOutputMetadata.release;
756     if FTriggerMetadata <> nil then
757     FTriggerMetadata.release;
758     inherited Destroy;
759     end;
760    
761     function TFBUDRRoutineMetadata.AsText: AnsiString;
762    
763     function MetadataToText(metadata: Firebird.IMessageMetadata): AnsiString;
764     var fbMetadata: TFBUDRMessageMetadata;
765     begin
766     if metadata = nil then
767     Result := '(nil)'
768     else
769     begin
770     fbMetadata := TFBUDRMessageMetadata.Create(FContext,metadata);
771     try
772     Result := fbMetadata.AsText;
773     finally
774     fbMetadata.Free;
775     end;
776     end;
777     end;
778    
779     function TriggerTypeToText(TriggerType: TFBUDRTriggerType): AnsiString;
780     begin
781     case TriggerType of
782     ttAfter:
783     Result := 'After';
784     ttBefore:
785     Result := 'Before';
786     ttDatabase:
787     Result := 'Database';
788     end;
789     end;
790    
791     begin
792     Result := Format('Package Name = %s' + NewLineTAB,[getPackage]) +
793     Format('Name = %s' + NewLineTAB,[getName]) +
794     Format('Entry Point = %s (%s,%s,%s)' + NewLineTAB,[getEntryPoint,getModuleName,getRoutineName,getInfo]) +
795     Format('Body = %s' + NewLineTAB,[getBody]);
796     if HasInputMetaData then
797     Result := Result + Format('Input Metadata:' + NewLineTAB + '%s',[MetadataToText(FInputMetaData)]) + LineEnding;
798     if HasOutputMetaData then
799     Result := Result + Format('Output Metadata:' + NewLineTAB + '%s',[MetadataToText(FOutputMetaData)]);
800     if FRoutineMetadata.getTriggerType(FStatus) > 0 then
801     begin
802     if HasTriggerMetaData then
803     Result := Result + Format('Trigger Metadata:' + NewLineTAB + '%s',[MetadataToText(FTriggerMetaData)]);
804     Result := Result +
805     Format('Trigger Table = %s' + NewLineTAB,[getTriggerTable]) +
806     Format('Trigger Type = %s' + NewLineTAB,[TriggerTypeToText(getTriggerType)]);
807     end;
808     CheckStatus;
809     end;
810    
811     function TFBUDRRoutineMetadata.getPackage: AnsiString;
812     begin
813     Result := strpas(FRoutineMetadata.getPackage(FStatus));
814     CheckStatus;
815     end;
816    
817     function TFBUDRRoutineMetadata.getName: AnsiString;
818     begin
819     Result := strpas(FRoutineMetadata.getName(FStatus));
820     CheckStatus;
821     end;
822    
823     function TFBUDRRoutineMetadata.getModuleName: AnsiString;
824     begin
825     Result := FModuleName;
826     end;
827    
828     function TFBUDRRoutineMetadata.getRoutineName: AnsiString;
829     begin
830     Result := FRoutineName;
831     end;
832    
833     function TFBUDRRoutineMetadata.getInfo: AnsiString;
834     begin
835     Result := FInfo;
836     end;
837    
838     function TFBUDRRoutineMetadata.getEntryPoint: AnsiString;
839     begin
840     Result := strpas(FRoutineMetadata.getEntryPoint(FStatus));
841     CheckStatus;
842     end;
843    
844     function TFBUDRRoutineMetadata.getBody: AnsiString;
845     begin
846     Result := strpas(FRoutineMetadata.getBody(FStatus));
847     CheckStatus;
848     end;
849    
850     function TFBUDRRoutineMetadata.HasInputMetadata: boolean;
851     begin
852     Result := FInputMetadata <> nil;
853     end;
854    
855     function TFBUDRRoutineMetadata.HasOutputMetadata: boolean;
856     begin
857     Result := FOutputMetadata <> nil;
858     end;
859    
860     function TFBUDRRoutineMetadata.HasTriggerMetadata: boolean;
861     begin
862     Result := FTriggerMetadata <> nil;
863     end;
864    
865     function TFBUDRRoutineMetadata.getFBInputMetadata: IFBUDRMessageMetadata;
866     begin
867     Result := nil;
868     if (FFBInputMetadata = nil) and (FInputMetadata <> nil) then
869     FFBInputMetadata := TFBUDRMessageMetadata.Create(FContext,FInputMetadata);
870     Result := FFBInputMetadata;
871     end;
872    
873     function TFBUDRRoutineMetadata.getFBOutputMetadata: IFBUDRMessageMetadata;
874     begin
875     Result := nil;
876     if (FFBOutputMetadata = nil) and (FOutputMetadata <> nil) then
877     FFBOutputMetadata := TFBUDRMessageMetadata.Create(FContext,FOutputMetadata);
878     Result := FFBOutputMetadata;
879     end;
880    
881     function TFBUDRRoutineMetadata.getFBTriggerMetadata: IFBUDRMessageMetadata;
882     begin
883     Result := nil;
884     if (FFBTriggerMetadata = nil) and (FTriggerMetadata <> nil) then
885     FFBTriggerMetadata := TFBUDRMessageMetadata.Create(FContext,FTriggerMetadata);
886     Result := FFBTriggerMetadata;
887     end;
888    
889     function TFBUDRRoutineMetadata.getInputMetadata: firebird.IMessageMetadata;
890     begin
891     Result := FInputMetaData;
892     if Result <> nil then
893     Result.addRef;
894     end;
895    
896     function TFBUDRRoutineMetadata.getOutputMetadata: firebird.IMessageMetadata;
897     begin
898     Result := FOutputMetadata;
899     if Result <> nil then
900     Result.addRef;
901     end;
902    
903     function TFBUDRRoutineMetadata.getTriggerMetadata: firebird.IMessageMetadata;
904     begin
905     Result := FTriggerMetadata;
906     if Result <> nil then
907     Result.addRef;
908     end;
909    
910     function TFBUDRRoutineMetadata.getTriggerTable: AnsiString;
911     begin
912     Result := strpas(FRoutineMetadata.getTriggerTable(FStatus));
913     CheckStatus;
914     end;
915    
916     function TFBUDRRoutineMetadata.getTriggerType: TFBUDRTriggerType;
917     var TriggerType: cardinal;
918     begin
919     TriggerType := FRoutineMetadata.getTriggerType(FStatus);
920     CheckStatus;
921     with Firebird.IExternalTrigger do
922     case TriggerType of
923     TYPE_BEFORE:
924     Result := ttBefore;
925     TYPE_AFTER:
926     Result := ttAfter;
927     TYPE_DATABASE:
928     Result := ttDatabase;
929     else
930     FBUDRError(ibxeUnknownTriggerType,[TriggerType]);
931     end;
932     end;
933    
934     { EFBUDRException }
935    
936     constructor EFBUDRException.Create(aStatus: Firebird.IStatus);
937     begin
938     inherited Create(SFirebirdStatusError);
939     FStatus := aStatus.clone;
940     end;
941    
942     destructor EFBUDRException.Destroy;
943     begin
944     FStatus.dispose;
945     inherited Destroy;
946     end;
947    
948     end.
949    

Properties

Name Value
svn:eol-style native