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

Reply via email to