delphi sqlite3 teechart firedac delphi-10.2-tokyo

delphi - TFDQuery y SQLite: no coinciden los tipos de campo, esperando: LargeInt actual: WideString



sqlite3 teechart (1)

Usando Delphi 10.2, SQLite y Teecharts. Mi base de datos SQLite tiene dos campos, creados con:

CREATE TABLE HistoryRuntime (''DayTime'' DateTime, Device1 INTEGER DEFAULT (0));

TFDQuery la tabla usando un TFDQuery llamado qryGrpahRuntime con el siguiente SQL:

SELECT DayTime AS TheDate, Sum(Device1) As DeviceTotal FROM HistoryRuntime WHERE (DayTime >= "2017-06-01") and (DayTime <= "2017-06-26") Group by Date(DayTime)

Utilizando el Editor de campo en Delphi IDE, puedo agregar dos campos persistentes, obteniendo TheDate como TDateTimeField y DeviceTotal como TLargeIntField .

Ejecuto esta consulta en un programa para crear un TeeChart, que creé en el momento del diseño. Siempre que la consulta devuelva algunos registros, todo esto funciona. Sin embargo, si no hay registros para las fechas solicitadas, recibo una excepción EDatabaseError con el mensaje:

qryGrpahRuntime: no coincidencia de tipos para el campo ''DeviceTotal'', esperando: LargeInt actual: Widestring

He hecho muchas búsquedas de soluciones en la web sobre cómo prevenir este error en una consulta vacía, pero no he tenido suerte con nada que haya encontrado. Por lo que puedo decir, SQLite se establece de manera predeterminada en el campo de cadena ancha cuando no se devuelve ningún dato. Intenté usar CAST en la consulta y no pareció hacer ninguna diferencia.

Si elimino los campos persistentes, la consulta se abrirá sin problemas en un conjunto de devolución vacío. Sin embargo, para utilizar el editor TeeChart en el IDE, parece que necesito campos persistentes.

¿Hay alguna manera de hacer que esto funcione con campos persistentes, o voy a tener que descartar los campos persistentes y luego agregar la serie TeeChart en tiempo de ejecución?


Este comportamiento se describe en el capítulo Ajuste del mapa de FireDAC del manual de SQLite de FireDAC:

Para una expresión en una lista SELECT, SQLite evita la información del nombre de tipo. Cuando el conjunto de resultados no está vacío, FireDAC usa los tipos de datos de valor del primer registro. Cuando está vacío, FireDAC describe esas columnas como dtWideString. Para especificar explícitamente el tipo de datos de columna, añada ::<type name> al alias de columna:

SELECT count(*) as "cnt::INT" FROM mytab

Así que modifique su comando, por ejemplo, de esta manera (utilicé BIGINT , pero puede usar cualquier tipo de pseudo-datos que se correlacione con un tipo de datos entero con signo de 64 bits y no aumente automáticamente, lo que corresponde a su campo persistente TLargeIntField ):

SELECT DayTime AS "TheDate", Sum(Device1) AS "DeviceTotal::BIGINT" FROM HistoryRuntime WHERE DayTime BETWEEN {d 2017-06-01} AND {d 2017-06-26} GROUP BY Date(DayTime)

PD Hice una pequeña optimización usando el operador BETWEEN (que evalúa el valor de la columna solo una vez), y usé una secuencia de escape para las constantes de fecha (que, en realidad, reemplazas por parámetro, supongo, así que solo por curiosidad).

Esta sugerencia de tipo de datos es analizada por el procedimiento FDSQLiteTypeName2ADDataType que toma y analiza el nombre de columna en formato <nombre de columna> :: <nombre de tipo> en su parámetro AColName .