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 45 by tony, Tue Dec 6 10:33:46 2016 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 Transliterate(s: string; CodePage: TSystemCodePage): RawByteString;
110 >     function getCharSetID: cardinal; virtual; abstract;
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 139 | 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 156 | 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 174 | 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 191 | 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 204 | 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 226 | 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 267 | 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 295 | Line 294 | type
294      FIBXSQLVAR: TSQLVarData;
295      FOwner: IUnknown;         {Keep reference to ensure Metadata/statement not discarded}
296      FPrepareSeqNo: integer;
298    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 307 | Line 305 | type
305      constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
306      destructor Destroy; override;
307      function GetSQLDialect: integer; override;
310    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;
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 352 | 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 360 | 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 377 | 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 400 | 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 422 | 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 442 | 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 471 | 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 502 | Line 508 | begin
508      Column[i].Initialize;
509   end;
510  
511 < procedure TSQLDataArea.PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
512 <  var sProcessedSQL: string);
507 < var
508 <  cCurChar, cNextChar, cQuoteChar: Char;
509 <  sParamName: String;
510 <  j, i, iLenSQL, iSQLPos: Integer;
511 <  iCurState {$ifdef ALLOWDIALECT3PARAMNAMES}, iCurParamState {$endif}: Integer;
512 <  iParamSuffix: Integer;
513 <  slNames: TStrings;
514 <  StrBuffer: PChar;
515 <  found: boolean;
516 <
517 < const
518 <  DefaultState = 0;
519 <  CommentState = 1;
520 <  QuoteState = 2;
521 <  ParamState = 3;
522 < {$ifdef ALLOWDIALECT3PARAMNAMES}
523 <  ParamDefaultState = 0;
524 <  ParamQuoteState = 1;
525 <  {$endif}
511 > procedure TSQLDataArea.PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
512 >  var sProcessedSQL: AnsiString);
513  
514 <  procedure AddToProcessedSQL(cChar: Char);
528 <  begin
529 <    StrBuffer[iSQLPos] := cChar;
530 <    Inc(iSQLPos);
531 <  end;
532 <
533 < begin
534 <  if not IsInputDataArea then
535 <    IBError(ibxeNotPermitted,[nil]);
514 > var slNames: TStrings;
515  
516 <  sParamName := '';
517 <  iLenSQL := Length(sSQL);
518 <  GetMem(StrBuffer,iLenSQL + 1);
519 <  slNames := TStringList.Create;
520 <  try
542 <    { Do some initializations of variables }
543 <    iParamSuffix := 0;
544 <    cQuoteChar := '''';
545 <    i := 1;
546 <    iSQLPos := 0;
547 <    iCurState := DefaultState;
548 <    {$ifdef ALLOWDIALECT3PARAMNAMES}
549 <    iCurParamState := ParamDefaultState;
550 <    {$endif}
551 <    { Now, traverse through the SQL string, character by character,
552 <     picking out the parameters and formatting correctly for InterBase }
553 <    while (i <= iLenSQL) do begin
554 <      { Get the current token and a look-ahead }
555 <      cCurChar := sSQL[i];
556 <      if i = iLenSQL then
557 <        cNextChar := #0
558 <      else
559 <        cNextChar := sSQL[i + 1];
560 <      { Now act based on the current state }
561 <      case iCurState of
562 <        DefaultState: begin
563 <          case cCurChar of
564 <            '''', '"': begin
565 <              cQuoteChar := cCurChar;
566 <              iCurState := QuoteState;
567 <            end;
568 <            '?', ':': begin
569 <              iCurState := ParamState;
570 <              AddToProcessedSQL('?');
571 <            end;
572 <            '/': if (cNextChar = '*') then begin
573 <              AddToProcessedSQL(cCurChar);
574 <              Inc(i);
575 <              iCurState := CommentState;
576 <            end;
577 <          end;
578 <        end;
579 <        CommentState: begin
580 <          if (cNextChar = #0) then
581 <            IBError(ibxeSQLParseError, [SEOFInComment])
582 <          else if (cCurChar = '*') then begin
583 <            if (cNextChar = '/') then
584 <              iCurState := DefaultState;
585 <          end;
586 <        end;
587 <        QuoteState: begin
588 <          if cNextChar = #0 then
589 <            IBError(ibxeSQLParseError, [SEOFInString])
590 <          else if (cCurChar = cQuoteChar) then begin
591 <            if (cNextChar = cQuoteChar) then begin
592 <              AddToProcessedSQL(cCurChar);
593 <              Inc(i);
594 <            end else
595 <              iCurState := DefaultState;
596 <          end;
597 <        end;
598 <        ParamState:
599 <        begin
600 <          { collect the name of the parameter }
601 <          {$ifdef ALLOWDIALECT3PARAMNAMES}
602 <          if iCurParamState = ParamDefaultState then
603 <          begin
604 <            if cCurChar = '"' then
605 <              iCurParamState := ParamQuoteState
606 <            else
607 <            {$endif}
608 <            if (cCurChar in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$']) then
609 <                sParamName := sParamName + cCurChar
610 <            else if GenerateParamNames then
611 <            begin
612 <              sParamName := 'IBXParam' + IntToStr(iParamSuffix); {do not localize}
613 <              Inc(iParamSuffix);
614 <              iCurState := DefaultState;
615 <              slNames.AddObject(sParamName,self); //Note local convention
616 <                                                  //add pointer to self to mark entry
617 <              sParamName := '';
618 <            end
619 <            else
620 <              IBError(ibxeSQLParseError, [SParamNameExpected]);
621 <          {$ifdef ALLOWDIALECT3PARAMNAMES}
622 <          end
623 <          else begin
624 <            { determine if Quoted parameter name is finished }
625 <            if cCurChar = '"' then
626 <            begin
627 <              Inc(i);
628 <              slNames.Add(sParamName);
629 <              SParamName := '';
630 <              iCurParamState := ParamDefaultState;
631 <              iCurState := DefaultState;
632 <            end
633 <            else
634 <              sParamName := sParamName + cCurChar
635 <          end;
636 <          {$endif}
637 <          { determine if the unquoted parameter name is finished }
638 <          if {$ifdef ALLOWDIALECT3PARAMNAMES}(iCurParamState <> ParamQuoteState) and {$endif}
639 <            (iCurState <> DefaultState) then
640 <          begin
641 <            if not (cNextChar in ['A'..'Z', 'a'..'z',
642 <                                  '0'..'9', '_', '$']) then begin
643 <              Inc(i);
644 <              iCurState := DefaultState;
645 <              slNames.Add(sParamName);
646 <              sParamName := '';
647 <            end;
648 <          end;
649 <        end;
650 <      end;
651 <      if (iCurState <> ParamState) and (i <= iLenSQL) then
652 <        AddToProcessedSQL(sSQL[i]);
653 <      Inc(i);
654 <    end;
655 <    AddToProcessedSQL(#0);
656 <    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 674 | 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;
679    FreeMem(StrBuffer);
553    end;
554   end;
555  
# Line 685 | 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 705 | 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 724 | 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;
730 <  {$ifdef UseCaseInSensitiveParamName}
731 <  if Parent.IsInputDataArea then
602 >  if not Parent.IsInputDataArea or not Parent.CaseSensitiveParams then
603      FName := AnsiUpperCase(AValue)
604    else
734  {$endif}
605      FName := AValue;
606   end;
607  
# Line 743 | 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 768 | 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 783 | 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 871 | 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 890 | 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 905 | 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 975 | 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 1003 | 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 1029 | 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 1109 | 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 1238 | 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 TSQLDataItem.GetAsString: String;
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: AnsiString;
1244   var
1245 <  sz: PChar;
1245 >  sz: PByte;
1246    str_len: Integer;
1247    rs: RawByteString;
1248   begin
# Line 1249 | 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 1261 | 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 <        Result := Trim(rs);
1277 >        Result := rs;
1278        end;
1279        SQL_TYPE_DATE:
1280 <        case GetSQLDialect of
1275 <          1 : result := DateTimeToStr(AsDateTime);
1276 <          3 : result := DateToStr(AsDateTime);
1277 <        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 + ' ' +
1282 <                            FormatSettings.LongTimeFormat+'.zzz',AsDateTime);
1284 >        result := FormatDateTime(GetTimestampFormatStr,AsDateTime);
1285        SQL_SHORT, SQL_LONG:
1286          if Scale = 0 then
1287            result := IntToStr(AsLong)
# Line 1307 | 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 1355 | 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 1366 | 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 1418 | 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 1438 | 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 1451 | Line 1468 | begin
1468  
1469    Changing;
1470    SQLType := SQL_TIMESTAMP;
1471 <  DataLength := SizeOf(TISC_QUAD);
1472 <  with FirebirdClientAPI do
1471 >  DataLength := SizeOf(ISC_TIME) + sizeof(ISC_DATE);
1472 >  with FFirebirdClientAPI do
1473      SQLEncodeDateTime(Value,SQLData);
1474    Changed;
1475   end;
# Line 1542 | 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 1577 | 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 1607 | 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 1624 | 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 1660 | 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 1726 | 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 1745 | 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 1769 | 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 1777 | Line 1826 | begin
1826    if not IsNull then
1827    case SQLType of
1828      SQL_ARRAY:
1829 <      result := '(Array)'; {do not localize}
1829 >      result := SArray;
1830      SQL_BLOB:
1831 <      Result := Trim(FIBXSQLVAR.GetAsBlob(AsQuad,nil).GetAsString);
1831 >      Result := FIBXSQLVAR.GetAsBlob(AsQuad,nil).GetAsString;
1832      else
1833        Result := inherited GetAsString;
1834    end;
# Line 1787 | 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 1814 | Line 1874 | begin
1874  
1875    SQL_VARYING,
1876    SQL_TEXT:
1877 <    begin
1818 <      Changing;
1819 <      FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1820 <      Changed;
1821 <    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 1891 | 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 2197 | 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 2310 | 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 2338 | 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 2398 | 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 2423 | 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 2441 | 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 2466 | 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 2498 | 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 2514 | Line 2598 | begin
2598    RetainInterfaces := aValue;
2599   end;
2600  
2517
2601   end.
2602  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines