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 308 by tony, Sat Jul 18 10:26:30 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, {$IFDEF WINDOWS} Windows, {$ENDIF} 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 +     function GetSize: cardinal; virtual; abstract;
142       procedure SetAsBoolean(AValue: boolean); virtual;
143       procedure SetAsCurrency(Value: Currency); virtual;
144       procedure SetAsInt64(Value: Int64); virtual;
# Line 157 | Line 151 | type
151       procedure SetAsPointer(Value: Pointer);
152       procedure SetAsQuad(Value: TISC_QUAD);
153       procedure SetAsShort(Value: short); virtual;
154 <     procedure SetAsString(Value: String); virtual;
154 >     procedure SetAsString(Value: AnsiString); virtual;
155       procedure SetAsVariant(Value: Variant);
156 +     procedure SetAsNumeric(Value: Int64; aScale: integer);
157       procedure SetIsNull(Value: Boolean); virtual;
158       procedure SetIsNullable(Value: Boolean); virtual;
159 <     procedure SetName(aValue: string); virtual;
159 >     procedure SetName(aValue: AnsiString); virtual;
160       property AsDate: TDateTime read GetAsDateTime write SetAsDate;
161       property AsBoolean:boolean read GetAsBoolean write SetAsBoolean;
162       property AsTime: TDateTime read GetAsDateTime write SetAsTime;
# Line 175 | Line 170 | type
170       property AsPointer: Pointer read GetAsPointer write SetAsPointer;
171       property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
172       property AsShort: short read GetAsShort write SetAsShort;
173 <     property AsString: String read GetAsString write SetAsString;
173 >     property AsString: AnsiString read GetAsString write SetAsString;
174       property AsVariant: Variant read GetAsVariant write SetAsVariant;
175       property Modified: Boolean read getModified;
176       property IsNull: Boolean read GetIsNull write SetIsNull;
# Line 192 | Line 187 | type
187  
188    TSQLDataArea = class
189    private
190 +    FCaseSensitiveParams: boolean;
191      function GetColumn(index: integer): TSQLVarData;
192      function GetCount: integer;
193    protected
194 <    FUniqueRelationName: string;
194 >    FUniqueRelationName: AnsiString;
195      FColumnList: array of TSQLVarData;
196      function GetStatement: IStatement; virtual; abstract;
197      function GetPrepareSeqNo: integer; virtual; abstract;
# Line 205 | Line 201 | type
201    public
202      procedure Initialize; virtual;
203      function IsInputDataArea: boolean; virtual; abstract; {Input to Database}
204 <    procedure PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
205 <      var sProcessedSQL: string);
204 >    procedure PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
205 >      var sProcessedSQL: AnsiString);
206      function ColumnsInUseCount: integer; virtual;
207 <    function ColumnByName(Idx: string): TSQLVarData;
207 >    function ColumnByName(Idx: AnsiString): TSQLVarData;
208      function CheckStatementStatus(Request: TStatementStatus): boolean; virtual; abstract;
209      procedure GetData(index: integer; var IsNull: boolean; var len: short;
210 <      var data: PChar); virtual;
210 >      var data: PByte); virtual;
211      procedure RowChange;
212      function StateChanged(var ChangeSeqNo: integer): boolean; virtual; abstract;
213 +    property CaseSensitiveParams: boolean read FCaseSensitiveParams
214 +                                            write FCaseSensitiveParams; {Only used when IsInputDataArea true}
215      property Count: integer read GetCount;
216      property Column[index: integer]: TSQLVarData read GetColumn;
217 <    property UniqueRelationName: string read FUniqueRelationName;
217 >    property UniqueRelationName: AnsiString read FUniqueRelationName;
218      property Statement: IStatement read GetStatement;
219      property PrepareSeqNo: integer read GetPrepareSeqNo;
220      property TransactionSeqNo: integer read GetTransactionSeqNo;
# Line 227 | Line 225 | type
225    TSQLVarData = class
226    private
227      FParent: TSQLDataArea;
228 <    FName: string;
228 >    FName: AnsiString;
229      FIndex: integer;
230      FModified: boolean;
231      FUniqueName: boolean;
232      FVarString: RawByteString;
233      function GetStatement: IStatement;
234 <    procedure SetName(AValue: string);
234 >    procedure SetName(AValue: AnsiString);
235    protected
236      function GetSQLType: cardinal; virtual; abstract;
237      function GetSubtype: integer; virtual; abstract;
238 <    function GetAliasName: string;  virtual; abstract;
239 <    function GetFieldName: string; virtual; abstract;
240 <    function GetOwnerName: string;  virtual; abstract;
241 <    function GetRelationName: string;  virtual; abstract;
238 >    function GetAliasName: AnsiString;  virtual; abstract;
239 >    function GetFieldName: AnsiString; virtual; abstract;
240 >    function GetOwnerName: AnsiString;  virtual; abstract;
241 >    function GetRelationName: AnsiString;  virtual; abstract;
242      function GetScale: integer; virtual; abstract;
243      function GetCharSetID: cardinal; virtual; abstract;
244      function GetCodePage: TSystemCodePage; virtual; abstract;
245      function GetIsNull: Boolean;   virtual; abstract;
246      function GetIsNullable: boolean; virtual; abstract;
247 <    function GetSQLData: PChar;  virtual; abstract;
247 >    function GetSQLData: PByte;  virtual; abstract;
248      function GetDataLength: cardinal; virtual; abstract;
249      procedure SetIsNull(Value: Boolean); virtual; abstract;
250      procedure SetIsNullable(Value: Boolean);  virtual; abstract;
251 <    procedure SetSQLData(AValue: PChar; len: cardinal); virtual; abstract;
251 >    procedure SetSQLData(AValue: PByte; len: cardinal); virtual; abstract;
252      procedure SetScale(aValue: integer); virtual; abstract;
253      procedure SetDataLength(len: cardinal); virtual; abstract;
254      procedure SetSQLType(aValue: cardinal); virtual; abstract;
255      procedure SetCharSetID(aValue: cardinal); virtual; abstract;
256    public
257      constructor Create(aParent: TSQLDataArea; aIndex: integer);
258 <    procedure SetString(aValue: string);
258 >    procedure SetString(aValue: AnsiString);
259      procedure Changed; virtual;
260      procedure RowChange; virtual;
261      function GetAsArray(Array_ID: TISC_QUAD): IArray; virtual; abstract;
# Line 268 | Line 266 | type
266      procedure Initialize; virtual;
267  
268    public
269 <    property AliasName: string read GetAliasName;
270 <    property FieldName: string read GetFieldName;
271 <    property OwnerName: string read GetOwnerName;
272 <    property RelationName: string read GetRelationName;
269 >    property AliasName: AnsiString read GetAliasName;
270 >    property FieldName: AnsiString read GetFieldName;
271 >    property OwnerName: AnsiString read GetOwnerName;
272 >    property RelationName: AnsiString read GetRelationName;
273      property Parent: TSQLDataArea read FParent;
274      property Index: integer read FIndex;
275 <    property Name: string read FName write SetName;
275 >    property Name: AnsiString read FName write SetName;
276      property CharSetID: cardinal read GetCharSetID write SetCharSetID;
277      property SQLType: cardinal read GetSQLType write SetSQLType;
278      property SQLSubtype: integer read GetSubtype;
279 <    property SQLData: PChar read GetSQLData;
279 >    property SQLData: PByte read GetSQLData;
280      property DataLength: cardinal read GetDataLength write SetDataLength;
281      property IsNull: Boolean read GetIsNull write SetIsNull;
282      property IsNullable: Boolean read GetIsNullable write SetIsNullable;
# Line 296 | Line 294 | type
294      FIBXSQLVAR: TSQLVarData;
295      FOwner: IUnknown;         {Keep reference to ensure Metadata/statement not discarded}
296      FPrepareSeqNo: integer;
299    FStatement: IStatement;
297      FChangeSeqNo: integer;
298    protected
299      procedure CheckActive; override;
300 <    function SQLData: PChar; override;
300 >    function SQLData: PByte; override;
301      function GetDataLength: cardinal; override;
302      function GetCodePage: TSystemCodePage; override;
303  
# Line 308 | Line 305 | type
305      constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
306      destructor Destroy; override;
307      function GetSQLDialect: integer; override;
311    property Statement: IStatement read FStatement;
308  
309    public
310      {IColumnMetaData}
311      function GetIndex: integer;
312      function GetSQLType: cardinal; override;
313      function getSubtype: integer;
314 <    function getRelationName: string;
315 <    function getOwnerName: string;
316 <    function getSQLName: string;    {Name of the column}
317 <    function getAliasName: string;  {Alias Name of column or Column Name if not alias}
318 <    function GetName: string; override;      {Disambiguated uppercase Field Name}
314 >    function getRelationName: AnsiString;
315 >    function getOwnerName: AnsiString;
316 >    function getSQLName: AnsiString;    {Name of the column}
317 >    function getAliasName: AnsiString;  {Alias Name of column or Column Name if not alias}
318 >    function GetName: AnsiString; override;      {Disambiguated uppercase Field Name}
319      function GetScale: integer; override;
320      function getCharSetID: cardinal; override;
321      function GetIsNullable: boolean; override;
322 <    function GetSize: cardinal;
322 >    function GetSize: cardinal; override;
323      function GetArrayMetaData: IArrayMetaData;
324      function GetBlobMetaData: IBlobMetaData;
325 <    property Name: string read GetName;
325 >    function GetStatement: IStatement;
326 >    function GetTransaction: ITransaction; virtual;
327 >    property Name: AnsiString read GetName;
328      property Size: cardinal read GetSize;
329      property CharSetID: cardinal read getCharSetID;
330      property SQLSubtype: integer read getSubtype;
331      property IsNullable: Boolean read GetIsNullable;
332 +  public
333 +    property Statement: IStatement read GetStatement;
334    end;
335  
336    { TIBSQLData }
337  
338    TIBSQLData = class(TColumnMetaData,ISQLData)
339 +  private
340 +    FTransaction: ITransaction;
341    protected
342      procedure CheckActive; override;
343    public
344 +    function GetTransaction: ITransaction; override;
345      function GetIsNull: Boolean; override;
346      function GetAsArray: IArray;
347      function GetAsBlob: IBlob; overload;
348      function GetAsBlob(BPB: IBPB): IBlob; overload;
349 <    function GetAsString: String; override;
349 >    function GetAsString: AnsiString; override;
350      property AsBlob: IBlob read GetAsBlob;
351   end;
352  
# Line 353 | Line 356 | type
356    protected
357      procedure CheckActive; override;
358      procedure Changed; override;
359 <    procedure InternalSetAsString(Value: String); override;
359 >    procedure InternalSetAsString(Value: AnsiString); override;
360      procedure SetScale(aValue: integer); override;
361      procedure SetDataLength(len: cardinal); override;
362      procedure SetSQLType(aValue: cardinal); override;
# Line 361 | Line 364 | type
364      procedure Clear;
365      function GetModified: boolean; override;
366      function GetAsPointer: Pointer;
367 <    procedure SetName(Value: string); override;
367 >    procedure SetName(Value: AnsiString); override;
368      procedure SetIsNull(Value: Boolean);  override;
369      procedure SetIsNullable(Value: Boolean); override;
370      procedure SetAsArray(anArray: IArray);
# Line 378 | Line 381 | type
381      procedure SetAsFloat(AValue: Float);
382      procedure SetAsPointer(AValue: Pointer);
383      procedure SetAsShort(AValue: Short);
384 <    procedure SetAsString(AValue: String); override;
384 >    procedure SetAsString(AValue: AnsiString); override;
385      procedure SetAsVariant(AValue: Variant);
386      procedure SetAsBlob(aValue: IBlob);
387      procedure SetAsQuad(AValue: TISC_QUAD);
# Line 401 | Line 404 | type
404      destructor Destroy; override;
405    public
406      {IMetaData}
407 <    function GetUniqueRelationName: string;
407 >    function GetUniqueRelationName: AnsiString;
408      function getCount: integer;
409      function getColumnMetaData(index: integer): IColumnMetaData;
410 <    function ByName(Idx: String): IColumnMetaData;
410 >    function ByName(Idx: AnsiString): IColumnMetaData;
411    end;
412  
413    { TSQLParams }
# Line 423 | Line 426 | type
426      {ISQLParams}
427      function getCount: integer;
428      function getSQLParam(index: integer): ISQLParam;
429 <    function ByName(Idx: String): ISQLParam ;
429 >    function ByName(Idx: AnsiString): ISQLParam ;
430      function GetModified: Boolean;
431 +    function GetHasCaseSensitiveParams: Boolean;
432    end;
433  
434    { TResults }
# Line 443 | Line 447 | type
447       constructor Create(aResults: TSQLDataArea);
448        {IResults}
449       function getCount: integer;
450 <     function ByName(Idx: String): ISQLData;
450 >     function ByName(Idx: AnsiString): ISQLData;
451       function getSQLData(index: integer): ISQLData;
452 <     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
452 >     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PByte);
453 >     function GetStatement: IStatement;
454       function GetTransaction: ITransaction; virtual;
455       procedure SetRetainInterfaces(aValue: boolean);
456   end;
457  
458   implementation
459  
460 < uses FBMessages, FBClientAPI, variants, IBUtils, FBTransaction;
460 > uses FBMessages, variants, IBUtils, FBTransaction, DateUtils;
461  
462   { TSQLDataArea }
463  
# Line 472 | Line 477 | procedure TSQLDataArea.SetUniqueRelation
477   var
478    i: Integer;
479    bUnique: Boolean;
480 <  RelationName: string;
480 >  RelationName: AnsiString;
481   begin
482    bUnique := True;
483    for i := 0 to ColumnsInUseCount - 1 do
# Line 503 | Line 508 | begin
508      Column[i].Initialize;
509   end;
510  
511 < procedure TSQLDataArea.PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
512 <  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;
534 <
535 < begin
536 <  if not IsInputDataArea then
537 <    IBError(ibxeNotPermitted,[nil]);
538 <
539 <  sParamName := '';
540 <  iLenSQL := Length(sSQL);
541 <  GetMem(StrBuffer,iLenSQL + 1);
542 <  slNames := TStringList.Create;
543 <  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;
511 > procedure TSQLDataArea.PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
512 >  var sProcessedSQL: AnsiString);
513  
514 <        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;
514 > var slNames: TStrings;
515  
516 <        CommentState:
517 <        begin
518 <          if (cNextChar = #0) then
519 <            IBError(ibxeSQLParseError, [SEOFInComment])
520 <          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);
516 >  procedure SetColumnNames(slNames: TStrings);
517 >  var i, j: integer;
518 >      found: boolean;
519 >  begin
520 >    found := false;
521      SetCount(slNames.Count);
522      for i := 0 to slNames.Count - 1 do
523      begin
# Line 705 | Line 538 | begin
538          Column[i].UniqueName := not found;
539        end;
540      end;
541 +  end;
542 +
543 + begin
544 +  if not IsInputDataArea then
545 +    IBError(ibxeNotPermitted,[nil]);
546 +
547 +  slNames := TStringList.Create;
548 +  try
549 +    sProcessedSQL := TSQLParamProcessor.Execute(sSQL,GenerateParamNames,slNames);
550 +    SetColumnNames(slNames);
551    finally
552      slNames.Free;
710    FreeMem(StrBuffer);
553    end;
554   end;
555  
# Line 716 | Line 558 | begin
558    Result := Count;
559   end;
560  
561 < function TSQLDataArea.ColumnByName(Idx: string): TSQLVarData;
561 > function TSQLDataArea.ColumnByName(Idx: AnsiString): TSQLVarData;
562   var
563 <  s: String;
563 >  s: AnsiString;
564    i: Integer;
565   begin
566 <  {$ifdef UseCaseInSensitiveParamName}
567 <   s := AnsiUpperCase(Idx);
568 <  {$else}
566 >  if not IsInputDataArea or not CaseSensitiveParams then
567 >   s := AnsiUpperCase(Idx)
568 >  else
569     s := Idx;
570 <  {$endif}
570 >
571    for i := 0 to Count - 1 do
572      if Column[i].Name = s then
573      begin
# Line 736 | Line 578 | begin
578   end;
579  
580   procedure TSQLDataArea.GetData(index: integer; var IsNull: boolean;
581 <  var len: short; var data: PChar);
581 >  var len: short; var data: PByte);
582   begin
583    //Do Nothing
584   end;
# Line 755 | Line 597 | begin
597    Result := FParent.Statement;
598   end;
599  
600 < procedure TSQLVarData.SetName(AValue: string);
600 > procedure TSQLVarData.SetName(AValue: AnsiString);
601   begin
602 <  if FName = AValue then Exit;
761 <  {$ifdef UseCaseInSensitiveParamName}
762 <  if Parent.IsInputDataArea then
602 >  if not Parent.IsInputDataArea or not Parent.CaseSensitiveParams then
603      FName := AnsiUpperCase(AValue)
604    else
765  {$endif}
605      FName := AValue;
606   end;
607  
# Line 774 | Line 613 | begin
613    FUniqueName := true;
614   end;
615  
616 < procedure TSQLVarData.SetString(aValue: string);
616 > procedure TSQLVarData.SetString(aValue: AnsiString);
617   begin
618    {we take full advantage here of reference counted strings. When setting a string
619     value, a reference is kept in FVarString and a pointer to it placed in the
620 <   SQLVar. This avoids string copies. Note that PChar is guaranteed to point to
620 >   SQLVar. This avoids string copies. Note that PAnsiChar is guaranteed to point to
621     a zero byte when the string is empty, neatly avoiding a nil pointer error.}
622  
623    FVarString := aValue;
624    SQLType := SQL_TEXT;
625 <  SetSQLData(PChar(FVarString),Length(aValue));
625 >  Scale := 0;
626 >  SetSQLData(PByte(PAnsiChar(FVarString)),Length(aValue));
627   end;
628  
629   procedure TSQLVarData.Changed;
# Line 799 | Line 639 | end;
639  
640   procedure TSQLVarData.Initialize;
641  
642 <  function FindVarByName(idx: string; limit: integer): TSQLVarData;
642 >  function FindVarByName(idx: AnsiString; limit: integer): TSQLVarData;
643    var
644      k: integer;
645    begin
# Line 814 | Line 654 | procedure TSQLVarData.Initialize;
654  
655   var
656    j, j_len: Integer;
657 <  st: String;
658 <  sBaseName: string;
657 >  st: AnsiString;
658 >  sBaseName: AnsiString;
659   begin
660    RowChange;
661  
# Line 902 | Line 742 | function TSQLDataItem.AdjustScaleToCurre
742   var
743    Scaling : Int64;
744    i : Integer;
745 <  FractionText, PadText, CurrText: string;
745 >  FractionText, PadText, CurrText: AnsiString;
746   begin
747    Result := 0;
748    Scaling := 1;
# Line 921 | Line 761 | begin
761        FractionText := IntToStr(abs(Value mod Scaling));
762        for i := Length(FractionText) to -aScale -1 do
763          PadText := '0' + PadText;
764 +      {$IF declared(DefaultFormatSettings)}
765 +      with DefaultFormatSettings do
766 +      {$ELSE}
767 +      {$IF declared(FormatSettings)}
768 +      with FormatSettings do
769 +      {$IFEND}
770 +      {$IFEND}
771        if Value < 0 then
772 <        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText
772 >        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText
773        else
774 <        CurrText := IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText;
774 >        CurrText := IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText;
775        try
776          result := StrToCurr(CurrText);
777        except
# Line 936 | Line 783 | begin
783        result := Value;
784   end;
785  
786 + function TSQLDataItem.GetDateFormatStr(IncludeTime: boolean): AnsiString;
787 + begin
788 +  {$IF declared(DefaultFormatSettings)}
789 +  with DefaultFormatSettings do
790 +  {$ELSE}
791 +  {$IF declared(FormatSettings)}
792 +  with FormatSettings do
793 +  {$IFEND}
794 +  {$IFEND}
795 +  case GetSQLDialect of
796 +    1:
797 +      if IncludeTime then
798 +        result := ShortDateFormat + ' ' + LongTimeFormat
799 +      else
800 +        result := ShortDateFormat;
801 +    3:
802 +      result := ShortDateFormat;
803 +  end;
804 + end;
805 +
806 + function TSQLDataItem.GetTimeFormatStr: AnsiString;
807 + begin
808 +  {$IF declared(DefaultFormatSettings)}
809 +  with DefaultFormatSettings do
810 +  {$ELSE}
811 +  {$IF declared(FormatSettings)}
812 +  with FormatSettings do
813 +  {$IFEND}
814 +  {$IFEND}
815 +    Result := LongTimeFormat;
816 + end;
817 +
818 + function TSQLDataItem.GetTimestampFormatStr: AnsiString;
819 + begin
820 +  {$IF declared(DefaultFormatSettings)}
821 +  with DefaultFormatSettings do
822 +  {$ELSE}
823 +  {$IF declared(FormatSettings)}
824 +  with FormatSettings do
825 +  {$IFEND}
826 +  {$IFEND}
827 +    Result := ShortDateFormat + ' ' +  LongTimeFormat + '.zzz';
828 + end;
829 +
830   procedure TSQLDataItem.SetAsInteger(AValue: Integer);
831   begin
832    SetAsLong(aValue);
# Line 1006 | Line 897 | begin
897    //Do nothing by default
898   end;
899  
900 < procedure TSQLDataItem.InternalSetAsString(Value: String);
900 > procedure TSQLDataItem.InternalSetAsString(Value: AnsiString);
901   begin
902    //Do nothing by default
903   end;
904  
905 < function TSQLDataItem.Transliterate(s: string; CodePage: TSystemCodePage
905 > function TSQLDataItem.Transliterate(s: AnsiString; CodePage: TSystemCodePage
906    ): RawByteString;
907   begin
908    Result := s;
# Line 1034 | Line 925 | begin
925     //Do nothing by default
926   end;
927  
928 < function TSQLDataItem.GetSQLTypeName: string;
928 > constructor TSQLDataItem.Create(api: TFBClientAPI);
929 > begin
930 >  inherited Create;
931 >  FFirebirdClientAPI := api;
932 > end;
933 >
934 > function TSQLDataItem.GetSQLTypeName: AnsiString;
935   begin
936    Result := GetSQLTypeName(GetSQLType);
937   end;
938  
939 < class function TSQLDataItem.GetSQLTypeName(SQLType: short): string;
939 > class function TSQLDataItem.GetSQLTypeName(SQLType: short): AnsiString;
940   begin
941    Result := 'Unknown';
942    case SQLType of
# Line 1060 | Line 957 | begin
957    end;
958   end;
959  
960 + function TSQLDataItem.GetStrDataLength: short;
961 + begin
962 +  with FFirebirdClientAPI do
963 +  if SQLType = SQL_VARYING then
964 +    Result := DecodeInteger(SQLData, 2)
965 +  else
966 +    Result := DataLength;
967 + end;
968 +
969   function TSQLDataItem.GetAsBoolean: boolean;
970   begin
971    CheckActive;
# Line 1140 | Line 1046 | begin
1046    CheckActive;
1047    result := 0;
1048    if not IsNull then
1049 <    with FirebirdClientAPI do
1049 >    with FFirebirdClientAPI do
1050      case SQLType of
1051        SQL_TEXT, SQL_VARYING: begin
1052          try
# Line 1269 | Line 1175 | begin
1175    end;
1176   end;
1177  
1178 + {Copied from LazUTF8}
1179 +
1180 + function UTF8CodepointSizeFull(p: PAnsiChar): integer;
1181 + const TopBitSetMask   = $8000; {%10000000}
1182 +      Top2BitsSetMask = $C000; {%11000000}
1183 +      Top3BitsSetMask = $E000; {%11100000}
1184 +      Top4BitsSetMask = $F000; {%11110000}
1185 +      Top5BitsSetMask = $F800; {%11111000}
1186 + begin
1187 +  case p^ of
1188 +  #0..#191: // %11000000
1189 +    // regular single byte character (#0 is a character, this is Pascal ;)
1190 +    Result:=1;
1191 +  #192..#223: // p^ and %11100000 = %11000000
1192 +    begin
1193 +      // could be 2 byte character
1194 +      if (ord(p[1]) and Top2BitsSetMask) = TopBitSetMask then
1195 +        Result:=2
1196 +      else
1197 +        Result:=1;
1198 +    end;
1199 +  #224..#239: // p^ and %11110000 = %11100000
1200 +    begin
1201 +      // could be 3 byte character
1202 +      if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1203 +      and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask) then
1204 +        Result:=3
1205 +      else
1206 +        Result:=1;
1207 +    end;
1208 +  #240..#247: // p^ and %11111000 = %11110000
1209 +    begin
1210 +      // could be 4 byte character
1211 +      if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1212 +      and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask)
1213 +      and ((ord(p[3]) and Top2BitsSetMask) = TopBitSetMask) then
1214 +        Result:=4
1215 +      else
1216 +        Result:=1;
1217 +    end;
1218 +  else
1219 +    Result:=1;
1220 +  end;
1221 + end;
1222 +
1223 + {Returns the byte length of a UTF8 string with a fixed charwidth}
1224 +
1225 + function GetStrLen(p: PAnsiChar; CharWidth, MaxDataLength: cardinal): integer;
1226 + var i: integer;
1227 +    cplen: integer;
1228 + begin
1229 +  Result := 0;
1230 +  for i := 1 to CharWidth do
1231 +  begin
1232 +    cplen := UTF8CodepointSizeFull(p);
1233 +    Inc(p,cplen);
1234 +    Inc(Result,cplen);
1235 +    if Result >= MaxDataLength then
1236 +    begin
1237 +      Result := MaxDataLength;
1238 +      Exit;
1239 +    end;
1240 +  end;
1241 + end;
1242  
1243 < function TSQLDataItem.GetAsString: String;
1243 > function TSQLDataItem.GetAsString: AnsiString;
1244   var
1245 <  sz: PChar;
1245 >  sz: PByte;
1246    str_len: Integer;
1247    rs: RawByteString;
1248   begin
# Line 1280 | Line 1250 | begin
1250    result := '';
1251    { Check null, if so return a default string }
1252    if not IsNull then
1253 <  with FirebirdClientAPI do
1253 >  with FFirebirdClientAPI do
1254      case SQLType of
1255        SQL_BOOLEAN:
1256          if AsBoolean then
# Line 1292 | Line 1262 | begin
1262        begin
1263          sz := SQLData;
1264          if (SQLType = SQL_TEXT) then
1265 <          str_len := DataLength
1265 >        begin
1266 >          if GetCodePage = cp_utf8 then
1267 >            str_len := GetStrLen(PAnsiChar(sz),GetSize,DataLength)
1268 >          else
1269 >            str_len := DataLength
1270 >        end
1271          else begin
1272 <          str_len := DecodeInteger(SQLData, 2);
1272 >          str_len := DecodeInteger(sz, 2);
1273            Inc(sz, 2);
1274          end;
1275 <        SetString(rs, sz, str_len);
1275 >        SetString(rs, PAnsiChar(sz), str_len);
1276          SetCodePage(rs,GetCodePage,false);
1277 <        if (SQLType = SQL_TEXT) and (GetCharSetID <> 1) then
1303 <          Result := TrimRight(rs)
1304 <        else
1305 <          Result := rs
1277 >        Result := rs;
1278        end;
1279        SQL_TYPE_DATE:
1280 <        case GetSQLDialect of
1309 <          1 : result := DateTimeToStr(AsDateTime);
1310 <          3 : result := DateToStr(AsDateTime);
1311 <        end;
1280 >        result := FormatDateTime(GetDateFormatStr(TimeOf(AsDateTime)<>0),AsDateTime);
1281        SQL_TYPE_TIME :
1282 <        result := TimeToStr(AsDateTime);
1282 >        result := FormatDateTime(GetTimeFormatStr,AsDateTime);
1283        SQL_TIMESTAMP:
1284 <        result := FormatDateTime(FormatSettings.ShortDateFormat + ' ' +
1316 <                            FormatSettings.LongTimeFormat+'.zzz',AsDateTime);
1284 >        result := FormatDateTime(GetTimestampFormatStr,AsDateTime);
1285        SQL_SHORT, SQL_LONG:
1286          if Scale = 0 then
1287            result := IntToStr(AsLong)
# Line 1341 | Line 1309 | begin
1309    Result := false;
1310   end;
1311  
1312 < function TSQLDataItem.getIsNullable: boolean;
1312 > function TSQLDataItem.GetIsNullable: boolean;
1313   begin
1314    CheckActive;
1315    Result := false;
# Line 1389 | Line 1357 | begin
1357    Result := false;
1358   end;
1359  
1360 + function TSQLDataItem.GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats
1361 +  ): integer;
1362 + begin
1363 +  case DateTimeFormat of
1364 +  dfTimestamp:
1365 +    Result := Length(GetTimestampFormatStr);
1366 +  dfDateTime:
1367 +    Result := Length(GetDateFormatStr(true));
1368 +  dfTime:
1369 +    Result := Length(GetTimeFormatStr);
1370 +  else
1371 +    Result := 0;
1372 +  end;
1373 + end;
1374 +
1375  
1376   procedure TSQLDataItem.SetIsNull(Value: Boolean);
1377   begin
# Line 1400 | Line 1383 | begin
1383    //ignore unless overridden
1384   end;
1385  
1386 < procedure TSQLDataItem.SetName(aValue: string);
1386 > procedure TSQLDataItem.SetName(aValue: AnsiString);
1387   begin
1388    //ignore unless overridden
1389   end;
# Line 1452 | Line 1435 | begin
1435  
1436    SQLType := SQL_TYPE_DATE;
1437    DataLength := SizeOf(ISC_DATE);
1438 <  with FirebirdClientAPI do
1438 >  with FFirebirdClientAPI do
1439      SQLEncodeDate(Value,SQLData);
1440    Changed;
1441   end;
# Line 1472 | Line 1455 | begin
1455  
1456    SQLType := SQL_TYPE_TIME;
1457    DataLength := SizeOf(ISC_TIME);
1458 <  with FirebirdClientAPI do
1458 >  with FFirebirdClientAPI do
1459      SQLEncodeTime(Value,SQLData);
1460    Changed;
1461   end;
# Line 1486 | Line 1469 | begin
1469    Changing;
1470    SQLType := SQL_TIMESTAMP;
1471    DataLength := SizeOf(ISC_TIME) + sizeof(ISC_DATE);
1472 <  with FirebirdClientAPI do
1472 >  with FFirebirdClientAPI do
1473      SQLEncodeDateTime(Value,SQLData);
1474    Changed;
1475   end;
# Line 1576 | Line 1559 | begin
1559    Changed;
1560   end;
1561  
1562 < procedure TSQLDataItem.SetAsString(Value: String);
1562 > procedure TSQLDataItem.SetAsString(Value: AnsiString);
1563   begin
1564    InternalSetAsString(Value);
1565   end;
# Line 1611 | Line 1594 | begin
1594    end;
1595   end;
1596  
1597 + procedure TSQLDataItem.SetAsNumeric(Value: Int64; aScale: integer);
1598 + begin
1599 +  CheckActive;
1600 +  Changing;
1601 +  if IsNullable then
1602 +    IsNull := False;
1603 +
1604 +  SQLType := SQL_INT64;
1605 +  Scale := aScale;
1606 +  DataLength := SizeOf(Int64);
1607 +  PInt64(SQLData)^ := Value;
1608 +  Changed;
1609 + end;
1610 +
1611   procedure TSQLDataItem.SetAsBoolean(AValue: boolean);
1612   begin
1613    CheckActive;
# Line 1641 | Line 1638 | begin
1638      IBError(ibxeStatementNotPrepared, [nil]);
1639   end;
1640  
1641 < function TColumnMetaData.SQLData: PChar;
1641 > function TColumnMetaData.SQLData: PByte;
1642   begin
1643    Result := FIBXSQLVAR.SQLData;
1644   end;
# Line 1658 | Line 1655 | end;
1655  
1656   constructor TColumnMetaData.Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
1657   begin
1658 <  inherited Create;
1658 >  inherited Create(aIBXSQLVAR.GetStatement.GetAttachment.getFirebirdAPI as TFBClientAPI);
1659    FIBXSQLVAR := aIBXSQLVAR;
1660    FOwner := aOwner;
1661    FPrepareSeqNo := FIBXSQLVAR.Parent.PrepareSeqNo;
# Line 1694 | Line 1691 | begin
1691    result := FIBXSQLVAR.SQLSubtype;
1692   end;
1693  
1694 < function TColumnMetaData.getRelationName: string;
1694 > function TColumnMetaData.getRelationName: AnsiString;
1695   begin
1696    CheckActive;
1697     result :=  FIBXSQLVAR.RelationName;
1698   end;
1699  
1700 < function TColumnMetaData.getOwnerName: string;
1700 > function TColumnMetaData.getOwnerName: AnsiString;
1701   begin
1702    CheckActive;
1703    result :=  FIBXSQLVAR.OwnerName;
1704   end;
1705  
1706 < function TColumnMetaData.getSQLName: string;
1706 > function TColumnMetaData.getSQLName: AnsiString;
1707   begin
1708    CheckActive;
1709    result :=  FIBXSQLVAR.FieldName;
1710   end;
1711  
1712 < function TColumnMetaData.getAliasName: string;
1712 > function TColumnMetaData.getAliasName: AnsiString;
1713   begin
1714    CheckActive;
1715    result := FIBXSQLVAR.AliasName;
1716   end;
1717  
1718 < function TColumnMetaData.GetName: string;
1718 > function TColumnMetaData.GetName: AnsiString;
1719   begin
1720    CheckActive;
1721    Result := FIBXSQLVAR. Name;
# Line 1760 | Line 1757 | begin
1757    result := FIBXSQLVAR.GetBlobMetaData;
1758   end;
1759  
1760 + function TColumnMetaData.GetStatement: IStatement;
1761 + begin
1762 +  Result := FIBXSQLVAR.GetStatement;
1763 + end;
1764 +
1765 + function TColumnMetaData.GetTransaction: ITransaction;
1766 + begin
1767 +  Result := GetStatement.GetTransaction;
1768 + end;
1769 +
1770   { TIBSQLData }
1771  
1772   procedure TIBSQLData.CheckActive;
# Line 1779 | Line 1786 | begin
1786      IBError(ibxeBOF,[nil]);
1787   end;
1788  
1789 + function TIBSQLData.GetTransaction: ITransaction;
1790 + begin
1791 +  if FTransaction = nil then
1792 +    Result := inherited GetTransaction
1793 +  else
1794 +    Result := FTransaction;
1795 + end;
1796 +
1797   function TIBSQLData.GetIsNull: Boolean;
1798   begin
1799    CheckActive;
# Line 1803 | Line 1818 | begin
1818    result := FIBXSQLVAR.GetAsBlob(AsQuad,BPB);
1819   end;
1820  
1821 < function TIBSQLData.GetAsString: String;
1821 > function TIBSQLData.GetAsString: AnsiString;
1822   begin
1823    CheckActive;
1824    Result := '';
# Line 1821 | Line 1836 | end;
1836  
1837   { TSQLParam }
1838  
1839 < procedure TSQLParam.InternalSetAsString(Value: String);
1839 > procedure TSQLParam.InternalSetAsString(Value: AnsiString);
1840 >
1841 > procedure DoSetString;
1842 > begin
1843 >  Changing;
1844 >  FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1845 >  Changed;
1846 > end;
1847 >
1848   var b: IBlob;
1849 +    dt: TDateTime;
1850 +    CurrValue: Currency;
1851 +    FloatValue: single;
1852   begin
1853    CheckActive;
1854    if IsNullable then
1855      IsNull := False;
1856    case SQLTYPE of
1857    SQL_BOOLEAN:
1858 <    if CompareText(Value,STrue) = 0 then
1858 >    if AnsiCompareText(Value,STrue) = 0 then
1859        AsBoolean := true
1860      else
1861 <    if CompareText(Value,SFalse) = 0 then
1861 >    if AnsiCompareText(Value,SFalse) = 0 then
1862        AsBoolean := false
1863      else
1864        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1848 | Line 1874 | begin
1874  
1875    SQL_VARYING,
1876    SQL_TEXT:
1877 <    begin
1852 <      Changing;
1853 <      FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1854 <      Changed;
1855 <    end;
1877 >    DoSetString;
1878  
1879      SQL_SHORT,
1880      SQL_LONG,
1881      SQL_INT64:
1882 <      SetAsInt64(StrToInt(Value));
1882 >      if TryStrToCurr(Value,CurrValue) then
1883 >        SetAsNumeric(AdjustScaleFromCurrency(CurrValue,GetScale),GetScale)
1884 >      else
1885 >        DoSetString;
1886  
1887      SQL_D_FLOAT,
1888      SQL_DOUBLE,
1889      SQL_FLOAT:
1890 <      SetAsDouble(StrToFloat(Value));
1890 >      if TryStrToFloat(Value,FloatValue) then
1891 >        SetAsDouble(FloatValue)
1892 >      else
1893 >        DoSetString;
1894  
1895      SQL_TIMESTAMP:
1896 <      SetAsDateTime(StrToDateTime(Value));
1896 >      if TryStrToDateTime(Value,dt) then
1897 >        SetAsDateTime(dt)
1898 >      else
1899 >        DoSetString;
1900  
1901      SQL_TYPE_DATE:
1902 <      SetAsDate(StrToDateTime(Value));
1902 >      if TryStrToDateTime(Value,dt) then
1903 >        SetAsDate(dt)
1904 >      else
1905 >        DoSetString;
1906  
1907      SQL_TYPE_TIME:
1908 <      SetAsTime(StrToDateTime(Value));
1908 >      if TryStrToDateTime(Value,dt) then
1909 >        SetAsTime(dt)
1910 >      else
1911 >        DoSetString;
1912  
1913      else
1914        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1925 | Line 1962 | begin
1962    Result := inherited GetAsPointer;
1963   end;
1964  
1965 < procedure TSQLParam.SetName(Value: string);
1965 > procedure TSQLParam.SetName(Value: AnsiString);
1966   begin
1967    CheckActive;
1968    FIBXSQLVAR.Name := Value;
# Line 2231 | Line 2268 | begin
2268    end;
2269   end;
2270  
2271 < procedure TSQLParam.SetAsString(AValue: String);
2271 > procedure TSQLParam.SetAsString(AValue: AnsiString);
2272   var i: integer;
2273      OldSQLVar: TSQLVarData;
2274   begin
# Line 2344 | Line 2381 | begin
2381    inherited Destroy;
2382   end;
2383  
2384 < function TMetaData.GetUniqueRelationName: string;
2384 > function TMetaData.GetUniqueRelationName: AnsiString;
2385   begin
2386    CheckActive;
2387    Result := FMetaData.UniqueRelationName;
# Line 2372 | Line 2409 | begin
2409    end;
2410   end;
2411  
2412 < function TMetaData.ByName(Idx: String): IColumnMetaData;
2412 > function TMetaData.ByName(Idx: AnsiString): IColumnMetaData;
2413   var aIBXSQLVAR: TSQLVarData;
2414   begin
2415    CheckActive;
# Line 2432 | Line 2469 | begin
2469    end;
2470   end;
2471  
2472 < function TSQLParams.ByName(Idx: String): ISQLParam;
2472 > function TSQLParams.ByName(Idx: AnsiString): ISQLParam;
2473   var aIBXSQLVAR: TSQLVarData;
2474   begin
2475    CheckActive;
# Line 2457 | Line 2494 | begin
2494      end;
2495   end;
2496  
2497 + function TSQLParams.GetHasCaseSensitiveParams: Boolean;
2498 + begin
2499 +  Result := FSQLParams.CaseSensitiveParams;
2500 + end;
2501 +
2502   { TResults }
2503  
2504   procedure TResults.CheckActive;
# Line 2475 | Line 2517 | begin
2517   end;
2518  
2519   function TResults.GetISQLData(aIBXSQLVAR: TSQLVarData): ISQLData;
2520 + var col: TIBSQLData;
2521   begin
2522    if (aIBXSQLVAR.Index < 0) or (aIBXSQLVAR.Index >= getCount) then
2523      IBError(ibxeInvalidColumnIndex,[nil]);
2524  
2525    if not HasInterface(aIBXSQLVAR.Index) then
2526      AddInterface(aIBXSQLVAR.Index, TIBSQLData.Create(self,aIBXSQLVAR));
2527 <  Result := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2527 >  col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2528 >  col.FTransaction := GetTransaction;
2529 >  Result := col;
2530   end;
2531  
2532   constructor TResults.Create(aResults: TSQLDataArea);
# Line 2500 | Line 2545 | begin
2545    Result := FResults.Count;
2546   end;
2547  
2548 < function TResults.ByName(Idx: String): ISQLData;
2548 > function TResults.ByName(Idx: AnsiString): ISQLData;
2549   var col: TSQLVarData;
2550   begin
2551    Result := nil;
# Line 2532 | Line 2577 | begin
2577   end;
2578  
2579   procedure TResults.GetData(index: integer; var IsNull: boolean; var len: short;
2580 <  var data: PChar);
2580 >  var data: PByte);
2581   begin
2582    CheckActive;
2583    FResults.GetData(index,IsNull, len,data);
2584   end;
2585  
2586 + function TResults.GetStatement: IStatement;
2587 + begin
2588 +  Result := FStatement;
2589 + end;
2590 +
2591   function TResults.GetTransaction: ITransaction;
2592   begin
2593    Result := FStatement.GetTransaction;
# Line 2548 | Line 2598 | begin
2598    RetainInterfaces := aValue;
2599   end;
2600  
2551
2601   end.
2602  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines