【问题标题】:Zeoslib fails to read LargeInt fields from sqlite databaseZeoslib 无法从 sqlite 数据库中读取 LargeInt 字段
【发布时间】:2013-10-08 17:17:48
【问题描述】:

我正在尝试使用 ZeosLib 组件和 Delphi XE2 读取 sqlite 数据库。一切正常,除非我尝试读取存储的三个时间戳值,它们基本上是 17 位数字。而不是得到正确的值,我得到零。读取数据库数据的函数(注意注释行):

procedure TCookieImporter.LoadCookies(const AChromeDatabase: String);
var
  zconn          : TZConnection;
  zquery         : TZReadOnlyQuery;
  creation_utc   : Int64;
  expires_utc    : Int64;
  last_access_utc: Int64;
  host_key       : String;
  name           : String;
  value          : String;
  path           : String;
  secure         : Integer;
  httponly       : Integer;
  has_expires    : Integer;
  persistent     : Integer;
  priority       : Integer;
  cookie         : TChromeCookie;
begin
  zconn := TZConnection.Create(nil);
  try
    zconn.Protocol := 'sqlite-3';
    zconn.Database := AChromeDatabase;
    zconn.Connect;
    if zconn.Connected then
    try
      zquery := TZReadOnlyQuery.Create(nil);
      try
        zquery.Connection := zconn;
        zquery.SQL.Text := 'SELECT * FROM cookies';
        zquery.Active := TRUE;
        while not zquery.Eof do
        begin
          // bug: following three lines - they all return zero
          creation_utc := zquery.FieldByName('creation_utc').AsLargeInt;
          expires_utc := zquery.FieldByName('expires_utc').AsLargeInt;
          last_access_utc := zquery.FieldByName('last_access_utc').AsLargeInt;

          // debug info for SO
          WriteLn(zquery.FieldDefs[0].Name); // = creation_utc
          WriteLn(zquery.FieldDefs[0].Size); // = 0
          WriteLn(zquery.FieldByName('creation_utc').AsString); // = 0
          WriteLn(VarToStr(zquery.FieldValues['creation_utc'])); // = 0
          dt := zquery.FieldDefs[0].DataType; // dt = ftInteger

          host_key := zquery.FieldByName('host_key').AsString;
          name := zquery.FieldByName('name').AsString;
          value := zquery.FieldByName('value').AsString;
          path := zquery.FieldByName('path').AsString;
          secure := zquery.FieldByName('secure').AsInteger;
          httponly := zquery.FieldByName('httponly').AsInteger;
          has_expires := zquery.FieldByName('has_expires').AsInteger;
          persistent := zquery.FieldByName('persistent').AsInteger;
          priority := zquery.FieldByName('priority').AsInteger;

          cookie := TChromeCookie.Create(creation_utc, host_key, name, value, path, expires_utc, secure, httponly, last_access_utc, has_expires, persistent, priority);
          FChromeCookies.Add(cookie);

          zquery.Next;
        end;
      finally
        zquery.Free;
      end;
    finally
      zconn.Disconnect;
    end;
  finally
    zconn.Free;
  end;
end;

我已经尝试了所有想到的方法,从简单地使用 .AsLargeInt() getter 获取价值,到将其设置为 Variant,然后转换为 Integer/Int64/String 等。在所有情况下,我都得到零作为返回值。我也尝试过使用不同版本的 ZeosLib,特别是 7.0.6-stable7.1.1-rc。由于与较新版本的 Delphi 不兼容,无法使用 6.6.6-stable 编译。

以下是我使用 SQLite Manager(firefox 插件)打开数据时的样子:

及表结构:

我尝试了另一种方法,通过使用 DISqlite3 组件读取数据,它们可以工作,但是它们是共享软件,如果可能的话,我宁愿使用免费软件。

任何想法是什么导致了这个奇怪的错误?

【问题讨论】:

  • 试试 trunc(...AsDouble)。不完美但可能有效。或者我们的开源课程,用于全速直接访问 SQlite3 - 请参阅blog.synopse.info/post/2011/07/22/… - 并且 Int64 大数没有问题。 :)
  • 非常感谢。我现在就试试 SynDBSQLite3。顺便说一句,Trunc() 没有做到这一点。
  • 尝试将字段定义为 BIGINT;在这里查看帖子:zeoslib.sourceforge.net/viewtopic.php?f=5&t=1275
  • 数据库是外部的,所以我不能编辑它——但是,SynDBSQLite 似乎可以完美地工作:)
  • 您有可用的交易方式。其余的听起来不错。另请参阅独占模式以获得最佳速度。我们的博客有一些文章,mORMot 文档也很详尽。

标签: database sqlite delphi delphi-xe2 zeos


【解决方案1】:

为了回答我自己的问题,我在他们的官方论坛上创建了帖子并得到了以下回复:

Zeos 是一个通用的访问组件。我知道我们可以为 Integer 字段假设 Int64 类型。

实际上我们使用 BIGINT 来假设 TLongInt-Fields。大多数 RDBM 用于哪个。

这是一个公开讨论。 Internaly SQLite 为准备好的语句接受两个整数绑定。制作这个补丁没问题..

所以如果我们应该改变这个,其他人可以在这里发布。如果您怀疑,请在 7.2 上,而不是在 7.0 或 7.1 上。想一想:这是一个由来已久的代码。如果用户确实更新了那里的组件,这可能会带来很多麻烦。

[link to the thread]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 2018-12-28
    • 2012-09-24
    • 2018-05-28
    • 2012-01-06
    相关资源
    最近更新 更多