ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBSQLData.pas
Revision: 372
Committed: Wed Jan 5 16:20:22 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 92729 byte(s)
Log Message:
string overflow fix

File Contents

# Content
1 (*
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 FBSQLData;
63 {$IFDEF MSWINDOWS}
64 {$DEFINE WINDOWS}
65 {$ENDIF}
66
67 {$IFDEF FPC}
68 {$mode delphi}
69 {$codepage UTF8}
70 {$interfaces COM}
71 {$ENDIF}
72
73 { This Unit was hacked out of the IBSQL unit and defines a class used as the
74 base for interfaces accessing SQLDAVar data and Array Elements. The abstract
75 methods are used to customise for an SQLDAVar or Array Element. The empty
76 methods are needed for SQL parameters only. The string getters and setters
77 are virtual as SQLVar and Array encodings of string data is different.}
78
79
80 interface
81
82 uses
83 Classes, SysUtils, IBExternals, {$IFDEF WINDOWS} Windows, {$ENDIF} IB, FBActivityMonitor, FBClientAPI,
84 FmtBCD;
85
86 type
87
88 {The IExTimeZoneServices is only available in FB4 and onwards}
89
90 IExTimeZoneServices = interface(ITimeZoneServices)
91 ['{789c2eeb-c4a7-4fed-837e-0cbdef775904}']
92 {encode/decode - used to encode/decode the wire protocol}
93 procedure EncodeTimestampTZ(timestamp: TDateTime; timezoneID: TFBTimeZoneID;
94 bufptr: PByte); overload;
95 procedure EncodeTimestampTZ(timestamp: TDateTime; timezone: AnsiString;
96 bufptr: PByte); overload;
97 procedure EncodeTimeTZ(time: TDateTime; timezoneID: TFBTimeZoneID; OnDate: TDateTime;
98 bufptr: PByte); overload;
99 procedure EncodeTimeTZ(time: TDateTime; timezone: AnsiString; OnDate: TDateTime;
100 bufptr: PByte); overload;
101 procedure DecodeTimestampTZ(bufptr: PByte; var timestamp: TDateTime;
102 var dstOffset: smallint; var timezoneID: TFBTimeZoneID); overload;
103 procedure DecodeTimestampTZ(bufptr: PByte; var timestamp: TDateTime;
104 var dstOffset: smallint; var timezone: AnsiString); overload;
105 procedure DecodeTimestampTZEx(bufptr: PByte; var timestamp: TDateTime;
106 var dstOffset: smallint; var timezoneID: TFBTimeZoneID); overload;
107 procedure DecodeTimestampTZEx(bufptr: PByte; var timestamp: TDateTime;
108 var dstOffset: smallint; var timezone: AnsiString); overload;
109 procedure DecodeTimeTZ(bufptr: PByte; OnDate: TDateTime; var time: TDateTime;
110 var dstOffset: smallint; var timezoneID: TFBTimeZoneID); overload;
111 procedure DecodeTimeTZ(bufptr: PByte; OnDate: TDateTime; var time: TDateTime;
112 var dstOffset: smallint; var timezone: AnsiString); overload;
113 procedure DecodeTimeTZEx(bufptr: PByte; OnDate: TDateTime; var time: TDateTime;
114 var dstOffset: smallint; var timezoneID: TFBTimeZoneID); overload;
115 procedure DecodeTimeTZEx(bufptr: PByte; OnDate: TDateTime; var time: TDateTime;
116 var dstOffset: smallint; var timezone: AnsiString); overload;
117 end;
118
119 { TSQLDataItem }
120
121 TSQLDataItem = class(TFBInterfacedObject)
122 private
123 FFirebirdClientAPI: TFBClientAPI;
124 FTimeZoneServices: IExTimeZoneServices;
125 function GetDateFormatStr(IncludeTime: boolean): AnsiString;
126 function GetTimeFormatStr: AnsiString;
127 function GetTimestampFormatStr: AnsiString;
128 procedure SetAsInteger(AValue: Integer);
129 procedure InternalGetAsDateTime(var aDateTime: TDateTime; var dstOffset: smallint;
130 var aTimezone: AnsiString; var aTimeZoneID: TFBTimeZoneID);
131 protected
132 procedure CheckActive; virtual;
133 procedure CheckTZSupport;
134 function GetAttachment: IAttachment; virtual; abstract;
135 function GetTransaction: ITransaction; virtual; abstract;
136 function GetSQLDialect: integer; virtual; abstract;
137 function GetTimeZoneServices: IExTimeZoneServices; virtual;
138 procedure Changed; virtual;
139 procedure Changing; virtual;
140 procedure InternalSetAsString(Value: AnsiString); virtual;
141 function SQLData: PByte; virtual; abstract;
142 function GetDataLength: cardinal; virtual; abstract;
143 function GetCodePage: TSystemCodePage; virtual; abstract;
144 function getCharSetID: cardinal; virtual; abstract;
145 function Transliterate(s: AnsiString; CodePage: TSystemCodePage): RawByteString;
146 procedure SetScale(aValue: integer); virtual;
147 procedure SetDataLength(len: cardinal); virtual;
148 procedure SetSQLType(aValue: cardinal); virtual;
149 property DataLength: cardinal read GetDataLength write SetDataLength;
150 property FirebirdClientAPI: TFBClientAPI read FFirebirdClientAPI;
151 public
152 constructor Create(api: TFBClientAPI);
153 function CanChangeMetaData: boolean; virtual;
154 function GetSQLType: cardinal; virtual; abstract; {Current Field Data SQL Type}
155 function GetSQLTypeName: AnsiString; overload;
156 class function GetSQLTypeName(SQLType: cardinal): AnsiString; overload;
157 function GetStrDataLength: short;
158 function getColMetadata: IParamMetaData; virtual; abstract;
159 function GetName: AnsiString; virtual; abstract;
160 function GetScale: integer; virtual; abstract; {Current Field Data scale}
161 function GetAsBoolean: boolean;
162 function GetAsCurrency: Currency;
163 function GetAsInt64: Int64;
164 function GetAsDateTime: TDateTime; overload;
165 procedure GetAsDateTime(var aDateTime: TDateTime; var dstOffset: smallint; var aTimezone: AnsiString); overload;
166 procedure GetAsDateTime(var aDateTime: TDateTime; var dstOffset: smallint; var aTimezoneID: TFBTimeZoneID); overload;
167 procedure GetAsTime(var aTime: TDateTime; var dstOffset: smallint; var aTimezoneID: TFBTimeZoneID; OnDate: TDateTime); overload;
168 procedure GetAsTime(var aTime: TDateTime; var dstOffset: smallint; var aTimezone: AnsiString; OnDate: TDateTime); overload;
169 procedure GetAsTime(var aTime: TDateTime; var dstOffset: smallint; var aTimezoneID: TFBTimeZoneID); overload;
170 procedure GetAsTime(var aTime: TDateTime; var dstOffset: smallint; var aTimezone: AnsiString); overload;
171 function GetAsUTCDateTime: TDateTime;
172 function GetAsDouble: Double;
173 function GetAsFloat: Float;
174 function GetAsLong: Long;
175 function GetAsPointer: Pointer;
176 function GetAsQuad: TISC_QUAD;
177 function GetAsShort: short;
178 function GetAsString: AnsiString; virtual;
179 function GetAsNumeric: IFBNumeric;
180 function GetIsNull: Boolean; virtual;
181 function GetIsNullable: boolean; virtual;
182 function GetAsVariant: Variant;
183 function GetModified: boolean; virtual;
184 function GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats): integer;
185 function GetAsBCD: tBCD;
186 function GetSize: cardinal; virtual; abstract;
187 function GetCharSetWidth: integer; virtual; abstract;
188 procedure SetAsBoolean(AValue: boolean); virtual;
189 procedure SetAsCurrency(Value: Currency); virtual;
190 procedure SetAsInt64(Value: Int64); virtual;
191 procedure SetAsDate(Value: TDateTime); virtual;
192 procedure SetAsLong(Value: Long); virtual;
193 procedure SetAsTime(Value: TDateTime); overload;
194 procedure SetAsTime(aValue: TDateTime; OnDate: TDateTime;aTimeZoneID: TFBTimeZoneID); overload;
195 procedure SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZone: AnsiString); overload;
196 procedure SetAsDateTime(Value: TDateTime); overload;
197 procedure SetAsDateTime(aValue: TDateTime; aTimeZoneID: TFBTimeZoneID); overload;
198 procedure SetAsDateTime(aValue: TDateTime; aTimeZone: AnsiString); overload;
199 procedure SetAsUTCDateTime(aUTCTime: TDateTime);
200 procedure SetAsDouble(Value: Double); virtual;
201 procedure SetAsFloat(Value: Float); virtual;
202 procedure SetAsPointer(Value: Pointer);
203 procedure SetAsQuad(Value: TISC_QUAD);
204 procedure SetAsShort(Value: short); virtual;
205 procedure SetAsString(Value: AnsiString); virtual;
206 procedure SetAsVariant(Value: Variant);
207 procedure SetAsNumeric(Value: IFBNumeric); virtual;
208 procedure SetAsBcd(aValue: tBCD); virtual;
209 procedure SetIsNull(Value: Boolean); virtual;
210 procedure SetIsNullable(Value: Boolean); virtual;
211 procedure SetName(aValue: AnsiString); virtual;
212 property AsDate: TDateTime read GetAsDateTime write SetAsDate;
213 property AsBoolean:boolean read GetAsBoolean write SetAsBoolean;
214 property AsTime: TDateTime read GetAsDateTime write SetAsTime;
215 property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
216 property AsDouble: Double read GetAsDouble write SetAsDouble;
217 property AsFloat: Float read GetAsFloat write SetAsFloat;
218 property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
219 property AsInt64: Int64 read GetAsInt64 write SetAsInt64;
220 property AsInteger: Integer read GetAsLong write SetAsInteger;
221 property AsLong: Long read GetAsLong write SetAsLong;
222 property AsPointer: Pointer read GetAsPointer write SetAsPointer;
223 property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
224 property AsShort: short read GetAsShort write SetAsShort;
225 property AsString: AnsiString read GetAsString write SetAsString;
226 property AsVariant: Variant read GetAsVariant write SetAsVariant;
227 property Modified: Boolean read getModified;
228 property IsNull: Boolean read GetIsNull write SetIsNull;
229 property IsNullable: Boolean read GetIsNullable write SetIsNullable;
230 property Scale: integer read GetScale write SetScale;
231 property SQLType: cardinal read GetSQLType write SetSQLType;
232 end;
233
234 TSQLVarData = class;
235
236 TStatementStatus = (ssPrepared, ssExecuteResults, ssCursorOpen, ssBOF, ssEOF);
237
238 { TSQLDataArea }
239
240 TSQLDataArea = class
241 private
242 FCaseSensitiveParams: boolean;
243 function GetColumn(index: integer): TSQLVarData;
244 function GetCount: integer;
245 protected
246 FUniqueRelationName: AnsiString;
247 FColumnList: array of TSQLVarData;
248 function GetStatement: IStatement; virtual; abstract;
249 function GetAttachment: IAttachment; virtual;
250 function GetTransaction: ITransaction; virtual;
251 function GetPrepareSeqNo: integer; virtual; abstract;
252 function GetTransactionSeqNo: integer; virtual; abstract;
253 procedure SetCount(aValue: integer); virtual; abstract;
254 procedure SetUniqueRelationName;
255 public
256 procedure Initialize; virtual;
257 function IsInputDataArea: boolean; virtual; abstract; {Input to Database}
258 procedure PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
259 var sProcessedSQL: AnsiString);
260 function ColumnsInUseCount: integer; virtual;
261 function ColumnByName(Idx: AnsiString): TSQLVarData;
262 function CheckStatementStatus(Request: TStatementStatus): boolean; virtual; abstract;
263 procedure GetData(index: integer; var IsNull: boolean; var len: short;
264 var data: PByte); virtual;
265 procedure RowChange;
266 function StateChanged(var ChangeSeqNo: integer): boolean; virtual; abstract;
267 property CaseSensitiveParams: boolean read FCaseSensitiveParams
268 write FCaseSensitiveParams; {Only used when IsInputDataArea true}
269 function CanChangeMetaData: boolean; virtual; abstract;
270 property Count: integer read GetCount;
271 property Column[index: integer]: TSQLVarData read GetColumn; default;
272 property UniqueRelationName: AnsiString read FUniqueRelationName;
273 property Statement: IStatement read GetStatement;
274 property Attachment: IAttachment read GetAttachment;
275 property PrepareSeqNo: integer read GetPrepareSeqNo;
276 property Transaction: ITransaction read GetTransaction;
277 property TransactionSeqNo: integer read GetTransactionSeqNo;
278 end;
279
280 { TSQLVarData }
281
282 TSQLVarData = class
283 private
284 FParent: TSQLDataArea;
285 FName: AnsiString;
286 FIndex: integer;
287 FModified: boolean;
288 FUniqueName: boolean;
289 FVarString: RawByteString;
290 FColMetaData: IParamMetaData;
291 function GetStatement: IStatement;
292 procedure SetName(AValue: AnsiString);
293 protected
294 FArrayIntf: IArray;
295 function GetAttachment: IAttachment;
296 function GetTransaction: ITransaction;
297 function GetSQLType: cardinal; virtual; abstract;
298 function GetSubtype: integer; virtual; abstract;
299 function GetAliasName: AnsiString; virtual; abstract;
300 function GetFieldName: AnsiString; virtual; abstract;
301 function GetOwnerName: AnsiString; virtual; abstract;
302 function GetRelationName: AnsiString; virtual; abstract;
303 function GetScale: integer; virtual; abstract;
304 function GetCharSetID: cardinal; virtual; abstract;
305 function GetCharSetWidth: integer;
306 function GetCodePage: TSystemCodePage;
307 function GetIsNull: Boolean; virtual; abstract;
308 function GetIsNullable: boolean; virtual; abstract;
309 function GetSQLData: PByte; virtual; abstract;
310 function GetDataLength: cardinal; virtual; abstract; {current field length}
311 function GetSize: cardinal; virtual; abstract; {field length as given by metadata}
312 function GetDefaultTextSQLType: cardinal; virtual; abstract;
313 procedure InternalSetSQLType(aValue: cardinal); virtual; abstract;
314 procedure InternalSetScale(aValue: integer); virtual; abstract;
315 procedure InternalSetDataLength(len: cardinal); virtual; abstract;
316 procedure SetIsNull(Value: Boolean); virtual; abstract;
317 procedure SetIsNullable(Value: Boolean); virtual; abstract;
318 procedure SetSQLData(AValue: PByte; len: cardinal); virtual; abstract;
319 procedure SetScale(aValue: integer);
320 procedure SetDataLength(len: cardinal);
321 procedure SetSQLType(aValue: cardinal);
322 procedure SetCharSetID(aValue: cardinal); virtual; abstract;
323 procedure SetMetaSize(aValue: cardinal); virtual;
324 public
325 constructor Create(aParent: TSQLDataArea; aIndex: integer);
326 function CanChangeMetaData: boolean;
327 procedure SetString(aValue: AnsiString);
328 procedure Changed; virtual;
329 procedure RowChange; virtual;
330 function GetAsArray: IArray; virtual; abstract;
331 function GetAsBlob(Blob_ID: TISC_QUAD; BPB: IBPB): IBlob; virtual; abstract;
332 function CreateBlob: IBlob; virtual; abstract;
333 function GetArrayMetaData: IArrayMetaData; virtual; abstract;
334 function GetBlobMetaData: IBlobMetaData; virtual; abstract;
335 function getColMetadata: IParamMetaData;
336 procedure Initialize; virtual;
337 procedure SaveMetaData;
338 procedure SetArray(AValue: IArray);
339
340 public
341 property AliasName: AnsiString read GetAliasName;
342 property FieldName: AnsiString read GetFieldName;
343 property OwnerName: AnsiString read GetOwnerName;
344 property RelationName: AnsiString read GetRelationName;
345 property Parent: TSQLDataArea read FParent;
346 property Index: integer read FIndex;
347 property Name: AnsiString read FName write SetName;
348 property CharSetID: cardinal read GetCharSetID write SetCharSetID;
349 property CodePage: TSystemCodePage read GetCodePage;
350 property SQLType: cardinal read GetSQLType write SetSQLType;
351 property SQLSubtype: integer read GetSubtype;
352 property SQLData: PByte read GetSQLData;
353 property DataLength: cardinal read GetDataLength write SetDataLength;
354 property IsNull: Boolean read GetIsNull write SetIsNull;
355 property IsNullable: Boolean read GetIsNullable write SetIsNullable;
356 property Scale: integer read GetScale write SetScale;
357 public
358 property Modified: Boolean read FModified;
359 property Statement: IStatement read GetStatement;
360 property UniqueName: boolean read FUniqueName write FUniqueName;
361 end;
362
363 { TColumnMetaData }
364
365 TColumnMetaData = class(TSQLDataItem,IColumnMetaData,IParamMetaData)
366 private
367 FIBXSQLVAR: TSQLVarData;
368 FOwner: IUnknown; {Keep reference to ensure Metadata/statement not discarded}
369 FPrepareSeqNo: integer;
370 FChangeSeqNo: integer;
371 protected
372 procedure CheckActive; override;
373 function SQLData: PByte; override;
374 function GetDataLength: cardinal; override;
375 function GetCodePage: TSystemCodePage; override;
376
377 public
378 constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
379 destructor Destroy; override;
380 function GetSQLDialect: integer; override;
381 function getColMetadata: IParamMetaData; override;
382
383 public
384 {IColumnMetaData}
385 function GetIndex: integer;
386 function GetSQLType: cardinal; override;
387 function getSubtype: integer;
388 function getRelationName: AnsiString;
389 function getOwnerName: AnsiString;
390 function getSQLName: AnsiString; {Name of the column}
391 function getAliasName: AnsiString; {Alias Name of column or Column Name if not alias}
392 function GetName: AnsiString; override; {Disambiguated uppercase Field Name}
393 function GetScale: integer; override;
394 function getCharSetID: cardinal; override;
395 function GetIsNullable: boolean; override;
396 function GetSize: cardinal; override;
397 function GetCharSetWidth: integer; override;
398 function GetArrayMetaData: IArrayMetaData;
399 function GetBlobMetaData: IBlobMetaData;
400 function GetStatement: IStatement;
401 function GetTransaction: ITransaction; override;
402 function GetAttachment: IAttachment; override;
403 property Name: AnsiString read GetName;
404 property Size: cardinal read GetSize;
405 property CharSetID: cardinal read getCharSetID;
406 property SQLSubtype: integer read getSubtype;
407 property IsNullable: Boolean read GetIsNullable;
408 public
409 property Statement: IStatement read GetStatement;
410 end;
411
412 { TIBSQLData }
413
414 TIBSQLData = class(TColumnMetaData,ISQLData)
415 protected
416 procedure CheckActive; override;
417 public
418 function GetIsNull: Boolean; override;
419 function GetAsArray: IArray;
420 function GetAsBlob: IBlob; overload;
421 function GetAsBlob(BPB: IBPB): IBlob; overload;
422 function GetAsString: AnsiString; override;
423 property AsBlob: IBlob read GetAsBlob;
424 end;
425
426 { TSQLParamMetaData }
427
428 TSQLParamMetaData = class(TFBInterfacedObject,IParamMetaData)
429 private
430 FSQLType: cardinal;
431 FSQLSubType: integer;
432 FScale: integer;
433 FCharSetID: cardinal;
434 FNullable: boolean;
435 FSize: cardinal;
436 FCodePage: TSystemCodePage;
437 public
438 constructor Create(src: TSQLVarData);
439 {IParamMetaData}
440 function GetSQLType: cardinal;
441 function GetSQLTypeName: AnsiString;
442 function getSubtype: integer;
443 function getScale: integer;
444 function getCharSetID: cardinal;
445 function getCodePage: TSystemCodePage;
446 function getIsNullable: boolean;
447 function GetSize: cardinal;
448 property SQLType: cardinal read GetSQLType;
449 end;
450
451 { TSQLParam }
452
453 TSQLParam = class(TIBSQLData,ISQLParam,ISQLData)
454 protected
455 procedure CheckActive; override;
456 procedure Changed; override;
457 procedure InternalSetAsString(Value: AnsiString); override;
458 procedure SetScale(aValue: integer); override;
459 procedure SetDataLength(len: cardinal); override;
460 procedure SetSQLType(aValue: cardinal); override;
461 public
462 procedure Clear;
463 function CanChangeMetaData: boolean; override;
464 function getColMetadata: IParamMetaData; override;
465 function GetModified: boolean; override;
466 function GetAsPointer: Pointer;
467 function GetAsString: AnsiString; override;
468 procedure SetName(Value: AnsiString); override;
469 procedure SetIsNull(Value: Boolean); override;
470 procedure SetIsNullable(Value: Boolean); override;
471 procedure SetAsArray(anArray: IArray);
472
473 {overrides}
474 procedure SetAsBoolean(AValue: boolean);
475 procedure SetAsCurrency(AValue: Currency);
476 procedure SetAsInt64(AValue: Int64);
477 procedure SetAsDate(AValue: TDateTime);
478 procedure SetAsLong(AValue: Long);
479 procedure SetAsTime(AValue: TDateTime); overload;
480 procedure SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZoneID: TFBTimeZoneID); overload;
481 procedure SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZone: AnsiString); overload;
482 procedure SetAsTime(aValue: TDateTime; aTimeZoneID: TFBTimeZoneID); overload;
483 procedure SetAsTime(aValue: TDateTime; aTimeZone: AnsiString); overload;
484 procedure SetAsDateTime(AValue: TDateTime); overload;
485 procedure SetAsDateTime(aValue: TDateTime; aTimeZoneID: TFBTimeZoneID); overload;
486 procedure SetAsDateTime(aValue: TDateTime; aTimeZone: AnsiString); overload;
487 procedure SetAsDouble(AValue: Double);
488 procedure SetAsFloat(AValue: Float);
489 procedure SetAsPointer(AValue: Pointer);
490 procedure SetAsShort(AValue: Short);
491 procedure SetAsString(AValue: AnsiString); override;
492 procedure SetAsVariant(AValue: Variant);
493 procedure SetAsBlob(aValue: IBlob);
494 procedure SetAsQuad(AValue: TISC_QUAD);
495 procedure SetCharSetID(aValue: cardinal);
496 procedure SetAsBcd(aValue: tBCD);
497 procedure SetAsNumeric(aValue: IFBNumeric);
498
499 property AsBlob: IBlob read GetAsBlob write SetAsBlob;
500 property IsNullable: Boolean read GetIsNullable write SetIsNullable;
501 end;
502
503 { TMetaData }
504
505 TMetaData = class(TInterfaceOwner,IMetaData)
506 private
507 FPrepareSeqNo: integer;
508 FMetaData: TSQLDataArea;
509 FStatement: IStatement; {ensure FStatement not destroyed until no longer needed}
510 procedure CheckActive;
511 public
512 constructor Create(aMetaData: TSQLDataArea);
513 destructor Destroy; override;
514 public
515 {IMetaData}
516 function GetUniqueRelationName: AnsiString;
517 function getCount: integer;
518 function getColumnMetaData(index: integer): IColumnMetaData;
519 function ByName(Idx: AnsiString): IColumnMetaData;
520 end;
521
522 { TSQLParams }
523
524 TSQLParams = class(TInterfaceOwner,ISQLParams)
525 private
526 FPrepareSeqNo: integer;
527 FChangeSeqNo: integer;
528 FSQLParams: TSQLDataArea;
529 FStatement: IStatement; {ensure FStatement not destroyed until no longer needed}
530 procedure CheckActive;
531 public
532 constructor Create(aSQLParams: TSQLDataArea);
533 destructor Destroy; override;
534 public
535 {ISQLParams}
536 function getCount: integer;
537 function getSQLParam(index: integer): ISQLParam;
538 function ByName(Idx: AnsiString): ISQLParam ;
539 function GetModified: Boolean;
540 function GetHasCaseSensitiveParams: Boolean;
541 function GetStatement: IStatement;
542 function GetTransaction: ITransaction;
543 function GetAttachment: IAttachment;
544 procedure Clear;
545 end;
546
547 { TResults }
548
549 TResults = class(TInterfaceOwner,IResults)
550 private
551 FPrepareSeqNo: integer;
552 FTransactionSeqNo: integer;
553 FChangeSeqNo: integer;
554 FResults: TSQLDataArea;
555 FStatement: IStatement; {ensure FStatement not destroyed until no longer needed}
556 function GetISQLData(aIBXSQLVAR: TSQLVarData): ISQLData;
557 protected
558 procedure CheckActive;
559 public
560 constructor Create(aResults: TSQLDataArea);
561 {IResults}
562 function getCount: integer;
563 function ByName(Idx: AnsiString): ISQLData;
564 function getSQLData(index: integer): ISQLData;
565 procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PByte);
566 function GetStatement: IStatement;
567 function GetTransaction: ITransaction;
568 function GetAttachment: IAttachment;
569 procedure SetRetainInterfaces(aValue: boolean);
570 end;
571
572 implementation
573
574 uses FBMessages, variants, IBUtils, FBTransaction, FBNumeric, DateUtils;
575
576 { TSQLParamMetaData }
577
578 constructor TSQLParamMetaData.Create(src: TSQLVarData);
579 begin
580 inherited Create;
581 FSQLType := src.GetSQLType;
582 FSQLSubType := src.getSubtype;
583 FScale := src.GetScale;
584 FCharSetID := src.getCharSetID;
585 FNullable := src.GetIsNullable;
586 FSize := src.GetSize;
587 FCodePage := src.GetCodePage;
588 end;
589
590 function TSQLParamMetaData.GetSQLType: cardinal;
591 begin
592 Result := FSQLType;
593 end;
594
595 function TSQLParamMetaData.GetSQLTypeName: AnsiString;
596 begin
597 Result := TSQLDataItem.GetSQLTypeName(FSQLType);
598 end;
599
600 function TSQLParamMetaData.getSubtype: integer;
601 begin
602 Result := FSQLSubType;
603 end;
604
605 function TSQLParamMetaData.getScale: integer;
606 begin
607 Result := FScale;
608 end;
609
610 function TSQLParamMetaData.getCharSetID: cardinal;
611 begin
612 Result := FCharSetID;
613 end;
614
615 function TSQLParamMetaData.getCodePage: TSystemCodePage;
616 begin
617 Result := FCodePage;
618 end;
619
620 function TSQLParamMetaData.getIsNullable: boolean;
621 begin
622 Result := FNullable;
623 end;
624
625 function TSQLParamMetaData.GetSize: cardinal;
626 begin
627 Result := FSize;
628 end;
629
630 { TSQLDataArea }
631
632 function TSQLDataArea.GetColumn(index: integer): TSQLVarData;
633 begin
634 if (index < 0) or (index >= Count) then
635 IBError(ibxeInvalidColumnIndex,[nil]);
636 Result := FColumnList[index];
637 end;
638
639 function TSQLDataArea.GetCount: integer;
640 begin
641 Result := Length(FColumnList);
642 end;
643
644 function TSQLDataArea.GetTransaction: ITransaction;
645 begin
646 Result := GetStatement.GetTransaction;
647 end;
648
649 function TSQLDataArea.GetAttachment: IAttachment;
650 begin
651 Result := GetStatement.GetAttachment;
652 end;
653
654 procedure TSQLDataArea.SetUniqueRelationName;
655 var
656 i: Integer;
657 bUnique: Boolean;
658 RelationName: AnsiString;
659 begin
660 bUnique := True;
661 for i := 0 to ColumnsInUseCount - 1 do
662 begin
663 RelationName := Column[i].RelationName;
664
665 {First get the unique relation name, if any}
666
667 if bUnique and (RelationName <> '') then
668 begin
669 if FUniqueRelationName = '' then
670 FUniqueRelationName := RelationName
671 else
672 if RelationName <> FUniqueRelationName then
673 begin
674 FUniqueRelationName := '';
675 bUnique := False;
676 end;
677 end;
678 end;
679 end;
680
681 procedure TSQLDataArea.Initialize;
682 var
683 i: Integer;
684 begin
685 for i := 0 to ColumnsInUseCount - 1 do
686 Column[i].Initialize;
687 end;
688
689 procedure TSQLDataArea.PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
690 var sProcessedSQL: AnsiString);
691
692 var slNames: TStrings;
693
694 procedure SetColumnNames(slNames: TStrings);
695 var i, j: integer;
696 found: boolean;
697 begin
698 found := false;
699 SetCount(slNames.Count);
700 for i := 0 to slNames.Count - 1 do
701 begin
702 Column[i].Name := slNames[i];
703 Column[i].UniqueName := (slNames.Objects[i] <> nil);
704 end;
705 for i := 0 to Count - 1 do
706 begin
707 if not Column[i].UniqueName then
708 begin
709 found := false;
710 for j := i + 1 to Count - 1 do
711 if Column[i].Name = Column[j].Name then
712 begin
713 found := true;
714 break;
715 end;
716 Column[i].UniqueName := not found;
717 end;
718 end;
719 end;
720
721 begin
722 if not IsInputDataArea then
723 IBError(ibxeNotPermitted,[nil]);
724
725 slNames := TStringList.Create;
726 try
727 sProcessedSQL := TSQLParamProcessor.Execute(sSQL,GenerateParamNames,slNames);
728 SetColumnNames(slNames);
729 finally
730 slNames.Free;
731 end;
732 end;
733
734 function TSQLDataArea.ColumnsInUseCount: integer;
735 begin
736 Result := Count;
737 end;
738
739 function TSQLDataArea.ColumnByName(Idx: AnsiString): TSQLVarData;
740 var
741 s: AnsiString;
742 i: Integer;
743 begin
744 if not IsInputDataArea or not CaseSensitiveParams then
745 s := AnsiUpperCase(Idx)
746 else
747 s := Idx;
748
749 for i := 0 to Count - 1 do
750 if Column[i].Name = s then
751 begin
752 Result := Column[i];
753 Exit;
754 end;
755 Result := nil;
756 end;
757
758 procedure TSQLDataArea.GetData(index: integer; var IsNull: boolean;
759 var len: short; var data: PByte);
760 begin
761 //Do Nothing
762 end;
763
764 procedure TSQLDataArea.RowChange;
765 var i: integer;
766 begin
767 for i := 0 to Count - 1 do
768 Column[i].RowChange;
769 end;
770
771 {TSQLVarData}
772
773 function TSQLVarData.GetStatement: IStatement;
774 begin
775 Result := FParent.Statement;
776 end;
777
778 procedure TSQLVarData.SetName(AValue: AnsiString);
779 begin
780 if not Parent.IsInputDataArea or not Parent.CaseSensitiveParams then
781 FName := AnsiUpperCase(AValue)
782 else
783 FName := AValue;
784 end;
785
786 function TSQLVarData.GetAttachment: IAttachment;
787 begin
788 Result := Parent.Attachment;
789 end;
790
791 function TSQLVarData.GetTransaction: ITransaction;
792 begin
793 Result := Parent.Transaction;
794 end;
795
796 function TSQLVarData.GetCharSetWidth: integer;
797 begin
798 result := 1;
799 GetAttachment.CharSetWidth(GetCharSetID,result);
800 end;
801
802 function TSQLVarData.GetCodePage: TSystemCodePage;
803 begin
804 result := CP_NONE;
805 GetAttachment.CharSetID2CodePage(GetCharSetID,result);
806 end;
807
808 procedure TSQLVarData.SetScale(aValue: integer);
809 begin
810 if aValue = Scale then
811 Exit;
812 if not CanChangeMetaData then
813 IBError(ibxeScaleCannotBeChanged,[]);
814 InternalSetScale(aValue);
815 end;
816
817 procedure TSQLVarData.SetDataLength(len: cardinal);
818 begin
819 if len = DataLength then
820 Exit;
821 InternalSetDataLength(len);
822 end;
823
824 procedure TSQLVarData.SetSQLType(aValue: cardinal);
825 begin
826 if aValue = SQLType then
827 Exit;
828 if not CanChangeMetaData then
829 IBError(ibxeSQLTypeUnchangeable,[TSQLDataItem.GetSQLTypeName(SQLType),
830 TSQLDataItem.GetSQLTypeName(aValue)]);
831 InternalSetSQLType(aValue);
832 end;
833
834 procedure TSQLVarData.SetMetaSize(aValue: cardinal);
835 begin
836 //Ignore
837 end;
838
839 procedure TSQLVarData.SaveMetaData;
840 begin
841 FColMetaData := TSQLParamMetaData.Create(self);
842 end;
843
844 procedure TSQLVarData.SetArray(AValue: IArray);
845 begin
846 FArrayIntf := AValue;
847 end;
848
849 constructor TSQLVarData.Create(aParent: TSQLDataArea; aIndex: integer);
850 begin
851 inherited Create;
852 FParent := aParent;
853 FIndex := aIndex;
854 FUniqueName := true;
855 end;
856
857 function TSQLVarData.CanChangeMetaData: boolean;
858 begin
859 Result := Parent.CanChangeMetaData;
860 end;
861
862 procedure TSQLVarData.SetString(aValue: AnsiString);
863 begin
864 {we take full advantage here of reference counted strings. When setting a string
865 value, a reference is kept in FVarString and a pointer to it placed in the
866 SQLVar. This avoids string copies. Note that PAnsiChar is guaranteed to point to
867 a zero byte when the string is empty, neatly avoiding a nil pointer error.}
868
869 FVarString := aValue;
870 if SQLType = SQL_BLOB then
871 SetMetaSize(GetAttachment.GetInlineBlobLimit);
872 if CanChangeMetaData then
873 SQLType := GetDefaultTextSQLType
874 else
875 if Length(aValue) > DataLength then
876 IBError(ibxeStringOverflow,[Length(aValue),DataLength]);
877 Scale := 0;
878 if (SQLType <> SQL_VARYING) and (SQLType <> SQL_TEXT) then
879 IBError(ibxeUnableTosetaTextType,[Index,Name,TSQLDataItem.GetSQLTypeName(SQLType)]);
880 SetSQLData(PByte(PAnsiChar(FVarString)),Length(aValue));
881 end;
882
883 procedure TSQLVarData.Changed;
884 begin
885 FModified := true;
886 end;
887
888 procedure TSQLVarData.RowChange;
889 begin
890 FArrayIntf := nil;
891 FModified := false;
892 FVarString := '';
893 end;
894
895 function TSQLVarData.getColMetadata: IParamMetaData;
896 begin
897 Result := FColMetaData;
898 end;
899
900 procedure TSQLVarData.Initialize;
901
902 function FindVarByName(idx: AnsiString; limit: integer): TSQLVarData;
903 var
904 k: integer;
905 begin
906 for k := 0 to limit do
907 if Parent.Column[k].Name = idx then
908 begin
909 Result := Parent.Column[k];
910 Exit;
911 end;
912 Result := nil;
913 end;
914
915 var
916 j, j_len: Integer;
917 st: AnsiString;
918 sBaseName: AnsiString;
919 begin
920 RowChange;
921
922 {If an output SQLDA then copy the aliasname to the FName. Ensure
923 that they are all upper case only and disambiguated.
924 }
925
926 if not Parent.IsInputDataArea then
927 begin
928 st := Space2Underscore(AnsiUppercase(AliasName));
929 if st = '' then
930 begin
931 sBaseName := 'F_'; {do not localize}
932 j := 1; j_len := 1;
933 st := sBaseName + IntToStr(j);
934 end
935 else
936 begin
937 j := 0; j_len := 0;
938 sBaseName := st;
939 end;
940
941 {Look for other columns with the same name and make unique}
942
943 while FindVarByName(st,Index-1) <> nil do
944 begin
945 Inc(j);
946 j_len := Length(IntToStr(j));
947 if j_len + Length(sBaseName) > 31 then
948 st := system.Copy(sBaseName, 1, 31 - j_len) + IntToStr(j)
949 else
950 st := sBaseName + IntToStr(j);
951 end;
952
953 Name := st;
954 end;
955 end;
956
957 {TSQLDataItem}
958
959 function TSQLDataItem.GetDateFormatStr(IncludeTime: boolean): AnsiString;
960 begin
961 {$IF declared(DefaultFormatSettings)}
962 with DefaultFormatSettings do
963 {$ELSE}
964 {$IF declared(FormatSettings)}
965 with FormatSettings do
966 {$IFEND}
967 {$IFEND}
968 case GetSQLDialect of
969 1:
970 if IncludeTime then
971 result := ShortDateFormat + ' ' + LongTimeFormat
972 else
973 result := ShortDateFormat;
974 3:
975 result := ShortDateFormat;
976 end;
977 end;
978
979 function TSQLDataItem.GetTimeFormatStr: AnsiString;
980 begin
981 {$IF declared(DefaultFormatSettings)}
982 with DefaultFormatSettings do
983 {$ELSE}
984 {$IF declared(FormatSettings)}
985 with FormatSettings do
986 {$IFEND}
987 {$IFEND}
988 Result := 'hh' + TimeSeparator + 'nn' + TimeSeparator + 'ss' + '.zzzz';;
989 end;
990
991 function TSQLDataItem.GetTimestampFormatStr: AnsiString;
992 begin
993 {$IF declared(DefaultFormatSettings)}
994 with DefaultFormatSettings do
995 {$ELSE}
996 {$IF declared(FormatSettings)}
997 with FormatSettings do
998 {$IFEND}
999 {$IFEND}
1000 Result := ShortDateFormat + ' ' + 'hh' + TimeSeparator + 'nn' + TimeSeparator + 'ss' + '.zzzz';
1001 end;
1002
1003 procedure TSQLDataItem.SetAsInteger(AValue: Integer);
1004 begin
1005 SetAsLong(aValue);
1006 end;
1007
1008 procedure TSQLDataItem.InternalGetAsDateTime(var aDateTime: TDateTime;
1009 var dstOffset: smallint; var aTimezone: AnsiString;
1010 var aTimeZoneID: TFBTimeZoneID);
1011 begin
1012 CheckActive;
1013 aDateTime := 0;
1014 dstOffset := 0;
1015 aTimezone := '';
1016 aTimeZoneID := TimeZoneID_GMT;
1017 if not IsNull then
1018 with FFirebirdClientAPI do
1019 case SQLType of
1020 SQL_TEXT, SQL_VARYING:
1021 if not ParseDateTimeTZString(AsString,aDateTime,aTimeZone) then
1022 IBError(ibxeInvalidDataConversion, [nil]);
1023 SQL_TYPE_DATE:
1024 aDateTime := SQLDecodeDate(SQLData);
1025 SQL_TYPE_TIME:
1026 aDateTime := SQLDecodeTime(SQLData);
1027 SQL_TIMESTAMP:
1028 aDateTime := SQLDecodeDateTime(SQLData);
1029 SQL_TIMESTAMP_TZ:
1030 begin
1031 GetTimeZoneServices.DecodeTimestampTZ(SQLData,aDateTime,dstOffset,aTimeZone);
1032 aTimeZoneID := PISC_TIMESTAMP_TZ(SQLData)^.time_zone;
1033 end;
1034 SQL_TIMESTAMP_TZ_EX:
1035 begin
1036 GetTimeZoneServices.DecodeTimestampTZEx(SQLData,aDateTime,dstOffset,aTimeZone);
1037 aTimeZoneID := PISC_TIMESTAMP_TZ_EX(SQLData)^.time_zone;
1038 end;
1039 SQL_TIME_TZ:
1040 with GetTimeZoneServices do
1041 begin
1042 DecodeTimeTZ(SQLData,GetTimeTZDate,aDateTime,dstOffset,aTimeZone);
1043 aTimeZoneID := PISC_TIME_TZ(SQLData)^.time_zone;
1044 end;
1045 SQL_TIME_TZ_EX:
1046 with GetTimeZoneServices do
1047 begin
1048 DecodeTimeTZEx(SQLData,GetTimeTZDate,aDateTime,dstOffset,aTimeZone);
1049 aTimeZoneID := PISC_TIME_TZ_EX(SQLData)^.time_zone;
1050 end;
1051 else
1052 IBError(ibxeInvalidDataConversion, [nil]);
1053 end;
1054 end;
1055
1056 procedure TSQLDataItem.CheckActive;
1057 begin
1058 //Do nothing by default
1059 end;
1060
1061 procedure TSQLDataItem.CheckTZSupport;
1062 begin
1063 if not FFirebirdClientAPI.HasTimeZoneSupport then
1064 IBError(ibxeNoTimezoneSupport,[]);
1065 end;
1066
1067 function TSQLDataItem.GetTimeZoneServices: IExTimeZoneServices;
1068 begin
1069 if FTimeZoneServices = nil then
1070 begin
1071 if not GetAttachment.HasTimeZoneSupport then
1072 IBError(ibxeNoTimezoneSupport,[]);
1073 GetAttachment.GetTimeZoneServices.QueryInterface(IExTimeZoneServices,FTimeZoneServices);
1074 end;
1075 Result := FTimeZoneServices;
1076 end;
1077
1078 procedure TSQLDataItem.Changed;
1079 begin
1080 //Do nothing by default
1081 end;
1082
1083 procedure TSQLDataItem.Changing;
1084 begin
1085 //Do nothing by default
1086 end;
1087
1088 procedure TSQLDataItem.InternalSetAsString(Value: AnsiString);
1089 begin
1090 //Do nothing by default
1091 end;
1092
1093 function TSQLDataItem.Transliterate(s: AnsiString; CodePage: TSystemCodePage
1094 ): RawByteString;
1095 begin
1096 Result := s;
1097 if StringCodePage(Result) <> CodePage then
1098 SetCodePage(Result,CodePage,CodePage <> CP_NONE);
1099 end;
1100
1101 procedure TSQLDataItem.SetScale(aValue: integer);
1102 begin
1103 //Do nothing by default
1104 end;
1105
1106 procedure TSQLDataItem.SetDataLength(len: cardinal);
1107 begin
1108 //Do nothing by default
1109 end;
1110
1111 procedure TSQLDataItem.SetSQLType(aValue: cardinal);
1112 begin
1113 //Do nothing by default
1114 end;
1115
1116 constructor TSQLDataItem.Create(api: TFBClientAPI);
1117 begin
1118 inherited Create;
1119 FFirebirdClientAPI := api;
1120 end;
1121
1122 function TSQLDataItem.CanChangeMetaData: boolean;
1123 begin
1124 Result := false;
1125 end;
1126
1127 function TSQLDataItem.GetSQLTypeName: AnsiString;
1128 begin
1129 Result := GetSQLTypeName(GetSQLType);
1130 end;
1131
1132 class function TSQLDataItem.GetSQLTypeName(SQLType: cardinal): AnsiString;
1133 begin
1134 Result := 'Unknown';
1135 case SQLType of
1136 SQL_VARYING: Result := 'SQL_VARYING';
1137 SQL_TEXT: Result := 'SQL_TEXT';
1138 SQL_DOUBLE: Result := 'SQL_DOUBLE';
1139 SQL_FLOAT: Result := 'SQL_FLOAT';
1140 SQL_LONG: Result := 'SQL_LONG';
1141 SQL_SHORT: Result := 'SQL_SHORT';
1142 SQL_TIMESTAMP: Result := 'SQL_TIMESTAMP';
1143 SQL_TIMESTAMP_TZ: Result := 'SQL_TIMESTAMP_TZ';
1144 SQL_TIMESTAMP_TZ_EX: Result := 'SQL_TIMESTAMP_TZ_EX';
1145 SQL_BLOB: Result := 'SQL_BLOB';
1146 SQL_D_FLOAT: Result := 'SQL_D_FLOAT';
1147 SQL_ARRAY: Result := 'SQL_ARRAY';
1148 SQL_QUAD: Result := 'SQL_QUAD';
1149 SQL_TYPE_TIME: Result := 'SQL_TYPE_TIME';
1150 SQL_TYPE_DATE: Result := 'SQL_TYPE_DATE';
1151 SQL_INT64: Result := 'SQL_INT64';
1152 SQL_TIME_TZ: Result := 'SQL_TIME_TZ';
1153 SQL_TIME_TZ_EX: Result := 'SQL_TIME_TZ_EX';
1154 SQL_DEC_FIXED: Result := 'SQL_DEC_FIXED';
1155 SQL_DEC16: Result := 'SQL_DEC16';
1156 SQL_DEC34: Result := 'SQL_DEC34';
1157 SQL_INT128: Result := 'SQL_INT128';
1158 SQL_NULL: Result := 'SQL_NULL';
1159 SQL_BOOLEAN: Result := 'SQL_BOOLEAN';
1160 end;
1161 end;
1162
1163 function TSQLDataItem.GetStrDataLength: short;
1164 begin
1165 with FFirebirdClientAPI do
1166 if SQLType = SQL_VARYING then
1167 Result := DecodeInteger(SQLData, 2)
1168 else
1169 Result := DataLength;
1170 end;
1171
1172 function TSQLDataItem.GetAsBoolean: boolean;
1173 begin
1174 CheckActive;
1175 result := false;
1176 if not IsNull then
1177 begin
1178 if SQLType = SQL_BOOLEAN then
1179 result := PByte(SQLData)^ = ISC_TRUE
1180 else
1181 IBError(ibxeInvalidDataConversion, [nil]);
1182 end
1183 end;
1184
1185 function TSQLDataItem.GetAsCurrency: Currency;
1186 begin
1187 CheckActive;
1188 result := 0;
1189 if GetSQLDialect < 3 then
1190 result := GetAsDouble
1191 else begin
1192 if not IsNull then
1193 case SQLType of
1194 SQL_TEXT, SQL_VARYING: begin
1195 try
1196 result := StrtoCurr(AsString);
1197 except
1198 on E: Exception do IBError(ibxeInvalidDataConversion, [nil]);
1199 end;
1200 end;
1201 SQL_SHORT:
1202 result := NumericFromRawValues(Int64(PShort(SQLData)^),
1203 Scale).getAsCurrency;
1204 SQL_LONG:
1205 result := NumericFromRawValues(Int64(PLong(SQLData)^),
1206 Scale).getAsCurrency;
1207 SQL_INT64:
1208 result := NumericFromRawValues(PInt64(SQLData)^,
1209 Scale).getAsCurrency;
1210 SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1211 result := Round(AsDouble);
1212
1213 SQL_DEC_FIXED,
1214 SQL_DEC16,
1215 SQL_DEC34,
1216 SQL_INT128:
1217 if not BCDToCurr(GetAsBCD,Result) then
1218 IBError(ibxeInvalidDataConversion, [nil]);
1219
1220 else
1221 IBError(ibxeInvalidDataConversion, [nil]);
1222 end;
1223 end;
1224 end;
1225
1226 function TSQLDataItem.GetAsInt64: Int64;
1227 begin
1228 CheckActive;
1229 result := 0;
1230 if not IsNull then
1231 case SQLType of
1232 SQL_TEXT, SQL_VARYING: begin
1233 try
1234 result := StrToInt64(AsString);
1235 except
1236 on E: Exception do IBError(ibxeInvalidDataConversion, [nil]);
1237 end;
1238 end;
1239 SQL_SHORT:
1240 result := NumericFromRawValues(Int64(PShort(SQLData)^),
1241 Scale).getAsInt64;
1242 SQL_LONG:
1243 result := NumericFromRawValues(Int64(PLong(SQLData)^),
1244 Scale).getAsInt64;
1245 SQL_INT64:
1246 result := NumericFromRawValues(PInt64(SQLData)^,
1247 Scale).getAsInt64;
1248 SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1249 result := Round(AsDouble);
1250 else
1251 IBError(ibxeInvalidDataConversion, [nil]);
1252 end;
1253 end;
1254
1255 function TSQLDataItem.GetAsDateTime: TDateTime;
1256 var aTimezone: AnsiString;
1257 aTimeZoneID: TFBTimeZoneID;
1258 dstOffset: smallint;
1259 begin
1260 InternalGetAsDateTime(Result,dstOffset,aTimeZone,aTimeZoneID);
1261 end;
1262
1263 procedure TSQLDataItem.GetAsDateTime(var aDateTime: TDateTime;
1264 var dstOffset: smallint; var aTimezone: AnsiString);
1265 var aTimeZoneID: TFBTimeZoneID;
1266 begin
1267 InternalGetAsDateTime(aDateTime,dstOffset,aTimeZone,aTimeZoneID);
1268 end;
1269
1270 procedure TSQLDataItem.GetAsDateTime(var aDateTime: TDateTime; var dstOffset: smallint;
1271 var aTimezoneID: TFBTimeZoneID);
1272 var aTimezone: AnsiString;
1273 begin
1274 InternalGetAsDateTime(aDateTime,dstOffset,aTimeZone,aTimeZoneID);
1275 end;
1276
1277 procedure TSQLDataItem.GetAsTime(var aTime: TDateTime; var dstOffset: smallint;
1278 var aTimezoneID: TFBTimeZoneID; OnDate: TDateTime);
1279 var aTimeZone: AnsiString;
1280 begin
1281 CheckActive;
1282 aTime := 0;
1283 dstOffset := 0;
1284 if not IsNull then
1285 with FFirebirdClientAPI do
1286 case SQLType of
1287 SQL_TIME_TZ:
1288 begin
1289 GetTimeZoneServices.DecodeTimeTZ(SQLData,OnDate,aTime,dstOffset,aTimeZone);
1290 aTimeZoneID := PISC_TIME_TZ(SQLData)^.time_zone;
1291 end;
1292 SQL_TIME_TZ_EX:
1293 begin
1294 GetTimeZoneServices.DecodeTimeTZEx(SQLData,OnDate,aTime,dstOffset,aTimeZone);
1295 aTimeZoneID := PISC_TIME_TZ_EX(SQLData)^.time_zone;
1296 end;
1297 else
1298 IBError(ibxeInvalidDataConversion, [nil]);
1299 end;
1300 end;
1301
1302 procedure TSQLDataItem.GetAsTime(var aTime: TDateTime; var dstOffset: smallint;
1303 var aTimezone: AnsiString; OnDate: TDateTime);
1304 begin
1305 CheckActive;
1306 aTime := 0;
1307 dstOffset := 0;
1308 if not IsNull then
1309 with FFirebirdClientAPI do
1310 case SQLType of
1311 SQL_TIME_TZ:
1312 GetTimeZoneServices.DecodeTimeTZ(SQLData,OnDate,aTime,dstOffset,aTimeZone);
1313 SQL_TIME_TZ_EX:
1314 GetTimeZoneServices.DecodeTimeTZEx(SQLData,OnDate,aTime,dstOffset,aTimeZone);
1315 else
1316 IBError(ibxeInvalidDataConversion, [nil]);
1317 end;
1318 end;
1319
1320 procedure TSQLDataItem.GetAsTime(var aTime: TDateTime; var dstOffset: smallint;
1321 var aTimezoneID: TFBTimeZoneID);
1322 begin
1323 GetAsTime(aTime,dstOffset,aTimeZoneID,GetTimeZoneServices.GetTimeTZDate);
1324 end;
1325
1326 procedure TSQLDataItem.GetAsTime(var aTime: TDateTime; var dstOffset: smallint;
1327 var aTimezone: AnsiString);
1328 begin
1329 GetAsTime(aTime,dstOffset,aTimeZone,GetTimeZoneServices.GetTimeTZDate);
1330 end;
1331
1332 function TSQLDataItem.GetAsUTCDateTime: TDateTime;
1333 var aTimezone: AnsiString;
1334 begin
1335 CheckActive;
1336 result := 0;
1337 aTimezone := '';
1338 if not IsNull then
1339 with FFirebirdClientAPI do
1340 case SQLType of
1341 SQL_TEXT, SQL_VARYING:
1342 begin
1343 if not ParseDateTimeTZString(AsString,Result,aTimeZone) then
1344 IBError(ibxeInvalidDataConversion, [nil]);
1345 Result := GetTimeZoneServices.LocalTimeToGMT(Result,aTimeZone);
1346 end;
1347 SQL_TYPE_DATE:
1348 result := SQLDecodeDate(SQLData);
1349 SQL_TYPE_TIME,
1350 SQL_TIME_TZ,
1351 SQL_TIME_TZ_EX:
1352 result := SQLDecodeTime(SQLData);
1353 SQL_TIMESTAMP,
1354 SQL_TIMESTAMP_TZ,
1355 SQL_TIMESTAMP_TZ_EX:
1356 result := SQLDecodeDateTime(SQLData);
1357 else
1358 IBError(ibxeInvalidDataConversion, [nil]);
1359 end;
1360 end;
1361
1362 function TSQLDataItem.GetAsDouble: Double;
1363 begin
1364 CheckActive;
1365 result := 0;
1366 if not IsNull then begin
1367 case SQLType of
1368 SQL_TEXT, SQL_VARYING: begin
1369 try
1370 result := StrToFloat(AsString);
1371 except
1372 on E: Exception do IBError(ibxeInvalidDataConversion, [nil]);
1373 end;
1374 end;
1375 SQL_SHORT:
1376 result := NumericFromRawValues(Int64(PShort(SQLData)^),
1377 Scale).getAsDouble;
1378 SQL_LONG:
1379 result := NumericFromRawValues(Int64(PLong(SQLData)^),
1380 Scale).getAsDouble;
1381 SQL_INT64:
1382 result := NumericFromRawValues(PInt64(SQLData)^, Scale).getAsDouble;
1383 SQL_FLOAT:
1384 result := PFloat(SQLData)^;
1385 SQL_DOUBLE, SQL_D_FLOAT:
1386 result := PDouble(SQLData)^;
1387 SQL_DEC_FIXED,
1388 SQL_DEC16,
1389 SQL_DEC34,
1390 SQL_INT128:
1391 Result := BCDToDouble(GetAsBCD);
1392 else
1393 IBError(ibxeInvalidDataConversion, [nil]);
1394 end;
1395 if Scale <> 0 then
1396 result :=
1397 StrToFloat(FloatToStrF(result, fffixed, 15,
1398 Abs(Scale) ));
1399 end;
1400 end;
1401
1402 function TSQLDataItem.GetAsFloat: Float;
1403 begin
1404 CheckActive;
1405 result := 0;
1406 try
1407 result := AsDouble;
1408 except
1409 on E: EOverflow do
1410 IBError(ibxeInvalidDataConversion, [nil]);
1411 end;
1412 end;
1413
1414 function TSQLDataItem.GetAsLong: Long;
1415 begin
1416 CheckActive;
1417 result := 0;
1418 if not IsNull then
1419 case SQLType of
1420 SQL_TEXT, SQL_VARYING: begin
1421 try
1422 result := StrToInt(AsString);
1423 except
1424 on E: Exception do IBError(ibxeInvalidDataConversion, [nil]);
1425 end;
1426 end;
1427 SQL_SHORT:
1428 result := NumericFromRawValues(Int64(PShort(SQLData)^),
1429 Scale).getAsInteger;
1430 SQL_LONG:
1431 result := NumericFromRawValues(Int64(PLong(SQLData)^),
1432 Scale).getAsInteger;
1433 SQL_INT64:
1434 result := NumericFromRawValues(PInt64(SQLData)^, Scale).getAsInteger;
1435
1436 SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1437 result := Round(AsDouble);
1438 SQL_DEC_FIXED,
1439 SQL_DEC16,
1440 SQL_DEC34,
1441 SQL_INT128:
1442 Result := BCDToInteger(GetAsBCD);
1443 else
1444 IBError(ibxeInvalidDataConversion, [GetSQLTypeName]);
1445 end;
1446 end;
1447
1448 function TSQLDataItem.GetAsPointer: Pointer;
1449 begin
1450 CheckActive;
1451 if not IsNull then
1452 result := SQLData
1453 else
1454 result := nil;
1455 end;
1456
1457 function TSQLDataItem.GetAsQuad: TISC_QUAD;
1458 begin
1459 CheckActive;
1460 result.gds_quad_high := 0;
1461 result.gds_quad_low := 0;
1462 if not IsNull then
1463 case SQLType of
1464 SQL_BLOB, SQL_ARRAY, SQL_QUAD:
1465 result := PISC_QUAD(SQLData)^;
1466 else
1467 IBError(ibxeInvalidDataConversion, [nil]);
1468 end;
1469 end;
1470
1471 function TSQLDataItem.GetAsShort: short;
1472 begin
1473 CheckActive;
1474 result := 0;
1475 try
1476 result := AsLong;
1477 except
1478 on E: Exception do IBError(ibxeInvalidDataConversion, [nil]);
1479 end;
1480 end;
1481
1482 {Copied from LazUTF8}
1483
1484 function UTF8CodepointSizeFull(p: PAnsiChar): integer;
1485 const TopBitSetMask = $80; {%10000000}
1486 Top2BitsSetMask = $C0; {%11000000}
1487 Top3BitsSetMask = $E0; {%11100000}
1488 Top4BitsSetMask = $F0; {%11110000}
1489 Top5BitsSetMask = $F8; {%11111000}
1490 begin
1491 case p^ of
1492 #0..#191: // %11000000
1493 // regular single byte character (#0 is a character, this is Pascal ;)
1494 Result:=1;
1495 #192..#223: // p^ and %11100000 = %11000000
1496 begin
1497 // could be 2 byte character
1498 if (ord(p[1]) and Top2BitsSetMask) = TopBitSetMask then
1499 Result:=2
1500 else
1501 Result:=1;
1502 end;
1503 #224..#239: // p^ and %11110000 = %11100000
1504 begin
1505 // could be 3 byte character
1506 if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1507 and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask) then
1508 Result:=3
1509 else
1510 Result:=1;
1511 end;
1512 #240..#247: // p^ and %11111000 = %11110000
1513 begin
1514 // could be 4 byte character
1515 if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1516 and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask)
1517 and ((ord(p[3]) and Top2BitsSetMask) = TopBitSetMask) then
1518 Result:=4
1519 else
1520 Result:=1;
1521 end;
1522 else
1523 Result:=1;
1524 end;
1525 end;
1526
1527 {Returns the byte length of a UTF8 string with a fixed charwidth}
1528
1529 function GetStrLen(p: PAnsiChar; FieldWidth, MaxDataLength: cardinal): integer;
1530 var i: integer;
1531 cplen: integer;
1532 begin
1533 Result := 0;
1534 for i := 1 to FieldWidth do
1535 begin
1536 cplen := UTF8CodepointSizeFull(p);
1537 Inc(p,cplen);
1538 Inc(Result,cplen);
1539 if Result >= MaxDataLength then
1540 begin
1541 Result := MaxDataLength;
1542 Exit;
1543 end;
1544 end;
1545 end;
1546
1547 function TSQLDataItem.GetAsString: AnsiString;
1548 var
1549 sz: PByte;
1550 str_len: Integer;
1551 rs: RawByteString;
1552 aTimeZone: AnsiString;
1553 aDateTime: TDateTime;
1554 dstOffset: smallint;
1555 begin
1556 CheckActive;
1557 result := '';
1558 { Check null, if so return a default string }
1559 if not IsNull then
1560 with FFirebirdClientAPI do
1561 case SQLType of
1562 SQL_BOOLEAN:
1563 if AsBoolean then
1564 Result := sTrue
1565 else
1566 Result := SFalse;
1567
1568 SQL_TEXT, SQL_VARYING:
1569 begin
1570 sz := SQLData;
1571 if (SQLType = SQL_TEXT) then
1572 begin
1573 if GetCodePage = cp_utf8 then
1574 str_len := GetStrLen(PAnsiChar(sz),GetSize div GetCharSetWidth,DataLength)
1575 else
1576 str_len := DataLength
1577 end
1578 else begin
1579 str_len := DecodeInteger(sz, 2);
1580 Inc(sz, 2);
1581 end;
1582 SetString(rs, PAnsiChar(sz), str_len);
1583 SetCodePage(rs,GetCodePage,false);
1584 Result := rs;
1585 end;
1586
1587 SQL_TYPE_DATE:
1588 Result := DateToStr(GetAsDateTime);
1589 SQL_TIMESTAMP:
1590 Result := FBFormatDateTime(GetTimestampFormatStr,GetAsDateTime);
1591 SQL_TYPE_TIME:
1592 Result := FBFormatDateTime(GetTimeFormatStr,GetAsDateTime);
1593 SQL_TIMESTAMP_TZ,
1594 SQL_TIMESTAMP_TZ_EX:
1595 with GetAttachment.GetTimeZoneServices do
1596 begin
1597 if GetTZTextOption = tzGMT then
1598 Result := FBFormatDateTime(GetTimestampFormatStr,GetAsUTCDateTime)
1599 else
1600 begin
1601 GetAsDateTime(aDateTime,dstOffset,aTimeZone);
1602 if GetTZTextOption = tzOffset then
1603 Result := FBFormatDateTime(GetTimestampFormatStr,aDateTime) + ' ' + FormatTimeZoneOffset(dstOffset)
1604 else
1605 Result := FBFormatDateTime(GetTimestampFormatStr,aDateTime) + ' ' + aTimeZone;
1606 end;
1607 end;
1608 SQL_TIME_TZ,
1609 SQL_TIME_TZ_EX:
1610 with GetAttachment.GetTimeZoneServices do
1611 begin
1612 if GetTZTextOption = tzGMT then
1613 Result := FBFormatDateTime(GetTimeFormatStr,GetAsUTCDateTime)
1614 else
1615 begin
1616 GetAsTime(aDateTime,dstOffset,aTimeZone,GetTimeTZDate);
1617 if GetTZTextOption = tzOffset then
1618 Result := FBFormatDateTime(GetTimeFormatStr,aDateTime) + ' ' + FormatTimeZoneOffset(dstOffset)
1619 else
1620 Result := FBFormatDateTime(GetTimeFormatStr,aDateTime) + ' ' + aTimeZone;
1621 end;
1622 end;
1623
1624 SQL_SHORT, SQL_LONG:
1625 if Scale = 0 then
1626 result := IntToStr(AsLong)
1627 else if Scale >= (-4) then
1628 result := CurrToStr(AsCurrency)
1629 else
1630 result := FloatToStr(AsDouble);
1631 SQL_INT64:
1632 if Scale = 0 then
1633 result := IntToStr(AsInt64)
1634 else if Scale >= (-4) then
1635 result := CurrToStr(AsCurrency)
1636 else
1637 result := FloatToStr(AsDouble);
1638 SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1639 result := FloatToStr(AsDouble);
1640
1641 SQL_DEC16,
1642 SQL_DEC34:
1643 result := BCDToStr(GetAsBCD);
1644
1645 SQL_DEC_FIXED,
1646 SQL_INT128:
1647 result := Int128ToStr(SQLData,scale);
1648
1649 else
1650 IBError(ibxeInvalidDataConversion, [GetSQLTypeName]);
1651 end;
1652 end;
1653
1654 function TSQLDataItem.GetAsNumeric: IFBNumeric;
1655 var aValue: Int64;
1656 begin
1657 case SQLType of
1658 SQL_TEXT, SQL_VARYING:
1659 Result := NewNumeric(GetAsString);
1660
1661 SQL_SHORT:
1662 Result := NumericFromRawValues(PShort(SQLData)^, Scale);
1663
1664 SQL_LONG:
1665 Result := NumericFromRawValues(PLong(SQLData)^, Scale);
1666
1667 SQL_INT64:
1668 Result := NumericFromRawValues(PInt64(SQLData)^, Scale);
1669
1670 SQL_DEC16,
1671 SQL_DEC34,
1672 SQL_DEC_FIXED,
1673 SQL_INT128:
1674 Result := NewNumeric(GetAsBCD);
1675
1676 else
1677 IBError(ibxeInvalidDataConversion, [nil]);
1678 end;
1679 end;
1680
1681 function TSQLDataItem.GetIsNull: Boolean;
1682 begin
1683 CheckActive;
1684 Result := false;
1685 end;
1686
1687 function TSQLDataItem.GetIsNullable: boolean;
1688 begin
1689 CheckActive;
1690 Result := false;
1691 end;
1692
1693 function TSQLDataItem.GetAsVariant: Variant;
1694 var ts: TDateTime;
1695 dstOffset: smallint;
1696 timezone: AnsiString;
1697 begin
1698 CheckActive;
1699 if IsNull then
1700 result := NULL
1701 { Check null, if so return a default string }
1702 else case SQLType of
1703 SQL_ARRAY:
1704 result := '(Array)'; {do not localize}
1705 SQL_BLOB,
1706 SQL_TEXT, SQL_VARYING:
1707 result := AsString;
1708 SQL_TIMESTAMP, SQL_TYPE_DATE, SQL_TYPE_TIME:
1709 result := AsDateTime;
1710 SQL_TIMESTAMP_TZ,
1711 SQL_TIME_TZ,
1712 SQL_TIMESTAMP_TZ_EX,
1713 SQL_TIME_TZ_EX:
1714 begin
1715 GetAsDateTime(ts,dstOffset,timezone);
1716 result := VarArrayOf([ts,dstOffset,timezone]);
1717 end;
1718 SQL_SHORT, SQL_LONG:
1719 if Scale = 0 then
1720 result := AsLong
1721 else if Scale >= (-4) then
1722 result := AsCurrency
1723 else
1724 result := AsDouble;
1725 SQL_INT64:
1726 if Scale = 0 then
1727 result := AsInt64
1728 else if Scale >= (-4) then
1729 result := AsCurrency
1730 else
1731 result := AsDouble;
1732 SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1733 result := AsDouble;
1734 SQL_BOOLEAN:
1735 result := AsBoolean;
1736 SQL_DEC_FIXED,
1737 SQL_DEC16,
1738 SQL_DEC34,
1739 SQL_INT128:
1740 result := VarFmtBCDCreate(GetAsBcd);
1741 else
1742 IBError(ibxeInvalidDataConversion, [nil]);
1743 end;
1744 end;
1745
1746 function TSQLDataItem.GetModified: boolean;
1747 begin
1748 Result := false;
1749 end;
1750
1751 function TSQLDataItem.GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats
1752 ): integer;
1753 begin
1754 case DateTimeFormat of
1755 dfTimestamp:
1756 Result := Length(GetTimestampFormatStr);
1757 dfDateTime:
1758 Result := Length(GetDateFormatStr(true));
1759 dfTime:
1760 Result := Length(GetTimeFormatStr);
1761 dfTimestampTZ:
1762 Result := Length(GetTimestampFormatStr) + 6; {assume time offset format}
1763 dfTimeTZ:
1764 Result := Length(GetTimeFormatStr)+ 6;
1765 else
1766 Result := 0;
1767 end;end;
1768
1769 function TSQLDataItem.GetAsBCD: tBCD;
1770
1771 begin
1772 CheckActive;
1773 if IsNull then
1774 with Result do
1775 begin
1776 FillChar(Result,sizeof(Result),0);
1777 Precision := 1;
1778 exit;
1779 end;
1780
1781 case SQLType of
1782 SQL_DEC16,
1783 SQL_DEC34:
1784 with FFirebirdClientAPI do
1785 Result := SQLDecFloatDecode(SQLType, SQLData);
1786
1787 SQL_DEC_FIXED,
1788 SQL_INT128:
1789 with FFirebirdClientAPI do
1790 Result := StrToBCD(Int128ToStr(SQLData,scale));
1791 else
1792 if not CurrToBCD(GetAsCurrency,Result) then
1793 IBError(ibxeBadBCDConversion,[]);
1794 end;
1795 end;
1796
1797
1798 procedure TSQLDataItem.SetIsNull(Value: Boolean);
1799 begin
1800 //ignore unless overridden
1801 end;
1802
1803 procedure TSQLDataItem.SetIsNullable(Value: Boolean);
1804 begin
1805 //ignore unless overridden
1806 end;
1807
1808 procedure TSQLDataItem.SetName(aValue: AnsiString);
1809 begin
1810 //ignore unless overridden
1811 end;
1812
1813 procedure TSQLDataItem.SetAsCurrency(Value: Currency);
1814 begin
1815 CheckActive;
1816 if GetSQLDialect < 3 then
1817 AsDouble := Value
1818 else
1819 if not CanChangeMetaData and ((SQLType <> SQL_INT64) or (Scale <> -4)) then
1820 SetAsNumeric(NewNumeric(Value))
1821 else
1822 begin
1823 Changing;
1824 if IsNullable then
1825 IsNull := False;
1826 SQLType := SQL_INT64;
1827 Scale := -4;
1828 DataLength := SizeOf(Int64);
1829 PCurrency(SQLData)^ := Value;
1830 Changed;
1831 end;
1832 end;
1833
1834 procedure TSQLDataItem.SetAsInt64(Value: Int64);
1835 begin
1836 CheckActive;
1837 if not CanChangeMetaData and ((SQLType <> SQL_INT64) or (Scale <> 0)) then
1838 SetAsNumeric(NewNumeric(Value))
1839 else
1840 begin
1841 Changing;
1842 if IsNullable then
1843 IsNull := False;
1844
1845 SQLType := SQL_INT64;
1846 Scale := 0;
1847 DataLength := SizeOf(Int64);
1848 PInt64(SQLData)^ := Value;
1849 Changed;
1850 end;
1851 end;
1852
1853 procedure TSQLDataItem.SetAsDate(Value: TDateTime);
1854 begin
1855 CheckActive;
1856 if GetSQLDialect < 3 then
1857 begin
1858 AsDateTime := Value;
1859 exit;
1860 end;
1861
1862 Changing;
1863 if IsNullable then
1864 IsNull := False;
1865
1866 SQLType := SQL_TYPE_DATE;
1867 DataLength := SizeOf(ISC_DATE);
1868 with FFirebirdClientAPI do
1869 SQLEncodeDate(Value,SQLData);
1870 Changed;
1871 end;
1872
1873 procedure TSQLDataItem.SetAsTime(Value: TDateTime);
1874 begin
1875 CheckActive;
1876 if GetSQLDialect < 3 then
1877 begin
1878 AsDateTime := Value;
1879 exit;
1880 end;
1881
1882 Changing;
1883 if IsNullable then
1884 IsNull := False;
1885
1886 SQLType := SQL_TYPE_TIME;
1887 DataLength := SizeOf(ISC_TIME);
1888 with FFirebirdClientAPI do
1889 SQLEncodeTime(Value,SQLData);
1890 Changed;
1891 end;
1892
1893 procedure TSQLDataItem.SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZoneID: TFBTimeZoneID);
1894 begin
1895 CheckActive;
1896 CheckTZSupport;
1897 if GetSQLDialect < 3 then
1898 begin
1899 AsDateTime := aValue;
1900 exit;
1901 end;
1902
1903 Changing;
1904 if IsNullable then
1905 IsNull := False;
1906
1907 SQLType := SQL_TIME_TZ;
1908 DataLength := SizeOf(ISC_TIME_TZ);
1909 GetTimeZoneServices.EncodeTimeTZ(aValue, aTimeZoneID,OnDate,SQLData);
1910 Changed;
1911 end;
1912
1913 procedure TSQLDataItem.SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZone: AnsiString);
1914 begin
1915 CheckActive;
1916 CheckTZSupport;
1917 if GetSQLDialect < 3 then
1918 begin
1919 AsDateTime := aValue;
1920 exit;
1921 end;
1922
1923 Changing;
1924 if IsNullable then
1925 IsNull := False;
1926
1927 SQLType := SQL_TIME_TZ;
1928 DataLength := SizeOf(ISC_TIME_TZ);
1929 GetTimeZoneServices.EncodeTimeTZ(aValue, aTimeZone,OnDate,SQLData);
1930 Changed;
1931 end;
1932
1933 procedure TSQLDataItem.SetAsDateTime(Value: TDateTime);
1934 begin
1935 CheckActive;
1936 if IsNullable then
1937 IsNull := False;
1938
1939 Changing;
1940 SQLType := SQL_TIMESTAMP;
1941 DataLength := SizeOf(ISC_TIME) + sizeof(ISC_DATE);
1942 with FFirebirdClientAPI do
1943 SQLEncodeDateTime(Value,SQLData);
1944 Changed;
1945 end;
1946
1947 procedure TSQLDataItem.SetAsDateTime(aValue: TDateTime;
1948 aTimeZoneID: TFBTimeZoneID);
1949 begin
1950 CheckActive;
1951 CheckTZSupport;
1952 if IsNullable then
1953 IsNull := False;
1954
1955 Changing;
1956 SQLType := SQL_TIMESTAMP_TZ;
1957 DataLength := SizeOf(ISC_TIMESTAMP_TZ);
1958 GetTimeZoneServices.EncodeTimestampTZ(aValue,aTimeZoneID,SQLData);
1959 Changed;
1960 end;
1961
1962 procedure TSQLDataItem.SetAsDateTime(aValue: TDateTime; aTimeZone: AnsiString
1963 );
1964 begin
1965 CheckActive;
1966 CheckTZSupport;
1967 if IsNullable then
1968 IsNull := False;
1969
1970 Changing;
1971 SQLType := SQL_TIMESTAMP_TZ;
1972 DataLength := SizeOf(ISC_TIMESTAMP_TZ);
1973 GetTimeZoneServices.EncodeTimestampTZ(aValue,aTimeZone,SQLData);
1974 Changed;
1975 end;
1976
1977 procedure TSQLDataItem.SetAsUTCDateTime(aUTCTime: TDateTime);
1978 begin
1979 SetAsDateTime(aUTCTime,TimeZoneID_GMT);
1980 end;
1981
1982 procedure TSQLDataItem.SetAsDouble(Value: Double);
1983 begin
1984 CheckActive;
1985 if IsNullable then
1986 IsNull := False;
1987
1988 Changing;
1989 SQLType := SQL_DOUBLE;
1990 DataLength := SizeOf(Double);
1991 Scale := 0;
1992 PDouble(SQLData)^ := Value;
1993 Changed;
1994 end;
1995
1996 procedure TSQLDataItem.SetAsFloat(Value: Float);
1997 begin
1998 CheckActive;
1999 if IsNullable then
2000 IsNull := False;
2001
2002 Changing;
2003 SQLType := SQL_FLOAT;
2004 DataLength := SizeOf(Float);
2005 Scale := 0;
2006 PSingle(SQLData)^ := Value;
2007 Changed;
2008 end;
2009
2010 procedure TSQLDataItem.SetAsLong(Value: Long);
2011 begin
2012 CheckActive;
2013 if not CanChangeMetaData and ((SQLType <> SQL_LONG) or (Scale <> 0)) then
2014 SetAsNumeric(NewNumeric(Value))
2015 else
2016 begin
2017 if IsNullable then
2018 IsNull := False;
2019
2020 Changing;
2021 SQLType := SQL_LONG;
2022 DataLength := SizeOf(Long);
2023 Scale := 0;
2024 PLong(SQLData)^ := Value;
2025 Changed;
2026 end;
2027 end;
2028
2029 procedure TSQLDataItem.SetAsPointer(Value: Pointer);
2030 begin
2031 CheckActive;
2032 Changing;
2033 if IsNullable and (Value = nil) then
2034 IsNull := True
2035 else
2036 begin
2037 IsNull := False;
2038 SQLType := SQL_TEXT;
2039 Move(Value^, SQLData^, DataLength);
2040 end;
2041 Changed;
2042 end;
2043
2044 procedure TSQLDataItem.SetAsQuad(Value: TISC_QUAD);
2045 begin
2046 CheckActive;
2047 Changing;
2048 if IsNullable then
2049 IsNull := False;
2050 if (SQLType <> SQL_BLOB) and
2051 (SQLType <> SQL_ARRAY) then
2052 IBError(ibxeInvalidDataConversion, [nil]);
2053 DataLength := SizeOf(TISC_QUAD);
2054 PISC_QUAD(SQLData)^ := Value;
2055 Changed;
2056 end;
2057
2058 procedure TSQLDataItem.SetAsShort(Value: short);
2059 begin
2060 CheckActive;
2061 if not CanChangeMetaData and ((SQLType <> SQL_SHORT) or (Scale <> 0)) then
2062 SetAsNumeric(NewNumeric(Value))
2063 else
2064 begin
2065 Changing;
2066 if IsNullable then
2067 IsNull := False;
2068
2069 SQLType := SQL_SHORT;
2070 DataLength := SizeOf(Short);
2071 Scale := 0;
2072 PShort(SQLData)^ := Value;
2073 Changed;
2074 end;
2075 end;
2076
2077 procedure TSQLDataItem.SetAsString(Value: AnsiString);
2078 begin
2079 InternalSetAsString(Value);
2080 end;
2081
2082 procedure TSQLDataItem.SetAsVariant(Value: Variant);
2083 begin
2084 CheckActive;
2085 if VarIsNull(Value) then
2086 IsNull := True
2087 else
2088 if VarIsArray(Value) then {must be datetime plus timezone}
2089 SetAsDateTime(Value[0],AnsiString(Value[1]))
2090 else case VarType(Value) of
2091 varEmpty, varNull:
2092 IsNull := True;
2093 varSmallint, varInteger, varByte,
2094 varWord, varShortInt, varInt64:
2095 SetAsNumeric(NewNumeric(Int64(Value)));
2096 varSingle, varDouble:
2097 AsDouble := Value;
2098 varCurrency:
2099 SetAsNumeric(NewNumeric(Currency(Value)));
2100 varBoolean:
2101 AsBoolean := Value;
2102 varDate:
2103 AsDateTime := Value;
2104 varOleStr, varString:
2105 AsString := Value;
2106 varArray:
2107 IBError(ibxeNotSupported, [nil]);
2108 varByRef, varDispatch, varError, varUnknown, varVariant:
2109 IBError(ibxeNotPermitted, [nil]);
2110 else
2111 if VarIsFmtBCD(Value) then
2112 SetAsBCD(VarToBCD(Value))
2113 else
2114 IBError(ibxeNotSupported, [nil]);
2115 end;
2116 end;
2117
2118 procedure TSQLDataItem.SetAsNumeric(Value: IFBNumeric);
2119 begin
2120 CheckActive;
2121 Changing;
2122 if IsNullable then
2123 IsNull := False;
2124
2125 if CanChangeMetadata then
2126 begin
2127 {Restore original values}
2128 SQLType := getColMetadata.GetSQLType;
2129 Scale := getColMetadata.getScale;
2130 SetDataLength(getColMetadata.GetSize);
2131 end;
2132
2133 with FFirebirdClientAPI do
2134 case GetSQLType of
2135 SQL_LONG:
2136 PLong(SQLData)^ := SafeInteger(Value.clone(Scale).getRawValue);
2137 SQL_SHORT:
2138 PShort(SQLData)^ := SafeSmallInt(Value.clone(Scale).getRawValue);
2139 SQL_INT64:
2140 PInt64(SQLData)^ := Value.clone(Scale).getRawValue;
2141 SQL_TEXT, SQL_VARYING:
2142 SetAsString(Value.getAsString);
2143 SQL_D_FLOAT,
2144 SQL_DOUBLE:
2145 PDouble(SQLData)^ := Value.getAsDouble;
2146 SQL_FLOAT:
2147 PSingle(SQLData)^ := Value.getAsDouble;
2148 SQL_DEC_FIXED,
2149 SQL_DEC16,
2150 SQL_DEC34:
2151 SQLDecFloatEncode(Value.getAsBCD,SQLType,SQLData);
2152 SQL_INT128:
2153 StrToInt128(Scale,Value.getAsString,SQLData);
2154 else
2155 IBError(ibxeInvalidDataConversion, [nil]);
2156 end;
2157 Changed;
2158 end;
2159
2160 procedure TSQLDataItem.SetAsBcd(aValue: tBCD);
2161 begin
2162 CheckActive;
2163 Changing;
2164 if IsNullable then
2165 IsNull := False;
2166
2167 if not CanChangeMetaData then
2168 begin
2169 SetAsNumeric(NewNumeric(aValue));
2170 Exit;
2171 end;
2172
2173 with FFirebirdClientAPI do
2174 if aValue.Precision <= 16 then
2175 begin
2176 if not HasDecFloatSupport then
2177 IBError(ibxeDecFloatNotSupported,[]);
2178
2179 SQLType := SQL_DEC16;
2180 DataLength := 8;
2181 SQLDecFloatEncode(aValue,SQLType,SQLData);
2182 end
2183 else
2184 if aValue.Precision <= 34 then
2185 begin
2186 if not HasDecFloatSupport then
2187 IBError(ibxeDecFloatNotSupported,[]);
2188
2189 SQLType := SQL_DEC34;
2190 DataLength := 16;
2191 SQLDecFloatEncode(aValue,SQLType,SQLData);
2192 end
2193 else
2194 if aValue.Precision <= 38 then
2195 begin
2196 if not HasInt128Support then
2197 IBError(ibxeInt128NotSupported,[]);
2198
2199 SQLType := SQL_INT128;
2200 DataLength := 16;
2201 StrToInt128(scale,BcdToStr(aValue),SQLData);
2202 end
2203 else
2204 IBError(ibxeBCDOverflow,[BCDToStr(aValue)]);
2205
2206 Changed;
2207 end;
2208
2209 procedure TSQLDataItem.SetAsBoolean(AValue: boolean);
2210 begin
2211 CheckActive;
2212 Changing;
2213 if IsNullable then
2214 IsNull := False;
2215
2216 SQLType := SQL_BOOLEAN;
2217 DataLength := 1;
2218 Scale := 0;
2219 if AValue then
2220 PByte(SQLData)^ := ISC_TRUE
2221 else
2222 PByte(SQLData)^ := ISC_FALSE;
2223 Changed;
2224 end;
2225
2226 {TColumnMetaData}
2227
2228 procedure TColumnMetaData.CheckActive;
2229 begin
2230 if not FIBXSQLVAR.Parent.StateChanged(FChangeSeqNo) then Exit;
2231
2232 if FPrepareSeqNo < FIBXSQLVAR.Parent.GetPrepareSeqNo then
2233 IBError(ibxeInterfaceOutofDate,[nil]);
2234
2235 if not FIBXSQLVAR.Parent.CheckStatementStatus(ssPrepared) then
2236 IBError(ibxeStatementNotPrepared, [nil]);
2237 end;
2238
2239 function TColumnMetaData.GetAttachment: IAttachment;
2240 begin
2241 Result := FIBXSQLVAR.GetAttachment;
2242 end;
2243
2244 function TColumnMetaData.SQLData: PByte;
2245 begin
2246 Result := FIBXSQLVAR.SQLData;
2247 end;
2248
2249 function TColumnMetaData.GetDataLength: cardinal;
2250 begin
2251 Result := FIBXSQLVAR.DataLength;
2252 end;
2253
2254 function TColumnMetaData.GetCodePage: TSystemCodePage;
2255 begin
2256 Result := FIBXSQLVAR.GetCodePage;
2257 end;
2258
2259 constructor TColumnMetaData.Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
2260 begin
2261 inherited Create(aIBXSQLVAR.GetAttachment.getFirebirdAPI as TFBClientAPI);
2262 FIBXSQLVAR := aIBXSQLVAR;
2263 FOwner := aOwner;
2264 FPrepareSeqNo := FIBXSQLVAR.Parent.PrepareSeqNo;
2265 FIBXSQLVAR.Parent.StateChanged(FChangeSeqNo)
2266 end;
2267
2268 destructor TColumnMetaData.Destroy;
2269 begin
2270 (FOwner as TInterfaceOwner).Remove(self);
2271 inherited Destroy;
2272 end;
2273
2274
2275 function TColumnMetaData.GetSQLDialect: integer;
2276 begin
2277 Result := FIBXSQLVAR.GetAttachment.GetSQLDialect;
2278 end;
2279
2280 function TColumnMetaData.getColMetadata: IParamMetaData;
2281 begin
2282 Result := self;
2283 end;
2284
2285 function TColumnMetaData.GetIndex: integer;
2286 begin
2287 Result := FIBXSQLVAR.Index;
2288 end;
2289
2290 function TColumnMetaData.GetSQLType: cardinal;
2291 begin
2292 CheckActive;
2293 result := FIBXSQLVAR.SQLType;
2294 end;
2295
2296 function TColumnMetaData.getSubtype: integer;
2297 begin
2298 CheckActive;
2299 result := FIBXSQLVAR.SQLSubtype;
2300 end;
2301
2302 function TColumnMetaData.getRelationName: AnsiString;
2303 begin
2304 CheckActive;
2305 result := FIBXSQLVAR.RelationName;
2306 end;
2307
2308 function TColumnMetaData.getOwnerName: AnsiString;
2309 begin
2310 CheckActive;
2311 result := FIBXSQLVAR.OwnerName;
2312 end;
2313
2314 function TColumnMetaData.getSQLName: AnsiString;
2315 begin
2316 CheckActive;
2317 result := FIBXSQLVAR.FieldName;
2318 end;
2319
2320 function TColumnMetaData.getAliasName: AnsiString;
2321 begin
2322 CheckActive;
2323 result := FIBXSQLVAR.AliasName;
2324 end;
2325
2326 function TColumnMetaData.GetName: AnsiString;
2327 begin
2328 CheckActive;
2329 Result := FIBXSQLVAR. Name;
2330 end;
2331
2332 function TColumnMetaData.GetScale: integer;
2333 begin
2334 CheckActive;
2335 result := FIBXSQLVAR.Scale;
2336 end;
2337
2338 function TColumnMetaData.getCharSetID: cardinal;
2339 begin
2340 CheckActive;
2341 Result := FIBXSQLVAR.CharSetID;
2342 end;
2343
2344 function TColumnMetaData.GetIsNullable: boolean;
2345 begin
2346 CheckActive;
2347 result := FIBXSQLVAR.IsNullable;
2348 end;
2349
2350 function TColumnMetaData.GetSize: cardinal;
2351 begin
2352 CheckActive;
2353 result := FIBXSQLVAR.GetSize;
2354 end;
2355
2356 function TColumnMetaData.GetCharSetWidth: integer;
2357 begin
2358 CheckActive;
2359 result := FIBXSQLVAR.GetCharSetWidth;
2360 end;
2361
2362 function TColumnMetaData.GetArrayMetaData: IArrayMetaData;
2363 begin
2364 CheckActive;
2365 result := FIBXSQLVAR.GetArrayMetaData;
2366 end;
2367
2368 function TColumnMetaData.GetBlobMetaData: IBlobMetaData;
2369 begin
2370 CheckActive;
2371 result := FIBXSQLVAR.GetBlobMetaData;
2372 end;
2373
2374 function TColumnMetaData.GetStatement: IStatement;
2375 begin
2376 Result := FIBXSQLVAR.GetStatement;
2377 end;
2378
2379 function TColumnMetaData.GetTransaction: ITransaction;
2380 begin
2381 Result := FIBXSQLVAR.GetTransaction;
2382 end;
2383
2384 { TIBSQLData }
2385
2386 procedure TIBSQLData.CheckActive;
2387 begin
2388 if not FIBXSQLVAR.Parent.StateChanged(FChangeSeqNo) then Exit;
2389
2390 inherited CheckActive;
2391
2392 if not FIBXSQLVAR.Parent.CheckStatementStatus(ssCursorOpen) and
2393 not FIBXSQLVAR.Parent.CheckStatementStatus(ssExecuteResults) then
2394 IBError(ibxeSQLClosed, [nil]);
2395
2396 if FIBXSQLVAR.Parent.CheckStatementStatus(ssEOF) then
2397 IBError(ibxeEOF,[nil]);
2398
2399 if FIBXSQLVAR.Parent.CheckStatementStatus(ssBOF) then
2400 IBError(ibxeBOF,[nil]);
2401 end;
2402
2403 function TIBSQLData.GetIsNull: Boolean;
2404 begin
2405 CheckActive;
2406 result := FIBXSQLVAR.IsNull;
2407 end;
2408
2409 function TIBSQLData.GetAsArray: IArray;
2410 begin
2411 CheckActive;
2412 result := FIBXSQLVAR.GetAsArray;
2413 end;
2414
2415 function TIBSQLData.GetAsBlob: IBlob;
2416 begin
2417 CheckActive;
2418 result := FIBXSQLVAR.GetAsBlob(AsQuad,nil);
2419 end;
2420
2421 function TIBSQLData.GetAsBlob(BPB: IBPB): IBlob;
2422 begin
2423 CheckActive;
2424 result := FIBXSQLVAR.GetAsBlob(AsQuad,BPB);
2425 end;
2426
2427 function TIBSQLData.GetAsString: AnsiString;
2428 begin
2429 CheckActive;
2430 Result := '';
2431 { Check null, if so return a default string }
2432 if not IsNull then
2433 case SQLType of
2434 SQL_ARRAY:
2435 result := SArray;
2436 SQL_BLOB:
2437 Result := FIBXSQLVAR.GetAsBlob(AsQuad,nil).GetAsString;
2438 else
2439 Result := inherited GetAsString;
2440 end;
2441 end;
2442
2443 { TSQLParam }
2444
2445 procedure TSQLParam.InternalSetAsString(Value: AnsiString);
2446
2447 procedure DoSetString;
2448 begin
2449 Changing;
2450 FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
2451 Changed;
2452 end;
2453
2454 var b: IBlob;
2455 dt: TDateTime;
2456 timezone: AnsiString;
2457 Int64Value: Int64;
2458 BCDValue: TBCD;
2459 aScale: integer;
2460 begin
2461 CheckActive;
2462 if IsNullable then
2463 IsNull := False;
2464 with FFirebirdClientAPI do
2465 case SQLTYPE of
2466 SQL_BOOLEAN:
2467 if AnsiCompareText(Value,STrue) = 0 then
2468 AsBoolean := true
2469 else
2470 if AnsiCompareText(Value,SFalse) = 0 then
2471 AsBoolean := false
2472 else
2473 IBError(ibxeInvalidDataConversion,[nil]);
2474
2475 SQL_BLOB:
2476 if Length(Value) < GetAttachment.GetInlineBlobLimit then
2477 DoSetString
2478 else
2479 begin
2480 Changing;
2481 b := FIBXSQLVAR.CreateBlob;
2482 b.SetAsString(Value);
2483 AsBlob := b;
2484 Changed;
2485 end;
2486
2487 SQL_VARYING,
2488 SQL_TEXT:
2489 DoSetString;
2490
2491 SQL_SHORT,
2492 SQL_LONG,
2493 SQL_INT64:
2494 if TryStrToNumeric(Value,Int64Value,aScale) then
2495 SetAsNumeric(NumericFromRawValues(Int64Value,aScale))
2496 else
2497 DoSetString;
2498
2499 SQL_DEC_FIXED,
2500 SQL_DEC16,
2501 SQL_DEC34,
2502 SQL_INT128:
2503 if TryStrToBCD(Value,BCDValue) then
2504 SetAsNumeric(NewNumeric(BCDValue))
2505 else
2506 DoSetString;
2507
2508 SQL_D_FLOAT,
2509 SQL_DOUBLE,
2510 SQL_FLOAT:
2511 if TryStrToNumeric(Value,Int64Value,aScale) then
2512 SetAsNumeric(NumericFromRawValues(Int64Value,AScale))
2513 else
2514 DoSetString;
2515
2516 SQL_TIMESTAMP:
2517 if TryStrToDateTime(Value,dt) then
2518 SetAsDateTime(dt)
2519 else
2520 DoSetString;
2521
2522 SQL_TYPE_DATE:
2523 if TryStrToDateTime(Value,dt) then
2524 SetAsDate(dt)
2525 else
2526 DoSetString;
2527
2528 SQL_TYPE_TIME:
2529 if TryStrToDateTime(Value,dt) then
2530 SetAsTime(dt)
2531 else
2532 DoSetString;
2533
2534 SQL_TIMESTAMP_TZ,
2535 SQL_TIMESTAMP_TZ_EX:
2536 if ParseDateTimeTZString(value,dt,timezone) then
2537 SetAsDateTime(dt,timezone)
2538 else
2539 DoSetString;
2540
2541 SQL_TIME_TZ,
2542 SQL_TIME_TZ_EX:
2543 if ParseDateTimeTZString(value,dt,timezone,true) then
2544 SetAsTime(dt,GetAttachment.GetTimeZoneServices.GetTimeTZDate,timezone)
2545 else
2546 DoSetString;
2547
2548 else
2549 IBError(ibxeInvalidDataConversion,[GetSQLTypeName(getColMetaData.SQLTYPE)]);
2550 end;
2551 end;
2552
2553 procedure TSQLParam.CheckActive;
2554 begin
2555 if not FIBXSQLVAR.Parent.StateChanged(FChangeSeqNo) then Exit;
2556
2557 if FPrepareSeqNo < FIBXSQLVAR.Parent.GetPrepareSeqNo then
2558 IBError(ibxeInterfaceOutofDate,[nil]);
2559
2560 if not FIBXSQLVAR.Parent.CheckStatementStatus(ssPrepared) then
2561 IBError(ibxeStatementNotPrepared, [nil]);
2562 end;
2563
2564 procedure TSQLParam.SetScale(aValue: integer);
2565 begin
2566 CheckActive;
2567 FIBXSQLVAR.Scale := aValue;
2568 end;
2569
2570 procedure TSQLParam.SetDataLength(len: cardinal);
2571 begin
2572 CheckActive;
2573 FIBXSQLVAR.DataLength := len;
2574 end;
2575
2576 procedure TSQLParam.SetSQLType(aValue: cardinal);
2577 begin
2578 CheckActive;
2579 FIBXSQLVAR.SQLType := aValue;
2580 end;
2581
2582 procedure TSQLParam.Clear;
2583 begin
2584 IsNull := true;
2585 end;
2586
2587 function TSQLParam.CanChangeMetaData: boolean;
2588 begin
2589 Result := FIBXSQLVAR.CanChangeMetaData;
2590 end;
2591
2592 function TSQLParam.getColMetadata: IParamMetaData;
2593 begin
2594 Result := FIBXSQLVAR.getColMetadata;
2595 end;
2596
2597 function TSQLParam.GetModified: boolean;
2598 begin
2599 CheckActive;
2600 Result := FIBXSQLVAR.Modified;
2601 end;
2602
2603 function TSQLParam.GetAsPointer: Pointer;
2604 begin
2605 IsNull := false; {Assume that we get the pointer in order to set a value}
2606 Changed;
2607 Result := inherited GetAsPointer;
2608 end;
2609
2610 function TSQLParam.GetAsString: AnsiString;
2611 var rs: RawByteString;
2612 begin
2613 Result := '';
2614 if (SQLType = SQL_VARYING) and not IsNull then
2615 {SQLData points to start of string - default is to length word}
2616 begin
2617 CheckActive;
2618 SetString(rs,PAnsiChar(SQLData),DataLength);
2619 SetCodePage(rs,GetCodePage,false);
2620 Result := rs;
2621 end
2622 else
2623 Result := inherited GetAsString;
2624 end;
2625
2626 procedure TSQLParam.SetName(Value: AnsiString);
2627 begin
2628 CheckActive;
2629 FIBXSQLVAR.Name := Value;
2630 end;
2631
2632 procedure TSQLParam.SetIsNull(Value: Boolean);
2633 var i: integer;
2634 begin
2635 CheckActive;
2636 if FIBXSQLVAR.UniqueName then
2637 FIBXSQLVAR.IsNull := Value
2638 else
2639 with FIBXSQLVAR.Parent do
2640 begin
2641 for i := 0 to Count - 1 do
2642 if Column[i].Name = Name then
2643 Column[i].IsNull := Value;
2644 end
2645 end;
2646
2647 procedure TSQLParam.SetIsNullable(Value: Boolean);
2648 var i: integer;
2649 begin
2650 CheckActive;
2651 if FIBXSQLVAR.UniqueName then
2652 FIBXSQLVAR.IsNullable := Value
2653 else
2654 with FIBXSQLVAR.Parent do
2655 begin
2656 for i := 0 to Count - 1 do
2657 if Column[i].Name = Name then
2658 Column[i].IsNullable := Value;
2659 end
2660 end;
2661
2662 procedure TSQLParam.SetAsArray(anArray: IArray);
2663 begin
2664 CheckActive;
2665 if GetSQLType <> SQL_ARRAY then
2666 IBError(ibxeInvalidDataConversion,[nil]);
2667
2668 if not FIBXSQLVAR.UniqueName then
2669 IBError(ibxeDuplicateParamName,[FIBXSQLVAR.Name]);
2670
2671 FIBXSQLVAR.SetArray(anArray); {save array interface}
2672 SetAsQuad(AnArray.GetArrayID);
2673 end;
2674
2675 procedure TSQLParam.Changed;
2676 begin
2677 FIBXSQLVAR.Changed;
2678 end;
2679
2680 procedure TSQLParam.SetAsBoolean(AValue: boolean);
2681 var i: integer;
2682 OldSQLVar: TSQLVarData;
2683 begin
2684 if FIBXSQLVAR.UniqueName then
2685 inherited SetAsBoolean(AValue)
2686 else
2687 with FIBXSQLVAR.Parent do
2688 begin
2689 for i := 0 to Count - 1 do
2690 if Column[i].Name = Name then
2691 begin
2692 OldSQLVar := FIBXSQLVAR;
2693 FIBXSQLVAR := Column[i];
2694 try
2695 inherited SetAsBoolean(AValue);
2696 finally
2697 FIBXSQLVAR := OldSQLVar;
2698 end;
2699 end;
2700 end;
2701 end;
2702
2703 procedure TSQLParam.SetAsCurrency(AValue: Currency);
2704 var i: integer;
2705 OldSQLVar: TSQLVarData;
2706 begin
2707 if FIBXSQLVAR.UniqueName then
2708 inherited SetAsCurrency(AValue)
2709 else
2710 with FIBXSQLVAR.Parent do
2711 begin
2712 for i := 0 to Count - 1 do
2713 if Column[i].Name = Name then
2714 begin
2715 OldSQLVar := FIBXSQLVAR;
2716 FIBXSQLVAR := Column[i];
2717 try
2718 inherited SetAsCurrency(AValue);
2719 finally
2720 FIBXSQLVAR := OldSQLVar;
2721 end;
2722 end;
2723 end;
2724 end;
2725
2726 procedure TSQLParam.SetAsInt64(AValue: Int64);
2727 var i: integer;
2728 OldSQLVar: TSQLVarData;
2729 begin
2730 if FIBXSQLVAR.UniqueName then
2731 inherited SetAsInt64(AValue)
2732 else
2733 with FIBXSQLVAR.Parent do
2734 begin
2735 for i := 0 to Count - 1 do
2736 if Column[i].Name = Name then
2737 begin
2738 OldSQLVar := FIBXSQLVAR;
2739 FIBXSQLVAR := Column[i];
2740 try
2741 inherited SetAsInt64(AValue);
2742 finally
2743 FIBXSQLVAR := OldSQLVar;
2744 end;
2745 end;
2746 end;
2747 end;
2748
2749 procedure TSQLParam.SetAsDate(AValue: TDateTime);
2750 var i: integer;
2751 OldSQLVar: TSQLVarData;
2752 begin
2753 if FIBXSQLVAR.UniqueName then
2754 inherited SetAsDate(AValue)
2755 else
2756 with FIBXSQLVAR.Parent do
2757 begin
2758 for i := 0 to Count - 1 do
2759 if Column[i].Name = Name then
2760 begin
2761 OldSQLVar := FIBXSQLVAR;
2762 FIBXSQLVAR := Column[i];
2763 try
2764 inherited SetAsDate(AValue);
2765 finally
2766 FIBXSQLVAR := OldSQLVar;
2767 end;
2768 end;
2769 end;
2770 end;
2771
2772 procedure TSQLParam.SetAsLong(AValue: Long);
2773 var i: integer;
2774 OldSQLVar: TSQLVarData;
2775 begin
2776 if FIBXSQLVAR.UniqueName then
2777 inherited SetAsLong(AValue)
2778 else
2779 with FIBXSQLVAR.Parent do
2780 begin
2781 for i := 0 to Count - 1 do
2782 if Column[i].Name = Name then
2783 begin
2784 OldSQLVar := FIBXSQLVAR;
2785 FIBXSQLVAR := Column[i];
2786 try
2787 inherited SetAsLong(AValue);
2788 finally
2789 FIBXSQLVAR := OldSQLVar;
2790 end;
2791 end;
2792 end;
2793 end;
2794
2795 procedure TSQLParam.SetAsTime(AValue: TDateTime);
2796 var i: integer;
2797 OldSQLVar: TSQLVarData;
2798 begin
2799 if FIBXSQLVAR.UniqueName then
2800 inherited SetAsTime(AValue)
2801 else
2802 with FIBXSQLVAR.Parent do
2803 begin
2804 for i := 0 to Count - 1 do
2805 if Column[i].Name = Name then
2806 begin
2807 OldSQLVar := FIBXSQLVAR;
2808 FIBXSQLVAR := Column[i];
2809 try
2810 inherited SetAsTime(AValue);
2811 finally
2812 FIBXSQLVAR := OldSQLVar;
2813 end;
2814 end;
2815 end;
2816 end;
2817
2818 procedure TSQLParam.SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZoneID: TFBTimeZoneID);
2819 var i: integer;
2820 OldSQLVar: TSQLVarData;
2821 begin
2822 if FIBXSQLVAR.UniqueName then
2823 inherited SetAsTime(AValue,OnDate, aTimeZoneID)
2824 else
2825 with FIBXSQLVAR.Parent do
2826 begin
2827 for i := 0 to Count - 1 do
2828 if Column[i].Name = Name then
2829 begin
2830 OldSQLVar := FIBXSQLVAR;
2831 FIBXSQLVAR := Column[i];
2832 try
2833 inherited SetAsTime(AValue,OnDate, aTimeZoneID);
2834 finally
2835 FIBXSQLVAR := OldSQLVar;
2836 end;
2837 end;
2838 end;
2839 end;
2840
2841 procedure TSQLParam.SetAsTime(aValue: TDateTime; OnDate: TDateTime; aTimeZone: AnsiString);
2842 var i: integer;
2843 OldSQLVar: TSQLVarData;
2844 begin
2845 if FIBXSQLVAR.UniqueName then
2846 inherited SetAsTime(AValue,OnDate,aTimeZone)
2847 else
2848 with FIBXSQLVAR.Parent do
2849 begin
2850 for i := 0 to Count - 1 do
2851 if Column[i].Name = Name then
2852 begin
2853 OldSQLVar := FIBXSQLVAR;
2854 FIBXSQLVAR := Column[i];
2855 try
2856 inherited SetAsTime(AValue,OnDate,aTimeZone);
2857 finally
2858 FIBXSQLVAR := OldSQLVar;
2859 end;
2860 end;
2861 end;
2862 end;
2863
2864 procedure TSQLParam.SetAsTime(aValue: TDateTime; aTimeZoneID: TFBTimeZoneID);
2865 begin
2866 SetAsTime(aValue,GetTimeZoneServices.GetTimeTZDate,aTimeZoneID);
2867 end;
2868
2869 procedure TSQLParam.SetAsTime(aValue: TDateTime; aTimeZone: AnsiString);
2870 begin
2871 SetAsTime(aValue,GetTimeZoneServices.GetTimeTZDate,aTimeZone);
2872 end;
2873
2874 procedure TSQLParam.SetAsDateTime(AValue: TDateTime);
2875 var i: integer;
2876 OldSQLVar: TSQLVarData;
2877 begin
2878 if FIBXSQLVAR.UniqueName then
2879 inherited SetAsDateTime(AValue)
2880 else
2881 with FIBXSQLVAR.Parent do
2882 begin
2883 for i := 0 to Count - 1 do
2884 if Column[i].Name = Name then
2885 begin
2886 OldSQLVar := FIBXSQLVAR;
2887 FIBXSQLVAR := Column[i];
2888 try
2889 inherited SetAsDateTime(AValue);
2890 finally
2891 FIBXSQLVAR := OldSQLVar;
2892 end;
2893 end;
2894 end;
2895 end;
2896
2897 procedure TSQLParam.SetAsDateTime(aValue: TDateTime; aTimeZoneID: TFBTimeZoneID
2898 );
2899 var i: integer;
2900 OldSQLVar: TSQLVarData;
2901 begin
2902 if FIBXSQLVAR.UniqueName then
2903 inherited SetAsDateTime(AValue,aTimeZoneID)
2904 else
2905 with FIBXSQLVAR.Parent do
2906 begin
2907 for i := 0 to Count - 1 do
2908 if Column[i].Name = Name then
2909 begin
2910 OldSQLVar := FIBXSQLVAR;
2911 FIBXSQLVAR := Column[i];
2912 try
2913 inherited SetAsDateTime(AValue,aTimeZoneID);
2914 finally
2915 FIBXSQLVAR := OldSQLVar;
2916 end;
2917 end;
2918 end;
2919 end;
2920
2921 procedure TSQLParam.SetAsDateTime(aValue: TDateTime; aTimeZone: AnsiString);
2922 var i: integer;
2923 OldSQLVar: TSQLVarData;
2924 begin
2925 if FIBXSQLVAR.UniqueName then
2926 inherited SetAsDateTime(AValue,aTimeZone)
2927 else
2928 with FIBXSQLVAR.Parent do
2929 begin
2930 for i := 0 to Count - 1 do
2931 if Column[i].Name = Name then
2932 begin
2933 OldSQLVar := FIBXSQLVAR;
2934 FIBXSQLVAR := Column[i];
2935 try
2936 inherited SetAsDateTime(AValue,aTimeZone);
2937 finally
2938 FIBXSQLVAR := OldSQLVar;
2939 end;
2940 end;
2941 end;
2942 end;
2943
2944 procedure TSQLParam.SetAsDouble(AValue: Double);
2945 var i: integer;
2946 OldSQLVar: TSQLVarData;
2947 begin
2948 if FIBXSQLVAR.UniqueName then
2949 inherited SetAsDouble(AValue)
2950 else
2951 with FIBXSQLVAR.Parent do
2952 begin
2953 for i := 0 to Count - 1 do
2954 if Column[i].Name = Name then
2955 begin
2956 OldSQLVar := FIBXSQLVAR;
2957 FIBXSQLVAR := Column[i];
2958 try
2959 inherited SetAsDouble(AValue);
2960 finally
2961 FIBXSQLVAR := OldSQLVar;
2962 end;
2963 end;
2964 end;
2965 end;
2966
2967 procedure TSQLParam.SetAsFloat(AValue: Float);
2968 var i: integer;
2969 OldSQLVar: TSQLVarData;
2970 begin
2971 if FIBXSQLVAR.UniqueName then
2972 inherited SetAsFloat(AValue)
2973 else
2974 with FIBXSQLVAR.Parent do
2975 begin
2976 for i := 0 to Count - 1 do
2977 if Column[i].Name = Name then
2978 begin
2979 OldSQLVar := FIBXSQLVAR;
2980 FIBXSQLVAR := Column[i];
2981 try
2982 inherited SetAsFloat(AValue);
2983 finally
2984 FIBXSQLVAR := OldSQLVar;
2985 end;
2986 end;
2987 end;
2988 end;
2989
2990 procedure TSQLParam.SetAsPointer(AValue: Pointer);
2991 var i: integer;
2992 OldSQLVar: TSQLVarData;
2993 begin
2994 if FIBXSQLVAR.UniqueName then
2995 inherited SetAsPointer(AValue)
2996 else
2997 with FIBXSQLVAR.Parent do
2998 begin
2999 for i := 0 to Count - 1 do
3000 if Column[i].Name = Name then
3001 begin
3002 OldSQLVar := FIBXSQLVAR;
3003 FIBXSQLVAR := Column[i];
3004 try
3005 inherited SetAsPointer(AValue);
3006 finally
3007 FIBXSQLVAR := OldSQLVar;
3008 end;
3009 end;
3010 end;
3011 end;
3012
3013 procedure TSQLParam.SetAsShort(AValue: Short);
3014 var i: integer;
3015 OldSQLVar: TSQLVarData;
3016 begin
3017 if FIBXSQLVAR.UniqueName then
3018 inherited SetAsShort(AValue)
3019 else
3020 with FIBXSQLVAR.Parent do
3021 begin
3022 for i := 0 to Count - 1 do
3023 if Column[i].Name = Name then
3024 begin
3025 OldSQLVar := FIBXSQLVAR;
3026 FIBXSQLVAR := Column[i];
3027 try
3028 inherited SetAsShort(AValue);
3029 finally
3030 FIBXSQLVAR := OldSQLVar;
3031 end;
3032 end;
3033 end;
3034 end;
3035
3036 procedure TSQLParam.SetAsString(AValue: AnsiString);
3037 var i: integer;
3038 OldSQLVar: TSQLVarData;
3039 begin
3040 if FIBXSQLVAR.UniqueName then
3041 InternalSetAsString(AValue)
3042 else
3043 with FIBXSQLVAR.Parent do
3044 begin
3045 for i := 0 to Count - 1 do
3046 if Column[i].Name = Name then
3047 begin
3048 OldSQLVar := FIBXSQLVAR;
3049 FIBXSQLVAR := Column[i];
3050 try
3051 InternalSetAsString(AValue);
3052 finally
3053 FIBXSQLVAR := OldSQLVar;
3054 end;
3055 end;
3056 end;
3057 end;
3058
3059 procedure TSQLParam.SetAsVariant(AValue: Variant);
3060 var i: integer;
3061 OldSQLVar: TSQLVarData;
3062 begin
3063 if FIBXSQLVAR.UniqueName then
3064 inherited SetAsVariant(AValue)
3065 else
3066 with FIBXSQLVAR.Parent do
3067 begin
3068 for i := 0 to Count - 1 do
3069 if Column[i].Name = Name then
3070 begin
3071 OldSQLVar := FIBXSQLVAR;
3072 FIBXSQLVAR := Column[i];
3073 try
3074 inherited SetAsVariant(AValue);
3075 finally
3076 FIBXSQLVAR := OldSQLVar;
3077 end;
3078 end;
3079 end;
3080 end;
3081
3082 procedure TSQLParam.SetAsBlob(aValue: IBlob);
3083 begin
3084 with FIBXSQLVAR do
3085 if not UniqueName then
3086 IBError(ibxeDuplicateParamName,[Name]);
3087 CheckActive;
3088 Changing;
3089 aValue.Close;
3090 if aValue.GetSubType <> GetSubType then
3091 IBError(ibxeIncompatibleBlob,[GetSubType,aValue.GetSubType]);
3092 AsQuad := aValue.GetBlobID;
3093 Changed;
3094 end;
3095
3096 procedure TSQLParam.SetAsQuad(AValue: TISC_QUAD);
3097 var i: integer;
3098 OldSQLVar: TSQLVarData;
3099 begin
3100 if FIBXSQLVAR.UniqueName then
3101 inherited SetAsQuad(AValue)
3102 else
3103 with FIBXSQLVAR.Parent do
3104 begin
3105 for i := 0 to Count - 1 do
3106 if Column[i].Name = Name then
3107 begin
3108 OldSQLVar := FIBXSQLVAR;
3109 FIBXSQLVAR := Column[i];
3110 try
3111 inherited SetAsQuad(AValue);
3112 finally
3113 FIBXSQLVAR := OldSQLVar;
3114 end;
3115 end;
3116 end;
3117 end;
3118
3119 procedure TSQLParam.SetCharSetID(aValue: cardinal);
3120 begin
3121 FIBXSQLVAR.SetCharSetID(aValue);
3122 end;
3123
3124 procedure TSQLParam.SetAsBcd(aValue: tBCD);
3125 var i: integer;
3126 OldSQLVar: TSQLVarData;
3127 begin
3128 if FIBXSQLVAR.UniqueName then
3129 inherited SetAsBcd(AValue)
3130 else
3131 with FIBXSQLVAR.Parent do
3132 begin
3133 for i := 0 to Count - 1 do
3134 if Column[i].Name = Name then
3135 begin
3136 OldSQLVar := FIBXSQLVAR;
3137 FIBXSQLVAR := Column[i];
3138 try
3139 inherited SetAsBcd(AValue);
3140 finally
3141 FIBXSQLVAR := OldSQLVar;
3142 end;
3143 end;
3144 end;
3145 end;
3146
3147 procedure TSQLParam.SetAsNumeric(aValue: IFBNumeric);
3148 var i: integer;
3149 OldSQLVar: TSQLVarData;
3150 begin
3151 if FIBXSQLVAR.UniqueName then
3152 inherited SetAsNumeric(AValue)
3153 else
3154 with FIBXSQLVAR.Parent do
3155 begin
3156 for i := 0 to Count - 1 do
3157 if Column[i].Name = Name then
3158 begin
3159 OldSQLVar := FIBXSQLVAR;
3160 FIBXSQLVAR := Column[i];
3161 try
3162 inherited SetAsNumeric(AValue);
3163 finally
3164 FIBXSQLVAR := OldSQLVar;
3165 end;
3166 end;
3167 end;
3168 end;
3169
3170 { TMetaData }
3171
3172 procedure TMetaData.CheckActive;
3173 begin
3174 if FPrepareSeqNo < FMetaData.PrepareSeqNo then
3175 IBError(ibxeInterfaceOutofDate,[nil]);
3176
3177 if not FMetaData.CheckStatementStatus(ssPrepared) then
3178 IBError(ibxeStatementNotPrepared, [nil]);
3179 end;
3180
3181 constructor TMetaData.Create(aMetaData: TSQLDataArea);
3182 begin
3183 inherited Create(aMetaData.Count);
3184 FMetaData := aMetaData;
3185 FStatement := aMetaData.Statement;
3186 FPrepareSeqNo := aMetaData.PrepareSeqNo;
3187 end;
3188
3189 destructor TMetaData.Destroy;
3190 begin
3191 if FStatement <> nil then
3192 (FStatement as TInterfaceOwner).Remove(self);
3193 inherited Destroy;
3194 end;
3195
3196 function TMetaData.GetUniqueRelationName: AnsiString;
3197 begin
3198 CheckActive;
3199 Result := FMetaData.UniqueRelationName;
3200 end;
3201
3202 function TMetaData.getCount: integer;
3203 begin
3204 CheckActive;
3205 Result := FMetaData.ColumnsInUseCount;
3206 end;
3207
3208 function TMetaData.getColumnMetaData(index: integer): IColumnMetaData;
3209 begin
3210 CheckActive;
3211 if (index < 0) or (index >= getCount) then
3212 IBError(ibxeInvalidColumnIndex,[nil]);
3213
3214 if FMetaData.Count = 0 then
3215 Result := nil
3216 else
3217 begin
3218 if not HasInterface(index) then
3219 AddInterface(index,TColumnMetaData.Create(self,FMetaData.Column[index]));
3220 Result := TColumnMetaData(GetInterface(index));
3221 end;
3222 end;
3223
3224 function TMetaData.ByName(Idx: AnsiString): IColumnMetaData;
3225 var aIBXSQLVAR: TSQLVarData;
3226 begin
3227 CheckActive;
3228 aIBXSQLVAR := FMetaData.ColumnByName(Idx);
3229 if aIBXSQLVAR = nil then
3230 IBError(ibxeFieldNotFound,[Idx]);
3231 Result := getColumnMetaData(aIBXSQLVAR.index);
3232 end;
3233
3234 { TSQLParams }
3235
3236 procedure TSQLParams.CheckActive;
3237 begin
3238 if not FSQLParams.StateChanged(FChangeSeqNo) then Exit;
3239
3240 if FPrepareSeqNo < FSQLParams.PrepareSeqNo then
3241 IBError(ibxeInterfaceOutofDate,[nil]);
3242
3243 if not FSQLParams.CheckStatementStatus(ssPrepared) then
3244 IBError(ibxeStatementNotPrepared, [nil]);
3245 end;
3246
3247 constructor TSQLParams.Create(aSQLParams: TSQLDataArea);
3248 begin
3249 inherited Create(aSQLParams.Count);
3250 FSQLParams := aSQLParams;
3251 FStatement := aSQLParams.Statement;
3252 FPrepareSeqNo := aSQLParams.PrepareSeqNo;
3253 FSQLParams.StateChanged(FChangeSeqNo);
3254 end;
3255
3256 destructor TSQLParams.Destroy;
3257 begin
3258 if FStatement <> nil then
3259 (FStatement as TInterfaceOwner).Remove(self);
3260 inherited Destroy;
3261 end;
3262
3263 function TSQLParams.getCount: integer;
3264 begin
3265 CheckActive;
3266 Result := FSQLParams.ColumnsInUseCount;
3267 end;
3268
3269 function TSQLParams.getSQLParam(index: integer): ISQLParam;
3270 begin
3271 CheckActive;
3272 if (index < 0) or (index >= getCount) then
3273 IBError(ibxeInvalidColumnIndex,[nil]);
3274
3275 if getCount = 0 then
3276 Result := nil
3277 else
3278 begin
3279 if not HasInterface(index) then
3280 AddInterface(index, TSQLParam.Create(self,FSQLParams.Column[index]));
3281 Result := TSQLParam(GetInterface(index));
3282 end;
3283 end;
3284
3285 function TSQLParams.ByName(Idx: AnsiString): ISQLParam;
3286 var aIBXSQLVAR: TSQLVarData;
3287 begin
3288 CheckActive;
3289 aIBXSQLVAR := FSQLParams.ColumnByName(Idx);
3290 if aIBXSQLVAR = nil then
3291 IBError(ibxeFieldNotFound,[Idx]);
3292 Result := getSQLParam(aIBXSQLVAR.index);
3293 end;
3294
3295 function TSQLParams.GetModified: Boolean;
3296 var
3297 i: Integer;
3298 begin
3299 CheckActive;
3300 result := False;
3301 with FSQLParams do
3302 for i := 0 to Count - 1 do
3303 if Column[i].Modified then
3304 begin
3305 result := True;
3306 exit;
3307 end;
3308 end;
3309
3310 function TSQLParams.GetHasCaseSensitiveParams: Boolean;
3311 begin
3312 Result := FSQLParams.CaseSensitiveParams;
3313 end;
3314
3315 function TSQLParams.GetStatement: IStatement;
3316 begin
3317 Result := FSQLParams.GetStatement;
3318 end;
3319
3320 function TSQLParams.GetTransaction: ITransaction;
3321 begin
3322 Result := FSQLParams.GetTransaction;
3323 end;
3324
3325 function TSQLParams.GetAttachment: IAttachment;
3326 begin
3327 Result := FSQLParams.GetAttachment;
3328 end;
3329
3330 procedure TSQLParams.Clear;
3331 var i: integer;
3332 begin
3333 for i := 0 to getCount - 1 do
3334 getSQLParam(i).Clear;
3335 end;
3336
3337 { TResults }
3338
3339 procedure TResults.CheckActive;
3340 begin
3341 if not FResults.StateChanged(FChangeSeqNo) then Exit;
3342
3343 if FPrepareSeqNo < FResults.PrepareSeqNo then
3344 IBError(ibxeInterfaceOutofDate,[nil]);
3345
3346 if not FResults.CheckStatementStatus(ssPrepared) then
3347 IBError(ibxeStatementNotPrepared, [nil]);
3348
3349 with GetTransaction do
3350 if not InTransaction or (FResults.TransactionSeqNo <> FTransactionSeqNo) then
3351 IBError(ibxeInterfaceOutofDate,[nil]);
3352 end;
3353
3354 function TResults.GetISQLData(aIBXSQLVAR: TSQLVarData): ISQLData;
3355 var col: TIBSQLData;
3356 begin
3357 if (aIBXSQLVAR.Index < 0) or (aIBXSQLVAR.Index >= getCount) then
3358 IBError(ibxeInvalidColumnIndex,[nil]);
3359
3360 if not HasInterface(aIBXSQLVAR.Index) then
3361 begin
3362 col := TIBSQLData.Create(self,aIBXSQLVAR);
3363 AddInterface(aIBXSQLVAR.Index, col);
3364 end
3365 else
3366 col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
3367 Result := col;
3368 end;
3369
3370 constructor TResults.Create(aResults: TSQLDataArea);
3371 begin
3372 inherited Create(aResults.Count);
3373 FResults := aResults;
3374 FStatement := aResults.Statement;
3375 FPrepareSeqNo := aResults.PrepareSeqNo;
3376 FTransactionSeqNo := aResults.TransactionSeqNo;
3377 FResults.StateChanged(FChangeSeqNo);
3378 end;
3379
3380 function TResults.getCount: integer;
3381 begin
3382 CheckActive;
3383 Result := FResults.Count;
3384 end;
3385
3386 function TResults.ByName(Idx: AnsiString): ISQLData;
3387 var col: TSQLVarData;
3388 begin
3389 Result := nil;
3390 CheckActive;
3391 if FResults.CheckStatementStatus(ssBOF) then
3392 IBError(ibxeBOF,[nil]);
3393 if FResults.CheckStatementStatus(ssEOF) then
3394 IBError(ibxeEOF,[nil]);
3395
3396 if FResults.Count > 0 then
3397 begin
3398 col := FResults.ColumnByName(Idx);
3399 if col <> nil then
3400 Result := GetISQLData(col);
3401 end;
3402 end;
3403
3404 function TResults.getSQLData(index: integer): ISQLData;
3405 begin
3406 CheckActive;
3407 if FResults.CheckStatementStatus(ssBOF) then
3408 IBError(ibxeBOF,[nil]);
3409 if FResults.CheckStatementStatus(ssEOF) then
3410 IBError(ibxeEOF,[nil]);
3411 if (index < 0) or (index >= FResults.Count) then
3412 IBError(ibxeInvalidColumnIndex,[nil]);
3413
3414 Result := GetISQLData(FResults.Column[index]);
3415 end;
3416
3417 procedure TResults.GetData(index: integer; var IsNull: boolean; var len: short;
3418 var data: PByte);
3419 begin
3420 CheckActive;
3421 FResults.GetData(index,IsNull, len,data);
3422 end;
3423
3424 function TResults.GetStatement: IStatement;
3425 begin
3426 Result := FStatement;
3427 end;
3428
3429 function TResults.GetTransaction: ITransaction;
3430 begin
3431 Result := FResults.GetTransaction;
3432 end;
3433
3434 function TResults.GetAttachment: IAttachment;
3435 begin
3436 Result := FResults.GetAttachment;
3437 end;
3438
3439 procedure TResults.SetRetainInterfaces(aValue: boolean);
3440 begin
3441 RetainInterfaces := aValue;
3442 end;
3443
3444 end.
3445