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

Comparing:
ibx/trunk/fbintf/client/FBSQLData.pas (file contents), Revision 345 by tony, Mon Aug 23 14:22:29 2021 UTC vs.
ibx/branches/udr/client/FBSQLData.pas (file contents), Revision 381 by tony, Sat Jan 15 00:06:22 2022 UTC

# Line 122 | Line 122 | type
122    private
123       FFirebirdClientAPI: TFBClientAPI;
124       FTimeZoneServices: IExTimeZoneServices;
125     function AdjustScale(Value: Int64; aScale: Integer): Double;
126     function AdjustScaleToInt64(Value: Int64; aScale: Integer): Int64;
127     function AdjustScaleToCurrency(Value: Int64; aScale: Integer): Currency;
125       function GetDateFormatStr(IncludeTime: boolean): AnsiString;
126       function GetTimeFormatStr: AnsiString;
127       function GetTimestampFormatStr: AnsiString;
# Line 132 | Line 129 | type
129       procedure InternalGetAsDateTime(var aDateTime: TDateTime; var dstOffset: smallint;
130         var aTimezone: AnsiString; var aTimeZoneID: TFBTimeZoneID);
131    protected
135     function AdjustScaleFromCurrency(Value: Currency; aScale: Integer): Int64;
136     function AdjustScaleFromDouble(Value: Double; aScale: Integer): Int64;
132       procedure CheckActive; virtual;
133       procedure CheckTZSupport;
134       function GetAttachment: IAttachment; virtual; abstract;
135 +     function GetTransaction: ITransaction; virtual; abstract;
136       function GetSQLDialect: integer; virtual; abstract;
137       function GetTimeZoneServices: IExTimeZoneServices; virtual;
138       procedure Changed; virtual;
# Line 154 | Line 150 | type
150       property FirebirdClientAPI: TFBClientAPI read FFirebirdClientAPI;
151    public
152       constructor Create(api: TFBClientAPI);
153 <     function GetSQLType: cardinal; virtual; abstract;
153 >     function CanChangeMetaData: boolean; virtual;
154 >     function GetSQLType: cardinal; virtual; abstract; {Current Field Data SQL Type}
155       function GetSQLTypeName: AnsiString; overload;
156 <     class function GetSQLTypeName(SQLType: short): AnsiString; overload;
156 >     class function GetSQLTypeName(SQLType: cardinal): AnsiString; overload;
157       function GetStrDataLength: short;
158 +     function getColMetadata: IParamMetaData; virtual; abstract;
159       function GetName: AnsiString; virtual; abstract;
160 <     function GetScale: integer; virtual; abstract;
160 >     function GetScale: integer; virtual; abstract; {Current Field Data scale}
161       function GetAsBoolean: boolean;
162       function GetAsCurrency: Currency;
163       function GetAsInt64: Int64;
# Line 178 | Line 176 | type
176       function GetAsQuad: TISC_QUAD;
177       function GetAsShort: short;
178       function GetAsString: AnsiString; virtual;
179 +     function GetAsNumeric: IFBNumeric;
180       function GetIsNull: Boolean; virtual;
181       function GetIsNullable: boolean; virtual;
182       function GetAsVariant: Variant;
# Line 205 | Line 204 | type
204       procedure SetAsShort(Value: short); virtual;
205       procedure SetAsString(Value: AnsiString); virtual;
206       procedure SetAsVariant(Value: Variant);
207 <     procedure SetAsNumeric(Value: Int64; aScale: integer);
207 >     procedure SetAsNumeric(Value: IFBNumeric); virtual;
208       procedure SetAsBcd(aValue: tBCD); virtual;
209       procedure SetIsNull(Value: Boolean); virtual;
210       procedure SetIsNullable(Value: Boolean); virtual;
# Line 247 | Line 246 | type
246      FUniqueRelationName: AnsiString;
247      FColumnList: array of TSQLVarData;
248      function GetStatement: IStatement; virtual; abstract;
249 +    function GetAttachment: IAttachment; virtual;
250 +    function GetTransaction: ITransaction; virtual;
251      function GetPrepareSeqNo: integer; virtual; abstract;
252      function GetTransactionSeqNo: integer; virtual; abstract;
253      procedure SetCount(aValue: integer); virtual; abstract;
# Line 267 | Line 268 | type
268                                              write FCaseSensitiveParams; {Only used when IsInputDataArea true}
269      function CanChangeMetaData: boolean; virtual; abstract;
270      property Count: integer read GetCount;
271 <    property Column[index: integer]: TSQLVarData read GetColumn;
271 >    property Column[index: integer]: TSQLVarData read GetColumn; default;
272      property UniqueRelationName: AnsiString read FUniqueRelationName;
273      property Statement: IStatement read GetStatement;
274 +    property Attachment: IAttachment read GetAttachment;
275      property PrepareSeqNo: integer read GetPrepareSeqNo;
276 +    property Transaction: ITransaction read GetTransaction;
277      property TransactionSeqNo: integer read GetTransactionSeqNo;
278    end;
279  
# Line 284 | Line 287 | type
287      FModified: boolean;
288      FUniqueName: boolean;
289      FVarString: RawByteString;
290 +    FColMetaData: IParamMetaData;
291      function GetStatement: IStatement;
292      procedure SetName(AValue: AnsiString);
293    protected
294 <    function GetAttachment: IAttachment; virtual; abstract;
294 >    FArrayIntf: IArray;
295 >    function GetAttachment: IAttachment;
296 >    function GetTransaction: ITransaction;
297      function GetSQLType: cardinal; virtual; abstract;
298      function GetSubtype: integer; virtual; abstract;
299      function GetAliasName: AnsiString;  virtual; abstract;
# Line 296 | Line 302 | type
302      function GetRelationName: AnsiString;  virtual; abstract;
303      function GetScale: integer; virtual; abstract;
304      function GetCharSetID: cardinal; virtual; abstract;
305 <    function GetCharSetWidth: integer; virtual; abstract;
306 <    function GetCodePage: TSystemCodePage; virtual; abstract;
305 >    function GetCharSetWidth: integer;
306 >    function GetCodePage: TSystemCodePage;
307      function GetIsNull: Boolean;   virtual; abstract;
308      function GetIsNullable: boolean; virtual; abstract;
309      function GetSQLData: PByte;  virtual; abstract;
310      function GetDataLength: cardinal; virtual; abstract; {current field length}
311      function GetSize: cardinal; virtual; abstract; {field length as given by metadata}
312      function GetDefaultTextSQLType: cardinal; virtual; abstract;
313 +    procedure InternalSetSQLType(aValue: cardinal); virtual; abstract;
314 +    procedure InternalSetScale(aValue: integer); virtual; abstract;
315 +    procedure InternalSetDataLength(len: cardinal); virtual; abstract;
316      procedure SetIsNull(Value: Boolean); virtual; abstract;
317      procedure SetIsNullable(Value: Boolean);  virtual; abstract;
318      procedure SetSQLData(AValue: PByte; len: cardinal); virtual; abstract;
319 <    procedure SetScale(aValue: integer); virtual; abstract;
320 <    procedure SetDataLength(len: cardinal); virtual; abstract;
321 <    procedure SetSQLType(aValue: cardinal); virtual; abstract;
319 >    procedure SetScale(aValue: integer);
320 >    procedure SetDataLength(len: cardinal);
321 >    procedure SetSQLType(aValue: cardinal);
322      procedure SetCharSetID(aValue: cardinal); virtual; abstract;
323      procedure SetMetaSize(aValue: cardinal); virtual;
324    public
325      constructor Create(aParent: TSQLDataArea; aIndex: integer);
326 +    function CanChangeMetaData: boolean;
327      procedure SetString(aValue: AnsiString);
328      procedure Changed; virtual;
329      procedure RowChange; virtual;
330 <    function GetAsArray(Array_ID: TISC_QUAD): IArray; virtual; abstract;
330 >    function GetAsArray: IArray; virtual; abstract;
331      function GetAsBlob(Blob_ID: TISC_QUAD; BPB: IBPB): IBlob; virtual; abstract;
332      function CreateBlob: IBlob; virtual; abstract;
333      function GetArrayMetaData: IArrayMetaData; virtual; abstract;
334      function GetBlobMetaData: IBlobMetaData; virtual; abstract;
335 +    function getColMetadata: IParamMetaData;
336      procedure Initialize; virtual;
337 +    procedure SaveMetaData;
338 +    procedure SetArray(AValue: IArray);
339  
340    public
341      property AliasName: AnsiString read GetAliasName;
# Line 333 | Line 346 | type
346      property Index: integer read FIndex;
347      property Name: AnsiString read FName write SetName;
348      property CharSetID: cardinal read GetCharSetID write SetCharSetID;
349 +    property CodePage: TSystemCodePage read GetCodePage;
350      property SQLType: cardinal read GetSQLType write SetSQLType;
351      property SQLSubtype: integer read GetSubtype;
352      property SQLData: PByte read GetSQLData;
# Line 348 | Line 362 | type
362  
363    { TColumnMetaData }
364  
365 <  TColumnMetaData = class(TSQLDataItem,IColumnMetaData)
365 >  TColumnMetaData = class(TSQLDataItem,IColumnMetaData,IParamMetaData)
366    private
367      FIBXSQLVAR: TSQLVarData;
368      FOwner: IUnknown;         {Keep reference to ensure Metadata/statement not discarded}
# Line 356 | Line 370 | type
370      FChangeSeqNo: integer;
371    protected
372      procedure CheckActive; override;
359    function GetAttachment: IAttachment; override;
373      function SQLData: PByte; override;
374      function GetDataLength: cardinal; override;
375      function GetCodePage: TSystemCodePage; override;
# Line 365 | Line 378 | type
378      constructor Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
379      destructor Destroy; override;
380      function GetSQLDialect: integer; override;
381 +    function getColMetadata: IParamMetaData; override;
382  
383    public
384      {IColumnMetaData}
# Line 384 | Line 398 | type
398      function GetArrayMetaData: IArrayMetaData;
399      function GetBlobMetaData: IBlobMetaData;
400      function GetStatement: IStatement;
401 <    function GetTransaction: ITransaction; virtual;
401 >    function GetTransaction: ITransaction; override;
402 >    function GetAttachment: IAttachment; override;
403      property Name: AnsiString read GetName;
404      property Size: cardinal read GetSize;
405      property CharSetID: cardinal read getCharSetID;
# Line 397 | Line 412 | type
412    { TIBSQLData }
413  
414    TIBSQLData = class(TColumnMetaData,ISQLData)
400  private
401    FTransaction: ITransaction;
415    protected
416      procedure CheckActive; override;
417    public
405    function GetTransaction: ITransaction; override;
418      function GetIsNull: Boolean; override;
419      function GetAsArray: IArray;
420      function GetAsBlob: IBlob; overload;
# Line 411 | Line 423 | type
423      property AsBlob: IBlob read GetAsBlob;
424   end;
425  
426 +  { TSQLParamMetaData }
427 +
428 +  TSQLParamMetaData = class(TFBInterfacedObject,IParamMetaData)
429 +  private
430 +    FSQLType: cardinal;
431 +    FSQLSubType: integer;
432 +    FScale: integer;
433 +    FCharSetID: cardinal;
434 +    FNullable: boolean;
435 +    FSize: cardinal;
436 +    FCodePage: TSystemCodePage;
437 +  public
438 +    constructor Create(src: TSQLVarData);
439 +    {IParamMetaData}
440 +    function GetSQLType: cardinal;
441 +    function GetSQLTypeName: AnsiString;
442 +    function getSubtype: integer;
443 +    function getScale: integer;
444 +    function getCharSetID: cardinal;
445 +    function getCodePage: TSystemCodePage;
446 +    function getIsNullable: boolean;
447 +    function GetSize: cardinal;
448 +    property SQLType: cardinal read GetSQLType;
449 +  end;
450 +
451    { TSQLParam }
452  
453    TSQLParam = class(TIBSQLData,ISQLParam,ISQLData)
# Line 423 | Line 460 | type
460      procedure SetSQLType(aValue: cardinal); override;
461    public
462      procedure Clear;
463 +    function CanChangeMetaData: boolean; override;
464 +    function getColMetadata: IParamMetaData; override;
465      function GetModified: boolean; override;
466      function GetAsPointer: Pointer;
467      function GetAsString: AnsiString; override;
# Line 455 | Line 494 | type
494      procedure SetAsQuad(AValue: TISC_QUAD);
495      procedure SetCharSetID(aValue: cardinal);
496      procedure SetAsBcd(aValue: tBCD);
497 +    procedure SetAsNumeric(aValue: IFBNumeric);
498  
499      property AsBlob: IBlob read GetAsBlob write SetAsBlob;
500      property IsNullable: Boolean read GetIsNullable write SetIsNullable;
# Line 495 | Line 535 | type
535      {ISQLParams}
536      function getCount: integer;
537      function getSQLParam(index: integer): ISQLParam;
538 <    function ByName(Idx: AnsiString): ISQLParam ;
538 >    function ByName(Idx: AnsiString): ISQLParam ; virtual;
539      function GetModified: Boolean;
540      function GetHasCaseSensitiveParams: Boolean;
541 +    function GetStatement: IStatement;
542 +    function GetTransaction: ITransaction;
543 +    function GetAttachment: IAttachment;
544 +    procedure Clear;
545    end;
546  
547    { TResults }
# Line 516 | Line 560 | type
560       constructor Create(aResults: TSQLDataArea);
561        {IResults}
562       function getCount: integer;
563 <     function ByName(Idx: AnsiString): ISQLData;
563 >     function ByName(Idx: AnsiString): ISQLData; virtual;
564       function getSQLData(index: integer): ISQLData;
565       procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PByte);
566       function GetStatement: IStatement;
567 <     function GetTransaction: ITransaction; virtual;
567 >     function GetTransaction: ITransaction;
568 >     function GetAttachment: IAttachment;
569       procedure SetRetainInterfaces(aValue: boolean);
570   end;
571  
572   implementation
573  
574 < uses FBMessages, variants, IBUtils, FBTransaction, DateUtils;
574 > uses FBMessages, variants, IBUtils, FBTransaction, FBNumeric, DateUtils;
575 >
576 > { TSQLParamMetaData }
577 >
578 > constructor TSQLParamMetaData.Create(src: TSQLVarData);
579 > begin
580 >  inherited Create;
581 >  FSQLType := src.GetSQLType;
582 >  FSQLSubType := src.getSubtype;
583 >  FScale := src.GetScale;
584 >  FCharSetID := src.getCharSetID;
585 >  FNullable := src.GetIsNullable;
586 >  FSize := src.GetSize;
587 >  FCodePage := src.GetCodePage;
588 > end;
589 >
590 > function TSQLParamMetaData.GetSQLType: cardinal;
591 > begin
592 >  Result := FSQLType;
593 > end;
594 >
595 > function TSQLParamMetaData.GetSQLTypeName: AnsiString;
596 > begin
597 >  Result := TSQLDataItem.GetSQLTypeName(FSQLType);
598 > end;
599 >
600 > function TSQLParamMetaData.getSubtype: integer;
601 > begin
602 >  Result := FSQLSubType;
603 > end;
604 >
605 > function TSQLParamMetaData.getScale: integer;
606 > begin
607 >  Result := FScale;
608 > end;
609 >
610 > function TSQLParamMetaData.getCharSetID: cardinal;
611 > begin
612 >  Result := FCharSetID;
613 > end;
614 >
615 > function TSQLParamMetaData.getCodePage: TSystemCodePage;
616 > begin
617 >  Result :=  FCodePage;
618 > end;
619 >
620 > function TSQLParamMetaData.getIsNullable: boolean;
621 > begin
622 >  Result :=  FNullable;
623 > end;
624 >
625 > function TSQLParamMetaData.GetSize: cardinal;
626 > begin
627 >  Result := FSize;
628 > end;
629  
630   { TSQLDataArea }
631  
# Line 542 | Line 641 | begin
641    Result := Length(FColumnList);
642   end;
643  
644 + function TSQLDataArea.GetTransaction: ITransaction;
645 + begin
646 +  Result := GetStatement.GetTransaction;
647 + end;
648 +
649 + function TSQLDataArea.GetAttachment: IAttachment;
650 + begin
651 +  Result := GetStatement.GetAttachment;
652 + end;
653 +
654   procedure TSQLDataArea.SetUniqueRelationName;
655   var
656    i: Integer;
# Line 674 | Line 783 | begin
783      FName := AValue;
784   end;
785  
786 + function TSQLVarData.GetAttachment: IAttachment;
787 + begin
788 +  Result := Parent.Attachment;
789 + end;
790 +
791 + function TSQLVarData.GetTransaction: ITransaction;
792 + begin
793 +  Result := Parent.Transaction;
794 + end;
795 +
796 + function TSQLVarData.GetCharSetWidth: integer;
797 + begin
798 +  result := 1;
799 +  GetAttachment.CharSetWidth(GetCharSetID,result);
800 + end;
801 +
802 + function TSQLVarData.GetCodePage: TSystemCodePage;
803 + begin
804 +  result := CP_NONE;
805 +  GetAttachment.CharSetID2CodePage(GetCharSetID,result);
806 + end;
807 +
808 + procedure TSQLVarData.SetScale(aValue: integer);
809 + begin
810 +  if aValue = Scale then
811 +    Exit;
812 +  if not CanChangeMetaData  then
813 +    IBError(ibxeScaleCannotBeChanged,[]);
814 +  InternalSetScale(aValue);
815 + end;
816 +
817 + procedure TSQLVarData.SetDataLength(len: cardinal);
818 + begin
819 +  if len = DataLength then
820 +    Exit;
821 +  InternalSetDataLength(len);
822 + end;
823 +
824 + procedure TSQLVarData.SetSQLType(aValue: cardinal);
825 + begin
826 +  if aValue = SQLType then
827 +    Exit;
828 +  if not CanChangeMetaData then
829 +    IBError(ibxeSQLTypeUnchangeable,[TSQLDataItem.GetSQLTypeName(SQLType),
830 +                                          TSQLDataItem.GetSQLTypeName(aValue)]);
831 +  InternalSetSQLType(aValue);
832 + end;
833 +
834   procedure TSQLVarData.SetMetaSize(aValue: cardinal);
835   begin
836    //Ignore
837   end;
838  
839 + procedure TSQLVarData.SaveMetaData;
840 + begin
841 +  FColMetaData := TSQLParamMetaData.Create(self);
842 + end;
843 +
844 + procedure TSQLVarData.SetArray(AValue: IArray);
845 + begin
846 +  FArrayIntf := AValue;
847 + end;
848 +
849   constructor TSQLVarData.Create(aParent: TSQLDataArea; aIndex: integer);
850   begin
851    inherited Create;
# Line 687 | Line 854 | begin
854    FUniqueName := true;
855   end;
856  
857 + function TSQLVarData.CanChangeMetaData: boolean;
858 + begin
859 +  Result := Parent.CanChangeMetaData;
860 + end;
861 +
862   procedure TSQLVarData.SetString(aValue: AnsiString);
863   begin
864    {we take full advantage here of reference counted strings. When setting a string
# Line 697 | Line 869 | begin
869    FVarString := aValue;
870    if SQLType = SQL_BLOB then
871      SetMetaSize(GetAttachment.GetInlineBlobLimit);
872 <  SQLType := GetDefaultTextSQLType;
872 >  if CanChangeMetaData then
873 >    SQLType := GetDefaultTextSQLType;
874    Scale := 0;
875 +  if  (SQLType <> SQL_VARYING) and (SQLType <> SQL_TEXT) then
876 +    IBError(ibxeUnableTosetaTextType,[Index,Name,TSQLDataItem.GetSQLTypeName(SQLType)]);
877 +  if not CanChangeMetaData and (Length(aValue) > GetSize) then
878 +    IBError(ibxeStringOverflow,[Length(aValue),DataLength]);
879    SetSQLData(PByte(PAnsiChar(FVarString)),Length(aValue));
880   end;
881  
# Line 709 | Line 886 | end;
886  
887   procedure TSQLVarData.RowChange;
888   begin
889 +  FArrayIntf := nil;
890    FModified := false;
891    FVarString := '';
892   end;
893  
894 + function TSQLVarData.getColMetadata: IParamMetaData;
895 + begin
896 +  Result := FColMetaData;
897 + end;
898 +
899   procedure TSQLVarData.Initialize;
900  
901    function FindVarByName(idx: AnsiString; limit: integer): TSQLVarData;
# Line 772 | Line 955 | end;
955  
956   {TSQLDataItem}
957  
775 function TSQLDataItem.AdjustScale(Value: Int64; aScale: Integer): Double;
776 var
777  Scaling : Int64;
778  i: Integer;
779  Val: Double;
780 begin
781  Scaling := 1; Val := Value;
782  if aScale > 0 then
783  begin
784    for i := 1 to aScale do
785      Scaling := Scaling * 10;
786    result := Val * Scaling;
787  end
788  else
789    if aScale < 0 then
790    begin
791      for i := -1 downto aScale do
792        Scaling := Scaling * 10;
793      result := Val / Scaling;
794    end
795    else
796      result := Val;
797 end;
798
799 function TSQLDataItem.AdjustScaleToInt64(Value: Int64; aScale: Integer): Int64;
800 var
801  Scaling : Int64;
802  i: Integer;
803  Val: Int64;
804 begin
805  Scaling := 1; Val := Value;
806  if aScale > 0 then begin
807    for i := 1 to aScale do Scaling := Scaling * 10;
808    result := Val * Scaling;
809  end else if aScale < 0 then begin
810    for i := -1 downto aScale do Scaling := Scaling * 10;
811    result := Val div Scaling;
812  end else
813    result := Val;
814 end;
815
816 function TSQLDataItem.AdjustScaleToCurrency(Value: Int64; aScale: Integer
817  ): Currency;
818 var
819  Scaling : Int64;
820  i : Integer;
821  FractionText, PadText, CurrText: AnsiString;
822 begin
823  Result := 0;
824  Scaling := 1;
825  PadText := '';
826  if aScale > 0 then
827  begin
828    for i := 1 to aScale do
829      Scaling := Scaling * 10;
830    result := Value * Scaling;
831  end
832  else
833    if aScale < 0 then
834    begin
835      for i := -1 downto aScale do
836        Scaling := Scaling * 10;
837      FractionText := IntToStr(abs(Value mod Scaling));
838      for i := Length(FractionText) to -aScale -1 do
839        PadText := '0' + PadText;
840      {$IF declared(DefaultFormatSettings)}
841      with DefaultFormatSettings do
842      {$ELSE}
843      {$IF declared(FormatSettings)}
844      with FormatSettings do
845      {$IFEND}
846      {$IFEND}
847      if Value < 0 then
848        CurrText := '-' + IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText
849      else
850        CurrText := IntToStr(Abs(Value div Scaling)) + DecimalSeparator + PadText + FractionText;
851      try
852        result := StrToCurr(CurrText);
853      except
854        on E: Exception do
855          IBError(ibxeInvalidDataConversion, [nil]);
856      end;
857    end
858    else
859      result := Value;
860 end;
861
958   function TSQLDataItem.GetDateFormatStr(IncludeTime: boolean): AnsiString;
959   begin
960    {$IF declared(DefaultFormatSettings)}
# Line 956 | Line 1052 | begin
1052      end;
1053   end;
1054  
959 function TSQLDataItem.AdjustScaleFromCurrency(Value: Currency; aScale: Integer
960  ): Int64;
961 var
962  Scaling : Int64;
963  i : Integer;
964 begin
965  Result := 0;
966  Scaling := 1;
967  if aScale < 0 then
968  begin
969    for i := -1 downto aScale do
970      Scaling := Scaling * 10;
971    result := trunc(Value * Scaling);
972  end
973  else
974  if aScale > 0 then
975  begin
976    for i := 1 to aScale do
977       Scaling := Scaling * 10;
978    result := trunc(Value / Scaling);
979  end
980  else
981    result := trunc(Value);
982 end;
983
984 function TSQLDataItem.AdjustScaleFromDouble(Value: Double; aScale: Integer
985  ): Int64;
986 var
987  Scaling : Int64;
988  i : Integer;
989 begin
990  Result := 0;
991  Scaling := 1;
992  if aScale < 0 then
993  begin
994    for i := -1 downto aScale do
995      Scaling := Scaling * 10;
996    result := trunc(Value * Scaling);
997  end
998  else
999  if aScale > 0 then
1000  begin
1001    for i := 1 to aScale do
1002       Scaling := Scaling * 10;
1003    result := trunc(Value / Scaling);
1004  end
1005  else
1006    result := trunc(Value);
1007 end;
1008
1055   procedure TSQLDataItem.CheckActive;
1056   begin
1057    //Do nothing by default
# Line 1072 | Line 1118 | begin
1118    FFirebirdClientAPI := api;
1119   end;
1120  
1121 + function TSQLDataItem.CanChangeMetaData: boolean;
1122 + begin
1123 +  Result := false;
1124 + end;
1125 +
1126   function TSQLDataItem.GetSQLTypeName: AnsiString;
1127   begin
1128    Result := GetSQLTypeName(GetSQLType);
1129   end;
1130  
1131 < class function TSQLDataItem.GetSQLTypeName(SQLType: short): AnsiString;
1131 > class function TSQLDataItem.GetSQLTypeName(SQLType: cardinal): AnsiString;
1132   begin
1133    Result := 'Unknown';
1134    case SQLType of
# Line 1147 | Line 1198 | begin
1198            end;
1199          end;
1200          SQL_SHORT:
1201 <          result := AdjustScaleToCurrency(Int64(PShort(SQLData)^),
1202 <                                      Scale);
1201 >          result := NumericFromRawValues(Int64(PShort(SQLData)^),
1202 >                                      Scale).getAsCurrency;
1203          SQL_LONG:
1204 <          result := AdjustScaleToCurrency(Int64(PLong(SQLData)^),
1205 <                                      Scale);
1204 >          result := NumericFromRawValues(Int64(PLong(SQLData)^),
1205 >                                      Scale).getAsCurrency;
1206          SQL_INT64:
1207 <          result := AdjustScaleToCurrency(PInt64(SQLData)^,
1208 <                                      Scale);
1207 >          result := NumericFromRawValues(PInt64(SQLData)^,
1208 >                                      Scale).getAsCurrency;
1209          SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1210            result := Round(AsDouble);
1211  
# Line 1185 | Line 1236 | begin
1236          end;
1237        end;
1238        SQL_SHORT:
1239 <        result := AdjustScaleToInt64(Int64(PShort(SQLData)^),
1240 <                                    Scale);
1239 >        result := NumericFromRawValues(Int64(PShort(SQLData)^),
1240 >                                    Scale).getAsInt64;
1241        SQL_LONG:
1242 <        result := AdjustScaleToInt64(Int64(PLong(SQLData)^),
1243 <                                    Scale);
1242 >        result := NumericFromRawValues(Int64(PLong(SQLData)^),
1243 >                                    Scale).getAsInt64;
1244        SQL_INT64:
1245 <        result := AdjustScaleToInt64(PInt64(SQLData)^,
1246 <                                    Scale);
1245 >        result := NumericFromRawValues(PInt64(SQLData)^,
1246 >                                    Scale).getAsInt64;
1247        SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1248          result := Round(AsDouble);
1249        else
# Line 1321 | Line 1372 | begin
1372          end;
1373        end;
1374        SQL_SHORT:
1375 <        result := AdjustScale(Int64(PShort(SQLData)^),
1376 <                              Scale);
1375 >        result := NumericFromRawValues(Int64(PShort(SQLData)^),
1376 >                              Scale).getAsDouble;
1377        SQL_LONG:
1378 <        result := AdjustScale(Int64(PLong(SQLData)^),
1379 <                              Scale);
1378 >        result := NumericFromRawValues(Int64(PLong(SQLData)^),
1379 >                              Scale).getAsDouble;
1380        SQL_INT64:
1381 <        result := AdjustScale(PInt64(SQLData)^, Scale);
1381 >        result := NumericFromRawValues(PInt64(SQLData)^, Scale).getAsDouble;
1382        SQL_FLOAT:
1383          result := PFloat(SQLData)^;
1384        SQL_DOUBLE, SQL_D_FLOAT:
# Line 1373 | Line 1424 | begin
1424          end;
1425        end;
1426        SQL_SHORT:
1427 <        result := Round(AdjustScale(Int64(PShort(SQLData)^),
1428 <                                    Scale));
1427 >        result := NumericFromRawValues(Int64(PShort(SQLData)^),
1428 >                                    Scale).getAsInteger;
1429        SQL_LONG:
1430 <        result := Round(AdjustScale(Int64(PLong(SQLData)^),
1431 <                                    Scale));
1430 >        result := NumericFromRawValues(Int64(PLong(SQLData)^),
1431 >                                    Scale).getAsInteger;
1432        SQL_INT64:
1433 <        result := Round(AdjustScale(PInt64(SQLData)^, Scale));
1433 >        result := NumericFromRawValues(PInt64(SQLData)^, Scale).getAsInteger;
1434 >
1435        SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT:
1436          result := Round(AsDouble);
1437        SQL_DEC_FIXED,
# Line 1476 | Line 1528 | end;
1528   function GetStrLen(p: PAnsiChar; FieldWidth, MaxDataLength: cardinal): integer;
1529   var i: integer;
1530      cplen: integer;
1479    s: AnsiString;
1531   begin
1532    Result := 0;
1482  s := strpas(p);
1533    for i := 1 to FieldWidth do
1534    begin
1535      cplen := UTF8CodepointSizeFull(p);
# Line 1596 | Line 1646 | begin
1646          result := Int128ToStr(SQLData,scale);
1647  
1648        else
1649 <        IBError(ibxeInvalidDataConversion, [nil]);
1649 >        IBError(ibxeInvalidDataConversion, [GetSQLTypeName]);
1650      end;
1651   end;
1652  
1653 + function TSQLDataItem.GetAsNumeric: IFBNumeric;
1654 + var aValue: Int64;
1655 + begin
1656 +  case SQLType of
1657 +   SQL_TEXT, SQL_VARYING:
1658 +     Result := StrToNumeric(GetAsString);
1659 +
1660 +   SQL_SHORT:
1661 +     Result := NumericFromRawValues(PShort(SQLData)^, Scale);
1662 +
1663 +   SQL_LONG:
1664 +     Result := NumericFromRawValues(PLong(SQLData)^, Scale);
1665 +
1666 +   SQL_INT64:
1667 +     Result := NumericFromRawValues(PInt64(SQLData)^, Scale);
1668 +
1669 +   SQL_DEC16,
1670 +   SQL_DEC34,
1671 +   SQL_DEC_FIXED,
1672 +   SQL_INT128:
1673 +     Result := BCDToNumeric(GetAsBCD);
1674 +
1675 +   else
1676 +     IBError(ibxeInvalidDataConversion, [nil]);
1677 +  end;
1678 + end;
1679 +
1680   function TSQLDataItem.GetIsNull: Boolean;
1681   begin
1682    CheckActive;
# Line 1738 | Line 1815 | begin
1815    if GetSQLDialect < 3 then
1816      AsDouble := Value
1817    else
1818 +  if not CanChangeMetaData and ((SQLType <> SQL_INT64) or (Scale <> -4)) then
1819 +    SetAsNumeric(CurrToNumeric(Value))
1820 +  else
1821    begin
1822      Changing;
1823      if IsNullable then
# Line 1753 | Line 1833 | end;
1833   procedure TSQLDataItem.SetAsInt64(Value: Int64);
1834   begin
1835    CheckActive;
1836 <  Changing;
1837 <  if IsNullable then
1838 <    IsNull := False;
1836 >  if not CanChangeMetaData and ((SQLType <> SQL_INT64) or (Scale <> 0)) then
1837 >    SetAsNumeric(IntToNumeric(Value))
1838 >  else
1839 >  begin
1840 >    Changing;
1841 >    if IsNullable then
1842 >      IsNull := False;
1843  
1844 <  SQLType := SQL_INT64;
1845 <  Scale := 0;
1846 <  DataLength := SizeOf(Int64);
1847 <  PInt64(SQLData)^ := Value;
1848 <  Changed;
1844 >    SQLType := SQL_INT64;
1845 >    Scale := 0;
1846 >    DataLength := SizeOf(Int64);
1847 >    PInt64(SQLData)^ := Value;
1848 >    Changed;
1849 >  end;
1850   end;
1851  
1852   procedure TSQLDataItem.SetAsDate(Value: TDateTime);
# Line 1896 | Line 1981 | end;
1981   procedure TSQLDataItem.SetAsDouble(Value: Double);
1982   begin
1983    CheckActive;
1984 <  if IsNullable then
1985 <    IsNull := False;
1984 >  if not CanChangeMetaData and (SQLType <> SQL_DOUBLE) then
1985 >    SetAsNumeric(DoubleToNumeric(Value))
1986 >  else
1987 >  begin
1988 >    if IsNullable then
1989 >      IsNull := False;
1990  
1991 <  Changing;
1992 <  SQLType := SQL_DOUBLE;
1993 <  DataLength := SizeOf(Double);
1994 <  Scale := 0;
1995 <  PDouble(SQLData)^ := Value;
1996 <  Changed;
1991 >    Changing;
1992 >    SQLType := SQL_DOUBLE;
1993 >    DataLength := SizeOf(Double);
1994 >    Scale := 0;
1995 >    PDouble(SQLData)^ := Value;
1996 >    Changed;
1997 >  end;
1998   end;
1999  
2000   procedure TSQLDataItem.SetAsFloat(Value: Float);
2001   begin
2002    CheckActive;
2003 <  if IsNullable then
2004 <    IsNull := False;
2003 >  if not CanChangeMetaData and (SQLType <> SQL_FLOAT) then
2004 >    SetAsNumeric(DoubleToNumeric(Value))
2005 >  else
2006 >  begin
2007 >    if IsNullable then
2008 >      IsNull := False;
2009  
2010 <  Changing;
2011 <  SQLType := SQL_FLOAT;
2012 <  DataLength := SizeOf(Float);
2013 <  Scale := 0;
2014 <  PSingle(SQLData)^ := Value;
2015 <  Changed;
2010 >    Changing;
2011 >    SQLType := SQL_FLOAT;
2012 >    DataLength := SizeOf(Float);
2013 >    Scale := 0;
2014 >    PSingle(SQLData)^ := Value;
2015 >    Changed;
2016 >  end;
2017   end;
2018  
2019   procedure TSQLDataItem.SetAsLong(Value: Long);
2020   begin
2021    CheckActive;
2022 <  if IsNullable then
2023 <    IsNull := False;
2022 >  if not CanChangeMetaData and ((SQLType <> SQL_LONG) or (Scale <> 0)) then
2023 >    SetAsNumeric(IntToNumeric(Value))
2024 >  else
2025 >  begin
2026 >    if IsNullable then
2027 >      IsNull := False;
2028  
2029 <  Changing;
2030 <  SQLType := SQL_LONG;
2031 <  DataLength := SizeOf(Long);
2032 <  Scale := 0;
2033 <  PLong(SQLData)^ := Value;
2034 <  Changed;
2029 >    Changing;
2030 >    SQLType := SQL_LONG;
2031 >    DataLength := SizeOf(Long);
2032 >    Scale := 0;
2033 >    PLong(SQLData)^ := Value;
2034 >    Changed;
2035 >  end;
2036   end;
2037  
2038   procedure TSQLDataItem.SetAsPointer(Value: Pointer);
# Line 1967 | Line 2067 | end;
2067   procedure TSQLDataItem.SetAsShort(Value: short);
2068   begin
2069    CheckActive;
2070 <  Changing;
2071 <  if IsNullable then
2072 <    IsNull := False;
2070 >  if not CanChangeMetaData and ((SQLType <> SQL_SHORT) or (Scale <> 0)) then
2071 >    SetAsNumeric(IntToNumeric(Value))
2072 >  else
2073 >  begin
2074 >    Changing;
2075 >    if IsNullable then
2076 >      IsNull := False;
2077  
2078 <  SQLType := SQL_SHORT;
2079 <  DataLength := SizeOf(Short);
2080 <  Scale := 0;
2081 <  PShort(SQLData)^ := Value;
2082 <  Changed;
2078 >    SQLType := SQL_SHORT;
2079 >    DataLength := SizeOf(Short);
2080 >    Scale := 0;
2081 >    PShort(SQLData)^ := Value;
2082 >    Changed;
2083 >  end;
2084   end;
2085  
2086   procedure TSQLDataItem.SetAsString(Value: AnsiString);
# Line 1994 | Line 2099 | begin
2099    else case VarType(Value) of
2100      varEmpty, varNull:
2101        IsNull := True;
2102 <    varSmallint, varInteger, varByte,
2103 <      varWord, varShortInt:
2104 <      AsLong := Value;
2000 <    varInt64:
2001 <      AsInt64 := Value;
2102 >    varSmallint, varInteger, varByte, varLongWord,
2103 >      varWord, varShortInt, varInt64:
2104 >        SetAsNumeric(IntToNumeric(Int64(Value)));
2105      varSingle, varDouble:
2106        AsDouble := Value;
2107      varCurrency:
2108 <      AsCurrency := Value;
2108 >      SetAsNumeric(CurrToNumeric(Currency(Value)));
2109      varBoolean:
2110        AsBoolean := Value;
2111      varDate:
# Line 2021 | Line 2124 | begin
2124    end;
2125   end;
2126  
2127 < procedure TSQLDataItem.SetAsNumeric(Value: Int64; aScale: integer);
2127 > procedure TSQLDataItem.SetAsNumeric(Value: IFBNumeric);
2128   begin
2129    CheckActive;
2130    Changing;
2131    if IsNullable then
2132      IsNull := False;
2133  
2134 <  SQLType := SQL_INT64;
2135 <  Scale := aScale;
2136 <  DataLength := SizeOf(Int64);
2137 <  PInt64(SQLData)^ := Value;
2134 >  if CanChangeMetadata then
2135 >  begin
2136 >    {Restore original values}
2137 >    SQLType := getColMetadata.GetSQLType;
2138 >    Scale := getColMetadata.getScale;
2139 >    SetDataLength(getColMetadata.GetSize);
2140 >  end;
2141 >
2142 >  with FFirebirdClientAPI do
2143 >  case GetSQLType of
2144 >  SQL_LONG:
2145 >      PLong(SQLData)^ := SafeInteger(Value.AdjustScaleTo(Scale).getRawValue);
2146 >  SQL_SHORT:
2147 >    PShort(SQLData)^ := SafeSmallInt(Value.AdjustScaleTo(Scale).getRawValue);
2148 >  SQL_INT64:
2149 >    PInt64(SQLData)^ := Value.AdjustScaleTo(Scale).getRawValue;
2150 >  SQL_TEXT, SQL_VARYING:
2151 >   SetAsString(Value.getAsString);
2152 >  SQL_D_FLOAT,
2153 >  SQL_DOUBLE:
2154 >    PDouble(SQLData)^ := Value.getAsDouble;
2155 >  SQL_FLOAT:
2156 >    PSingle(SQLData)^ := Value.getAsDouble;
2157 >  SQL_DEC_FIXED,
2158 >  SQL_DEC16,
2159 >  SQL_DEC34:
2160 >     SQLDecFloatEncode(Value.getAsBCD,SQLType,SQLData);
2161 >  SQL_INT128:
2162 >    StrToInt128(Scale,Value.getAsString,SQLData);
2163 >  else
2164 >    IBError(ibxeInvalidDataConversion, [nil]);
2165 >  end;
2166    Changed;
2167   end;
2168  
2169   procedure TSQLDataItem.SetAsBcd(aValue: tBCD);
2039 var C: Currency;
2170   begin
2171    CheckActive;
2172    Changing;
2173    if IsNullable then
2174      IsNull := False;
2175  
2176 +  if not CanChangeMetaData then
2177 +  begin
2178 +    SetAsNumeric(BCDToNumeric(aValue));
2179 +    Exit;
2180 +  end;
2181  
2182    with FFirebirdClientAPI do
2183    if aValue.Precision <= 16 then
# Line 2112 | Line 2247 | end;
2247  
2248   function TColumnMetaData.GetAttachment: IAttachment;
2249   begin
2250 <  Result := GetStatement.GetAttachment;
2250 >  Result := FIBXSQLVAR.GetAttachment;
2251   end;
2252  
2253   function TColumnMetaData.SQLData: PByte;
# Line 2132 | Line 2267 | end;
2267  
2268   constructor TColumnMetaData.Create(aOwner: IUnknown; aIBXSQLVAR: TSQLVarData);
2269   begin
2270 <  inherited Create(aIBXSQLVAR.GetStatement.GetAttachment.getFirebirdAPI as TFBClientAPI);
2270 >  inherited Create(aIBXSQLVAR.GetAttachment.getFirebirdAPI as TFBClientAPI);
2271    FIBXSQLVAR := aIBXSQLVAR;
2272    FOwner := aOwner;
2273    FPrepareSeqNo := FIBXSQLVAR.Parent.PrepareSeqNo;
# Line 2148 | Line 2283 | end;
2283  
2284   function TColumnMetaData.GetSQLDialect: integer;
2285   begin
2286 <  Result := FIBXSQLVAR.Statement.GetSQLDialect;
2286 >  Result := FIBXSQLVAR.GetAttachment.GetSQLDialect;
2287 > end;
2288 >
2289 > function TColumnMetaData.getColMetadata: IParamMetaData;
2290 > begin
2291 >  Result := self;
2292   end;
2293  
2294   function TColumnMetaData.GetIndex: integer;
# Line 2247 | Line 2387 | end;
2387  
2388   function TColumnMetaData.GetTransaction: ITransaction;
2389   begin
2390 <  Result := GetStatement.GetTransaction;
2390 >  Result := FIBXSQLVAR.GetTransaction;
2391   end;
2392  
2393   { TIBSQLData }
# Line 2269 | Line 2409 | begin
2409      IBError(ibxeBOF,[nil]);
2410   end;
2411  
2272 function TIBSQLData.GetTransaction: ITransaction;
2273 begin
2274  if FTransaction = nil then
2275    Result := inherited GetTransaction
2276  else
2277    Result := FTransaction;
2278 end;
2279
2412   function TIBSQLData.GetIsNull: Boolean;
2413   begin
2414    CheckActive;
# Line 2286 | Line 2418 | end;
2418   function TIBSQLData.GetAsArray: IArray;
2419   begin
2420    CheckActive;
2421 <  result := FIBXSQLVAR.GetAsArray(AsQuad);
2421 >  result := FIBXSQLVAR.GetAsArray;
2422   end;
2423  
2424   function TIBSQLData.GetAsBlob: IBlob;
# Line 2330 | Line 2462 | end;
2462  
2463   var b: IBlob;
2464      dt: TDateTime;
2333    CurrValue: Currency;
2334    FloatValue: single;
2465      timezone: AnsiString;
2466 +    Int64Value: Int64;
2467 +    BCDValue: TBCD;
2468 +    aScale: integer;
2469   begin
2470    CheckActive;
2471    if IsNullable then
# Line 2364 | Line 2497 | begin
2497    SQL_TEXT:
2498      DoSetString;
2499  
2500 <    SQL_SHORT,
2501 <    SQL_LONG,
2502 <    SQL_INT64:
2503 <      if TryStrToCurr(Value,CurrValue) then
2504 <        SetAsNumeric(AdjustScaleFromCurrency(CurrValue,GetScale),GetScale)
2505 <      else
2506 <        DoSetString;
2500 >  SQL_SHORT,
2501 >  SQL_LONG,
2502 >  SQL_INT64:
2503 >    if TryStrToNumeric(Value,Int64Value,aScale) then
2504 >      SetAsNumeric(NumericFromRawValues(Int64Value,aScale))
2505 >    else
2506 >      DoSetString;
2507  
2508 <    SQL_D_FLOAT,
2509 <    SQL_DOUBLE,
2510 <    SQL_FLOAT:
2511 <      if TryStrToFloat(Value,FloatValue) then
2512 <        SetAsDouble(FloatValue)
2513 <      else
2514 <        DoSetString;
2508 >  SQL_DEC_FIXED,
2509 >  SQL_DEC16,
2510 >  SQL_DEC34,
2511 >  SQL_INT128:
2512 >    if TryStrToBCD(Value,BCDValue) then
2513 >      SetAsNumeric(BCDToNumeric(BCDValue))
2514 >    else
2515 >      DoSetString;
2516  
2517 <    SQL_TIMESTAMP:
2517 >  SQL_D_FLOAT,
2518 >  SQL_DOUBLE,
2519 >  SQL_FLOAT:
2520 >    if TryStrToNumeric(Value,Int64Value,aScale) then
2521 >      SetAsNumeric(NumericFromRawValues(Int64Value,AScale))
2522 >    else
2523 >      DoSetString;
2524 >
2525 >  SQL_TIMESTAMP:
2526        if TryStrToDateTime(Value,dt) then
2527          SetAsDateTime(dt)
2528        else
2529          DoSetString;
2530  
2531 <    SQL_TYPE_DATE:
2531 >  SQL_TYPE_DATE:
2532        if TryStrToDateTime(Value,dt) then
2533          SetAsDate(dt)
2534        else
2535          DoSetString;
2536  
2537 <    SQL_TYPE_TIME:
2537 >  SQL_TYPE_TIME:
2538        if TryStrToDateTime(Value,dt) then
2539          SetAsTime(dt)
2540        else
2541          DoSetString;
2542  
2543 <    SQL_TIMESTAMP_TZ:
2543 >  SQL_TIMESTAMP_TZ,
2544 >  SQL_TIMESTAMP_TZ_EX:
2545        if ParseDateTimeTZString(value,dt,timezone) then
2546          SetAsDateTime(dt,timezone)
2547        else
2548          DoSetString;
2549  
2550 <    SQL_TIME_TZ:
2550 >  SQL_TIME_TZ,
2551 >  SQL_TIME_TZ_EX:
2552        if ParseDateTimeTZString(value,dt,timezone,true) then
2553          SetAsTime(dt,GetAttachment.GetTimeZoneServices.GetTimeTZDate,timezone)
2554        else
2555          DoSetString;
2556  
2557 <    SQL_DEC_FIXED,
2558 <    SQL_DEC16,
2415 <    SQL_DEC34,
2416 <    SQL_INT128:
2417 <      SetAsBCD(StrToBCD(Value));
2418 <
2419 <    else
2420 <      IBError(ibxeInvalidDataConversion,[GetSQLTypeName(SQLType)]);
2557 >  else
2558 >    IBError(ibxeInvalidDataConversion,[GetSQLTypeName(getColMetaData.SQLTYPE)]);
2559    end;
2560   end;
2561  
# Line 2455 | Line 2593 | begin
2593    IsNull := true;
2594   end;
2595  
2596 + function TSQLParam.CanChangeMetaData: boolean;
2597 + begin
2598 +  Result := FIBXSQLVAR.CanChangeMetaData;
2599 + end;
2600 +
2601 + function TSQLParam.getColMetadata: IParamMetaData;
2602 + begin
2603 +  Result := FIBXSQLVAR.getColMetadata;
2604 + end;
2605 +
2606   function TSQLParam.GetModified: boolean;
2607   begin
2608    CheckActive;
# Line 2529 | Line 2677 | begin
2677    if not FIBXSQLVAR.UniqueName then
2678      IBError(ibxeDuplicateParamName,[FIBXSQLVAR.Name]);
2679  
2680 +  FIBXSQLVAR.SetArray(anArray); {save array interface}
2681    SetAsQuad(AnArray.GetArrayID);
2682   end;
2683  
# Line 3004 | Line 3153 | begin
3153    end;
3154   end;
3155  
3156 + procedure TSQLParam.SetAsNumeric(aValue: IFBNumeric);
3157 + var i: integer;
3158 +    OldSQLVar: TSQLVarData;
3159 + begin
3160 +  if FIBXSQLVAR.UniqueName then
3161 +    inherited SetAsNumeric(AValue)
3162 +  else
3163 +  with FIBXSQLVAR.Parent do
3164 +  begin
3165 +    for i := 0 to Count - 1 do
3166 +      if Column[i].Name = Name then
3167 +      begin
3168 +        OldSQLVar := FIBXSQLVAR;
3169 +        FIBXSQLVAR := Column[i];
3170 +        try
3171 +          inherited SetAsNumeric(AValue);
3172 +        finally
3173 +          FIBXSQLVAR := OldSQLVar;
3174 +        end;
3175 +      end;
3176 +  end;
3177 + end;
3178 +
3179   { TMetaData }
3180  
3181   procedure TMetaData.CheckActive;
# Line 3025 | Line 3197 | end;
3197  
3198   destructor TMetaData.Destroy;
3199   begin
3200 <  (FStatement as TInterfaceOwner).Remove(self);
3200 >  if FStatement <> nil then
3201 >    (FStatement as TInterfaceOwner).Remove(self);
3202    inherited Destroy;
3203   end;
3204  
# Line 3091 | Line 3264 | end;
3264  
3265   destructor TSQLParams.Destroy;
3266   begin
3267 <  (FStatement as TInterfaceOwner).Remove(self);
3267 >  if FStatement <> nil then
3268 >    (FStatement as TInterfaceOwner).Remove(self);
3269    inherited Destroy;
3270   end;
3271  
# Line 3147 | Line 3321 | begin
3321    Result := FSQLParams.CaseSensitiveParams;
3322   end;
3323  
3324 + function TSQLParams.GetStatement: IStatement;
3325 + begin
3326 +  Result := FSQLParams.GetStatement;
3327 + end;
3328 +
3329 + function TSQLParams.GetTransaction: ITransaction;
3330 + begin
3331 +  Result := FSQLParams.GetTransaction;
3332 + end;
3333 +
3334 + function TSQLParams.GetAttachment: IAttachment;
3335 + begin
3336 +  Result := FSQLParams.GetAttachment;
3337 + end;
3338 +
3339 + procedure TSQLParams.Clear;
3340 + var i: integer;
3341 + begin
3342 +  for i := 0 to getCount - 1 do
3343 +    getSQLParam(i).Clear;
3344 + end;
3345 +
3346   { TResults }
3347  
3348   procedure TResults.CheckActive;
# Line 3171 | Line 3367 | begin
3367      IBError(ibxeInvalidColumnIndex,[nil]);
3368  
3369    if not HasInterface(aIBXSQLVAR.Index) then
3370 <    AddInterface(aIBXSQLVAR.Index, TIBSQLData.Create(self,aIBXSQLVAR));
3371 <  col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
3372 <  col.FTransaction := GetTransaction;
3370 >  begin
3371 >    col := TIBSQLData.Create(self,aIBXSQLVAR);
3372 >    AddInterface(aIBXSQLVAR.Index, col);
3373 >  end
3374 >  else
3375 >    col := TIBSQLData(GetInterface(aIBXSQLVAR.Index));
3376    Result := col;
3377   end;
3378  
# Line 3238 | Line 3437 | end;
3437  
3438   function TResults.GetTransaction: ITransaction;
3439   begin
3440 <  Result := FStatement.GetTransaction;
3440 >  Result := FResults.GetTransaction;
3441 > end;
3442 >
3443 > function TResults.GetAttachment: IAttachment;
3444 > begin
3445 >  Result := FResults.GetAttachment;
3446   end;
3447  
3448   procedure TResults.SetRetainInterfaces(aValue: boolean);

Comparing:
ibx/trunk/fbintf/client/FBSQLData.pas (property svn:eol-style), Revision 345 by tony, Mon Aug 23 14:22:29 2021 UTC vs.
ibx/branches/udr/client/FBSQLData.pas (property svn:eol-style), Revision 381 by tony, Sat Jan 15 00:06:22 2022 UTC

# Line 0 | Line 1
1 + native

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines