ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBSQLData.pas
Revision: 371
Committed: Wed Jan 5 15:21:22 2022 UTC (2 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 92624 byte(s)
Log Message:
Beta Release 0.1

File Contents

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