or better:
ftFmtBCD: begin
if P.AsFMTBCD.Precision > 15 then //we are out of REAL range, so we
must bind as BLOB
begin
s tr1=BCDTOStrP.AsFMTBCD,SQLFormatSettings);
checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1),
length(str1), @freebindstring));
end
else
begin
d o1=P.AsFloat
checkerror(sqlite3_bind_double(fstatement,I,do1));
end;
end;
This is wrong. There are some values which can't be written as floats,
but have precision<15.
Joost, look at ftBCD, ftCurrency they are also written as floats
So if there is it acceptable, then I would say, that also in this case
is it acceptable, isn't it ?
(I do not say, that it is perfect)
Can you create a patch which does this?
Patch is attached.
DECIMAL -> ftBCD (if precision and scale is not supplied, then scale=0)
DECIMAL(p) = DECIMAL(p,0) = DECIMAL(p,<nonnumeric>) -> if p<=18 then
ftLargeInt else ftFmtBCD
DECIMAL(p,s) -> if s>4 or p-s>14 then ftFmtBCD (number does not fit into
currency)
-Laco.
--- sqlite3conn.pp.ori Wed May 11 07:22:28 2011
+++ sqlite3conn.pp Wed May 11 08:58:48 2011
@@ -347,11 +347,35 @@ var
i : integer;
FN,FD : string;
ft1 : tfieldtype;
- size1 : word;
+ size1, size2 : integer;
ar1 : TStringArray;
fi : integer;
st : psqlite3_stmt;
-
+
+ function ExtractPrecisionAndScale(decltype: string; var precision, scale:
integer): boolean;
+ var p: integer;
+ begin
+ p:=pos('(', decltype);
+ Result:=p>0;
+ if not Result then Exit;
+ System.Delete(decltype,1,p);
+ p:=pos(')', decltype);
+ Result:=p>0;
+ if not Result then Exit;
+ decltype:=copy(decltype,1,p-1);
+ p:=pos(',', decltype);
+ if p=0 then
+ begin
+ precision:=StrToIntDef(decltype, precision);
+ scale:=0;
+ end
+ else
+ begin
+ precision:=StrToIntDef(copy(decltype,1,p-1), precision);
+ scale:=StrToIntDef(copy(decltype,p+1,length(decltype)-p), scale);
+ end;
+ end;
+
begin
st:=TSQLite3Cursor(cursor).fstatement;
for i:= 0 to sqlite3_column_count(st) - 1 do
@@ -379,27 +403,19 @@ begin
size1:=0;
case ft1 of
ftString: begin
- fi:=pos('(',FD);
- if (fi>0) then
- begin
- System.Delete(FD,1,fi);
- fi:=pos(')',FD);
- size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255);
- if size1 > dsMaxStringSize then size1 := dsMaxStringSize;
- end
- else size1 := 255;
+ size1 := 255; //sql: if length is omitted then length is 1
+ size2 := 0;
+ ExtractPrecisionAndScale(FD, size1, size2);
+ if size1 > dsMaxStringSize then size1 := dsMaxStringSize;
end;
ftBCD: begin
- fi:=pos(',',FD);
- if (fi>0) then
- begin
- System.Delete(FD,1,fi);
- fi:=pos(')',FD);
- size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255);
- if size1>4 then
- ft1 := ftFMTBcd;
- end
- else size1 := 4;
+ size2 := 18; //sql: if a precision is omitted, then use
implementation-defined
+ size1 := 0; //sql: if a scale is omitted then scale is 0
+ ExtractPrecisionAndScale(FD, size2, size1);
+ if (size2<=18) and (size1=0) then
+ ft1:=ftLargeInt
+ else if (size2-size1>14) or (size1>4) then
+ ft1:=ftFmtBCD;
end;
ftUnknown : DatabaseError('Unknown record type: '+FN);
end; // Case
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel