ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBSQLData.pas
Revision: 391
Committed: Thu Jan 27 16:34:24 2022 UTC (2 years, 9 months ago) by tony
Content type: text/x-pascal
File size: 93459 byte(s)
Log Message:
Fix issues with a select procedure returning an empty dataset

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

Properties

Name Value
svn:eol-style native