ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/udr/source/FBUDRUtils.pas
Revision: 387
Committed: Wed Jan 19 13:34:42 2022 UTC (2 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 26787 byte(s)
Log Message:
Transactions started within a UDR are not forcibly closed if still active immediately prior to UDR exit

File Contents

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

Properties

Name Value
svn:eol-style native