Hello,
The following patches fixes the lack of sqlscale var when writing decimal and numeric fields to ib/fb databases. I've used the same approach used to read such fields, ie, intpower.
Patch 1 has also a small improvement regarding the read of the XSQLVAR record, patch 2 only fixes the sqlscale.
Both patches are against fixes_2_2. Let me know if it's still useful, otherwise I will checkout trunk and create another patch.
-- Joao Morais
Index: fcl-db/src/sqldb/interbase/ibconnection.pp =================================================================== --- fcl-db/src/sqldb/interbase/ibconnection.pp (revision 11044) +++ fcl-db/src/sqldb/interbase/ibconnection.pp (working copy) @@ -693,6 +693,7 @@ var ParNr,SQLVarNr : integer; s : string; i : integer; + si : smallint; li : LargeInt; currbuff : pchar; w : word; @@ -736,30 +737,40 @@ {$R+} end; +var + VSQLVar: XSQLVAR; begin {$R-} with cursor as TIBCursor do for SQLVarNr := 0 to High(ParamBinding){AParams.count-1} do begin ParNr := ParamBinding[SQLVarNr]; + VSQLVar := in_sqlda^.SQLvar[SQLVarNr]; if AParams[ParNr].IsNull then begin - If Assigned(in_sqlda^.SQLvar[SQLVarNr].SQLInd) then - in_sqlda^.SQLvar[SQLVarNr].SQLInd^ := -1; + If Assigned(VSQLVar.SQLInd) then + VSQLVar.SQLInd^ := -1; end else begin - if assigned(in_sqlda^.SQLvar[SQLVarNr].SQLInd) then in_sqlda^.SQLvar[SQLVarNr].SQLInd^ := 0; + if assigned(VSQLVar.SQLInd) then VSQLVar.SQLInd^ := 0; - case (in_sqlda^.SQLvar[SQLVarNr].sqltype and not 1) of + case (VSQLVar.sqltype and not 1) of SQL_LONG : begin - i := AParams[ParNr].AsInteger; - Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if VSQLVar.sqlscale = 0 then + i := AParams[ParNr].AsInteger + else + i := Round(AParams[ParNr].AsCurrency * IntPower(10, -VSQLVar.sqlscale)); + Move(i, VSQLVar.SQLData^, VSQLVar.SQLLen); end; SQL_SHORT : begin - i := AParams[ParNr].AsSmallInt; - Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if VSQLVar.sqlscale = 0 then + si := AParams[ParNr].AsSmallint + else + si := Round(AParams[ParNr].AsCurrency * IntPower(10, -VSQLVar.sqlscale)); + i := si; + Move(i, VSQLVar.SQLData^, VSQLVar.SQLLen); end; SQL_BLOB : SetBlobParam; @@ -767,27 +778,30 @@ begin s := AParams[ParNr].AsString; w := length(s); // a word is enough, since the max-length of a string in interbase is 32k - if ((in_sqlda^.SQLvar[SQLVarNr].SQLType and not 1) = SQL_VARYING) then + if ((VSQLVar.SQLType and not 1) = SQL_VARYING) then begin - in_sqlda^.SQLvar[SQLVarNr].SQLLen := w; - ReAllocMem(in_sqlda^.SQLvar[SQLVarNr].SQLData,in_SQLDA^.SQLVar[SQLVarNr].SQLLen+2); - CurrBuff := in_sqlda^.SQLvar[SQLVarNr].SQLData; + VSQLVar.SQLLen := w; + ReAllocMem(VSQLVar.SQLData, VSQLVar.SQLLen+2); + CurrBuff := VSQLVar.SQLData; move(w,CurrBuff^,sizeof(w)); inc(CurrBuff,2); end else - CurrBuff := in_sqlda^.SQLvar[SQLVarNr].SQLData; + CurrBuff := VSQLVar.SQLData; Move(s[1], CurrBuff^, w); end; SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TIMESTAMP : - SetDateTime(in_sqlda^.SQLvar[SQLVarNr].SQLData, AParams[ParNr].AsDateTime, in_SQLDA^.SQLVar[SQLVarNr].SQLType); + SetDateTime(VSQLVar.SQLData, AParams[ParNr].AsDateTime, VSQLVar.SQLType); SQL_INT64: begin - li := AParams[ParNr].AsLargeInt; - Move(li, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if VSQLVar.sqlscale = 0 then + li := AParams[ParNr].AsLargeInt + else + li := Round(AParams[ParNr].AsCurrency * IntPower(10, -VSQLVar.sqlscale)); + Move(li, VSQLVar.SQLData^, VSQLVar.SQLLen); end; SQL_DOUBLE, SQL_FLOAT: - SetFloat(in_sqlda^.SQLvar[SQLVarNr].SQLData, AParams[ParNr].AsFloat, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + SetFloat(VSQLVar.SQLData, AParams[ParNr].AsFloat, VSQLVar.SQLLen); else DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[ParNr].DataType]],self); end {case}
Index: fcl-db/src/sqldb/interbase/ibconnection.pp =================================================================== --- fcl-db/src/sqldb/interbase/ibconnection.pp (revision 11044) +++ fcl-db/src/sqldb/interbase/ibconnection.pp (working copy) @@ -693,6 +693,7 @@ var ParNr,SQLVarNr : integer; s : string; i : integer; + si : smallint; li : LargeInt; currbuff : pchar; w : word; @@ -753,13 +754,20 @@ case (in_sqlda^.SQLvar[SQLVarNr].sqltype and not 1) of SQL_LONG : begin - i := AParams[ParNr].AsInteger; - Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if in_sqlda^.SQLvar[SQLVarNr].sqlscale = 0 then + i := AParams[ParNr].AsInteger + else + i := Round(AParams[ParNr].AsCurrency * IntPower(10, -in_sqlda^.SQLvar[SQLVarNr].sqlscale)); + Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_sqlda^.SQLvar[SQLVarNr].SQLLen); end; SQL_SHORT : begin - i := AParams[ParNr].AsSmallInt; - Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if in_sqlda^.SQLvar[SQLVarNr].sqlscale = 0 then + si := AParams[ParNr].AsSmallint + else + si := Round(AParams[ParNr].AsCurrency * IntPower(10, -in_sqlda^.SQLvar[SQLVarNr].sqlscale)); + i := si; + Move(i, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_sqlda^.SQLvar[SQLVarNr].SQLLen); end; SQL_BLOB : SetBlobParam; @@ -783,8 +791,11 @@ SetDateTime(in_sqlda^.SQLvar[SQLVarNr].SQLData, AParams[ParNr].AsDateTime, in_SQLDA^.SQLVar[SQLVarNr].SQLType); SQL_INT64: begin - li := AParams[ParNr].AsLargeInt; - Move(li, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_SQLDA^.SQLVar[SQLVarNr].SQLLen); + if in_sqlda^.SQLvar[SQLVarNr].sqlscale = 0 then + li := AParams[ParNr].AsLargeInt + else + li := Round(AParams[ParNr].AsCurrency * IntPower(10, -in_sqlda^.SQLvar[SQLVarNr].sqlscale)); + Move(li, in_sqlda^.SQLvar[SQLVarNr].SQLData^, in_sqlda^.SQLvar[SQLVarNr].SQLLen); end; SQL_DOUBLE, SQL_FLOAT: SetFloat(in_sqlda^.SQLvar[SQLVarNr].SQLData, AParams[ParNr].AsFloat, in_SQLDA^.SQLVar[SQLVarNr].SQLLen);
_______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal