Browse Source

* sqlite bcd fixes. Mantis #16924, patch by Lacak2

git-svn-id: trunk@18988 -
marco 14 years ago
parent
commit
d630a85cbd
1 changed files with 50 additions and 27 deletions
  1. 50 27
      packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp

+ 50 - 27
packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp

@@ -99,7 +99,7 @@ Var
 implementation
 implementation
 
 
 uses
 uses
-  dbconst, sysutils, dateutils,FmtBCD;
+  dbconst, sysutils, dateutils, FmtBCD;
 
 
 const
 const
   JulianDateShift = 2415018.5; //distance from "julian day 0" (January 1, 4713 BC 12:00AM) to "1899-12-30 00:00AM"
   JulianDateShift = 2415018.5; //distance from "julian day 0" (January 1, 4713 BC 12:00AM) to "1899-12-30 00:00AM"
@@ -111,6 +111,7 @@ type
  TSQLite3Cursor = class(tsqlcursor)
  TSQLite3Cursor = class(tsqlcursor)
   private
   private
    fhandle : psqlite3;
    fhandle : psqlite3;
+   fconnection: TSQLite3Connection;
    fstatement: psqlite3_stmt;
    fstatement: psqlite3_stmt;
    ftail: pchar;
    ftail: pchar;
    fstate: integer;
    fstate: integer;
@@ -189,7 +190,11 @@ begin
                 do1:= P.AsFloat + JulianDateShift;
                 do1:= P.AsFloat + JulianDateShift;
                 checkerror(sqlite3_bind_double(fstatement,I,do1));
                 checkerror(sqlite3_bind_double(fstatement,I,do1));
                 end;
                 end;
-        ftFMTBcd,
+        ftFMTBcd:
+                begin
+                str1:=BCDToStr(P.AsFMTBCD, Fconnection.FSQLFormatSettings);
+                checkerror(sqlite3_bind_text(fstatement, I, PChar(str1), length(str1), sqlite3_destructor_type(SQLITE_TRANSIENT)));
+                end;
         ftstring,
         ftstring,
         ftFixedChar,
         ftFixedChar,
         ftmemo: begin // According to SQLite documentation, CLOB's (ftMemo) have the Text affinity
         ftmemo: begin // According to SQLite documentation, CLOB's (ftMemo) have the Text affinity
@@ -315,6 +320,7 @@ Var
 
 
 begin
 begin
   Res:= TSQLite3Cursor.create;
   Res:= TSQLite3Cursor.create;
+  Res.fconnection:=Self;
   Result:=Res;
   Result:=Res;
 end;
 end;
 
 
@@ -382,11 +388,35 @@ var
  i     : integer;
  i     : integer;
  FN,FD : string;
  FN,FD : string;
  ft1   : tfieldtype;
  ft1   : tfieldtype;
- size1 : word;
+ size1, size2 : integer;
  ar1   : TStringArray;
  ar1   : TStringArray;
  fi    : integer;
  fi    : integer;
  st    : psqlite3_stmt;
  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
 begin
   st:=TSQLite3Cursor(cursor).fstatement;
   st:=TSQLite3Cursor(cursor).fstatement;
   for i:= 0 to sqlite3_column_count(st) - 1 do 
   for i:= 0 to sqlite3_column_count(st) - 1 do 
@@ -417,29 +447,21 @@ begin
       ftFixedChar,
       ftFixedChar,
       ftFixedWideChar,
       ftFixedWideChar,
       ftWideString:
       ftWideString:
-                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;
-                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)), 0);
-                  if size1>4 then
-                    ft1 := ftFMTBcd;
-                  end
-                else size1 := 0;
-                end;
+               begin
+                 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
+                 size2 := MaxBCDPrecision; //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>MaxBCDPrecision-MaxBCDScale) or (size1>MaxBCDScale) then
+                   ft1:=ftFmtBCD;
+               end;
       ftUnknown : DatabaseError('Unknown record type: '+FN);
       ftUnknown : DatabaseError('Unknown record type: '+FN);
     end; // Case
     end; // Case
     tfielddef.create(fielddefs,FieldDefs.MakeNameUnique(FN),ft1,size1,false,i+1);
     tfielddef.create(fielddefs,FieldDefs.MakeNameUnique(FN),ft1,size1,false,i+1);
@@ -528,6 +550,7 @@ begin
     end;
     end;
   Result:=ComposeDateTime(ParseSQLiteDate(DS),ParseSQLiteTime(TS,False));
   Result:=ComposeDateTime(ParseSQLiteDate(DS),ParseSQLiteTime(TS,False));
 end;
 end;
+
 function TSQLite3Connection.LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
 function TSQLite3Connection.LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
 
 
 var
 var