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 309 by tony, Tue Jul 21 08:00:42 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 +     function GetCharSetWidth: integer; virtual; abstract;
143       procedure SetAsBoolean(AValue: boolean); virtual;
144       procedure SetAsCurrency(Value: Currency); virtual;
145       procedure SetAsInt64(Value: Int64); virtual;
# Line 156 | Line 152 | type
152       procedure SetAsPointer(Value: Pointer);
153       procedure SetAsQuad(Value: TISC_QUAD);
154       procedure SetAsShort(Value: short); virtual;
155 <     procedure SetAsString(Value: String); virtual;
155 >     procedure SetAsString(Value: AnsiString); virtual;
156       procedure SetAsVariant(Value: Variant);
157 +     procedure SetAsNumeric(Value: Int64; aScale: integer);
158       procedure SetIsNull(Value: Boolean); virtual;
159       procedure SetIsNullable(Value: Boolean); virtual;
160 <     procedure SetName(aValue: string); virtual;
160 >     procedure SetName(aValue: AnsiString); virtual;
161       property AsDate: TDateTime read GetAsDateTime write SetAsDate;
162       property AsBoolean:boolean read GetAsBoolean write SetAsBoolean;
163       property AsTime: TDateTime read GetAsDateTime write SetAsTime;
# Line 174 | Line 171 | type
171       property AsPointer: Pointer read GetAsPointer write SetAsPointer;
172       property AsQuad: TISC_QUAD read GetAsQuad write SetAsQuad;
173       property AsShort: short read GetAsShort write SetAsShort;
174 <     property AsString: String read GetAsString write SetAsString;
174 >     property AsString: AnsiString read GetAsString write SetAsString;
175       property AsVariant: Variant read GetAsVariant write SetAsVariant;
176       property Modified: Boolean read getModified;
177       property IsNull: Boolean read GetIsNull write SetIsNull;
# Line 191 | Line 188 | type
188  
189    TSQLDataArea = class
190    private
191 +    FCaseSensitiveParams: boolean;
192      function GetColumn(index: integer): TSQLVarData;
193      function GetCount: integer;
194    protected
195 <    FUniqueRelationName: string;
195 >    FUniqueRelationName: AnsiString;
196      FColumnList: array of TSQLVarData;
197      function GetStatement: IStatement; virtual; abstract;
198      function GetPrepareSeqNo: integer; virtual; abstract;
# Line 204 | Line 202 | type
202    public
203      procedure Initialize; virtual;
204      function IsInputDataArea: boolean; virtual; abstract; {Input to Database}
205 <    procedure PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
206 <      var sProcessedSQL: string);
205 >    procedure PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
206 >      var sProcessedSQL: AnsiString);
207      function ColumnsInUseCount: integer; virtual;
208 <    function ColumnByName(Idx: string): TSQLVarData;
208 >    function ColumnByName(Idx: AnsiString): TSQLVarData;
209      function CheckStatementStatus(Request: TStatementStatus): boolean; virtual; abstract;
210      procedure GetData(index: integer; var IsNull: boolean; var len: short;
211 <      var data: PChar); virtual;
211 >      var data: PByte); virtual;
212      procedure RowChange;
213      function StateChanged(var ChangeSeqNo: integer): boolean; virtual; abstract;
214 +    property CaseSensitiveParams: boolean read FCaseSensitiveParams
215 +                                            write FCaseSensitiveParams; {Only used when IsInputDataArea true}
216      property Count: integer read GetCount;
217      property Column[index: integer]: TSQLVarData read GetColumn;
218 <    property UniqueRelationName: string read FUniqueRelationName;
218 >    property UniqueRelationName: AnsiString read FUniqueRelationName;
219      property Statement: IStatement read GetStatement;
220      property PrepareSeqNo: integer read GetPrepareSeqNo;
221      property TransactionSeqNo: integer read GetTransactionSeqNo;
# Line 226 | Line 226 | type
226    TSQLVarData = class
227    private
228      FParent: TSQLDataArea;
229 <    FName: string;
229 >    FName: AnsiString;
230      FIndex: integer;
231      FModified: boolean;
232      FUniqueName: boolean;
233      FVarString: RawByteString;
234      function GetStatement: IStatement;
235 <    procedure SetName(AValue: string);
235 >    procedure SetName(AValue: AnsiString);
236    protected
237      function GetSQLType: cardinal; virtual; abstract;
238      function GetSubtype: integer; virtual; abstract;
239 <    function GetAliasName: string;  virtual; abstract;
240 <    function GetFieldName: string; virtual; abstract;
241 <    function GetOwnerName: string;  virtual; abstract;
242 <    function GetRelationName: string;  virtual; abstract;
239 >    function GetAliasName: AnsiString;  virtual; abstract;
240 >    function GetFieldName: AnsiString; virtual; abstract;
241 >    function GetOwnerName: AnsiString;  virtual; abstract;
242 >    function GetRelationName: AnsiString;  virtual; abstract;
243      function GetScale: integer; virtual; abstract;
244      function GetCharSetID: cardinal; virtual; abstract;
245 +    function GetCharSetWidth: integer; virtual; abstract;
246      function GetCodePage: TSystemCodePage; virtual; abstract;
247      function GetIsNull: Boolean;   virtual; abstract;
248      function GetIsNullable: boolean; virtual; abstract;
249 <    function GetSQLData: PChar;  virtual; abstract;
249 >    function GetSQLData: PByte;  virtual; abstract;
250      function GetDataLength: cardinal; virtual; abstract;
251      procedure SetIsNull(Value: Boolean); virtual; abstract;
252      procedure SetIsNullable(Value: Boolean);  virtual; abstract;
253 <    procedure SetSQLData(AValue: PChar; len: cardinal); virtual; abstract;
253 >    procedure SetSQLData(AValue: PByte; len: cardinal); virtual; abstract;
254      procedure SetScale(aValue: integer); virtual; abstract;
255      procedure SetDataLength(len: cardinal); virtual; abstract;
256      procedure SetSQLType(aValue: cardinal); virtual; abstract;
257      procedure SetCharSetID(aValue: cardinal); virtual; abstract;
258    public
259      constructor Create(aParent: TSQLDataArea; aIndex: integer);
260 <    procedure SetString(aValue: string);
260 >    procedure SetString(aValue: AnsiString);
261      procedure Changed; virtual;
262      procedure RowChange; virtual;
263      function GetAsArray(Array_ID: TISC_QUAD): IArray; virtual; abstract;
# Line 267 | Line 268 | type
268      procedure Initialize; virtual;
269  
270    public
271 <    property AliasName: string read GetAliasName;
272 <    property FieldName: string read GetFieldName;
273 <    property OwnerName: string read GetOwnerName;
274 <    property RelationName: string read GetRelationName;
271 >    property AliasName: AnsiString read GetAliasName;
272 >    property FieldName: AnsiString read GetFieldName;
273 >    property OwnerName: AnsiString read GetOwnerName;
274 >    property RelationName: AnsiString read GetRelationName;
275      property Parent: TSQLDataArea read FParent;
276      property Index: integer read FIndex;
277 <    property Name: string read FName write SetName;
277 >    property Name: AnsiString read FName write SetName;
278      property CharSetID: cardinal read GetCharSetID write SetCharSetID;
279      property SQLType: cardinal read GetSQLType write SetSQLType;
280      property SQLSubtype: integer read GetSubtype;
281 <    property SQLData: PChar read GetSQLData;
281 >    property SQLData: PByte read GetSQLData;
282      property DataLength: cardinal read GetDataLength write SetDataLength;
283      property IsNull: Boolean read GetIsNull write SetIsNull;
284      property IsNullable: Boolean read GetIsNullable write SetIsNullable;
# Line 295 | Line 296 | type
296      FIBXSQLVAR: TSQLVarData;
297      FOwner: IUnknown;         {Keep reference to ensure Metadata/statement not discarded}
298      FPrepareSeqNo: integer;
298    FStatement: IStatement;
299      FChangeSeqNo: integer;
300    protected
301      procedure CheckActive; override;
302 <    function SQLData: PChar; override;
302 >    function SQLData: PByte; override;
303      function GetDataLength: cardinal; override;
304      function GetCodePage: TSystemCodePage; override;
305  
# Line 307 | Line 307 | type
307      constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
308      destructor Destroy; override;
309      function GetSQLDialect: integer; override;
310    property Statement: IStatement read FStatement;
310  
311    public
312      {IColumnMetaData}
313      function GetIndex: integer;
314      function GetSQLType: cardinal; override;
315      function getSubtype: integer;
316 <    function getRelationName: string;
317 <    function getOwnerName: string;
318 <    function getSQLName: string;    {Name of the column}
319 <    function getAliasName: string;  {Alias Name of column or Column Name if not alias}
320 <    function GetName: string; override;      {Disambiguated uppercase Field Name}
316 >    function getRelationName: AnsiString;
317 >    function getOwnerName: AnsiString;
318 >    function getSQLName: AnsiString;    {Name of the column}
319 >    function getAliasName: AnsiString;  {Alias Name of column or Column Name if not alias}
320 >    function GetName: AnsiString; override;      {Disambiguated uppercase Field Name}
321      function GetScale: integer; override;
322 <    function getCharSetID: cardinal;
322 >    function getCharSetID: cardinal; override;
323      function GetIsNullable: boolean; override;
324 <    function GetSize: cardinal;
324 >    function GetSize: cardinal; override;
325 >    function GetCharSetWidth: integer; override;
326      function GetArrayMetaData: IArrayMetaData;
327      function GetBlobMetaData: IBlobMetaData;
328 <    property Name: string read GetName;
328 >    function GetStatement: IStatement;
329 >    function GetTransaction: ITransaction; virtual;
330 >    property Name: AnsiString read GetName;
331      property Size: cardinal read GetSize;
332      property CharSetID: cardinal read getCharSetID;
333      property SQLSubtype: integer read getSubtype;
334      property IsNullable: Boolean read GetIsNullable;
335 +  public
336 +    property Statement: IStatement read GetStatement;
337    end;
338  
339    { TIBSQLData }
340  
341    TIBSQLData = class(TColumnMetaData,ISQLData)
342 +  private
343 +    FTransaction: ITransaction;
344    protected
345      procedure CheckActive; override;
346    public
347 +    function GetTransaction: ITransaction; override;
348      function GetIsNull: Boolean; override;
349      function GetAsArray: IArray;
350      function GetAsBlob: IBlob; overload;
351      function GetAsBlob(BPB: IBPB): IBlob; overload;
352 <    function GetAsString: String; override;
352 >    function GetAsString: AnsiString; override;
353      property AsBlob: IBlob read GetAsBlob;
354   end;
355  
# Line 352 | Line 359 | type
359    protected
360      procedure CheckActive; override;
361      procedure Changed; override;
362 <    procedure InternalSetAsString(Value: String); override;
362 >    procedure InternalSetAsString(Value: AnsiString); override;
363      procedure SetScale(aValue: integer); override;
364      procedure SetDataLength(len: cardinal); override;
365      procedure SetSQLType(aValue: cardinal); override;
# Line 360 | Line 367 | type
367      procedure Clear;
368      function GetModified: boolean; override;
369      function GetAsPointer: Pointer;
370 <    procedure SetName(Value: string); override;
370 >    procedure SetName(Value: AnsiString); override;
371      procedure SetIsNull(Value: Boolean);  override;
372      procedure SetIsNullable(Value: Boolean); override;
373      procedure SetAsArray(anArray: IArray);
# Line 377 | Line 384 | type
384      procedure SetAsFloat(AValue: Float);
385      procedure SetAsPointer(AValue: Pointer);
386      procedure SetAsShort(AValue: Short);
387 <    procedure SetAsString(AValue: String); override;
387 >    procedure SetAsString(AValue: AnsiString); override;
388      procedure SetAsVariant(AValue: Variant);
389      procedure SetAsBlob(aValue: IBlob);
390      procedure SetAsQuad(AValue: TISC_QUAD);
# Line 400 | Line 407 | type
407      destructor Destroy; override;
408    public
409      {IMetaData}
410 <    function GetUniqueRelationName: string;
410 >    function GetUniqueRelationName: AnsiString;
411      function getCount: integer;
412      function getColumnMetaData(index: integer): IColumnMetaData;
413 <    function ByName(Idx: String): IColumnMetaData;
413 >    function ByName(Idx: AnsiString): IColumnMetaData;
414    end;
415  
416    { TSQLParams }
# Line 422 | Line 429 | type
429      {ISQLParams}
430      function getCount: integer;
431      function getSQLParam(index: integer): ISQLParam;
432 <    function ByName(Idx: String): ISQLParam ;
432 >    function ByName(Idx: AnsiString): ISQLParam ;
433      function GetModified: Boolean;
434 +    function GetHasCaseSensitiveParams: Boolean;
435    end;
436  
437    { TResults }
# Line 442 | Line 450 | type
450       constructor Create(aResults: TSQLDataArea);
451        {IResults}
452       function getCount: integer;
453 <     function ByName(Idx: String): ISQLData;
453 >     function ByName(Idx: AnsiString): ISQLData;
454       function getSQLData(index: integer): ISQLData;
455 <     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
455 >     procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PByte);
456 >     function GetStatement: IStatement;
457       function GetTransaction: ITransaction; virtual;
458       procedure SetRetainInterfaces(aValue: boolean);
459   end;
460  
461   implementation
462  
463 < uses FBMessages, FBClientAPI, variants, IBUtils, FBTransaction;
463 > uses FBMessages, variants, IBUtils, FBTransaction, DateUtils;
464  
465   { TSQLDataArea }
466  
# Line 471 | Line 480 | procedure TSQLDataArea.SetUniqueRelation
480   var
481    i: Integer;
482    bUnique: Boolean;
483 <  RelationName: string;
483 >  RelationName: AnsiString;
484   begin
485    bUnique := True;
486    for i := 0 to ColumnsInUseCount - 1 do
# Line 502 | Line 511 | begin
511      Column[i].Initialize;
512   end;
513  
514 < procedure TSQLDataArea.PreprocessSQL(sSQL: string; GenerateParamNames: boolean;
515 <  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}
526 <
527 <  procedure AddToProcessedSQL(cChar: Char);
528 <  begin
529 <    StrBuffer[iSQLPos] := cChar;
530 <    Inc(iSQLPos);
531 <  end;
514 > procedure TSQLDataArea.PreprocessSQL(sSQL: AnsiString; GenerateParamNames: boolean;
515 >  var sProcessedSQL: AnsiString);
516  
517 < begin
534 <  if not IsInputDataArea then
535 <    IBError(ibxeNotPermitted,[nil]);
517 > var slNames: TStrings;
518  
519 <  sParamName := '';
520 <  iLenSQL := Length(sSQL);
521 <  GetMem(StrBuffer,iLenSQL + 1);
522 <  slNames := TStringList.Create;
523 <  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);
519 >  procedure SetColumnNames(slNames: TStrings);
520 >  var i, j: integer;
521 >      found: boolean;
522 >  begin
523 >    found := false;
524      SetCount(slNames.Count);
525      for i := 0 to slNames.Count - 1 do
526      begin
# Line 674 | Line 541 | begin
541          Column[i].UniqueName := not found;
542        end;
543      end;
544 +  end;
545 +
546 + begin
547 +  if not IsInputDataArea then
548 +    IBError(ibxeNotPermitted,[nil]);
549 +
550 +  slNames := TStringList.Create;
551 +  try
552 +    sProcessedSQL := TSQLParamProcessor.Execute(sSQL,GenerateParamNames,slNames);
553 +    SetColumnNames(slNames);
554    finally
555      slNames.Free;
679    FreeMem(StrBuffer);
556    end;
557   end;
558  
# Line 685 | Line 561 | begin
561    Result := Count;
562   end;
563  
564 < function TSQLDataArea.ColumnByName(Idx: string): TSQLVarData;
564 > function TSQLDataArea.ColumnByName(Idx: AnsiString): TSQLVarData;
565   var
566 <  s: String;
566 >  s: AnsiString;
567    i: Integer;
568   begin
569 <  {$ifdef UseCaseInSensitiveParamName}
570 <   s := AnsiUpperCase(Idx);
571 <  {$else}
569 >  if not IsInputDataArea or not CaseSensitiveParams then
570 >   s := AnsiUpperCase(Idx)
571 >  else
572     s := Idx;
573 <  {$endif}
573 >
574    for i := 0 to Count - 1 do
575      if Column[i].Name = s then
576      begin
# Line 705 | Line 581 | begin
581   end;
582  
583   procedure TSQLDataArea.GetData(index: integer; var IsNull: boolean;
584 <  var len: short; var data: PChar);
584 >  var len: short; var data: PByte);
585   begin
586    //Do Nothing
587   end;
# Line 724 | Line 600 | begin
600    Result := FParent.Statement;
601   end;
602  
603 < procedure TSQLVarData.SetName(AValue: string);
603 > procedure TSQLVarData.SetName(AValue: AnsiString);
604   begin
605 <  if FName = AValue then Exit;
730 <  {$ifdef UseCaseInSensitiveParamName}
731 <  if Parent.IsInputDataArea then
605 >  if not Parent.IsInputDataArea or not Parent.CaseSensitiveParams then
606      FName := AnsiUpperCase(AValue)
607    else
734  {$endif}
608      FName := AValue;
609   end;
610  
# Line 743 | Line 616 | begin
616    FUniqueName := true;
617   end;
618  
619 < procedure TSQLVarData.SetString(aValue: string);
619 > procedure TSQLVarData.SetString(aValue: AnsiString);
620   begin
621    {we take full advantage here of reference counted strings. When setting a string
622     value, a reference is kept in FVarString and a pointer to it placed in the
623 <   SQLVar. This avoids string copies. Note that PChar is guaranteed to point to
623 >   SQLVar. This avoids string copies. Note that PAnsiChar is guaranteed to point to
624     a zero byte when the string is empty, neatly avoiding a nil pointer error.}
625  
626    FVarString := aValue;
627    SQLType := SQL_TEXT;
628 <  SetSQLData(PChar(FVarString),Length(aValue));
628 >  Scale := 0;
629 >  SetSQLData(PByte(PAnsiChar(FVarString)),Length(aValue));
630   end;
631  
632   procedure TSQLVarData.Changed;
# Line 768 | Line 642 | end;
642  
643   procedure TSQLVarData.Initialize;
644  
645 <  function FindVarByName(idx: string; limit: integer): TSQLVarData;
645 >  function FindVarByName(idx: AnsiString; limit: integer): TSQLVarData;
646    var
647      k: integer;
648    begin
# Line 783 | Line 657 | procedure TSQLVarData.Initialize;
657  
658   var
659    j, j_len: Integer;
660 <  st: String;
661 <  sBaseName: string;
660 >  st: AnsiString;
661 >  sBaseName: AnsiString;
662   begin
663    RowChange;
664  
# Line 871 | Line 745 | function TSQLDataItem.AdjustScaleToCurre
745   var
746    Scaling : Int64;
747    i : Integer;
748 <  FractionText, PadText, CurrText: string;
748 >  FractionText, PadText, CurrText: AnsiString;
749   begin
750    Result := 0;
751    Scaling := 1;
# Line 890 | Line 764 | begin
764        FractionText := IntToStr(abs(Value mod Scaling));
765        for i := Length(FractionText) to -aScale -1 do
766          PadText := '0' + PadText;
767 +      {$IF declared(DefaultFormatSettings)}
768 +      with DefaultFormatSettings do
769 +      {$ELSE}
770 +      {$IF declared(FormatSettings)}
771 +      with FormatSettings do
772 +      {$IFEND}
773 +      {$IFEND}
774        if Value < 0 then
775 <        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText
775 >        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText
776        else
777 <        CurrText := IntToStr(Abs(Value div Scaling)) + DefaultFormatSettings.DecimalSeparator + PadText + FractionText;
777 >        CurrText := IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText;
778        try
779          result := StrToCurr(CurrText);
780        except
# Line 905 | Line 786 | begin
786        result := Value;
787   end;
788  
789 + function TSQLDataItem.GetDateFormatStr(IncludeTime: boolean): AnsiString;
790 + begin
791 +  {$IF declared(DefaultFormatSettings)}
792 +  with DefaultFormatSettings do
793 +  {$ELSE}
794 +  {$IF declared(FormatSettings)}
795 +  with FormatSettings do
796 +  {$IFEND}
797 +  {$IFEND}
798 +  case GetSQLDialect of
799 +    1:
800 +      if IncludeTime then
801 +        result := ShortDateFormat + ' ' + LongTimeFormat
802 +      else
803 +        result := ShortDateFormat;
804 +    3:
805 +      result := ShortDateFormat;
806 +  end;
807 + end;
808 +
809 + function TSQLDataItem.GetTimeFormatStr: AnsiString;
810 + begin
811 +  {$IF declared(DefaultFormatSettings)}
812 +  with DefaultFormatSettings do
813 +  {$ELSE}
814 +  {$IF declared(FormatSettings)}
815 +  with FormatSettings do
816 +  {$IFEND}
817 +  {$IFEND}
818 +    Result := LongTimeFormat;
819 + end;
820 +
821 + function TSQLDataItem.GetTimestampFormatStr: AnsiString;
822 + begin
823 +  {$IF declared(DefaultFormatSettings)}
824 +  with DefaultFormatSettings do
825 +  {$ELSE}
826 +  {$IF declared(FormatSettings)}
827 +  with FormatSettings do
828 +  {$IFEND}
829 +  {$IFEND}
830 +    Result := ShortDateFormat + ' ' +  LongTimeFormat + '.zzz';
831 + end;
832 +
833   procedure TSQLDataItem.SetAsInteger(AValue: Integer);
834   begin
835    SetAsLong(aValue);
# Line 975 | Line 900 | begin
900    //Do nothing by default
901   end;
902  
903 < procedure TSQLDataItem.InternalSetAsString(Value: String);
903 > procedure TSQLDataItem.InternalSetAsString(Value: AnsiString);
904   begin
905    //Do nothing by default
906   end;
907  
908 < function TSQLDataItem.Transliterate(s: string; CodePage: TSystemCodePage
908 > function TSQLDataItem.Transliterate(s: AnsiString; CodePage: TSystemCodePage
909    ): RawByteString;
910   begin
911    Result := s;
# Line 1003 | Line 928 | begin
928     //Do nothing by default
929   end;
930  
931 < function TSQLDataItem.GetSQLTypeName: string;
931 > constructor TSQLDataItem.Create(api: TFBClientAPI);
932 > begin
933 >  inherited Create;
934 >  FFirebirdClientAPI := api;
935 > end;
936 >
937 > function TSQLDataItem.GetSQLTypeName: AnsiString;
938   begin
939    Result := GetSQLTypeName(GetSQLType);
940   end;
941  
942 < class function TSQLDataItem.GetSQLTypeName(SQLType: short): string;
942 > class function TSQLDataItem.GetSQLTypeName(SQLType: short): AnsiString;
943   begin
944    Result := 'Unknown';
945    case SQLType of
# Line 1029 | Line 960 | begin
960    end;
961   end;
962  
963 + function TSQLDataItem.GetStrDataLength: short;
964 + begin
965 +  with FFirebirdClientAPI do
966 +  if SQLType = SQL_VARYING then
967 +    Result := DecodeInteger(SQLData, 2)
968 +  else
969 +    Result := DataLength;
970 + end;
971 +
972   function TSQLDataItem.GetAsBoolean: boolean;
973   begin
974    CheckActive;
# Line 1109 | Line 1049 | begin
1049    CheckActive;
1050    result := 0;
1051    if not IsNull then
1052 <    with FirebirdClientAPI do
1052 >    with FFirebirdClientAPI do
1053      case SQLType of
1054        SQL_TEXT, SQL_VARYING: begin
1055          try
# Line 1238 | Line 1178 | begin
1178    end;
1179   end;
1180  
1181 + {Copied from LazUTF8}
1182 +
1183 + function UTF8CodepointSizeFull(p: PAnsiChar): integer;
1184 + const TopBitSetMask   = $80; {%10000000}
1185 +      Top2BitsSetMask = $C0; {%11000000}
1186 +      Top3BitsSetMask = $E0; {%11100000}
1187 +      Top4BitsSetMask = $F0; {%11110000}
1188 +      Top5BitsSetMask = $F8; {%11111000}
1189 + begin
1190 +  case p^ of
1191 +  #0..#191: // %11000000
1192 +    // regular single byte character (#0 is a character, this is Pascal ;)
1193 +    Result:=1;
1194 +  #192..#223: // p^ and %11100000 = %11000000
1195 +    begin
1196 +      // could be 2 byte character
1197 +      if (ord(p[1]) and Top2BitsSetMask) = TopBitSetMask then
1198 +        Result:=2
1199 +      else
1200 +        Result:=1;
1201 +    end;
1202 +  #224..#239: // p^ and %11110000 = %11100000
1203 +    begin
1204 +      // could be 3 byte character
1205 +      if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1206 +      and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask) then
1207 +        Result:=3
1208 +      else
1209 +        Result:=1;
1210 +    end;
1211 +  #240..#247: // p^ and %11111000 = %11110000
1212 +    begin
1213 +      // could be 4 byte character
1214 +      if ((ord(p[1]) and Top2BitsSetMask) = TopBitSetMask)
1215 +      and ((ord(p[2]) and Top2BitsSetMask) = TopBitSetMask)
1216 +      and ((ord(p[3]) and Top2BitsSetMask) = TopBitSetMask) then
1217 +        Result:=4
1218 +      else
1219 +        Result:=1;
1220 +    end;
1221 +  else
1222 +    Result:=1;
1223 +  end;
1224 + end;
1225 +
1226 + {Returns the byte length of a UTF8 string with a fixed charwidth}
1227 +
1228 + function GetStrLen(p: PAnsiChar; CharWidth, MaxDataLength: cardinal): integer;
1229 + var i: integer;
1230 +    cplen: integer;
1231 +    s: AnsiString;
1232 + begin
1233 +  Result := 0;
1234 +  s := strpas(p);
1235 +  for i := 1 to CharWidth do
1236 +  begin
1237 +    cplen := UTF8CodepointSizeFull(p);
1238 +    Inc(p,cplen);
1239 +    Inc(Result,cplen);
1240 +    if Result >= MaxDataLength then
1241 +    begin
1242 +      Result := MaxDataLength;
1243 +      Exit;
1244 +    end;
1245 +  end;
1246 + end;
1247  
1248 < function TSQLDataItem.GetAsString: String;
1248 > function TSQLDataItem.GetAsString: AnsiString;
1249   var
1250 <  sz: PChar;
1250 >  sz: PByte;
1251    str_len: Integer;
1252    rs: RawByteString;
1253   begin
# Line 1249 | Line 1255 | begin
1255    result := '';
1256    { Check null, if so return a default string }
1257    if not IsNull then
1258 <  with FirebirdClientAPI do
1258 >  with FFirebirdClientAPI do
1259      case SQLType of
1260        SQL_BOOLEAN:
1261          if AsBoolean then
# Line 1261 | Line 1267 | begin
1267        begin
1268          sz := SQLData;
1269          if (SQLType = SQL_TEXT) then
1270 <          str_len := DataLength
1270 >        begin
1271 >          if GetCodePage = cp_utf8 then
1272 >            str_len := GetStrLen(PAnsiChar(sz),GetSize div GetCharSetWidth,DataLength)
1273 >          else
1274 >            str_len := DataLength
1275 >        end
1276          else begin
1277 <          str_len := DecodeInteger(SQLData, 2);
1277 >          str_len := DecodeInteger(sz, 2);
1278            Inc(sz, 2);
1279          end;
1280 <        SetString(rs, sz, str_len);
1280 >        SetString(rs, PAnsiChar(sz), str_len);
1281          SetCodePage(rs,GetCodePage,false);
1282 <        Result := Trim(rs);
1282 >        Result := rs;
1283        end;
1284        SQL_TYPE_DATE:
1285 <        case GetSQLDialect of
1275 <          1 : result := DateTimeToStr(AsDateTime);
1276 <          3 : result := DateToStr(AsDateTime);
1277 <        end;
1285 >        result := FormatDateTime(GetDateFormatStr(TimeOf(AsDateTime)<>0),AsDateTime);
1286        SQL_TYPE_TIME :
1287 <        result := TimeToStr(AsDateTime);
1287 >        result := FormatDateTime(GetTimeFormatStr,AsDateTime);
1288        SQL_TIMESTAMP:
1289 <        result := FormatDateTime(FormatSettings.ShortDateFormat + ' ' +
1282 <                            FormatSettings.LongTimeFormat+'.zzz',AsDateTime);
1289 >        result := FormatDateTime(GetTimestampFormatStr,AsDateTime);
1290        SQL_SHORT, SQL_LONG:
1291          if Scale = 0 then
1292            result := IntToStr(AsLong)
# Line 1307 | Line 1314 | begin
1314    Result := false;
1315   end;
1316  
1317 < function TSQLDataItem.getIsNullable: boolean;
1317 > function TSQLDataItem.GetIsNullable: boolean;
1318   begin
1319    CheckActive;
1320    Result := false;
# Line 1355 | Line 1362 | begin
1362    Result := false;
1363   end;
1364  
1365 + function TSQLDataItem.GetDateTimeStrLength(DateTimeFormat: TIBDateTimeFormats
1366 +  ): integer;
1367 + begin
1368 +  case DateTimeFormat of
1369 +  dfTimestamp:
1370 +    Result := Length(GetTimestampFormatStr);
1371 +  dfDateTime:
1372 +    Result := Length(GetDateFormatStr(true));
1373 +  dfTime:
1374 +    Result := Length(GetTimeFormatStr);
1375 +  else
1376 +    Result := 0;
1377 +  end;
1378 + end;
1379 +
1380  
1381   procedure TSQLDataItem.SetIsNull(Value: Boolean);
1382   begin
# Line 1366 | Line 1388 | begin
1388    //ignore unless overridden
1389   end;
1390  
1391 < procedure TSQLDataItem.SetName(aValue: string);
1391 > procedure TSQLDataItem.SetName(aValue: AnsiString);
1392   begin
1393    //ignore unless overridden
1394   end;
# Line 1418 | Line 1440 | begin
1440  
1441    SQLType := SQL_TYPE_DATE;
1442    DataLength := SizeOf(ISC_DATE);
1443 <  with FirebirdClientAPI do
1443 >  with FFirebirdClientAPI do
1444      SQLEncodeDate(Value,SQLData);
1445    Changed;
1446   end;
# Line 1438 | Line 1460 | begin
1460  
1461    SQLType := SQL_TYPE_TIME;
1462    DataLength := SizeOf(ISC_TIME);
1463 <  with FirebirdClientAPI do
1463 >  with FFirebirdClientAPI do
1464      SQLEncodeTime(Value,SQLData);
1465    Changed;
1466   end;
# Line 1451 | Line 1473 | begin
1473  
1474    Changing;
1475    SQLType := SQL_TIMESTAMP;
1476 <  DataLength := SizeOf(TISC_QUAD);
1477 <  with FirebirdClientAPI do
1476 >  DataLength := SizeOf(ISC_TIME) + sizeof(ISC_DATE);
1477 >  with FFirebirdClientAPI do
1478      SQLEncodeDateTime(Value,SQLData);
1479    Changed;
1480   end;
# Line 1542 | Line 1564 | begin
1564    Changed;
1565   end;
1566  
1567 < procedure TSQLDataItem.SetAsString(Value: String);
1567 > procedure TSQLDataItem.SetAsString(Value: AnsiString);
1568   begin
1569    InternalSetAsString(Value);
1570   end;
# Line 1577 | Line 1599 | begin
1599    end;
1600   end;
1601  
1602 + procedure TSQLDataItem.SetAsNumeric(Value: Int64; aScale: integer);
1603 + begin
1604 +  CheckActive;
1605 +  Changing;
1606 +  if IsNullable then
1607 +    IsNull := False;
1608 +
1609 +  SQLType := SQL_INT64;
1610 +  Scale := aScale;
1611 +  DataLength := SizeOf(Int64);
1612 +  PInt64(SQLData)^ := Value;
1613 +  Changed;
1614 + end;
1615 +
1616   procedure TSQLDataItem.SetAsBoolean(AValue: boolean);
1617   begin
1618    CheckActive;
# Line 1607 | Line 1643 | begin
1643      IBError(ibxeStatementNotPrepared, [nil]);
1644   end;
1645  
1646 < function TColumnMetaData.SQLData: PChar;
1646 > function TColumnMetaData.SQLData: PByte;
1647   begin
1648    Result := FIBXSQLVAR.SQLData;
1649   end;
# Line 1624 | Line 1660 | end;
1660  
1661   constructor TColumnMetaData.Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
1662   begin
1663 <  inherited Create;
1663 >  inherited Create(aIBXSQLVAR.GetStatement.GetAttachment.getFirebirdAPI as TFBClientAPI);
1664    FIBXSQLVAR := aIBXSQLVAR;
1665    FOwner := aOwner;
1666    FPrepareSeqNo := FIBXSQLVAR.Parent.PrepareSeqNo;
# Line 1660 | Line 1696 | begin
1696    result := FIBXSQLVAR.SQLSubtype;
1697   end;
1698  
1699 < function TColumnMetaData.getRelationName: string;
1699 > function TColumnMetaData.getRelationName: AnsiString;
1700   begin
1701    CheckActive;
1702     result :=  FIBXSQLVAR.RelationName;
1703   end;
1704  
1705 < function TColumnMetaData.getOwnerName: string;
1705 > function TColumnMetaData.getOwnerName: AnsiString;
1706   begin
1707    CheckActive;
1708    result :=  FIBXSQLVAR.OwnerName;
1709   end;
1710  
1711 < function TColumnMetaData.getSQLName: string;
1711 > function TColumnMetaData.getSQLName: AnsiString;
1712   begin
1713    CheckActive;
1714    result :=  FIBXSQLVAR.FieldName;
1715   end;
1716  
1717 < function TColumnMetaData.getAliasName: string;
1717 > function TColumnMetaData.getAliasName: AnsiString;
1718   begin
1719    CheckActive;
1720    result := FIBXSQLVAR.AliasName;
1721   end;
1722  
1723 < function TColumnMetaData.GetName: string;
1723 > function TColumnMetaData.GetName: AnsiString;
1724   begin
1725    CheckActive;
1726    Result := FIBXSQLVAR. Name;
# Line 1714 | Line 1750 | begin
1750    result := FIBXSQLVAR.DataLength;
1751   end;
1752  
1753 + function TColumnMetaData.GetCharSetWidth: integer;
1754 + begin
1755 +  CheckActive;
1756 +  result := FIBXSQLVAR.GetCharSetWidth;
1757 + end;
1758 +
1759   function TColumnMetaData.GetArrayMetaData: IArrayMetaData;
1760   begin
1761    CheckActive;
# Line 1726 | Line 1768 | begin
1768    result := FIBXSQLVAR.GetBlobMetaData;
1769   end;
1770  
1771 + function TColumnMetaData.GetStatement: IStatement;
1772 + begin
1773 +  Result := FIBXSQLVAR.GetStatement;
1774 + end;
1775 +
1776 + function TColumnMetaData.GetTransaction: ITransaction;
1777 + begin
1778 +  Result := GetStatement.GetTransaction;
1779 + end;
1780 +
1781   { TIBSQLData }
1782  
1783   procedure TIBSQLData.CheckActive;
# Line 1745 | Line 1797 | begin
1797      IBError(ibxeBOF,[nil]);
1798   end;
1799  
1800 + function TIBSQLData.GetTransaction: ITransaction;
1801 + begin
1802 +  if FTransaction = nil then
1803 +    Result := inherited GetTransaction
1804 +  else
1805 +    Result := FTransaction;
1806 + end;
1807 +
1808   function TIBSQLData.GetIsNull: Boolean;
1809   begin
1810    CheckActive;
# Line 1769 | Line 1829 | begin
1829    result := FIBXSQLVAR.GetAsBlob(AsQuad,BPB);
1830   end;
1831  
1832 < function TIBSQLData.GetAsString: String;
1832 > function TIBSQLData.GetAsString: AnsiString;
1833   begin
1834    CheckActive;
1835    Result := '';
# Line 1777 | Line 1837 | begin
1837    if not IsNull then
1838    case SQLType of
1839      SQL_ARRAY:
1840 <      result := '(Array)'; {do not localize}
1840 >      result := SArray;
1841      SQL_BLOB:
1842 <      Result := Trim(FIBXSQLVAR.GetAsBlob(AsQuad,nil).GetAsString);
1842 >      Result := FIBXSQLVAR.GetAsBlob(AsQuad,nil).GetAsString;
1843      else
1844        Result := inherited GetAsString;
1845    end;
# Line 1787 | Line 1847 | end;
1847  
1848   { TSQLParam }
1849  
1850 < procedure TSQLParam.InternalSetAsString(Value: String);
1850 > procedure TSQLParam.InternalSetAsString(Value: AnsiString);
1851 >
1852 > procedure DoSetString;
1853 > begin
1854 >  Changing;
1855 >  FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1856 >  Changed;
1857 > end;
1858 >
1859   var b: IBlob;
1860 +    dt: TDateTime;
1861 +    CurrValue: Currency;
1862 +    FloatValue: single;
1863   begin
1864    CheckActive;
1865    if IsNullable then
1866      IsNull := False;
1867    case SQLTYPE of
1868    SQL_BOOLEAN:
1869 <    if CompareText(Value,STrue) = 0 then
1869 >    if AnsiCompareText(Value,STrue) = 0 then
1870        AsBoolean := true
1871      else
1872 <    if CompareText(Value,SFalse) = 0 then
1872 >    if AnsiCompareText(Value,SFalse) = 0 then
1873        AsBoolean := false
1874      else
1875        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1814 | Line 1885 | begin
1885  
1886    SQL_VARYING,
1887    SQL_TEXT:
1888 <    begin
1818 <      Changing;
1819 <      FIBXSQLVar.SetString(Transliterate(Value,GetCodePage));
1820 <      Changed;
1821 <    end;
1888 >    DoSetString;
1889  
1890      SQL_SHORT,
1891      SQL_LONG,
1892      SQL_INT64:
1893 <      SetAsInt64(StrToInt(Value));
1893 >      if TryStrToCurr(Value,CurrValue) then
1894 >        SetAsNumeric(AdjustScaleFromCurrency(CurrValue,GetScale),GetScale)
1895 >      else
1896 >        DoSetString;
1897  
1898      SQL_D_FLOAT,
1899      SQL_DOUBLE,
1900      SQL_FLOAT:
1901 <      SetAsDouble(StrToFloat(Value));
1901 >      if TryStrToFloat(Value,FloatValue) then
1902 >        SetAsDouble(FloatValue)
1903 >      else
1904 >        DoSetString;
1905  
1906      SQL_TIMESTAMP:
1907 <      SetAsDateTime(StrToDateTime(Value));
1907 >      if TryStrToDateTime(Value,dt) then
1908 >        SetAsDateTime(dt)
1909 >      else
1910 >        DoSetString;
1911  
1912      SQL_TYPE_DATE:
1913 <      SetAsDate(StrToDateTime(Value));
1913 >      if TryStrToDateTime(Value,dt) then
1914 >        SetAsDate(dt)
1915 >      else
1916 >        DoSetString;
1917  
1918      SQL_TYPE_TIME:
1919 <      SetAsTime(StrToDateTime(Value));
1919 >      if TryStrToDateTime(Value,dt) then
1920 >        SetAsTime(dt)
1921 >      else
1922 >        DoSetString;
1923  
1924      else
1925        IBError(ibxeInvalidDataConversion,[nil]);
# Line 1891 | Line 1973 | begin
1973    Result := inherited GetAsPointer;
1974   end;
1975  
1976 < procedure TSQLParam.SetName(Value: string);
1976 > procedure TSQLParam.SetName(Value: AnsiString);
1977   begin
1978    CheckActive;
1979    FIBXSQLVAR.Name := Value;
# Line 2197 | Line 2279 | begin
2279    end;
2280   end;
2281  
2282 < procedure TSQLParam.SetAsString(AValue: String);
2282 > procedure TSQLParam.SetAsString(AValue: AnsiString);
2283   var i: integer;
2284      OldSQLVar: TSQLVarData;
2285   begin
# Line 2310 | Line 2392 | begin
2392    inherited Destroy;
2393   end;
2394  
2395 < function TMetaData.GetUniqueRelationName: string;
2395 > function TMetaData.GetUniqueRelationName: AnsiString;
2396   begin
2397    CheckActive;
2398    Result := FMetaData.UniqueRelationName;
# Line 2338 | Line 2420 | begin
2420    end;
2421   end;
2422  
2423 < function TMetaData.ByName(Idx: String): IColumnMetaData;
2423 > function TMetaData.ByName(Idx: AnsiString): IColumnMetaData;
2424   var aIBXSQLVAR: TSQLVarData;
2425   begin
2426    CheckActive;
# Line 2398 | Line 2480 | begin
2480    end;
2481   end;
2482  
2483 < function TSQLParams.ByName(Idx: String): ISQLParam;
2483 > function TSQLParams.ByName(Idx: AnsiString): ISQLParam;
2484   var aIBXSQLVAR: TSQLVarData;
2485   begin
2486    CheckActive;
# Line 2423 | Line 2505 | begin
2505      end;
2506   end;
2507  
2508 + function TSQLParams.GetHasCaseSensitiveParams: Boolean;
2509 + begin
2510 +  Result := FSQLParams.CaseSensitiveParams;
2511 + end;
2512 +
2513   { TResults }
2514  
2515   procedure TResults.CheckActive;
# Line 2441 | Line 2528 | begin
2528   end;
2529  
2530   function TResults.GetISQLData(aIBXSQLVAR: TSQLVarData): ISQLData;
2531 + var col: TIBSQLData;
2532   begin
2533    if (aIBXSQLVAR.Index < 0) or (aIBXSQLVAR.Index >= getCount) then
2534      IBError(ibxeInvalidColumnIndex,[nil]);
2535  
2536    if not HasInterface(aIBXSQLVAR.Index) then
2537      AddInterface(aIBXSQLVAR.Index, TIBSQLData.Create(self,aIBXSQLVAR));
2538 <  Result := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2538 >  col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
2539 >  col.FTransaction := GetTransaction;
2540 >  Result := col;
2541   end;
2542  
2543   constructor TResults.Create(aResults: TSQLDataArea);
# Line 2466 | Line 2556 | begin
2556    Result := FResults.Count;
2557   end;
2558  
2559 < function TResults.ByName(Idx: String): ISQLData;
2559 > function TResults.ByName(Idx: AnsiString): ISQLData;
2560   var col: TSQLVarData;
2561   begin
2562    Result := nil;
# Line 2498 | Line 2588 | begin
2588   end;
2589  
2590   procedure TResults.GetData(index: integer; var IsNull: boolean; var len: short;
2591 <  var data: PChar);
2591 >  var data: PByte);
2592   begin
2593    CheckActive;
2594    FResults.GetData(index,IsNull, len,data);
2595   end;
2596  
2597 + function TResults.GetStatement: IStatement;
2598 + begin
2599 +  Result := FStatement;
2600 + end;
2601 +
2602   function TResults.GetTransaction: ITransaction;
2603   begin
2604    Result := FStatement.GetTransaction;
# Line 2514 | Line 2609 | begin
2609    RetainInterfaces := aValue;
2610   end;
2611  
2517
2612   end.
2613  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines