[fpc-pascal] Cannot write datetime field on sqlite3 database on ARM

Toru Takubo takubo at e-parcel.co.jp
Tue Mar 9 01:47:49 CET 2021


On 2021/03/08 16:54, Michael Van Canneyt via fpc-pascal wrote:
> 
> 
> On Mon, 8 Mar 2021, Toru Takubo via fpc-pascal wrote:
> 
>> Hi,
>>
>> I am developing my app on Windows and building apps for other
>> platforms by using cross compiler. Now I have a problem only
>> occurred on Linux ARM.
>>
>> The problem is that it cannot write datetime field on sqlite3
>> database. It can read/write other fields like int, varchar
>> or blob, but always write zero in datetime (maybe float as well)
>> field.
>>
>> Does anyone have an idea about this issue? I am not sure it is
>> fpc issue, but better to report bug?
> 
> It sounds like a floating point problem. As you probably know, a TDateTime
> type is actually a double type. Did you try with a float value ?
> 
> The DB explorer tools probably just use strings to read/write from the
> database, so they will not be bothere by such things, but FPC stores dataset
> values in 'native' formats in memory.
> 
> I don't know what to advise to further investigate the issue, One thing to
> try would be to test whether normal float arithmetic or date arithmetic works.
> If not, then the compiler people will need to give more advice.
> 

I created a simple test code, and ran on linux-i386 and linux-arm.
Test on linux-i386 is OK but on linux-arm, I got unexpected values
"30-12-99" as datetime and "2.12199579096527E-314" as float, which are different
from values previously set. (except INT and VARCHAR fields)

---linux-i386--------------------------------------------
INT, VARCHAR,           DATETIME,           DOUBLE
0, 9-3-21 08:50:23, 9-3-21 08:50:23, 0
1, 9-3-21 12:16:06, 9-3-21 12:16:06, 0.142857142857143
2, 9-3-21 15:41:49, 9-3-21 15:41:49, 0.285714285714286
3, 9-3-21 19:07:32, 9-3-21 19:07:32, 0.428571428571429
4, 9-3-21 22:33:15, 9-3-21 22:33:15, 0.571428571428571
5, 10-3-21 01:58:58, 10-3-21 01:58:58, 0.714285714285714
6, 10-3-21 05:24:40, 10-3-21 05:24:40, 0.857142857142857
7, 10-3-21 08:50:23, 10-3-21 08:50:23, 1
8, 10-3-21 12:16:06, 10-3-21 12:16:06, 1.14285714285714
9, 10-3-21 15:41:49, 10-3-21 15:41:49, 1.28571428571429

---linux-arm---------------------------------------------
INT, VARCHAR,           DATETIME,           DOUBLE
0, 9-3-21 08:55:53, 30-12-99, 2.12199579096527E-314
1, 9-3-21 12:21:36, 30-12-99, 2.12199579096527E-314
2, 9-3-21 15:47:18, 30-12-99, 2.12199579096527E-314
3, 9-3-21 19:13:01, 30-12-99, 2.12199579096527E-314
4, 9-3-21 22:38:44, 30-12-99, 2.12199579096527E-314
5, 10-3-21 02:04:27, 30-12-99, 2.12199579096527E-314
6, 10-3-21 05:30:10, 30-12-99, 2.12199579096527E-314
7, 10-3-21 08:55:53, 30-12-99, 2.12199579096527E-314
8, 10-3-21 12:21:36, 30-12-99, 2.12199579096527E-314
9, 10-3-21 15:47:19, 30-12-99, 2.12199579096527E-314

I used a shared library libsqlite3.so included in the "DB Browser for SQLite",
so it should work. What can cause such a problem only in the specific field
on the specific platform?

Thank you in advance for any advice.

Toru



-------------- next part --------------
program project1;

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils, sqlite3conn, sqldb;

var
  DBC: TSQLite3Connection;
  QRY: TSQLQuery;
  TRN: TSQLTransaction;
  i: Integer;
  nw: TDateTime;

begin
  DBC:=TSQLite3Connection.Create(nil);
  QRY:=TSQLQuery.Create(nil);
  TRN:=TSQLTransaction.Create(nil);
  try
    //Initialize Connection
    DBC.DatabaseName:=ExtractFileDir(ParamStr(0))+PathDelim+'test.db';
    QRY.DataBase:=DBC;
    TRN.DataBase:=DBC;
    QRY.Transaction:=TRN;

    //create database
    DeleteFile(DBC.DatabaseName);
    DBC.CreateDB;
    QRY.SQL.Text:=
    'create table TEST ('+
    'VALUE_INT int,'+
    'VALUE_VARCHAR varchar(20),'+
    'VALUE_DATETIME datetime,'+
    'VALUE_DOUBLE double)';
    TRN.StartTransaction;
    try
      QRY.ExecSQL;
      TRN.Commit;
    except
      TRN.Rollback;
      raise;
    end;

    //insert values into table
    for i:=0 to 9 do begin
      nw:=Now+i/7;
      QRY.SQL.Text:=
      'insert into TEST ('+
      'VALUE_INT,'+
      'VALUE_VARCHAR,'+
      'VALUE_DATETIME,'+
      'VALUE_DOUBLE'+
      ') values ('+
      ':VALUE_INT,'+
      ':VALUE_VARCHAR,'+
      ':VALUE_DATETIME,'+
      ':VALUE_DOUBLE)';
      QRY.ParamByName('VALUE_INT').AsInteger:=i;
      QRY.ParamByName('VALUE_VARCHAR').AsString:=DateTimeToStr(nw);
      QRY.ParamByName('VALUE_DATETIME').AsDateTime:=nw;
      QRY.ParamByName('VALUE_DOUBLE').AsFloat:=i/7;
      QRY.Prepare;
      try
        QRY.ExecSQL;
        TRN.Commit;
      except
        TRN.Rollback;
        raise;
      end;
    end;

    //show table
    QRY.SQL.Text:='select * from TEST';
    try
      QRY.Open;
      Writeln('INT, VARCHAR,           DATETIME,           DOUBLE');
      while not QRY.EOF do begin
        Writeln(
          IntToStr(QRY.FieldByName('VALUE_INT').AsInteger)+', '+
          QRY.FieldByName('VALUE_VARCHAR').AsString+', '+
          DateTimeToStr(QRY.FieldByName('VALUE_DATETIME').AsDateTime)+', '+
          FloatToStr(QRY.FieldByName('VALUE_DOUBLE').AsFloat)
        );
        QRY.Next;
      end;
      TRN.Commit;
    except
      TRN.Rollback;
      raise;
    end;
  except
    on E:Exception do begin
      Writeln('ERROR:'+E.Message);
    end;
  end;
  DBC.Close;
  TRN.Free;
  QRY.Free;
  DBC.Free;
  Readln;
end.



More information about the fpc-pascal mailing list