Why is Delphi (Zeos) giving me widestring fields in SQLite when I ask for unsigned big int?

前端 未结 3 875
走了就别回头了
走了就别回头了 2020-12-22 05:29

I am using the latest Zeos with SQLite 3. It is generally going well, converting from MySQL, once we made all the persistent integer field TLargeInt.

Bu

相关标签:
3条回答
  • 2020-12-22 06:30

    No, it does not "revert" to string, SQlite just stores the data as it is provided.

    As the documentation states:

    SQLite supports the concept of "type affinity" on columns. The type affinity of a column is the recommended type for data stored in that column. The important idea here is that the type is recommended, not required. Any column can still store any type of data. It is just that some columns, given the choice, will prefer to use one storage class over another. The preferred storage class for a column is called its "affinity".

    If you supplied/bind a text value, it would store a text value. There is no conversion to the type supplied in the CREATE TABLE statement, as it may appear in other more strict RBMS, e.g. MySQL.

    So in your case, if you retrieve the data as ftWideString, I guess this is because you wrote the data as TEXT. For instance, the tool or program creating the SQLite3 content from your MySQL is writing this column as TEXT.

    About numbers, there is no "signed"/"unsigned", nor precision check in SQLite3. So if you want to store "unsigned big int" values, just use INTEGER, which are Int64.

    But, in all cases, even if SQLite3 API does support UNSIGNED 64 bit integers, this sqlite3_uint64 type may hardly be supported by the Zeos/ZDBC API or by Delphi (older versions of Delphi do NOT support UInt64). To be sure, you should better retrieve such values as TEXT, then convert it as UInt64 manually in your Delphi code.

    Update:

    Are you using the TDataSet descendant provided by Zeos? This component is tied to DB.Pas, so expects a single per-column type. It may be the source of confusion of your code (which you did not show at all, so it is hard to figure out what's happening).

    You should better use the lower level ZDBC interface, which allows to retrieve the column type for each row, and call the value getter method as you need.

    0 讨论(0)
  • 2020-12-22 06:31

    The latest Zeos, that is, which one? See if it's the same in 7.2 svn 3642: http://svn.code.sf.net/p/zeoslib/code-0/branches/testing-7.2/

    Michal

    0 讨论(0)
  • 2020-12-22 06:33

    Zeos uses the following code (in ZDbcSqLiteUtils.pas) to determine a column's type:

    Result := stString;
    ...
    if StartsWith(TypeName, 'BOOL') then
      Result := stBoolean
    else if TypeName = 'TINYINT' then
      Result := stShort
    else if TypeName = 'SMALLINT' then
      Result := stShort
    else if TypeName = 'MEDIUMINT' then
      Result := stInteger
    else if TypeName = {$IFDEF UNICODE}RawByteString{$ENDIF}('INTEGER') then
      Result := stLong //http://www.sqlite.org/autoinc.html
    else if StartsWith(TypeName, {$IFDEF UNICODE}RawByteString{$ENDIF}('INT')) then
      Result := stInteger
    else if TypeName = 'BIGINT' then
      Result := stLong
    else if StartsWith(TypeName, 'REAL') then
      Result := stDouble
    else if StartsWith(TypeName, 'FLOAT') then
      Result := stDouble
    else if (TypeName = 'NUMERIC') or (TypeName = 'DECIMAL')
      or (TypeName = 'NUMBER') then
    begin
     { if Decimals = 0 then
        Result := stInteger
      else} Result := stDouble;
    end
    else if StartsWith(TypeName, 'DOUB') then
      Result := stDouble
    else if TypeName = 'MONEY' then
      Result := stBigDecimal
    else if StartsWith(TypeName, 'CHAR') then
      Result := stString
    else if TypeName = 'VARCHAR' then
      Result := stString
    else if TypeName = 'VARBINARY' then
      Result := stBytes
    else if TypeName = 'BINARY' then
      Result := stBytes
    else if TypeName = 'DATE' then
      Result := stDate
    else if TypeName = 'TIME' then
      Result := stTime
    else if TypeName = 'TIMESTAMP' then
      Result := stTimestamp
    else if TypeName = 'DATETIME' then
      Result := stTimestamp
    else if Pos('BLOB', TypeName) > 0 then
      Result := stBinaryStream
    else if Pos('CLOB', TypeName) > 0 then
      Result := stAsciiStream
    else if Pos('TEXT', TypeName) > 0 then
      Result := stAsciiStream;
    

    If your table uses any other type name, or if the SELECT output column is not a table column, then Zeos falls back to stString. There's nothing you can do about that; you'd have to read the values from the string field (and hope that the conversion to string and back does not lose any information).

    It might be a better idea to use some other library that does not assume that every database has fixed column types.

    0 讨论(0)
提交回复
热议问题