ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/IB.pas
Revision: 45
Committed: Tue Dec 6 10:33:46 2016 UTC (7 years, 11 months ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/fbintf/IB.pas
File size: 45466 byte(s)
Log Message:
Committing updates for Release R2-0-0

File Contents

# User Rev Content
1 tony 45 (*
2     * Firebird Interface (fbintf). The fbintf components provide a set of
3     * Pascal language bindings for the Firebird API. Although predominantly
4     * a new development they include source code taken from IBX and may be
5     * considered a derived product. This software thus also includes the copyright
6     * notice and license conditions from IBX.
7     *
8     * Except for those parts dervied from IBX, contents of this file are subject
9     * to the Initial Developer's Public License Version 1.0 (the "License"); you
10     * may not use this file except in compliance with the License. You may obtain a
11     * copy of the License here:
12     *
13     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
14     *
15     * Software distributed under the License is distributed on an "AS
16     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17     * implied. See the License for the specific language governing rights
18     * and limitations under the License.
19     *
20     * The Initial Developer of the Original Code is Tony Whyman.
21     *
22     * The Original Code is (C) 2016 Tony Whyman, MWA Software
23     * (http://www.mwasoftware.co.uk).
24     *
25     * All Rights Reserved.
26     *
27     * Contributor(s): ______________________________________.
28     *
29     *)
30     {************************************************************************}
31     { }
32     { Borland Delphi Visual Component Library }
33     { InterBase Express core components }
34     { }
35     { Copyright (c) 1998-2000 Inprise Corporation }
36     { }
37     { InterBase Express is based in part on the product }
38     { Free IB Components, written by Gregory H. Deatz for }
39     { Hoagland, Longo, Moran, Dunst & Doukas Company. }
40     { Free IB Components is used under license. }
41     { }
42     { The contents of this file are subject to the InterBase }
43     { Public License Version 1.0 (the "License"); you may not }
44     { use this file except in compliance with the License. You }
45     { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
46     { Software distributed under the License is distributed on }
47     { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
48     { express or implied. See the License for the specific language }
49     { governing rights and limitations under the License. }
50     { The Original Code was created by InterBase Software Corporation }
51     { and its successors. }
52     { Portions created by Inprise Corporation are Copyright (C) Inprise }
53     { Corporation. All Rights Reserved. }
54     { Contributor(s): Jeff Overcash }
55     { }
56     { IBX For Lazarus (Firebird Express) }
57     { Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk }
58     { Portions created by MWA Software are copyright McCallum Whyman }
59     { Associates Ltd 2011 - 2015 }
60     { }
61     {************************************************************************}
62     unit IB;
63    
64     {$IFDEF FPC}
65     {$mode objfpc}{$H+}
66     {$codepage UTF8}
67     {$interfaces COM}
68     {$IF FPC_FULLVERSION < 30000 }
69     {$ERROR FPC Version 3.0.0 or later is required}
70     {$ENDIF}
71     {$ENDIF}
72    
73     {$DEFINE USEFIREBIRD3API}
74     {$DEFINE USELEGACYFIREBIRDAPI}
75    
76     {
77     This unit defines the interfaces used to provide the Pascal Language
78     bindings for the Firebird API. These are COM style references counted interfaces
79     and are automatically freed when they go out of scope.
80    
81     The interface definition is independent of the Firebird API version and two
82     implementations are provided. One is for the legacy API (2.5 and earlier) and the
83     other is for the new object orientated API (3.0 and later). By default, both are
84     available with the 3.0 API used if it is available. Otherwise the 2.5 API is used.
85     The above two defines can be used to force only one implementation by undefining
86     the symbol for the unwanted API.
87    
88     Note that the FirebirdAPI function defined below is used for initial access to
89     the language bindings.
90    
91     The goals of these Pascal Langauge bindings are to provide:
92    
93     1. A set of reference counted interfaces providing complete access to the Firebird API.
94    
95     2. Application Independence from the Firebird API version.
96    
97     3. All data access through strongly typed variables and functions with no need for
98     the end user to manipulate untyped data in buffers such as the legacy API SQLDA
99     or the Firebird 3.0 message buffer.
100    
101     4. A stable platform for LCL Packages (e.g. IBX) that implement the TDataSet model
102     with independence from the Firebird API version.
103    
104     5. Straightforward progammatic access to the Firebird API from Pascal programs.
105    
106     String Types
107     ============
108    
109     From FPC 3.0 onwards, ANSISTRINGs include the codepage in their definition. All
110     strings used by the interface are sensitive to the codepage in that the codepage
111     for all strings returned by an interface is consistent with the SQL Character set
112     used for the database connection. Input strings will be transliterated, where possible
113     and if necessary, to the codepage consistent with the character set used for
114     the database connection.
115     }
116    
117     interface
118    
119     uses
120     Classes, SysUtils, DB, FBMessages, IBExternals;
121    
122     {These include files are converted from the 'C' originals in the Firebird API
123     and define the various constants used by the API}
124    
125     {$I consts_pub.inc}
126     {$I inf_pub.inc}
127     {$I configkeys.inc}
128    
129     {The following constants define the values return by calls to the GetSQLType
130     methods provided by several of the interfaces defined below.}
131    
132     (*********************)
133     (** SQL definitions **)
134     (*********************)
135     SQL_VARYING = 448;
136     SQL_TEXT = 452;
137     SQL_DOUBLE = 480;
138     SQL_FLOAT = 482;
139     SQL_LONG = 496;
140     SQL_SHORT = 500;
141     SQL_TIMESTAMP = 510;
142     SQL_BLOB = 520;
143     SQL_D_FLOAT = 530;
144     SQL_ARRAY = 540;
145     SQL_QUAD = 550;
146     SQL_TYPE_TIME = 560;
147     SQL_TYPE_DATE = 570;
148     SQL_INT64 = 580;
149     SQL_BOOLEAN = 32764;
150     SQL_DATE = SQL_TIMESTAMP;
151    
152     type
153     TGDS_QUAD = record
154     gds_quad_high : ISC_LONG;
155     gds_quad_low : UISC_LONG;
156     end;
157     TGDS__QUAD = TGDS_QUAD;
158     TISC_QUAD = TGDS_QUAD;
159     PGDS_QUAD = ^TGDS_QUAD;
160     PGDS__QUAD = ^TGDS__QUAD;
161     PISC_QUAD = ^TISC_QUAD;
162    
163     TIBSQLStatementTypes =
164     (SQLUnknown, SQLSelect, SQLInsert,
165     SQLUpdate, SQLDelete, SQLDDL,
166     SQLGetSegment, SQLPutSegment,
167     SQLExecProcedure, SQLStartTransaction,
168     SQLCommit, SQLRollback,
169     SQLSelectForUpdate, SQLSetGenerator);
170    
171     TFBStatusCode = cardinal;
172     TByteArray = array of byte;
173    
174     IAttachment = interface;
175     ITransaction = interface;
176    
177     {The IParameterBlock generic interface provides the template for all parameter
178     block interfaces}
179    
180     generic IParameterBlock<_IItem> = interface
181     function getCount: integer;
182     function Add(ParamType: byte): _IItem;
183     function getItems(index: integer): _IItem;
184     function Find(ParamType: byte): _IItem;
185     procedure PrintBuf; {can be used to print buffer in hex for debugging}
186     property Count: integer read getCount;
187     property Items[index: integer]: _IItem read getItems; default;
188     end;
189    
190     {IParameterBlockItem is not used on its own but instead provides a base type for
191     different parameter block items }
192    
193     IParameterBlockItem = interface
194     function getParamType: byte;
195     function getAsInteger: integer;
196     function getAsString: string;
197     function getAsByte: byte;
198     procedure setAsString(aValue: string);
199     procedure setAsByte(aValue: byte);
200     procedure SetAsInteger(aValue: integer);
201     property AsString: string read getAsString write setAsString;
202     property AsByte: byte read getAsByte write setAsByte;
203     property AsInteger: integer read getAsInteger write SetAsInteger;
204     end;
205    
206    
207     {The IStatus interface provides access to error information, if any, returned
208     by the last API call. It can also be used to customise the error message
209     returned by a database engine exception - see EIBInterbaseError.
210    
211     This interface can be accessed from IFirebirdAPI.
212     }
213    
214     IStatus = interface
215     function GetIBErrorCode: Long;
216     function Getsqlcode: Long;
217     function GetMessage: string;
218     function CheckStatusVector(ErrorCodes: array of TFBStatusCode): Boolean;
219     function GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
220     procedure SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
221     end;
222    
223     { The array metadata interface provides access to the metadata used to describe
224     an array column in a Firebird table.
225     }
226    
227     TArrayBound = record
228     UpperBound: short;
229     LowerBound: short;
230     end;
231     TArrayBounds = array of TArrayBound;
232    
233     IArrayMetaData = interface
234     function GetSQLType: cardinal;
235     function GetSQLTypeName: string;
236     function GetScale: integer;
237     function GetSize: cardinal;
238     function GetCharSetID: cardinal;
239     function GetTableName: string;
240     function GetColumnName: string;
241     function GetDimensions: integer;
242     function GetBounds: TArrayBounds;
243     end;
244    
245     {The array interface provides access to and modification of the array data
246     contained in an array field of a Firebird Table. The array element is
247     selected by specifying its co-ordinates using an integer array. The
248     getter and setter methods used should be appropriate for the type of data
249     contained in the array. Automatic conversion is provided to and from strings.
250     That is GetAsString and SetAsString are safe to use for sql types other than
251     boolean.
252    
253     The interface is returned by a GetAsArray getter method (see ISQLData). A new array
254     can be obtained from the IAttachment interface. The SetAsArray setter method
255     (See ISQLParam) is used to apply an updated or new array to the database using
256     an UPDATE or INSERT statement.
257    
258     }
259    
260     TArrayEventReason = (arChanging,arChanged);
261     IArray = interface;
262     TArrayEventHandler = procedure(Sender: IArray; Reason: TArrayEventReason) of object;
263    
264     IArray = interface(IArrayMetaData)
265     function GetArrayID: TISC_QUAD;
266     procedure Clear;
267     function IsEmpty: boolean;
268     procedure PreLoad;
269     procedure CancelChanges;
270     procedure SaveChanges;
271     function GetAsInteger(index: array of integer): integer;
272     function GetAsBoolean(index: array of integer): boolean;
273     function GetAsCurrency(index: array of integer): Currency;
274     function GetAsInt64(index: array of integer): Int64;
275     function GetAsDateTime(index: array of integer): TDateTime;
276     function GetAsDouble(index: array of integer): Double;
277     function GetAsFloat(index: array of integer): Float;
278     function GetAsLong(index: array of integer): Long;
279     function GetAsShort(index: array of integer): Short;
280     function GetAsString(index: array of integer): String;
281     function GetAsVariant(index: array of integer): Variant;
282     procedure SetAsInteger(index: array of integer; AValue: integer);
283     procedure SetAsBoolean(index: array of integer; AValue: boolean);
284     procedure SetAsCurrency(index: array of integer; Value: Currency);
285     procedure SetAsInt64(index: array of integer; Value: Int64);
286     procedure SetAsDate(index: array of integer; Value: TDateTime);
287     procedure SetAsLong(index: array of integer; Value: Long);
288     procedure SetAsTime(index: array of integer; Value: TDateTime);
289     procedure SetAsDateTime(index: array of integer; Value: TDateTime);
290     procedure SetAsDouble(index: array of integer; Value: Double);
291     procedure SetAsFloat(index: array of integer; Value: Float);
292     procedure SetAsShort(index: array of integer; Value: Short);
293     procedure SetAsString(index: array of integer; Value: String);
294     procedure SetAsVariant(index: array of integer; Value: Variant);
295     procedure SetBounds(dim, UpperBound, LowerBound: integer);
296     function GetAttachment: IAttachment;
297     function GetTransaction: ITransaction;
298     procedure AddEventHandler(Handler: TArrayEventHandler);
299     procedure RemoveEventHandler(Handler: TArrayEventHandler);
300     end;
301    
302     { The Blob metadata interface provides access to the metadata used to describe
303     a blob column in a Firebird table.
304     }
305    
306     IBlobMetaData = interface
307     function GetSubType: integer;
308     function GetCharSetID: cardinal;
309     function GetCodePage: TSystemCodePage;
310     function GetSegmentSize: cardinal;
311     function GetRelationName: string;
312     function GetColumnName: string;
313     end;
314    
315     {The Blob Parameter block is used to select a Blob Filter}
316    
317     IBPBItem = interface (IParameterBlockItem) end;
318    
319     IBPB = specialize IParameterBlock<IBPBItem>;
320    
321     { The Blob Interface provides access to a blob data item.
322    
323     The interface is returned by a GetAsBlob getter method (see ISQLData). A new Blob
324     can be obtained from the IAttachment interface. The SetAsBlob setter method
325     (See ISQLParam) is used to apply an updated or new array to the database using
326     an UPDATE or INSERT statement.
327     }
328    
329     TFBBlobMode = (fbmRead,fbmWrite);
330     TBlobType = (btSegmented,btStream);
331    
332     IBlob = interface(IBlobMetaData)
333     function GetBPB: IBPB;
334     procedure Cancel;
335     procedure Close;
336     function GetBlobID: TISC_QUAD;
337     function GetBlobMode: TFBBlobMode;
338     function GetBlobSize: Int64;
339     procedure GetInfo(var NumSegments: Int64; var MaxSegmentSize,
340     TotalSize: Int64; var BlobType: TBlobType);
341     function Read(var Buffer; Count: Longint): Longint;
342     function Write(const Buffer; Count: Longint): Longint;
343     function LoadFromFile(Filename: string): IBlob;
344     function LoadFromStream(S: TStream) : IBlob;
345     function SaveToFile(Filename: string): IBlob;
346     function SaveToStream(S: TStream): IBlob;
347     function GetAsString: rawbytestring;
348     procedure SetAsString(aValue: rawbytestring);
349     function SetString(aValue: rawbytestring): IBlob;
350     function GetAttachment: IAttachment;
351     function GetTransaction: ITransaction;
352     property AsString: rawbytestring read GetAsString write SetAsString;
353     end;
354    
355     { The IColumnMetaData interface provides access to the per column metadata for
356     the output of an SQL Statement.
357     }
358    
359     { IColumnMetaData }
360    
361     IColumnMetaData = interface
362     function GetIndex: integer;
363     function GetSQLType: cardinal;
364     function GetSQLTypeName: string;
365     function getSubtype: integer;
366     function getRelationName: string;
367     function getOwnerName: string;
368     function getSQLName: string; {Name of the column}
369     function getAliasName: string; {Alias Name of column or Column Name if no alias}
370     function getName: string; {Disambiguated uppercase Field Name}
371     function getScale: integer;
372     function getCharSetID: cardinal;
373     function getCodePage: TSystemCodePage;
374     function getIsNullable: boolean;
375     function GetSize: cardinal;
376     function GetArrayMetaData: IArrayMetaData; {Valid only for Array SQL Type}
377     function GetBlobMetaData: IBlobMetaData; {Valid only for Blob SQL Type}
378     property Name: string read GetName;
379     property Size: cardinal read GetSize;
380     property SQLType: cardinal read GetSQLType;
381     property Scale: integer read getScale;
382     property SQLSubtype: integer read getSubtype;
383     property IsNullable: Boolean read GetIsNullable;
384     end;
385    
386     {
387     The IMetaData interface provides access to the set of column metadata
388     for the output of an SQL Statement
389     }
390    
391     { IMetaData }
392    
393     IMetaData = interface
394     function getCount: integer;
395     function getColumnMetaData(index: integer): IColumnMetaData;
396     function GetUniqueRelationName: string; {Non empty if all columns come from the same table}
397     function ByName(Idx: String): IColumnMetaData;
398     property ColMetaData[index: integer]: IColumnMetaData read getColumnMetaData; default;
399     property Count: integer read getCount;
400     end;
401    
402     {
403     The ISQLData interface provides access to the data returned in a field in the
404     current row returned from a query or the result of an SQL Execute statement.
405    
406     It subclasses IColumnMetaData and so also provides access to the metadata
407     associated with the column.
408    
409     The getter and setter methods, and the corresponding properties, provide typed
410     access to the field data. The method/property used should be consistent
411     with the SQL Type. Automatic conversion is provided from strings.
412     That is GetAsString is safe to use for sql types other than boolean.
413     }
414    
415    
416     ISQLData = interface(IColumnMetaData)
417     function GetAsBoolean: boolean;
418     function GetAsCurrency: Currency;
419     function GetAsInt64: Int64;
420     function GetAsDateTime: TDateTime;
421     function GetAsDouble: Double;
422     function GetAsFloat: Float;
423     function GetAsLong: Long;
424     function GetAsPointer: Pointer;
425     function GetAsQuad: TISC_QUAD;
426     function GetAsShort: short;
427     function GetAsString: String;
428     function GetIsNull: Boolean;
429     function GetAsVariant: Variant;
430     function GetAsBlob: IBlob; overload;
431     function GetAsBlob(BPB: IBPB): IBlob; overload;
432     function GetAsArray: IArray;
433     property AsDate: TDateTime read GetAsDateTime;
434     property AsBoolean:boolean read GetAsBoolean;
435     property AsTime: TDateTime read GetAsDateTime;
436     property AsDateTime: TDateTime read GetAsDateTime ;
437     property AsDouble: Double read GetAsDouble;
438     property AsFloat: Float read GetAsFloat;
439     property AsCurrency: Currency read GetAsCurrency;
440     property AsInt64: Int64 read GetAsInt64 ;
441     property AsInteger: Integer read GetAsLong;
442     property AsLong: Long read GetAsLong;
443     property AsPointer: Pointer read GetAsPointer;
444     property AsQuad: TISC_QUAD read GetAsQuad;
445     property AsShort: short read GetAsShort;
446     property AsString: String read GetAsString;
447     property AsVariant: Variant read GetAsVariant ;
448     property AsBlob: IBlob read GetAsBlob;
449     property AsArray: IArray read GetAsArray;
450     property IsNull: Boolean read GetIsNull;
451     property Value: Variant read GetAsVariant;
452     end;
453    
454     { An IResults interface is returned as the result of an SQL Execute statement
455     and provides access to the fields returned, if any. It is a collection of
456     ISQLData interfaces which are, in turn, used to access the data returned by
457     each field of the result set.
458     }
459    
460     IResults = interface
461     function getCount: integer;
462     function GetTransaction: ITransaction;
463     function ByName(Idx: String): ISQLData;
464     function getSQLData(index: integer): ISQLData;
465     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
466     procedure SetRetainInterfaces(aValue: boolean);
467     property Data[index: integer]: ISQLData read getSQLData; default;
468     property Count: integer read getCount;
469     end;
470    
471     { An IResultSet interface is returned as the result of an SQL Open Cursor statement
472     (e.g. Select Statement) and provides access to the fields returned, if any
473     for the current row. It is a collection of ISQLData interfaces which are,
474     in turn, used to access the data returned by each field of the current row.
475     }
476     IResultSet = interface(IResults)
477     function FetchNext: boolean;
478     function GetCursorName: string;
479     function IsEof: boolean;
480     procedure Close;
481     end;
482    
483     {The ISQLParam interface is used to provide access to each parameter in a
484     parametised SQL Statement. It subclasses IColumnMetaData and this part of
485     the interface may be used to access information on the expected SQL Type, etc.
486    
487     It also subclasses ISQLData and this part of the interface may be used to access
488     current values for each parameter.
489    
490     Otherwise, the interface comprises the Setter Methods and properties used to
491     set the value of each parameter.
492    
493     Automatic conversion is provided to and from strings. That is GetAsString and
494     SetAsString are safe to use for sql types other than boolean - provided automatic
495     conversion is possible.
496     }
497    
498     ISQLParam = interface
499     function GetIndex: integer;
500     function GetSQLType: cardinal;
501     function GetSQLTypeName: string;
502     function getSubtype: integer;
503     function getName: string;
504     function getScale: integer;
505     function getCharSetID: cardinal;
506     function getCodePage: TSystemCodePage;
507     function getIsNullable: boolean;
508     function GetSize: cardinal;
509     function GetAsBoolean: boolean;
510     function GetAsCurrency: Currency;
511     function GetAsInt64: Int64;
512     function GetAsDateTime: TDateTime;
513     function GetAsDouble: Double;
514     function GetAsFloat: Float;
515     function GetAsLong: Long;
516     function GetAsPointer: Pointer;
517     function GetAsQuad: TISC_QUAD;
518     function GetAsShort: short;
519     function GetAsString: String;
520     function GetIsNull: boolean;
521     function GetAsVariant: Variant;
522     function GetAsBlob: IBlob;
523     function GetAsArray: IArray;
524     procedure Clear;
525     function GetModified: boolean;
526     procedure SetAsBoolean(AValue: boolean);
527     procedure SetAsCurrency(aValue: Currency);
528     procedure SetAsInt64(aValue: Int64);
529     procedure SetAsDate(aValue: TDateTime);
530     procedure SetAsLong(aValue: Long);
531     procedure SetAsTime(aValue: TDateTime);
532     procedure SetAsDateTime(aValue: TDateTime);
533     procedure SetAsDouble(aValue: Double);
534     procedure SetAsFloat(aValue: Float);
535     procedure SetAsPointer(aValue: Pointer);
536     procedure SetAsShort(aValue: Short);
537     procedure SetAsString(aValue: String);
538     procedure SetAsVariant(aValue: Variant);
539     procedure SetIsNull(aValue: Boolean);
540     procedure SetAsBlob(aValue: IBlob);
541     procedure SetAsArray(anArray: IArray);
542     procedure SetAsQuad(aValue: TISC_QUAD);
543     procedure SetCharSetID(aValue: cardinal);
544     property AsDate: TDateTime read GetAsDateTime write SetAsDate;
545     property AsBoolean:boolean read GetAsBoolean write SetAsBoolean;
546     property AsTime: TDateTime read GetAsDateTime write SetAsTime;
547     property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
548     property AsDouble: Double read GetAsDouble write SetAsDouble;
549     property AsFloat: Float read GetAsFloat write SetAsFloat;
550     property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
551     property AsInt64: Int64 read GetAsInt64 write SetAsInt64;
552     property AsInteger: Integer read GetAsLong write SetAsLong;
553     property AsLong: Long read GetAsLong write SetAsLong;
554     property AsPointer: Pointer read GetAsPointer write SetAsPointer;
555     property AsShort: Short read GetAsShort write SetAsShort;
556     property AsString: String read GetAsString write SetAsString;
557     property AsVariant: Variant read GetAsVariant write SetAsVariant;
558     property AsBlob: IBlob read GetAsBlob write SetAsBlob;
559     property AsArray: IArray read GetAsArray write SetAsArray;
560     property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
561     property Value: Variant read GetAsVariant write SetAsVariant;
562     property IsNull: Boolean read GetIsNull write SetIsNull;
563     property IsNullable: Boolean read GetIsNullable;
564     property Modified: Boolean read getModified;
565     property Name: string read GetName;
566     property SQLType: cardinal read GetSQLType;
567     end;
568    
569     {
570     The ISQLParams interface provides access to the collection of parameters used
571     for the input to an SQL Statement
572     }
573    
574     ISQLParams = interface
575     function getCount: integer;
576     function getSQLParam(index: integer): ISQLParam;
577     function ByName(Idx: String): ISQLParam ;
578     function GetModified: Boolean;
579     property Modified: Boolean read GetModified;
580     property Params[index: integer]: ISQLParam read getSQLParam; default;
581     property Count: integer read getCount;
582     end;
583    
584     {The IStatement interface provides access to an SQL Statement once it has been
585     initially prepared. The interface is returned from the IAttachment interface.
586     }
587    
588     IStatement = interface
589     function GetMetaData: IMetaData; {Output Metadata}
590     function GetSQLParams: ISQLParams;{Statement Parameters}
591     function GetPlan: String;
592     function GetRowsAffected(var SelectCount, InsertCount, UpdateCount, DeleteCount: integer): boolean;
593     function GetSQLStatementType: TIBSQLStatementTypes;
594     function GetSQLText: string;
595     function GetSQLDialect: integer;
596     function IsPrepared: boolean;
597     procedure Prepare(aTransaction: ITransaction=nil);
598     function Execute(aTransaction: ITransaction=nil): IResults;
599     function OpenCursor(aTransaction: ITransaction=nil): IResultSet;
600     function GetAttachment: IAttachment;
601     function GetTransaction: ITransaction;
602     procedure SetRetainInterfaces(aValue: boolean);
603     property MetaData: IMetaData read GetMetaData;
604     property SQLParams: ISQLParams read GetSQLParams;
605     property SQLStatementType: TIBSQLStatementTypes read GetSQLStatementType;
606     end;
607    
608     {Transaction Parameter Block: (TPB)
609    
610     The TPB provides the parameters used when starting a transaction. It is allocated
611     empty by the FirebirdAPI and the parameters are then added to it. Each individual
612     parameter may be accessed by the ITPBItem interface which can be used to set the
613     value, if any, of the parameter.
614    
615     The TPB parameters, and the associated symbolic codes and parameter values may be
616     found in the Interbase 6.0 API Guide.
617     }
618    
619     ITPBItem = interface(IParameterBlockItem) end;
620    
621     ITPB = specialize IParameterBlock<ITPBItem>;
622    
623     {The ITransactionAction interface provides access to a Transaction once it
624     has been initially started. After a Commit or Rollback, a transaction
625     may be restarted, optinally with a new TPB.
626    
627     A multi-database transaction is started from the FirebirdAPI. A single database
628     transaction is started from the IAttachment interface.
629     }
630    
631     TTransactionAction = (TARollback, TACommit, TACommitRetaining, TARollbackRetaining);
632     TTransactionCompletion = TARollback.. TACommit;
633    
634     ITransaction = interface
635     function getTPB: ITPB;
636     procedure Start(DefaultCompletion: TTransactionCompletion=taCommit);
637     function GetInTransaction: boolean;
638     procedure PrepareForCommit; {Two phase commit - stage 1}
639     procedure Commit(Force: boolean=false);
640     procedure CommitRetaining;
641     function HasActivity: boolean;
642     procedure Rollback(Force: boolean=false);
643     procedure RollbackRetaining;
644     function GetAttachmentCount: integer;
645     function GetAttachment(index: integer): IAttachment;
646     property InTransaction: boolean read GetInTransaction;
647     end;
648    
649     { The IEvents Interface is used to handle events from a single database. The
650     interface is allocated from the IAttachment Interface.
651    
652     Note that the EventHandler called when an event occurs following AsynWaitForEvent
653     is called in a different thread to the calling program and TThread.Synchronize
654     may be needed to pass the event back to the main thread.
655    
656     Neither AsyncWaitForEvent nor WaitForEvent is intended to be thread safe
657     in a multi-threaded environment and should always be called from the main
658     thread.
659     }
660    
661     TEventInfo = record
662     EventName: string;
663     Count: integer;
664     end;
665    
666     TEventCounts = array of TEventInfo;
667     IEvents = interface;
668     TEventHandler = procedure(Sender: IEvents) of object;
669    
670     { IEvents }
671    
672     IEvents = interface
673     procedure GetEvents(EventNames: TStrings);
674     procedure SetEvents(EventNames: TStrings); overload;
675     procedure SetEvents(EventName: string); overload;
676     procedure Cancel;
677     function ExtractEventCounts: TEventCounts;
678     procedure WaitForEvent;
679     procedure AsyncWaitForEvent(EventHandler: TEventHandler);
680     function GetAttachment: IAttachment;
681     end;
682    
683     {The IDBInformation Interface.
684    
685     An IDBInformation interface is returned by the IAttachment GetDBInformation
686     method. The interface provides access to the information requested and
687     returned by the method.
688    
689     IDBInformation itself gives access to a collection of IDBInfoItems. Each one
690     provides information requested, as indicated by the ItemType and the actual
691     value of the information. In some cases, the returned item is itself a
692     colletion of IDBInfoItems.
693    
694     The IDBInformation items, and the associated symbolic codes and parameter values may be
695     found in the Interbase 6.0 API Guide.
696     }
697    
698     TDBOperationCount = record
699     TableID: UShort;
700     Count: cardinal;
701     end;
702    
703     TDBOperationCounts = array of TDBOperationCount;
704    
705     IDBInfoItem = interface
706     function getItemType: byte;
707     function getSize: integer;
708     procedure getRawBytes(var Buffer);
709     function getAsString: string;
710     function getAsInteger: integer;
711     procedure DecodeIDCluster(var ConnectionType: integer; var DBFileName, DBSiteName: string);
712     function getAsBytes: TByteArray;
713     procedure DecodeVersionString(var Version: byte; var VersionString: string);
714     function getOperationCounts: TDBOperationCounts;
715     procedure DecodeUserNames(UserNames: TStrings);
716    
717     {user names only}
718     function GetCount: integer;
719     function GetItem(index: integer): IDBInfoItem;
720     function Find(ItemType: byte): IDBInfoItem;
721     property AsInteger: integer read getAsInteger;
722     property AsString: string read GetAsString;
723     property Count: integer read GetCount;
724     property Items[index: integer]: IDBInfoItem read getItem; default;
725     end;
726    
727     { IDBInformation }
728    
729     IDBInformation = interface
730     function GetCount: integer;
731     function GetItem(index: integer): IDBInfoItem;
732     function Find(ItemType: byte): IDBInfoItem;
733     procedure PrintBuf; {can be used to print buffer in hex for debugging}
734     property Count: integer read GetCount;
735     property Items[index: integer]: IDBInfoItem read getItem; default;
736     end;
737    
738     {The Database Parameter Block (DPB).
739    
740     The DPB provides the parameters used when connecting to a database. It is allocated
741     empty by the FirebirdAPI and the parameters are then added to it. Each individual
742     parameter may be accessed by the IDPBItem interface which can be used to set the
743     value, if any, of the parameter.
744    
745     The DPB parameters, and the associated symbolic codes and parameter values may be
746     found in the Interbase 6.0 API Guide.
747     }
748    
749     IDPBItem = interface(IParameterBlockItem) end;
750    
751     IDPB = specialize IParameterBlock<IDPBItem>;
752    
753     {The IAttachment interface provides access to a Database Connection. It may be
754     used to:
755    
756     a. Disconnect and reconnect to the database.
757    
758     b. Start a Transaction on the database
759    
760     c. Execute directly SQL DDL Statements and others that return no information.
761    
762     d. OpenCursors (i.e. execute SQL Select statements and return the results)
763    
764     e. Prepare SQL Statements, returning an IStatement interface for further processing.
765    
766     f. Provide access to an SQL Event Handler.
767    
768     g. Access Database Information.
769    
770     h. Support the handling of Array and Blob data.
771    
772     Note that SQL statements can be prepared with named parameters (PSQL style).
773     This then allows the parameters to be accessed by name. The same name can
774     be used for more than one parameter, allowing a single operation to be used
775     to set all parameters with the same name.
776     }
777    
778     { IAttachment }
779    
780     IAttachment = interface
781     function getDPB: IDPB;
782     function AllocateBPB: IBPB;
783     procedure Connect;
784     procedure Disconnect(Force: boolean=false);
785     function IsConnected: boolean;
786     procedure DropDatabase;
787     function StartTransaction(TPB: array of byte; DefaultCompletion: TTransactionCompletion=taCommit): ITransaction; overload;
788     function StartTransaction(TPB: ITPB; DefaultCompletion: TTransactionCompletion=taCommit): ITransaction; overload;
789     procedure ExecImmediate(transaction: ITransaction; sql: string; SQLDialect: integer); overload;
790     procedure ExecImmediate(TPB: array of byte; sql: string; SQLDialect: integer); overload;
791     procedure ExecImmediate(transaction: ITransaction; sql: string); overload;
792     procedure ExecImmediate(TPB: array of byte; sql: string); overload;
793     function ExecuteSQL(TPB: array of byte; sql: string; SQLDialect: integer; params: array of const): IResults; overload;
794     function ExecuteSQL(transaction: ITransaction; sql: string; SQLDialect: integer; params: array of const): IResults; overload;
795     function ExecuteSQL(TPB: array of byte; sql: string; params: array of const): IResults; overload;
796     function ExecuteSQL(transaction: ITransaction; sql: string; params: array of const): IResults; overload;
797     function OpenCursor(transaction: ITransaction; sql: string; aSQLDialect: integer): IResultSet; overload;
798     function OpenCursor(transaction: ITransaction; sql: string; aSQLDialect: integer;
799     params: array of const): IResultSet; overload;
800     function OpenCursor(transaction: ITransaction; sql: string): IResultSet; overload;
801     function OpenCursor(transaction: ITransaction; sql: string;
802     params: array of const): IResultSet; overload;
803     function OpenCursorAtStart(transaction: ITransaction; sql: string; aSQLDialect: integer): IResultSet; overload;
804     function OpenCursorAtStart(transaction: ITransaction; sql: string; aSQLDialect: integer;
805     params: array of const): IResultSet; overload;
806     function OpenCursorAtStart(transaction: ITransaction; sql: string): IResultSet; overload;
807     function OpenCursorAtStart(transaction: ITransaction; sql: string;
808     params: array of const): IResultSet; overload;
809     function OpenCursorAtStart(sql: string): IResultSet; overload;
810     function OpenCursorAtStart(sql: string;
811     params: array of const): IResultSet; overload;
812     function Prepare(transaction: ITransaction; sql: string; aSQLDialect: integer): IStatement; overload;
813     function Prepare(transaction: ITransaction; sql: string): IStatement; overload;
814     function PrepareWithNamedParameters(transaction: ITransaction; sql: string;
815     aSQLDialect: integer; GenerateParamNames: boolean=false): IStatement; overload;
816     function PrepareWithNamedParameters(transaction: ITransaction; sql: string;
817     GenerateParamNames: boolean=false): IStatement; overload;
818    
819     {Events}
820     function GetEventHandler(Events: TStrings): IEvents; overload;
821     function GetEventHandler(Event: string): IEvents; overload;
822    
823     {Blob - may use to open existing Blobs. However, ISQLData.AsBlob is preferred}
824    
825     function CreateBlob(transaction: ITransaction; RelationName, ColumnName: string; BPB: IBPB=nil): IBlob; overload;
826     function CreateBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BPB: IBPB=nil): IBlob; overload;
827     function CreateBlob(transaction: ITransaction; SubType: integer; CharSetID: cardinal=0; BPB: IBPB=nil): IBlob; overload;
828     function OpenBlob(transaction: ITransaction; RelationName, ColumnName: string; BlobID: TISC_QUAD; BPB: IBPB=nil): IBlob;
829    
830     {Array - may use to open existing arrays. However, ISQLData.AsArray is preferred}
831    
832     function OpenArray(transaction: ITransaction; RelationName, ColumnName: string; ArrayID: TISC_QUAD): IArray;
833     function CreateArray(transaction: ITransaction; RelationName, ColumnName: string): IArray; overload;
834     function CreateArray(transaction: ITransaction; ArrayMetaData: IArrayMetaData): IArray; overload;
835    
836     {Database Information}
837     function GetSQLDialect: integer;
838     function GetBlobMetaData(Transaction: ITransaction; tableName, columnName: string): IBlobMetaData;
839     function GetArrayMetaData(Transaction: ITransaction; tableName, columnName: string): IArrayMetaData;
840     function GetDBInformation(Requests: array of byte): IDBInformation; overload;
841     function GetDBInformation(Request: byte): IDBInformation; overload;
842     function HasActivity: boolean;
843     end;
844    
845     TProtocol = (TCP, SPX, NamedPipe, Local);
846    
847     {Service Parameter Block (SPB).
848    
849     The SPB provides the parameters used when connecting to a Service Manager. It is
850     allocated empty by the FirebirdAPI and the parameters are then added to it. Each
851     individual parameter may be accessed by the ISPBItem interface which can be used
852     to set the value, if any, of the parameter.
853    
854     The SPB parameters, and the associated symbolic codes and parameter values may be
855     found in the Interbase 6.0 API Guide.
856    
857     }
858    
859     ISPBItem = interface(IParameterBlockItem) end;
860    
861     ISPB = specialize IParameterBlock<ISPBItem>;
862    
863     {Service Query Parameter Block (SQPB).
864    
865     This is a specialised parameter block used to send data to a service manager
866     in a Query Request.
867     }
868    
869     ISQPBItem = interface(IParameterBlockItem)
870     function CopyFrom(source: TStream; count: integer): integer;
871     end;
872    
873     ISQPB = specialize IParameterBlock<ISQPBItem>;
874    
875     {Service Request Block (SRB).
876    
877     The SRB specifies what is requested from the Service Manager when starting a
878     service or querying a service. It is allocated empty by the ServiceManager API and
879     the parameters are then added to it. Each individual parameter may be accessed
880     by the ISRBItem interface which can be used to set the value, if any, of the parameter.
881    
882     The SRB parameters, and the associated symbolic codes and parameter values may be
883     found in the Interbase 6.0 API Guide.
884    
885     }
886    
887     ISRBItem = interface(IParameterBlockItem) end;
888    
889     ISRB = specialize IParameterBlock<ISRBItem>;
890    
891     {The Service Query Results Interface.
892    
893     An IServiceQueryResults interface is returned by the IServiceManager Query
894     method. The interface provides access to the information requested and
895     returned by the method.
896    
897     IServiceQueryResults itself gives access to a collection of IServiceQueryResultItem.
898     Each one provides information requested, as indicated by the ItemType and the actual
899     value of the information. In some cases, the returned item is itself a
900     collection of IServiceQueryResultSubItem.
901    
902     The IServiceQueryResultItem items, and the associated symbolic codes and parameter values may be
903     found in the Interbase 6.0 API Guide.
904     }
905    
906     IServiceQueryResultSubItem = interface
907     function getItemType: byte;
908     function getSize: integer;
909     procedure getRawBytes(var Buffer);
910     function getAsString: string;
911     function getAsInteger: integer;
912     function getAsByte: byte;
913     function CopyTo(stream: TStream; count: integer): integer;
914     property AsString: string read getAsString;
915     property AsInteger: integer read getAsInteger;
916     property AsByte: byte read getAsByte;
917     end;
918    
919     IServiceQueryResultItem = interface(IServiceQueryResultSubItem)
920     function getCount: integer;
921     function getItem(index: integer): IServiceQueryResultSubItem;
922     function find(ItemType: byte): IServiceQueryResultSubItem;
923     property Items[index: integer]: IServiceQueryResultSubItem read getItem; default;
924     property Count: integer read getCount;
925     end;
926    
927     IServiceQueryResults = interface
928     function getCount: integer;
929     function getItem(index: integer): IServiceQueryResultItem;
930     function find(ItemType: byte): IServiceQueryResultItem;
931     procedure PrintBuf; {can be used to print buffer in hex for debugging}
932     property Items[index: integer]: IServiceQueryResultItem read getItem; default;
933     property Count: integer read getCount;
934     end;
935    
936     {The IServiceManager interface provides access to a service manager. It can
937     used to Detach and re-attach to Service Manager, to start services and to
938     query the service manager.
939    
940     The interface is returned by the FirebirdAPI GetService Manager method.
941     }
942    
943     { IServiceManager }
944    
945     IServiceManager = interface
946     function getSPB: ISPB;
947     function getServerName: string;
948     procedure Attach;
949     procedure Detach(Force: boolean=false);
950     function IsAttached: boolean;
951     function AllocateSRB: ISRB;
952     function AllocateSQPB: ISQPB;
953     procedure Start(Request: ISRB);
954     function Query(SQPB: ISQPB; Request: ISRB) :IServiceQueryResults; overload;
955     function Query(Request: ISRB) :IServiceQueryResults; overload;
956     end;
957    
958     {The Firebird API.
959    
960     This is the base interface and is used to create/open a database connection, to
961     start a transaction on multiple databases and the access the service manager.
962    
963     The interface is returned by the FirebirdAPI function.
964     }
965    
966     IFirebirdAPI = interface
967     {Database connections}
968     function AllocateDPB: IDPB;
969     function OpenDatabase(DatabaseName: string; DPB: IDPB; RaiseExceptionOnConnectError: boolean=true): IAttachment;
970     function CreateDatabase(DatabaseName: string; DPB: IDPB; RaiseExceptionOnError: boolean=true): IAttachment;
971    
972     {Start Transaction against multiple databases}
973     function AllocateTPB: ITPB;
974     function StartTransaction(Attachments: array of IAttachment;
975     TPB: array of byte; DefaultCompletion: TTransactionCompletion=taCommit): ITransaction; overload;
976     function StartTransaction(Attachments: array of IAttachment;
977     TPB: ITPB; DefaultCompletion: TTransactionCompletion=taCommit): ITransaction; overload;
978    
979     {Service Manager}
980     function HasServiceAPI: boolean;
981     function AllocateSPB: ISPB;
982     function GetServiceManager(ServerName: string; Protocol: TProtocol; SPB: ISPB): IServiceManager;
983    
984     {Information}
985     function GetStatus: IStatus;
986     function GetLibraryName: string;
987     function HasRollbackRetaining: boolean;
988     function IsEmbeddedServer: boolean;
989     function GetImplementationVersion: string;
990    
991     {Firebird 3 API}
992     function HasMasterIntf: boolean;
993     function GetIMaster: TObject;
994    
995     {utility}
996     function GetCharsetName(CharSetID: integer): string;
997     function CharSetID2CodePage(CharSetID: integer; var CodePage: TSystemCodePage): boolean;
998     function CodePage2CharSetID(CodePage: TSystemCodePage; var CharSetID: integer): boolean;
999     function CharSetName2CharSetID(CharSetName: string; var CharSetID: integer): boolean;
1000     function CharSetWidth(CharSetID: integer; var Width: integer): boolean;
1001     end;
1002    
1003     type
1004     TOnGetLibraryName = procedure(var libname: string);
1005    
1006     const
1007     OnGetLibraryName: TOnGetLibraryName = nil;
1008     AllowUseOfFBLIB: boolean = false;
1009    
1010     type
1011     { EIBError }
1012    
1013     EIBError = class(EDatabaseError)
1014     private
1015     FSQLCode: Long;
1016     public
1017     constructor Create(ASQLCode: Long; Msg: string);
1018     property SQLCode: Long read FSQLCode;
1019     end;
1020    
1021     { EIBInterBaseError - Firebird Engine errors}
1022    
1023     EIBInterBaseError = class(EIBError)
1024     private
1025     FIBErrorCode: Long;
1026     public
1027     constructor Create(Status: IStatus); overload;
1028     constructor Create(ASQLCode: Long; AIBErrorCode: Long; Msg: string); overload;
1029     property IBErrorCode: Long read FIBErrorCode;
1030     end;
1031    
1032     {IB Client Exceptions}
1033     EIBClientError = class(EIBError);
1034    
1035     {IBError is used internally and by IBX to throw an EIBClientError}
1036    
1037     procedure IBError(ErrMess: TIBClientError; const Args: array of const);
1038    
1039     {The Firebird API function is used to access the IFirebirdAPI interface.
1040    
1041     It will load the Firebird Client Library if this is not already loaded and
1042     select an implementation of the Firebird API (legacy 2.5 or 3.0.
1043     }
1044    
1045     function FirebirdAPI: IFirebirdAPI;
1046    
1047     {IBX support functions. Probably best ignored i.e. always used the FirebirdAPI
1048     functino to load the library and check if it's loaded.}
1049    
1050     function TryIBLoad: Boolean;
1051     procedure CheckIBLoaded;
1052    
1053     implementation
1054    
1055     uses FBClientAPI
1056     {$IFDEF USELEGACYFIREBIRDAPI}, FB25ClientAPI {$ENDIF}
1057     {$IFDEF USEFIREBIRD3API}, FB30ClientAPI {$ENDIF};
1058    
1059     var FFirebirdAPI: IFirebirdAPI;
1060    
1061     function FirebirdAPI: IFirebirdAPI;
1062     begin
1063     if FFirebirdAPI = nil then
1064     CheckIBLoaded;
1065     Result := FFirebirdAPI;
1066     end;
1067    
1068     function TryIBLoad: Boolean;
1069     begin
1070     Result := FFirebirdAPI <> nil;
1071     try
1072     {$IFDEF USEFIREBIRD3API}
1073     if not Result then
1074     begin
1075     FFirebirdAPI := TFB30ClientAPI.Create;
1076     Result := FFirebirdAPI.HasMasterIntf;
1077     end;
1078     {$ENDIF}
1079     {$IFDEF USELEGACYFIREBIRDAPI}
1080     if not Result then
1081     begin
1082     FFirebirdAPI := nil;
1083     FFirebirdAPI := TFB25ClientAPI.Create;
1084     Result := true;
1085     end;
1086     {$ENDIF}
1087     if Result and not (FFirebirdAPI as TFBClientAPI).IsLibraryLoaded then
1088     begin
1089     Result := false;
1090     FFirebirdAPI := nil;
1091     end;
1092     except
1093     SysUtils.showexception(ExceptObject,ExceptAddr);
1094     Result := false;
1095     end;
1096     end;
1097    
1098     procedure CheckIBLoaded;
1099     begin
1100     if not TryIBLoad then
1101     IBError(ibxeInterBaseMissing, [nil]);
1102     end;
1103    
1104     { EIBError }
1105    
1106     constructor EIBError.Create(ASQLCode: Long; Msg: string);
1107     begin
1108     inherited Create(Msg);
1109     FSQLCode := ASQLCode;
1110     end;
1111    
1112     { EIBInterBaseError }
1113    
1114     constructor EIBInterBaseError.Create(Status: IStatus);
1115     begin
1116     inherited Create(Status.Getsqlcode,Status.GetMessage);
1117     FIBErrorCode := Status.GetIBErrorCode;
1118     end;
1119    
1120     constructor EIBInterBaseError.Create(ASQLCode: Long; AIBErrorCode: Long;
1121     Msg: string);
1122     begin
1123     inherited Create(ASQLCode,Msg);
1124     FIBErrorCode := AIBErrorCode;
1125     end;
1126    
1127     procedure IBError(ErrMess: TIBClientError; const Args: array of const);
1128     begin
1129     raise EIBClientError.Create(Ord(ErrMess),
1130     Format(GetErrorMessage(ErrMess), Args));
1131     end;
1132    
1133     initialization
1134     FFirebirdAPI := nil;
1135    
1136    
1137     end.
1138