ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/udr/source/FBUDRUtils.pas
Revision: 392
Committed: Wed Feb 9 16:17:50 2022 UTC (2 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 27501 byte(s)
Log Message:
cloneAttachment and GetServiceManager added

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 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 DPB.Add(isc_dpb_set_db_SQL_dialect).setAsByte(GetAttachment.GetSQLDialect);
645 Result := GetFirebirdAPI.OpenDatabase(GetDatabaseName,DPB);
646 end;
647
648 function TFBUDRExternalContext.GetServiceManager: IServiceManager;
649 var SPB: ISPB;
650 begin
651 SPB := FirebirdAPI.AllocateSPB;
652 SPB.Add(isc_spb_user_name).setAsString(GetUserName);
653 Result := GetFirebirdAPI.GetServiceManager('',Local,SPB);
654 end;
655
656 function TFBUDRExternalContext.HasConfigFile: boolean;
657 begin
658 Result := Controller.HasConfigFile;
659 end;
660
661 function TFBUDRExternalContext.ReadConfigString(Section, Ident,
662 DefaultValue: AnsiString): AnsiString;
663 begin
664 Result := Controller.ReadConfigString(Section, Ident, DefaultValue);
665 end;
666
667 function TFBUDRExternalContext.ReadConfigInteger(Section, Ident: AnsiString;
668 DefaultValue: integer): integer;
669 begin
670 Result := Controller.ReadConfigInteger(Section, Ident, DefaultValue);
671 end;
672
673 function TFBUDRExternalContext.ReadConfigBool(Section, Ident: AnsiString;
674 DefaultValue: boolean): boolean;
675 begin
676 Result := Controller.ReadConfigBool(Section, Ident, DefaultValue);
677 end;
678
679 procedure TFBUDRExternalContext.WriteToLog(Msg: AnsiString);
680 begin
681 Controller.WriteToLog(Msg);
682 end;
683
684
685 { TFBUDRRoutineMetadata }
686
687 class procedure TFBUDRRoutineMetadata.ParseEntryPoint(aEntryPoint: AnsiString;
688 var aModuleName, aRoutineName, aInfo: AnsiString);
689 var p1,p2: integer;
690 begin
691 aModuleName := '';
692 aRoutineName := '';
693 aInfo := '';
694 p1 := 1;
695 P2 := 1;
696 while (p2 < length(aEntryPoint)) and (aEntryPoint[p2] <> '!') do
697 Inc(p2);
698 if p2 = length(aEntryPoint) then
699 begin
700 aModuleName := aEntryPoint;
701 Exit;
702 end;
703 aModuleName := system.copy(aEntryPoint,1,p2-1);
704 Inc(p2);
705 p1 := p2;
706 while (p2 < length(aEntryPoint)) and (aEntryPoint[p2] <> '!') do
707 Inc(p2);
708 if p2 = length(aEntryPoint) then
709 begin
710 aRoutineName := system.copy(aEntryPoint,p1,maxint);
711 Exit;
712 end;
713 aRoutineName := system.copy(aEntryPoint,p1,p2-p1);
714 aInfo := system.copy(aEntryPoint,p2+1,maxint);
715 end;
716
717 constructor TFBUDRRoutineMetadata.Create(context: IFBUDRExternalContext;
718 routineMetadata: firebird.IRoutineMetadata);
719 var TriggerType: cardinal;
720 begin
721 inherited Create((context as TFBUDRExternalContext).Controller);
722 FirebirdAPI := context.GetFirebirdAPI;
723 FContext := context;
724 FRoutineMetadata := routineMetadata;
725
726 TriggerType := FRoutineMetadata.getTriggerType(FStatus);
727 CheckStatus;
728
729 if TriggerType = 0 then
730 begin
731 FInputMetadata := FRoutineMetadata.getInputMetadata(FStatus);
732 CheckStatus;
733 if FInputMetadata <> nil then
734 FInputMetadata.addRef;
735
736 FOutputMetadata := FRoutineMetadata.getOutputMetadata(FStatus);
737 CheckStatus;
738 if FOutputMetadata <> nil then
739 FOutputMetadata.addRef;
740 end
741 else
742 begin
743 FTriggerMetadata := FRoutineMetadata.getTriggerMetadata(FStatus);
744 CheckStatus;
745 if FTriggerMetadata <> nil then
746 FTriggerMetadata.addRef;
747 end;
748 ParseEntryPoint(getEntryPoint,FModuleName,FRoutineName,FInfo);
749 end;
750
751 destructor TFBUDRRoutineMetadata.Destroy;
752 begin
753 if FInputMetadata <> nil then
754 FInputMetadata.release;
755 if FOutputMetadata <> nil then
756 FOutputMetadata.release;
757 if FTriggerMetadata <> nil then
758 FTriggerMetadata.release;
759 inherited Destroy;
760 end;
761
762 function TFBUDRRoutineMetadata.AsText: AnsiString;
763
764 function MetadataToText(metadata: Firebird.IMessageMetadata): AnsiString;
765 var fbMetadata: TFBUDRMessageMetadata;
766 begin
767 if metadata = nil then
768 Result := '(nil)'
769 else
770 begin
771 fbMetadata := TFBUDRMessageMetadata.Create(FContext,metadata);
772 try
773 Result := fbMetadata.AsText;
774 finally
775 fbMetadata.Free;
776 end;
777 end;
778 end;
779
780 function TriggerTypeToText(TriggerType: TFBUDRTriggerType): AnsiString;
781 begin
782 case TriggerType of
783 ttAfter:
784 Result := 'After';
785 ttBefore:
786 Result := 'Before';
787 ttDatabase:
788 Result := 'Database';
789 end;
790 end;
791
792 begin
793 Result := Format('Package Name = %s' + NewLineTAB,[getPackage]) +
794 Format('Name = %s' + NewLineTAB,[getName]) +
795 Format('Entry Point = %s (%s,%s,%s)' + NewLineTAB,[getEntryPoint,getModuleName,getRoutineName,getInfo]) +
796 Format('Body = %s' + NewLineTAB,[getBody]);
797 if HasInputMetaData then
798 Result := Result + Format('Input Metadata:' + NewLineTAB + '%s',[MetadataToText(FInputMetaData)]) + LineEnding;
799 if HasOutputMetaData then
800 Result := Result + Format('Output Metadata:' + NewLineTAB + '%s',[MetadataToText(FOutputMetaData)]);
801 if FRoutineMetadata.getTriggerType(FStatus) > 0 then
802 begin
803 if HasTriggerMetaData then
804 Result := Result + Format('Trigger Metadata:' + NewLineTAB + '%s',[MetadataToText(FTriggerMetaData)]);
805 Result := Result +
806 Format('Trigger Table = %s' + NewLineTAB,[getTriggerTable]) +
807 Format('Trigger Type = %s' + NewLineTAB,[TriggerTypeToText(getTriggerType)]);
808 end;
809 CheckStatus;
810 end;
811
812 function TFBUDRRoutineMetadata.getPackage: AnsiString;
813 begin
814 Result := strpas(FRoutineMetadata.getPackage(FStatus));
815 CheckStatus;
816 end;
817
818 function TFBUDRRoutineMetadata.getName: AnsiString;
819 begin
820 Result := strpas(FRoutineMetadata.getName(FStatus));
821 CheckStatus;
822 end;
823
824 function TFBUDRRoutineMetadata.getModuleName: AnsiString;
825 begin
826 Result := FModuleName;
827 end;
828
829 function TFBUDRRoutineMetadata.getRoutineName: AnsiString;
830 begin
831 Result := FRoutineName;
832 end;
833
834 function TFBUDRRoutineMetadata.getInfo: AnsiString;
835 begin
836 Result := FInfo;
837 end;
838
839 function TFBUDRRoutineMetadata.getEntryPoint: AnsiString;
840 begin
841 Result := strpas(FRoutineMetadata.getEntryPoint(FStatus));
842 CheckStatus;
843 end;
844
845 function TFBUDRRoutineMetadata.getBody: AnsiString;
846 begin
847 Result := strpas(FRoutineMetadata.getBody(FStatus));
848 CheckStatus;
849 end;
850
851 function TFBUDRRoutineMetadata.HasInputMetadata: boolean;
852 begin
853 Result := FInputMetadata <> nil;
854 end;
855
856 function TFBUDRRoutineMetadata.HasOutputMetadata: boolean;
857 begin
858 Result := FOutputMetadata <> nil;
859 end;
860
861 function TFBUDRRoutineMetadata.HasTriggerMetadata: boolean;
862 begin
863 Result := FTriggerMetadata <> nil;
864 end;
865
866 function TFBUDRRoutineMetadata.getFBInputMetadata: IFBUDRMessageMetadata;
867 begin
868 Result := nil;
869 if (FFBInputMetadata = nil) and (FInputMetadata <> nil) then
870 FFBInputMetadata := TFBUDRMessageMetadata.Create(FContext,FInputMetadata);
871 Result := FFBInputMetadata;
872 end;
873
874 function TFBUDRRoutineMetadata.getFBOutputMetadata: IFBUDRMessageMetadata;
875 begin
876 Result := nil;
877 if (FFBOutputMetadata = nil) and (FOutputMetadata <> nil) then
878 FFBOutputMetadata := TFBUDRMessageMetadata.Create(FContext,FOutputMetadata);
879 Result := FFBOutputMetadata;
880 end;
881
882 function TFBUDRRoutineMetadata.getFBTriggerMetadata: IFBUDRMessageMetadata;
883 begin
884 Result := nil;
885 if (FFBTriggerMetadata = nil) and (FTriggerMetadata <> nil) then
886 FFBTriggerMetadata := TFBUDRMessageMetadata.Create(FContext,FTriggerMetadata);
887 Result := FFBTriggerMetadata;
888 end;
889
890 function TFBUDRRoutineMetadata.getInputMetadata: firebird.IMessageMetadata;
891 begin
892 Result := FInputMetaData;
893 if Result <> nil then
894 Result.addRef;
895 end;
896
897 function TFBUDRRoutineMetadata.getOutputMetadata: firebird.IMessageMetadata;
898 begin
899 Result := FOutputMetadata;
900 if Result <> nil then
901 Result.addRef;
902 end;
903
904 function TFBUDRRoutineMetadata.getTriggerMetadata: firebird.IMessageMetadata;
905 begin
906 Result := FTriggerMetadata;
907 if Result <> nil then
908 Result.addRef;
909 end;
910
911 function TFBUDRRoutineMetadata.getTriggerTable: AnsiString;
912 begin
913 Result := strpas(FRoutineMetadata.getTriggerTable(FStatus));
914 CheckStatus;
915 end;
916
917 function TFBUDRRoutineMetadata.getTriggerType: TFBUDRTriggerType;
918 var TriggerType: cardinal;
919 begin
920 TriggerType := FRoutineMetadata.getTriggerType(FStatus);
921 CheckStatus;
922 with Firebird.IExternalTrigger do
923 case TriggerType of
924 TYPE_BEFORE:
925 Result := ttBefore;
926 TYPE_AFTER:
927 Result := ttAfter;
928 TYPE_DATABASE:
929 Result := ttDatabase;
930 else
931 FBUDRError(ibxeUnknownTriggerType,[TriggerType]);
932 end;
933 end;
934
935 { EFBUDRException }
936
937 constructor EFBUDRException.Create(aStatus: Firebird.IStatus);
938 begin
939 inherited Create(SFirebirdStatusError);
940 FStatus := aStatus.clone;
941 end;
942
943 destructor EFBUDRException.Destroy;
944 begin
945 FStatus.dispose;
946 inherited Destroy;
947 end;
948
949 end.
950

Properties

Name Value
svn:eol-style native