¿Por qué Delphi (Zeos) me está dando campos en SQLite cuando solicito unsigned big int?

Estoy usando los últimos Zeos con SQLite 3. En general, está yendo bien, convirtiéndolo de MySQL, una vez que creamos todos los campos integers persistentes TLargeInt .

Pero cuando utilizamos una definición de columna unsigned big int (el único tipo sin firmar permitido según https://www.sqlite.org/datatype3.html ), Delphi llama al campo resultante un ftWidestring .

No, no "revierte" a la cadena, SQlite solo almacena los datos tal como se proporcionan.

Como dice la documentation :

SQLite admite el concepto de "afinidad de types" en columnas. La afinidad de tipo de una columna es el tipo recomendado para los datos almacenados en esa columna. La idea importante aquí es que el tipo es recomendado, no obligatorio. Cualquier columna puede almacenar cualquier tipo de datos. Es solo que algunas columnas, dada la opción, preferirán usar una class de almacenamiento sobre otra. La class de almacenamiento preferida para una columna se llama su "afinidad".

Si suministra / vincula un valor de text, almacenaría un valor de text. No hay conversión al tipo proporcionado en la sentencia CREATE TABLE, ya que puede aparecer en otro RBMS más estricto, por ejemplo, MySQL.

Entonces, en su caso, si recupera los datos como ftWideString , supongo que esto se debe a que usted escribió los datos como TEXTO. Por ejemplo, la herramienta o el progtwig que crea el contenido SQLite3 de MySQL está escribiendo esta columna como TEXTO.

Acerca de los numbers, no hay "firmado" / "sin firmar", ni verificación de precisión en SQLite3. Entonces, si desea almacenar valores "unsigned big int", simplemente use INTEGER, que son Int64.

Pero, en todos los casos, incluso si la API SQLite3 admite integers de 64 bits no identificados , este tipo de sqlite3_uint64 puede ser soportado por la API Zeos / ZDBC o por Delphi (las versiones anteriores de Delphi NO son compatibles con UInt64). Para estar seguro, debería recuperar dichos valores como TEXTO, luego UInt64 como UInt64 manualmente en su código Delphi.

Actualizar:

¿Estás usando el descendiente TDataSet provisto por Zeos? Este componente está vinculado a DB.Pas , por lo que espera un único tipo por columna. Puede ser la fuente de confusión de tu código (que no has mostrado en absoluto, por lo que es difícil saber qué está pasando).

Debería utilizar mejor la interfaz ZDBC de nivel inferior, que permite recuperar el tipo de columna para cada fila, y llamar al método getter de valor que necesite.

El último Zeos, es decir, ¿cuál? Vea si es lo mismo en 7.2 svn 3642: http://svn.code.sf.net/p/zeoslib/code-0/branches/testing-7.2/

Michal

Zeos usa el siguiente código (en ZDbcSqLiteUtils.pas ) para determinar el tipo de columna:

 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; 

Si su tabla utiliza cualquier otro nombre de tipo, o si la columna de salida SELECCIONAR no es una columna de tabla, stString vuelve a stString . No hay nada que puedas hacer al respecto; Tendría que leer los valores del campo de cadena (y esperar que la conversión a cadena y a la inversa no pierda ninguna información).

Puede ser una mejor idea usar alguna otra biblioteca que no asum que cada database tiene types de columnas fijas.