仅在Android上查询时SQL逻辑错误
SQL logic error only when querying on Android
我正在研究一个依赖SQLite3数据库作为数据存储库的C Android NDK项目。该数据库有三个表;列计数为6、8和6;行计数为240,约1,250万,〜400万。
SQLite驱动程序正在编译,未修改,直接从SQLITE 3 AMALGAMATION源代码,版本3.19.3。
我的问题是,运行本机库时,数据库查询会导致" SQL逻辑错误或缺少数据库" 。我知道数据库是我期望的,并且可以访问。如果我在桌面环境(而不是在移动设备上(对同一数据库执行相同的查询,我会看到预期的结果。此外,如果我使用数据库在存储库中包含数据子集的数据库(〜300个记录(,请看到预期的结果。
,有什么想法?
供参考,这是我正在使用的查询:
WITH
weather_distance AS
(SELECT latitude, longitude, temperature, humidity, time, (ABS((latitude - $lat)) + ABS((longitude - $lon))) AS distance FROM Weather WHERE time BETWEEN $start AND $end),
min_weather_distance AS
(SELECT latitude, longitude, temperature, humidity, time FROM weather_distance WHERE distance = (SELECT MIN(distance) FROM weather_distance)),
solar_distance AS
(SELECT latitude, longitude, ghi, (time - 1800) AS time, (ABS((latitude - $lat)) + ABS((longitude - $lon))) AS distance FROM SolarData WHERE time BETWEEN $start AND $end),
min_solar_distance AS
(SELECT latitude, longitude, ghi, time FROM solar_distance WHERE distance = (SELECT MIN(distance) FROM solar_distance))
SELECT s.time, s.ghi, w.temperature, w.humidity FROM min_weather_distance w INNER JOIN min_solar_distance s ON w.time = s.time ORDER BY s.time ASC
和我用来进行查询的代码(C (:
const char* getEnvQuery =
"WITH "
"weather_distance AS "
"(SELECT latitude, longitude, temperature, humidity, time, (ABS((latitude - $lat)) + ABS((longitude - $lon))) AS distance FROM Weather WHERE time BETWEEN $start AND $end), "
"min_weather_distance AS "
"(SELECT latitude, longitude, temperature, humidity, time FROM weather_distance WHERE distance = (SELECT MIN(distance) FROM weather_distance)), "
"solar_distance AS "
"(SELECT latitude, longitude, ghi, (time - 1800) AS time, (ABS((latitude - $lat)) + ABS((longitude - $lon))) AS distance FROM SolarData WHERE time BETWEEN $start AND $end), "
"min_solar_distance AS (SELECT latitude, longitude, ghi, time FROM solar_distance WHERE distance = (SELECT MIN(distance) FROM solar_distance)) "
"SELECT s.time, s.ghi, w.temperature, w.humidity FROM min_weather_distance w INNER JOIN min_solar_distance s ON w.time = s.time ORDER BY s.time ASC; ";
sqlite3_stmt* getEnvStmt;
prepareSqlStatement(getEnvQuery, &getEnvStmt, envdbhandle, "Error preparing SQL statement to retrieve environmental data. SQLite return code: ");
sqlite3_bind_double(getEnvStmt, 1, iter->latitude); //iter is defined above quoted code
sqlite3_bind_double(getEnvStmt, 2, iter->longitude);
sqlite3_bind_double(getEnvStmt, 3, iter->startTime);
sqlite3_bind_double(getEnvStmt, 4, iter->endTime);
__android_log_print(ANDROID_LOG_DEBUG, "SPP/getEnvironment", "Bound parameters: lat=%f, lon=%f, start=%ld, end=%ld", iter->latitude, iter->longitude, iter->startTime, iter->endTime);
int rc = sqlite3_step(getEnvStmt);
__android_log_print(ANDROID_LOG_DEBUG, "SPP/getEnvironment", "step(getEnvStmt) = %d", rc);
int errCode = sqlite3_extended_errcode(envdbhandle);
__android_log_print(ANDROID_LOG_DEBUG, "SPP/getEnvironment", "Most recent SQLITE error code: %s. Message: %s", sqlite3_errstr(errCode), sqlite3_errmsg(envdbhandle));
while(rc == SQLITE_ROW)
{
EnvironmentDatum envData;
int dbTime = sqlite3_column_int(getEnvStmt, 0);
envData.UnixTime = timeconvert::secondsOfYearToUNIXTime(dbTime, year);
__android_log_print(ANDROID_LOG_DEBUG, "SPP/getEnvironment", "EnvironmentDatum dbTime=%d, UnixTime=%f", dbTime, envData.UnixTime);
envData.GHI = sqlite3_column_double(getEnvStmt, 1);
envData.Temperature = sqlite3_column_double(getEnvStmt, 2);
envData.Humidity = sqlite3_column_double(getEnvStmt, 3);
envCollection.push_back(envData);
rc = sqlite3_step(getEnvStmt);
}
sqlite3_finalize(getEnvStmt);
重要调试信息:
sqlite3_stmt* verQueryStmt;
prepareSqlStatement("select sqlite_version(); ", &verQueryStmt, envdbhandle, "Error getting driver version. Error code:");
sqlite3_step(verQueryStmt);
std::string sqliteVersion = parseSqliteStringColumn(verQueryStmt, 0);
sqlite3_finalize(verQueryStmt);
__android_log_print(ANDROID_LOG_DEBUG, "SPP/buildScenario", "sqlite version=%s", sqliteVersion.c_str()); // outputs "sqlite version=3.19.3"
__android_log_print(ANDROID_LOG_DEBUG, "SPP/buildScenario", "env db readability=%s", (sqlite3_db_readonly(envdbhandle, "main") == 1 ? "READONLY" : (sqlite3_db_readonly(envdbhandle, "main") == 0 ? "READ/WRITE" : "NOT CONNECTED"))); // outputs "READ/WRITE"
根据请求,这里是准备:
static int prepareSqlStatement(const char* query, sqlite3_stmt** statement, sqlite3* db, const char* failMsg)
{
int returnCode = sqlite3_prepare(db, query, -1, statement, NULL);
if(returnCode != SQLITE_OK || statement == NULL)
{
int errCode = sqlite3_extended_errcode(dbhandle);
std::cout << "Most recent SQLITE error code: " << sqlite3_errstr(errCode) << ". Message: " << sqlite3_errmsg(dbhandle) << std::endl;
reportError(failMsg, -1 * returnCode);
}
return returnCode;
}
预计,这是reporterror:
static void reportError(const char* message, int errorCode)
{
std::stringstream ss;
ss << message << errorCode;
throw std::runtime_error(ss.str());
}
当查询的中间结果变得太大时,数据库必须将某些数据交换为临时文件。
6410是 SQLITE_IOERR_GETTEMPPATH
,这意味着
Android没有任何默认的UNIX路径。内置数据库框架将其SQLITE库的副本与SQLITE_TEMP_STORE = 3一起编译。如果要获取实际的临时文件,则应将它们放入Context.getCacheDir()
返回的任何目录中;这将需要设置sqlite_tmpdir环境变量。
相关文章:
- 尝试创建表会给出 SQL 逻辑错误
- Qt SQL LIKE语句返回错误
- 仅在Android上查询时SQL逻辑错误
- QT 5.8 SQL连接错误:Windows 10上未加载QMYSQL驱动程序
- SQL Server 2016 CLR 存储过程错误:"A system assertion check has failed"
- 使用QT 5.8和SQL库配置错误
- 如何在编译时检测 C++ 代码中的 SQL 错误
- SQL 字符串错误?没有这样的列
- C++ SQL 连接"get_driver_instance(); is undefined "错误
- ODBC 错误"String data, right truncation State code: 22001"与 SQL Server 数据库
- 无法按列名从SQL表中获取数据.给出错误.只能通过列数来做同样的事情
- C++程序中存在SQL查询语法错误,但可在MySQL工作台中使用
- C++ Sqlite3 中,执行 2 个 sql 语句 - 第 2 条语句得到分段核心转储错误
- 插入到 SQL 中,出现 C++ 错误 1064 42000
- SQL 错误:接近 ".2016":语法错误
- 由于WSACleanup,sql server已消除错误
- 调试.dll C++时出现MS SQL Server 2008错误17058
- Qt Creator Sql Update语法错误
- 您的 SQL 语法错误;[...]在第 1 行的 '%+var+%' 附近 Consulta 喜欢 MYSQL
- 具有"与无人共享"属性的文件夹的 SQL 访问被拒绝错误