ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/fbintf/client/FBSQLData.pas
(Generate patch)

Comparing ibx/trunk/fbintf/client/FBSQLData.pas (file contents):
Revision 47 by tony, Mon Jan 9 15:31:51 2017 UTC vs.
Revision 291 by tony, Fri Apr 17 10:26:08 2020 UTC

# Line 60 | Line 60
60   {                                                                        }
61   {************************************************************************}
62   unit FBSQLData;
63 + {$IFDEF MSWINDOWS}
64 + {$DEFINE WINDOWS}
65 + {$ENDIF}
66  
67   {$IFDEF FPC}
68 < {$mode objfpc}{$H+}
68 > {$mode delphi}
69   {$codepage UTF8}
70   {$interfaces COM}
71   {$ENDIF}
# Line 73 | Line 76 | unit FBSQLData;
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  
76 { $define ALLOWDIALECT3PARAMNAMES}
77
78 {$ifndef ALLOWDIALECT3PARAMNAMES}
79
80 { Note on SQL Dialects and SQL Parameter Names
81  --------------------------------------------
82
83  Even when dialect 3 quoted format parameter names are not supported, IBX still processes
84  parameter names case insensitive. This does result in some additional overhead
85  due to a call to "AnsiUpperCase". This can be avoided by undefining
86  "UseCaseInSensitiveParamName" below.
87
88  Note: do not define "UseCaseSensitiveParamName" when "ALLOWDIALECT3PARAMNAMES"
89  is defined. This will not give a useful result.
90 }
91 {$define UseCaseInSensitiveParamName}
92 {$endif}
79  
80   interface
81  
82   uses
83 <  Classes, SysUtils, IBExternals, IBHeader, IB,  FBActivityMonitor;
83 >  Classes, SysUtils, IBExternals, IBHeader, IB,  FBActivityMonitor, FBClientAPI;
84  
85   type
86  
# Line 102 | Line 88 | type
88  
89    TSQLDataItem = class(TFBInterfacedObject)
90    private
91 +     FFirebirdClientAPI: TFBClientAPI;
92       function AdjustScale(Value: Int64; aScale: Integer): Double;
93       function AdjustScaleToInt64(Value: Int64; aScale: Integer): Int64;
94       function AdjustScaleToCurrency(Value: Int64; aScale: Integer): Currency;
95 +     function GetTimestampFormatStr: AnsiString;
96 +     function GetDateFormatStr(IncludeTime: boolean): AnsiString;
97 +     function GetTimeFormatStr: AnsiString;
98       procedure SetAsInteger(AValue: Integer);
99    protected
100       function AdjustScaleFromCurrency(Value: Currency; aScale: Integer): Int64;
# Line 113 | Line 103 | type
103       function GetSQLDialect: integer; virtual; abstract;
104       procedure Changed; virtual;
105       procedure Changing; virtual;
106 <     procedure InternalSetAsString(Value: String); virtual;
107 <     function SQLData: PChar; virtual; abstract;
106 >     procedure InternalSetAsString(Value: AnsiString); virtual;
107 >     function SQLData: PByte; virtual; abstract;
108       function GetDataLength: cardinal; virtual; abstract;
109       function GetCodePage: TSystemCodePage; virtual; abstract;
110       function getCharSetID: cardinal; virtual; abstract;
111 <     function Transliterate(s: string; CodePage: TSystemCodePage): RawByteString;
111 >     function Transliterate(s: AnsiString; CodePage: TSystemCodePage): RawByteString;
112       procedure SetScale(aValue: integer); virtual;
113       procedure SetDataLength(len: cardinal); virtual;
114       procedure SetSQLType(aValue: cardinal); virtual;
115       property DataLength: cardinal read GetDataLength write SetDataLength;
116  
117    public
118 +     constructor Create(api: TFBClientAPI);
119       function GetSQLType: cardinal; virtual; abstract;
120 <     function GetSQLTypeName: string; overload;
121 <     class function GetSQLTypeName(SQLType: short): string; overload;
122 <     function GetName: string; virtual; abstract;
120 >     function GetSQLTypeName: AnsiString; overload;
121 >     class function GetSQLTypeName(SQLType: short): AnsiString; overload;
122 >     function GetStrDataLength: short;
123 >     function GetName: AnsiString; virtual; abstract;
124       function GetScale: integer; virtual; abstract;
125       function GetAsBoolean: boolean;
126       function GetAsCurrency: Currency;
# Line 140 | Line 132 | type
132       function GetAsPointer: Pointer;
133       function GetAsQuad: TISC_QUAD;
134       function GetAsShort: short;
135 <     function GetAsString: String; virtual;
135 >     function GetAsString: AnsiString; virtual;
136       function GetIsNull: Boolean; virtual;
137 <     function getIsNullable: boolean; virtual;
137 >     function GetIsNullable: boolean; virtual;
138       function GetAsVariant: Variant;
139       function GetModified: boolean; virtual;
140 +     function GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats): integer;
141       procedure SetAsBoolean(AValue: boolean); virtual;
142       procedure SetAsCurrency(Value: Currency); virtual;
143       procedure SetAsInt64(Value: Int64); virtual;
# Line 157 | Line 150 | type
150       procedure SetAsPointer(Value: Pointer);
151       procedure SetAsQuad(Value: TISC_QUAD);
152       procedure SetAsShort(Value: short); virtual;
153 <     procedure SetAsString(Value: String); virtual;
153 >     procedure SetAsString(Value: AnsiString); virtual;
154       procedure SetAsVariant(Value: Variant);
155 +     procedure SetAsNumeric(Value: Int64; aScale: integer);
156       procedure SetIsNull(Value: Boolean); virtual;
157       procedure SetIsNullable(Value: Boolean); virtual;
158 <     procedure SetName(aValue: string); virtual;
158 >     procedure SetName(aValue: AnsiString); virtual;
159       property AsDate: TDateTime read GetAsDateTime write SetAsDate;
160       property AsBoolean:boolean read GetAsBoolean write SetAsBoolean;
161       property AsTime: TDateTime read GetAsDateTime write SetAsTime;
# Line 175 | Line 169 | type
169       property AsPointer: Pointer read GetAsPointer write SetAsPointer;
170       property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
171       property AsShort: short read GetAsShort write SetAsShort;
172 <     property AsString: String read GetAsString write SetAsString;
172 >     property AsString: AnsiString read GetAsString write SetAsString;
173       property AsVariant: Variant read GetAsVariant write SetAsVariant;
174       property Modified: Boolean read getModified;
175       property IsNull: Boolean read GetIsNull write SetIsNull;
# Line 192 | Line 186 | type
186  
187    TSQLDataArea = class
188    private
189 +    FCaseSensitiveParams: boolean;
190      function GetColumn(index: integer): TSQLVarData;
191      function GetCount: integer;
192    protected
193 <    FUniqueRelationName: string;
193 >    FUniqueRelationName: AnsiString;
194      FColumnList: array of TSQLVarData;
195      function GetStatement: IStatement; virtual; abstract;
196      function GetPrepareSeqNo: integer; virtual; abstract;
# Line 205 | Line 200 | type
200    public
201      procedure Initialize; virtual;
202      function IsInputDataArea: boolean; virtual; abstract; {Input to Database}
203 <    procedure PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
204 <      var sProcessedSQL: string);
203 >    procedure PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
204 >      var sProcessedSQL: AnsiString);
205      function ColumnsInUseCount: integer; virtual;
206 <    function ColumnByName(Idx: string): TSQLVarData;
206 >    function ColumnByName(Idx: AnsiString): TSQLVarData;
207      function CheckStatementStatus(Request: TStatementStatus): boolean; virtual; abstract;
208      procedure GetData(index: integer; var IsNull: boolean; var len: short;
209 <      var data: PChar); virtual;
209 >      var data: PByte); virtual;
210      procedure RowChange;
211      function StateChanged(var ChangeSeqNo: integer): boolean; virtual; abstract;
212 +    property CaseSensitiveParams: boolean read FCaseSensitiveParams
213 +                                            write FCaseSensitiveParams; {Only used when IsInputDataArea true}
214      property Count: integer read GetCount;
215      property Column[index: integer]: TSQLVarData read GetColumn;
216 <    property UniqueRelationName: string read FUniqueRelationName;
216 >    property UniqueRelationName: AnsiString read FUniqueRelationName;
217      property Statement: IStatement read GetStatement;
218      property PrepareSeqNo: integer read GetPrepareSeqNo;
219      property TransactionSeqNo: integer read GetTransactionSeqNo;
# Line 227 | Line 224 | type
224    TSQLVarData = class
225    private
226      FParent: TSQLDataArea;
227 <    FName: string;
227 >    FName: AnsiString;
228      FIndex: integer;
229      FModified: boolean;
230      FUniqueName: boolean;
231      FVarString: RawByteString;
232      function GetStatement: IStatement;
233 <    procedure SetName(AValue: string);
233 >    procedure SetName(AValue: AnsiString);
234    protected
235      function GetSQLType: cardinal; virtual; abstract;
236      function GetSubtype: integer; virtual; abstract;
237 <    function GetAliasName: string;  virtual; abstract;
238 <    function GetFieldName: string; virtual; abstract;
239 <    function GetOwnerName: string;  virtual; abstract;
240 <    function GetRelationName: string;  virtual; abstract;
237 >    function GetAliasName: AnsiString;  virtual; abstract;
238 >    function GetFieldName: AnsiString; virtual; abstract;
239 >    function GetOwnerName: AnsiString;  virtual; abstract;
240 >    function GetRelationName: AnsiString;  virtual; abstract;
241      function GetScale: integer; virtual; abstract;
242      function GetCharSetID: cardinal; virtual; abstract;
243      function GetCodePage: TSystemCodePage; virtual; abstract;
244      function GetIsNull: Boolean;   virtual; abstract;
245      function GetIsNullable: boolean; virtual; abstract;
246 <    function GetSQLData: PChar;  virtual; abstract;
246 >    function GetSQLData: PByte;  virtual; abstract;
247      function GetDataLength: cardinal; virtual; abstract;
248      procedure SetIsNull(Value: Boolean); virtual; abstract;
249      procedure SetIsNullable(Value: Boolean);  virtual; abstract;
250 <    procedure SetSQLData(AValue: PChar; len: cardinal); virtual; abstract;
250 >    procedure SetSQLData(AValue: PByte; len: cardinal); virtual; abstract;
251      procedure SetScale(aValue: integer); virtual; abstract;
252      procedure SetDataLength(len: cardinal); virtual; abstract;
253      procedure SetSQLType(aValue: cardinal); virtual; abstract;
254      procedure SetCharSetID(aValue: cardinal); virtual; abstract;
255    public
256      constructor Create(aParent: TSQLDataArea; aIndex: integer);
257 <    procedure SetString(aValue: string);
257 >    procedure SetString(aValue: AnsiString);
258      procedure Changed; virtual;
259      procedure RowChange; virtual;
260      function GetAsArray(Array_ID: TISC_QUAD): IArray; virtual; abstract;
# Line 268 | Line 265 | type
265      procedure Initialize; virtual;
266  
267    public
268 <    property AliasName: string read GetAliasName;
269 <    property FieldName: string read GetFieldName;
270 <    property OwnerName: string read GetOwnerName;
271 <    property RelationName: string read GetRelationName;
268 >    property AliasName: AnsiString read GetAliasName;
269 >    property FieldName: AnsiString read GetFieldName;
270 >    property OwnerName: AnsiString read GetOwnerName;
271 >    property RelationName: AnsiString read GetRelationName;
272      property Parent: TSQLDataArea read FParent;
273      property Index: integer read FIndex;
274 <    property Name: string read FName write SetName;
274 >    property Name: AnsiString read FName write SetName;
275      property CharSetID: cardinal read GetCharSetID write SetCharSetID;
276      property SQLType: cardinal read GetSQLType write SetSQLType;
277      property SQLSubtype: integer read GetSubtype;
278 <    property SQLData: PChar read GetSQLData;
278 >    property SQLData: PByte read GetSQLData;
279      property DataLength: cardinal read GetDataLength write SetDataLength;
280      property IsNull: Boolean read GetIsNull write SetIsNull;
281      property IsNullable: Boolean read GetIsNullable write SetIsNullable;
# Line 296 | Line 293 | type
293      FIBXSQLVAR: TSQLVarData;
294      FOwner: IUnknown;         {Keep reference to ensure Metadata/statement not discarded}
295      FPrepareSeqNo: integer;
299    FStatement: IStatement;
296      FChangeSeqNo: integer;
297    protected
298      procedure CheckActive; override;
299 <    function SQLData: PChar; override;
299 >    function SQLData: PByte; override;
300      function GetDataLength: cardinal; override;
301      function GetCodePage: TSystemCodePage; override;
302  
# Line 308 | Line 304 | type
304      constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
305      destructor Destroy; override;
306      function GetSQLDialect: integer; override;
311    property Statement: IStatement read FStatement;
307  
308    public
309      {IColumnMetaData}
310      function GetIndex: integer;
311      function GetSQLType: cardinal; override;
312      function getSubtype: integer;
313 <    function getRelationName: string;
314 <    function getOwnerName: string;
315 <    function getSQLName: string;    {Name of the column}
316 <    function getAliasName: string;  {Alias Name of column or Column Name if not alias}
317 <    function GetName: string; override;      {Disambiguated uppercase Field Name}
313 >    function getRelationName: AnsiString;
314 >    function getOwnerName: AnsiString;
315 >    function getSQLName: AnsiString;    {Name of the column}
316 >    function getAliasName: AnsiString;  {Alias Name of column or Column Name if not alias}
317 >    function GetName: AnsiString; override;      {Disambiguated uppercase Field Name}
318      function GetScale: integer; override;
319      function getCharSetID: cardinal; override;
320      function GetIsNullable: boolean; override;
321      function GetSize: cardinal;
322      function GetArrayMetaData: IArrayMetaData;
323      function GetBlobMetaData: IBlobMetaData;
324 <    property Name: string read GetName;
324 >    function GetStatement: IStatement;
325 >    function GetTransaction: ITransaction; virtual;
326 >    property Name: AnsiString read GetName;
327      property Size: cardinal read GetSize;
328      property CharSetID: cardinal read getCharSetID;
329      property SQLSubtype: integer read getSubtype;
330      property IsNullable: Boolean read GetIsNullable;
331 +  public
332 +    property Statement: IStatement read GetStatement;
333    end;
334  
335    { TIBSQLData }
336  
337    TIBSQLData = class(TColumnMetaData,ISQLData)
338 +  private
339 +    FTransaction: ITransaction;
340    protected
341      procedure CheckActive; override;
342    public
343 +    function GetTransaction: ITransaction; override;
344      function GetIsNull: Boolean; override;
345      function GetAsArray: IArray;
346      function GetAsBlob: IBlob; overload;
347      function GetAsBlob(BPB: IBPB): IBlob; overload;
348 <    function GetAsString: String; override;
348 >    function GetAsString: AnsiString; override;
349      property AsBlob: IBlob read GetAsBlob;
350   end;
351  
# Line 353 | Line 355 | type
355    protected
356      procedure CheckActive; override;
357      procedure Changed; override;
358 <    procedure InternalSetAsString(Value: String); override;
358 >    procedure InternalSetAsString(Value: AnsiString); override;
359      procedure SetScale(aValue: integer); override;
360      procedure SetDataLength(len: cardinal); override;
361      procedure SetSQLType(aValue: cardinal); override;
# Line 361 | Line 363 | type
363      procedure Clear;
364      function GetModified: boolean; override;
365      function GetAsPointer: Pointer;
366 <    procedure SetName(Value: string); override;
366 >    procedure SetName(Value: AnsiString); override;
367      procedure SetIsNull(Value: Boolean);  override;
368      procedure SetIsNullable(Value: Boolean); override;
369      procedure SetAsArray(anArray: IArray);
# Line 378 | Line 380 | type
380      procedure SetAsFloat(AValue: Float);
381      procedure SetAsPointer(AValue: Pointer);
382      procedure SetAsShort(AValue: Short);
383 <    procedure SetAsString(AValue: String); override;
383 >    procedure SetAsString(AValue: AnsiString); override;
384      procedure SetAsVariant(AValue: Variant);
385      procedure SetAsBlob(aValue: IBlob);
386      procedure SetAsQuad(AValue: TISC_QUAD);
# Line 401 | Line 403 | type
403      destructor Destroy; override;
404    public
405      {IMetaData}
406 <    function GetUniqueRelationName: string;
406 >    function GetUniqueRelationName: AnsiString;
407      function getCount: integer;
408      function getColumnMetaData(index: integer): IColumnMetaData;
409 <    function ByName(Idx: String): IColumnMetaData;
409 >    function ByName(Idx: AnsiString): IColumnMetaData;
410    end;
411  
412    { TSQLParams }
# Line 423 | Line 425 | type
425      {ISQLParams}
426      function getCount: integer;
427      function getSQLParam(index: integer): ISQLParam;
428 <    function ByName(Idx: String): ISQLParam ;
428 >    function ByName(Idx: AnsiString): ISQLParam ;
429      function GetModified: Boolean;
430 +    function GetHasCaseSensitiveParams: Boolean;
431    end;
432  
433    { TResults }
# Line 443 | Line 446 | type
446       constructor Create(aResults: TSQLDataArea);
447        {IResults}
448       function getCount: integer;
449 <     function ByName(Idx: String): ISQLData;
449 >     function ByName(Idx: AnsiString): ISQLData;
450       function getSQLData(index: integer): ISQLData;
451 <     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
451 >     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PByte);
452 >     function GetStatement: IStatement;
453       function GetTransaction: ITransaction; virtual;
454       procedure SetRetainInterfaces(aValue: boolean);
455   end;
456  
457   implementation
458  
459 < uses FBMessages, FBClientAPI, variants, IBUtils, FBTransaction;
459 > uses FBMessages, variants, IBUtils, FBTransaction, DateUtils;
460  
461   { TSQLDataArea }
462  
# Line 472 | Line 476 | procedure TSQLDataArea.SetUniqueRelation
476   var
477    i: Integer;
478    bUnique: Boolean;
479 <  RelationName: string;
479 >  RelationName: AnsiString;
480   begin
481    bUnique := True;
482    for i := 0 to ColumnsInUseCount - 1 do
# Line 503 | Line 507 | begin
507      Column[i].Initialize;
508   end;
509  
510 < procedure TSQLDataArea.PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
511 <  var sProcessedSQL: string);
508 < var
509 <  cCurChar, cNextChar, cQuoteChar: Char;
510 <  sParamName: String;
511 <  j, i, iLenSQL, iSQLPos: Integer;
512 <  iCurState {$ifdef ALLOWDIALECT3PARAMNAMES}, iCurParamState {$endif}: Integer;
513 <  iParamSuffix: Integer;
514 <  slNames: TStrings;
515 <  StrBuffer: PChar;
516 <  found: boolean;
517 <
518 < const
519 <  DefaultState = 0;
520 <  CommentState = 1;
521 <  QuoteState = 2;
522 <  ParamState = 3;
523 <  ArrayDimState = 4;
524 < {$ifdef ALLOWDIALECT3PARAMNAMES}
525 <  ParamDefaultState = 0;
526 <  ParamQuoteState = 1;
527 <  {$endif}
528 <
529 <  procedure AddToProcessedSQL(cChar: Char);
530 <  begin
531 <    StrBuffer[iSQLPos] := cChar;
532 <    Inc(iSQLPos);
533 <  end;
510 > procedure TSQLDataArea.PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
511 >  var sProcessedSQL: AnsiString);
512  
513 < begin
536 <  if not IsInputDataArea then
537 <    IBError(ibxeNotPermitted,[nil]);
513 > var slNames: TStrings;
514  
515 <  sParamName := '';
516 <  iLenSQL := Length(sSQL);
517 <  GetMem(StrBuffer,iLenSQL + 1);
518 <  slNames := TStringList.Create;
519 <  try
544 <    { Do some initializations of variables }
545 <    iParamSuffix := 0;
546 <    cQuoteChar := '''';
547 <    i := 1;
548 <    iSQLPos := 0;
549 <    iCurState := DefaultState;
550 <    {$ifdef ALLOWDIALECT3PARAMNAMES}
551 <    iCurParamState := ParamDefaultState;
552 <    {$endif}
553 <    { Now, traverse through the SQL string, character by character,
554 <     picking out the parameters and formatting correctly for InterBase }
555 <    while (i <= iLenSQL) do begin
556 <      { Get the current token and a look-ahead }
557 <      cCurChar := sSQL[i];
558 <      if i = iLenSQL then
559 <        cNextChar := #0
560 <      else
561 <        cNextChar := sSQL[i + 1];
562 <      { Now act based on the current state }
563 <      case iCurState of
564 <        DefaultState:
565 <        begin
566 <          case cCurChar of
567 <            '''', '"':
568 <            begin
569 <              cQuoteChar := cCurChar;
570 <              iCurState := QuoteState;
571 <            end;
572 <            '?', ':':
573 <            begin
574 <              iCurState := ParamState;
575 <              AddToProcessedSQL('?');
576 <            end;
577 <            '/': if (cNextChar = '*') then
578 <            begin
579 <              AddToProcessedSQL(cCurChar);
580 <              Inc(i);
581 <              iCurState := CommentState;
582 <            end;
583 <            '[':
584 <            begin
585 <              AddToProcessedSQL(cCurChar);
586 <              Inc(i);
587 <              iCurState := ArrayDimState;
588 <            end;
589 <          end;
590 <        end;
591 <
592 <        ArrayDimState:
593 <        begin
594 <          case cCurChar of
595 <          ':',',','0'..'9',' ',#9,#10,#13:
596 <            begin
597 <              AddToProcessedSQL(cCurChar);
598 <              Inc(i);
599 <            end;
600 <          else
601 <            begin
602 <              AddToProcessedSQL(cCurChar);
603 <              Inc(i);
604 <              iCurState := DefaultState;
605 <            end;
606 <          end;
607 <        end;
608 <
609 <        CommentState:
610 <        begin
611 <          if (cNextChar = #0) then
612 <            IBError(ibxeSQLParseError, [SEOFInComment])
613 <          else if (cCurChar = '*') then begin
614 <            if (cNextChar = '/') then
615 <              iCurState := DefaultState;
616 <          end;
617 <        end;
618 <        QuoteState: begin
619 <          if cNextChar = #0 then
620 <            IBError(ibxeSQLParseError, [SEOFInString])
621 <          else if (cCurChar = cQuoteChar) then begin
622 <            if (cNextChar = cQuoteChar) then begin
623 <              AddToProcessedSQL(cCurChar);
624 <              Inc(i);
625 <            end else
626 <              iCurState := DefaultState;
627 <          end;
628 <        end;
629 <        ParamState:
630 <        begin
631 <          { collect the name of the parameter }
632 <          {$ifdef ALLOWDIALECT3PARAMNAMES}
633 <          if iCurParamState = ParamDefaultState then
634 <          begin
635 <            if cCurChar = '"' then
636 <              iCurParamState := ParamQuoteState
637 <            else
638 <            {$endif}
639 <            if (cCurChar in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$']) then
640 <                sParamName := sParamName + cCurChar
641 <            else if GenerateParamNames then
642 <            begin
643 <              sParamName := 'IBXParam' + IntToStr(iParamSuffix); {do not localize}
644 <              Inc(iParamSuffix);
645 <              iCurState := DefaultState;
646 <              slNames.AddObject(sParamName,self); //Note local convention
647 <                                                  //add pointer to self to mark entry
648 <              sParamName := '';
649 <            end
650 <            else
651 <              IBError(ibxeSQLParseError, [SParamNameExpected]);
652 <          {$ifdef ALLOWDIALECT3PARAMNAMES}
653 <          end
654 <          else begin
655 <            { determine if Quoted parameter name is finished }
656 <            if cCurChar = '"' then
657 <            begin
658 <              Inc(i);
659 <              slNames.Add(sParamName);
660 <              SParamName := '';
661 <              iCurParamState := ParamDefaultState;
662 <              iCurState := DefaultState;
663 <            end
664 <            else
665 <              sParamName := sParamName + cCurChar
666 <          end;
667 <          {$endif}
668 <          { determine if the unquoted parameter name is finished }
669 <          if {$ifdef ALLOWDIALECT3PARAMNAMES}(iCurParamState <> ParamQuoteState) and {$endif}
670 <            (iCurState <> DefaultState) then
671 <          begin
672 <            if not (cNextChar in ['A'..'Z', 'a'..'z',
673 <                                  '0'..'9', '_', '$']) then begin
674 <              Inc(i);
675 <              iCurState := DefaultState;
676 <              slNames.Add(sParamName);
677 <              sParamName := '';
678 <            end;
679 <          end;
680 <        end;
681 <      end;
682 <      if (iCurState <> ParamState) and (i <= iLenSQL) then
683 <        AddToProcessedSQL(sSQL[i]);
684 <      Inc(i);
685 <    end;
686 <    AddToProcessedSQL(#0);
687 <    sProcessedSQL := strpas(StrBuffer);
515 >  procedure SetColumnNames(slNames: TStrings);
516 >  var i, j: integer;
517 >      found: boolean;
518 >  begin
519 >    found := false;
520      SetCount(slNames.Count);
521      for i := 0 to slNames.Count - 1 do
522      begin
# Line 705 | Line 537 | begin
537          Column[i].UniqueName := not found;
538        end;
539      end;
540 +  end;
541 +
542 + begin
543 +  if not IsInputDataArea then
544 +    IBError(ibxeNotPermitted,[nil]);
545 +
546 +  slNames := TStringList.Create;
547 +  try
548 +    sProcessedSQL := TSQLParamProcessor.Execute(sSQL,GenerateParamNames,slNames);
549 +    SetColumnNames(slNames);
550    finally
551      slNames.Free;
710    FreeMem(StrBuffer);
552    end;
553   end;
554  
# Line 716 | Line 557 | begin
557    Result := Count;
558   end;
559  
560 < function TSQLDataArea.ColumnByName(Idx: string): TSQLVarData;
560 > function TSQLDataArea.ColumnByName(Idx: AnsiString): TSQLVarData;
561   var
562 <  s: String;
562 >  s: AnsiString;
563    i: Integer;
564   begin
565 <  {$ifdef UseCaseInSensitiveParamName}
566 <   s := AnsiUpperCase(Idx);
567 <  {$else}
565 >  if not IsInputDataArea or not CaseSensitiveParams then
566 >   s := AnsiUpperCase(Idx)
567 >  else
568     s := Idx;
569 <  {$endif}
569 >
570    for i := 0 to Count - 1 do
571      if Column[i].Name = s then
572      begin
# Line 736 | Line 577 | begin
577   end;
578  
579   procedure TSQLDataArea.GetData(index: integer; var IsNull: boolean;
580 <  var len: short; var data: PChar);
580 >  var len: short; var data: PByte);
581   begin
582    //Do Nothing
583   end;
# Line 755 | Line 596 | begin
596    Result := FParent.Statement;
597   end;
598  
599 < procedure TSQLVarData.SetName(AValue: string);
599 > procedure TSQLVarData.SetName(AValue: AnsiString);
600   begin
601 <  if FName = AValue then Exit;
761 <  {$ifdef UseCaseInSensitiveParamName}
762 <  if Parent.IsInputDataArea then
601 >  if not Parent.IsInputDataArea or not Parent.CaseSensitiveParams then
602      FName := AnsiUpperCase(AValue)
603    else
765  {$endif}
604      FName := AValue;
605   end;
606  
# Line 774 | Line 612 | begin
612    FUniqueName := true;
613   end;
614  
615 < procedure TSQLVarData.SetString(aValue: string);
615 > procedure TSQLVarData.SetString(aValue: AnsiString);
616   begin
617    {we take full advantage here of reference counted strings. When setting a string
618     value, a reference is kept in FVarString and a pointer to it placed in the
619 <   SQLVar. This avoids string copies. Note that PChar is guaranteed to point to
619 >   SQLVar. This avoids string copies. Note that PAnsiChar is guaranteed to point to
620     a zero byte when the string is empty, neatly avoiding a nil pointer error.}
621  
622    FVarString := aValue;
623    SQLType := SQL_TEXT;
624 <  SetSQLData(PChar(FVarString),Length(aValue));
624 >  Scale := 0;
625 >  SetSQLData(PByte(PAnsiChar(FVarString)),Length(aValue));
626   end;
627  
628   procedure TSQLVarData.Changed;
# Line 799 | Line 638 | end;
638  
639   procedure TSQLVarData.Initialize;
640  
641 <  function FindVarByName(idx: string; limit: integer): TSQLVarData;
641 >  function FindVarByName(idx: AnsiString; limit: integer): TSQLVarData;
642    var
643      k: integer;
644    begin
# Line 814 | Line 653 | procedure TSQLVarData.Initialize;
653  
654   var
655    j, j_len: Integer;
656 <  st: String;
657 <  sBaseName: string;
656 >  st: AnsiString;
657 >  sBaseName: AnsiString;
658   begin
659    RowChange;
660  
# Line 902 | Line 741 | function TSQLDataItem.AdjustScaleToCurre
741   var
742    Scaling : Int64;
743    i : Integer;
744 <  FractionText, PadText, CurrText: string;
744 >  FractionText, PadText, CurrText: AnsiString;
745   begin
746    Result := 0;
747    Scaling := 1;
# Line 921 | Line 760 | begin
760        FractionText := IntToStr(abs(Value mod Scaling));
761        for i := Length(FractionText) to -aScale -1 do
762          PadText := '0' + PadText;
763 +      {$IF declared(DefaultFormatSettings)}
764 +      with DefaultFormatSettings do
765 +      {$ELSE}
766 +      {$IF declared(FormatSettings)}
767 +      with FormatSettings do
768 +      {$IFEND}
769 +      {$IFEND}
770        if Value < 0 then
771 <        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText
771 >        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText
772        else
773 <        CurrText := IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText;
773 >        CurrText := IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText;
774        try
775          result := StrToCurr(CurrText);
776        except
# Line 936 | Line 782 | begin
782        result := Value;
783   end;
784  
785 + function TSQLDataItem.GetDateFormatStr(IncludeTime: boolean): AnsiString;
786 + begin
787 +  {$IF declared(DefaultFormatSettings)}
788 +  with DefaultFormatSettings do
789 +  {$ELSE}
790 +  {$IF declared(FormatSettings)}
791 +  with FormatSettings do
792 +  {$IFEND}
793 +  {$IFEND}
794 +  case GetSQLDialect of
795 +    1:
796 +      if IncludeTime then
797 +        result := ShortDateFormat + ' ' + LongTimeFormat
798 +      else
799 +        result := ShortDateFormat;
800 +    3:
801 +      result := ShortDateFormat;
802 +  end;
803 + end;
804 +
805 + function TSQLDataItem.GetTimeFormatStr: AnsiString;
806 + begin
807 +  {$IF declared(DefaultFormatSettings)}
808 +  with DefaultFormatSettings do
809 +  {$ELSE}
810 +  {$IF declared(FormatSettings)}
811 +  with FormatSettings do
812 +  {$IFEND}
813 +  {$IFEND}
814 +    Result := LongTimeFormat;
815 + end;
816 +
817 + function TSQLDataItem.GetTimestampFormatStr: AnsiString;
818 + begin
819 +  {$IF declared(DefaultFormatSettings)}
820 +  with DefaultFormatSettings do
821 +  {$ELSE}
822 +  {$IF declared(FormatSettings)}
823 +  with FormatSettings do
824 +  {$IFEND}
825 +  {$IFEND}
826 +    Result := ShortDateFormat + ' ' +  LongTimeFormat + '.zzz';
827 + end;
828 +
829   procedure TSQLDataItem.SetAsInteger(AValue: Integer);
830   begin
831    SetAsLong(aValue);
# Line 1006 | Line 896 | begin
896    //Do nothing by default
897   end;
898  
899 < procedure TSQLDataItem.InternalSetAsString(Value: String);
899 > procedure TSQLDataItem.InternalSetAsString(Value: AnsiString);
900   begin
901    //Do nothing by default
902   end;
903  
904 < function TSQLDataItem.Transliterate(s: string; CodePage: TSystemCodePage
904 > function TSQLDataItem.Transliterate(s: AnsiString; CodePage: TSystemCodePage
905    ): RawByteString;
906   begin
907    Result := s;
# Line 1034 | Line 924 | begin
924     //Do nothing by default
925   end;
926  
927 < function TSQLDataItem.GetSQLTypeName: string;
927 > constructor TSQLDataItem.Create(api: TFBClientAPI);
928 > begin
929 >  inherited Create;
930 >  FFirebirdClientAPI := api;
931 > end;
932 >
933 > function TSQLDataItem.GetSQLTypeName: AnsiString;
934   begin
935    Result := GetSQLTypeName(GetSQLType);
936   end;
937  
938 < class function TSQLDataItem.GetSQLTypeName(SQLType: short): string;
938 > class function TSQLDataItem.GetSQLTypeName(SQLType: short): AnsiString;
939   begin
940    Result := 'Unknown';
941    case SQLType of
# Line 1060 | Line 956 | begin
956    end;
957   end;
958  
959 + function TSQLDataItem.GetStrDataLength: short;
960 + begin
961 +  with FFirebirdClientAPI do
962 +  if SQLType = SQL_VARYING then
963 +    Result := DecodeInteger(SQLData, 2)
964 +  else
965 +    Result := DataLength;
966 + end;
967 +
968   function TSQLDataItem.GetAsBoolean: boolean;
969   begin
970    CheckActive;
# Line 1140 | Line 1045 | begin
1045    CheckActive;
1046    result := 0;
1047    if not IsNull then
1048 <    with FirebirdClientAPI do
1048 >    with FFirebirdClientAPI do
1049      case SQLType of
1050        SQL_TEXT, SQL_VARYING: begin
1051          try
# Line 1270 | Line 1175 | begin
1175   end;
1176  
1177  
1178 < function TSQLDataItem.GetAsString: String;
1178 > function TSQLDataItem.GetAsString: AnsiString;
1179   var
1180 <  sz: PChar;
1180 >  sz: PByte;
1181    str_len: Integer;
1182    rs: RawByteString;
1183   begin
# Line 1280 | Line 1185 | begin
1185    result := '';
1186    { Check null, if so return a default string }
1187    if not IsNull then
1188 <  with FirebirdClientAPI do
1188 >  with FFirebirdClientAPI do
1189      case SQLType of
1190        SQL_BOOLEAN:
1191          if AsBoolean then
# Line 1297 | Line 1202 | begin
1202            str_len := DecodeInteger(SQLData, 2);
1203            Inc(sz, 2);
1204          end;
1205 <        SetString(rs, sz, str_len);
1205 >        SetString(rs, PAnsiChar(sz), str_len);
1206          SetCodePage(rs,GetCodePage,false);
1207          if (SQLType = SQL_TEXT) and (GetCharSetID <> 1) then
1208            Result := TrimRight(rs)
# Line 1305 | Line 1210 | begin
1210            Result := rs
1211        end;
1212        SQL_TYPE_DATE:
1213 <        case GetSQLDialect of
1309 <          1 : result := DateTimeToStr(AsDateTime);
1310 <          3 : result := DateToStr(AsDateTime);
1311 <        end;
1213 >        result := FormatDateTime(GetDateFormatStr(TimeOf(AsDateTime)<>0),AsDateTime);
1214        SQL_TYPE_TIME :
1215 <        result := TimeToStr(AsDateTime);
1215 >        result := FormatDateTime(GetTimeFormatStr,AsDateTime);
1216        SQL_TIMESTAMP:
1217 <        result := FormatDateTime(FormatSettings.ShortDateFormat + ' ' +
1316 <                            FormatSettings.LongTimeFormat+'.zzz',AsDateTime);
1217 >        result := FormatDateTime(GetTimestampFormatStr,AsDateTime);
1218        SQL_SHORT, SQL_LONG:
1219          if Scale = 0 then
1220            result := IntToStr(AsLong)
# Line 1341 | Line 1242 | begin
1242    Result := false;
1243   end;
1244  
1245 < function TSQLDataItem.getIsNullable: boolean;
1245 > function TSQLDataItem.GetIsNullable: boolean;
1246   begin
1247    CheckActive;
1248    Result := false;
# Line 1389 | Line 1290 | begin
1290    Result := false;
1291   end;
1292  
1293 + function TSQLDataItem.GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats
1294 +  ): integer;
1295 + begin
1296 +  case DateTimeFormat of
1297 +  dfTimestamp:
1298 +    Result := Length(GetTimestampFormatStr);
1299 +  dfDateTime:
1300 +    Result := Length(GetDateFormatStr(true));
1301 +  dfTime:
1302 +    Result := Length(GetTimeFormatStr);
1303 +  else
1304 +    Result := 0;
1305 +  end;
1306 + end;
1307 +
1308  
1309   procedure TSQLDataItem.SetIsNull(Value: Boolean);
1310   begin
# Line 1400 | Line 1316 | begin
1316    //ignore unless overridden
1317   end;
1318  
1319 < procedure TSQLDataItem.SetName(aValue: string);
1319 > procedure TSQLDataItem.SetName(aValue: AnsiString);
1320   begin
1321    //ignore unless overridden
1322   end;
# Line 1452 | Line 1368 | begin
1368  
1369    SQLType := SQL_TYPE_DATE;
1370    DataLength := SizeOf(ISC_DATE);
1371 <  with FirebirdClientAPI do
1371 >  with FFirebirdClientAPI do
1372      SQLEncodeDate(Value,SQLData);
1373    Changed;
1374   end;
# Line 1472 | Line 1388 | begin
1388  
1389    SQLType := SQL_TYPE_TIME;
1390    DataLength := SizeOf(ISC_TIME);
1391 <  with FirebirdClientAPI do
1391 >  with FFirebirdClientAPI do
1392      SQLEncodeTime(Value,SQLData);
1393    Changed;
1394   end;
# Line 1486 | Line 1402 | begin
1402    Changing;
1403    SQLType := SQL_TIMESTAMP;
1404    DataLength := SizeOf(ISC_TIME) + sizeof(ISC_DATE);
1405 <  with FirebirdClientAPI do
1405 >  with FFirebirdClientAPI do
1406      SQLEncodeDateTime(Value,SQLData);
1407    Changed;
1408   end;
# Line 1576 | Line 1492 | begin
1492    Changed;
1493   end;
1494  
1495 < procedure TSQLDataItem.SetAsString(Value: String);
1495 > procedure TSQLDataItem.SetAsString(Value: AnsiString);
1496   begin
1497    InternalSetAsString(Value);
1498   end;
# Line 1611 | Line 1527 | begin
1527    end;
1528   end;
1529  
1530 + procedure TSQLDataItem.SetAsNumeric(Value: Int64; aScale: integer);
1531 + begin
1532 +  CheckActive;
1533 +  Changing;
1534 +  if IsNullable then
1535 +    IsNull := False;
1536 +
1537 +  SQLType := SQL_INT64;
1538 +  Scale := aScale;
1539 +  DataLength := SizeOf(Int64);
1540 +  PInt64(SQLData)^ := Value;
1541 +  Changed;
1542 + end;
1543 +
1544   procedure TSQLDataItem.SetAsBoolean(AValue: boolean);
1545   begin
1546    CheckActive;
# Line 1641 | Line 1571 | begin
1571      IBError(ibxeStatementNotPrepared, [nil]);
1572   end;
1573  
1574 < function TColumnMetaData.SQLData: PChar;
1574 > function TColumnMetaData.SQLData: PByte;
1575   begin
1576    Result := FIBXSQLVAR.SQLData;
1577   end;
# Line 1658 | Line 1588 | end;
1588  
1589   constructor TColumnMetaData.Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
1590   begin
1591 <  inherited Create;
1591 >  inherited Create(aIBXSQLVAR.GetStatement.GetAttachment.getFirebirdAPI as TFBClientAPI);
1592    FIBXSQLVAR := aIBXSQLVAR;
1593    FOwner := aOwner;
1594    FPrepareSeqNo := FIBXSQLVAR.Parent.PrepareSeqNo;
# Line 1694 | Line 1624 | begin
1624    result := FIBXSQLVAR.SQLSubtype;
1625   end;
1626  
1627 < function TColumnMetaData.getRelationName: string;
1627 > function TColumnMetaData.getRelationName: AnsiString;
1628   begin
1629    CheckActive;
1630     result :=  FIBXSQLVAR.RelationName;
1631   end;
1632  
1633 < function TColumnMetaData.getOwnerName: string;
1633 > function TColumnMetaData.getOwnerName: AnsiString;
1634   begin
1635    CheckActive;
1636    result :=  FIBXSQLVAR.OwnerName;
1637   end;
1638  
1639 < function TColumnMetaData.getSQLName: string;
1639 > function TColumnMetaData.getSQLName: AnsiString;
1640   begin
1641    CheckActive;
1642    result :=  FIBXSQLVAR.FieldName;
1643   end;
1644  
1645 < function TColumnMetaData.getAliasName: string;
1645 > function TColumnMetaData.getAliasName: AnsiString;
1646   begin
1647    CheckActive;
1648    result := FIBXSQLVAR.AliasName;
1649   end;
1650  
1651 < function TColumnMetaData.GetName: string;
1651 > function TColumnMetaData.GetName: AnsiString;
1652   begin
1653    CheckActive;
1654    Result := FIBXSQLVAR. Name;
# Line 1760 | Line 1690 | begin
1690    result := FIBXSQLVAR.GetBlobMetaData;
1691   end;
1692  
1693 + function TColumnMetaData.GetStatement: IStatement;
1694 + begin
1695 +  Result := FIBXSQLVAR.GetStatement;
1696 + end;
1697 +
1698 + function TColumnMetaData.GetTransaction: ITransaction;
1699 + begin
1700 +  Result := GetStatement.GetTransaction;
1701 + end;
1702 +
1703   { TIBSQLData }
1704  
1705   procedure TIBSQLData.CheckActive;
# Line 1779 | Line 1719 | begin
1719      IBError(ibxeBOF,[nil]);
1720   end;
1721  
1722 + function TIBSQLData.GetTransaction: ITransaction;
1723 + begin
1724 +  if FTransaction = nil then
1725 +    Result := inherited GetTransaction
1726 +  else
1727 +    Result := FTransaction;
1728 + end;
1729 +
1730   function TIBSQLData.GetIsNull: Boolean;
1731   begin
1732    CheckActive;
# Line 1803 | Line 1751 | begin
1751    result := FIBXSQLVAR.GetAsBlob(AsQuad,BPB);
1752   end;
1753  
1754 < function TIBSQLData.GetAsString: String;
1754 > function TIBSQLData.GetAsString: AnsiString;
1755   begin
1756    CheckActive;
1757    Result := '';
# Line 1821 | Line 1769 | end;
1769  
1770   { TSQLParam }
1771  
1772 < procedure TSQLParam.InternalSetAsString(Value: String);
1772 > procedure TSQLParam.InternalSetAsString(Value: AnsiString);
1773 >
1774 > procedure DoSetString;
1775 > begin
1776 >  Changing;
1777 >  FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1778 >  Changed;
1779 > end;
1780 >
1781   var b: IBlob;
1782 +    dt: TDateTime;
1783 +    CurrValue: Currency;
1784 +    FloatValue: single;
1785   begin
1786    CheckActive;
1787    if IsNullable then
1788      IsNull := False;
1789    case SQLTYPE of
1790    SQL_BOOLEAN:
1791 <    if CompareText(Value,STrue) = 0 then
1791 >    if AnsiCompareText(Value,STrue) = 0 then
1792        AsBoolean := true
1793      else
1794 <    if CompareText(Value,SFalse) = 0 then
1794 >    if AnsiCompareText(Value,SFalse) = 0 then
1795        AsBoolean := false
1796      else
1797        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1848 | Line 1807 | begin
1807  
1808    SQL_VARYING,
1809    SQL_TEXT:
1810 <    begin
1852 <      Changing;
1853 <      FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1854 <      Changed;
1855 <    end;
1810 >    DoSetString;
1811  
1812      SQL_SHORT,
1813      SQL_LONG,
1814      SQL_INT64:
1815 <      SetAsInt64(StrToInt(Value));
1815 >      if TryStrToCurr(Value,CurrValue) then
1816 >        SetAsNumeric(AdjustScaleFromCurrency(CurrValue,GetScale),GetScale)
1817 >      else
1818 >        DoSetString;
1819  
1820      SQL_D_FLOAT,
1821      SQL_DOUBLE,
1822      SQL_FLOAT:
1823 <      SetAsDouble(StrToFloat(Value));
1823 >      if TryStrToFloat(Value,FloatValue) then
1824 >        SetAsDouble(FloatValue)
1825 >      else
1826 >        DoSetString;
1827  
1828      SQL_TIMESTAMP:
1829 <      SetAsDateTime(StrToDateTime(Value));
1829 >      if TryStrToDateTime(Value,dt) then
1830 >        SetAsDateTime(dt)
1831 >      else
1832 >        DoSetString;
1833  
1834      SQL_TYPE_DATE:
1835 <      SetAsDate(StrToDateTime(Value));
1835 >      if TryStrToDateTime(Value,dt) then
1836 >        SetAsDate(dt)
1837 >      else
1838 >        DoSetString;
1839  
1840      SQL_TYPE_TIME:
1841 <      SetAsTime(StrToDateTime(Value));
1841 >      if TryStrToDateTime(Value,dt) then
1842 >        SetAsTime(dt)
1843 >      else
1844 >        DoSetString;
1845  
1846      else
1847        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1925 | Line 1895 | begin
1895    Result := inherited GetAsPointer;
1896   end;
1897  
1898 < procedure TSQLParam.SetName(Value: string);
1898 > procedure TSQLParam.SetName(Value: AnsiString);
1899   begin
1900    CheckActive;
1901    FIBXSQLVAR.Name := Value;
# Line 2231 | Line 2201 | begin
2201    end;
2202   end;
2203  
2204 < procedure TSQLParam.SetAsString(AValue: String);
2204 > procedure TSQLParam.SetAsString(AValue: AnsiString);
2205   var i: integer;
2206      OldSQLVar: TSQLVarData;
2207   begin
# Line 2344 | Line 2314 | begin
2314    inherited Destroy;
2315   end;
2316  
2317 < function TMetaData.GetUniqueRelationName: string;
2317 > function TMetaData.GetUniqueRelationName: AnsiString;
2318   begin
2319    CheckActive;
2320    Result := FMetaData.UniqueRelationName;
# Line 2372 | Line 2342 | begin
2342    end;
2343   end;
2344  
2345 < function TMetaData.ByName(Idx: String): IColumnMetaData;
2345 > function TMetaData.ByName(Idx: AnsiString): IColumnMetaData;
2346   var aIBXSQLVAR: TSQLVarData;
2347   begin
2348    CheckActive;
# Line 2432 | Line 2402 | begin
2402    end;
2403   end;
2404  
2405 < function TSQLParams.ByName(Idx: String): ISQLParam;
2405 > function TSQLParams.ByName(Idx: AnsiString): ISQLParam;
2406   var aIBXSQLVAR: TSQLVarData;
2407   begin
2408    CheckActive;
# Line 2457 | Line 2427 | begin
2427      end;
2428   end;
2429  
2430 + function TSQLParams.GetHasCaseSensitiveParams: Boolean;
2431 + begin
2432 +  Result := FSQLParams.CaseSensitiveParams;
2433 + end;
2434 +
2435   { TResults }
2436  
2437   procedure TResults.CheckActive;
# Line 2475 | Line 2450 | begin
2450   end;
2451  
2452   function TResults.GetISQLData(aIBXSQLVAR: TSQLVarData): ISQLData;
2453 + var col: TIBSQLData;
2454   begin
2455    if (aIBXSQLVAR.Index < 0) or (aIBXSQLVAR.Index >= getCount) then
2456      IBError(ibxeInvalidColumnIndex,[nil]);
2457  
2458    if not HasInterface(aIBXSQLVAR.Index) then
2459      AddInterface(aIBXSQLVAR.Index, TIBSQLData.Create(self,aIBXSQLVAR));
2460 <  Result := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2460 >  col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2461 >  col.FTransaction := GetTransaction;
2462 >  Result := col;
2463   end;
2464  
2465   constructor TResults.Create(aResults: TSQLDataArea);
# Line 2500 | Line 2478 | begin
2478    Result := FResults.Count;
2479   end;
2480  
2481 < function TResults.ByName(Idx: String): ISQLData;
2481 > function TResults.ByName(Idx: AnsiString): ISQLData;
2482   var col: TSQLVarData;
2483   begin
2484    Result := nil;
# Line 2532 | Line 2510 | begin
2510   end;
2511  
2512   procedure TResults.GetData(index: integer; var IsNull: boolean; var len: short;
2513 <  var data: PChar);
2513 >  var data: PByte);
2514   begin
2515    CheckActive;
2516    FResults.GetData(index,IsNull, len,data);
2517   end;
2518  
2519 + function TResults.GetStatement: IStatement;
2520 + begin
2521 +  Result := FStatement;
2522 + end;
2523 +
2524   function TResults.GetTransaction: ITransaction;
2525   begin
2526    Result := FStatement.GetTransaction;
# Line 2548 | Line 2531 | begin
2531    RetainInterfaces := aValue;
2532   end;
2533  
2551
2534   end.
2535  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines