有人知道是否可以在Qt5 或visual studio 2010以及Qt-addin 的sqlite数据库上执行spaceite函数?
特别是,我对使用Point类型的函数感兴趣。
谢谢!
PS:函数在官方的spaceite-gui中工作,但我认为没有办法以编程方式使用spatialite-gui,是吗?
以下是我到目前为止所尝试的内容:在Qt5.4.2中我连接了SQLITE空间数据库并尝试使用函数ST_X(点),ST_Y(点),ST_PointN和ST_NumPoints但没有成功:
SELECT ST_X(ST_PointN(Geometry, 1)) AS StartX, ST_Y(ST_PointN(Geometry, 1)) AS StartY, ST_X(ST_PointN(Geometry, ST_NumPoints(Geometry))) AS EndX, ST_Y(ST_PointN(Geometry, ST_NumPoints(Geometry))) AS EndY FROM "国道"
然后这总是无法成功解决。我还在Sqlite: Execute Spatialite Functions in Intellij中找到了一些关于java的相关解决方案,但这些解决方案无法解决我的问题:
步骤1:从spatialite网站下载mod_spatialite-4.3.0a-win-x86.7z文件并将其解压缩到c:\ sqlite3
PS:在Window 10中,我用cmd打开sqlite3,SELECT load_extension('mod_spatialite')
可以成功执行的SQL语句。
步骤2:在我的Qt代码中,在SQL语句包含spatialite函数之前添加SELECT load_extension('mod_spatialite')
。不幸的是,excute QSqlQuery.exec("SELECT load_extension('mod_spatialite')")
的返回值为false。哦不,这是一个令人沮丧的消息。
更重要的是,我还在https://forum.qt.io/topic/69835/why-can-t-qt-be-installed-with-sqlite-that-has-load_extension-enabled中找到了关于Qt的一些相关解决方案。但是,这需要从源代码重新编译Qt,这超出了我的技能。最后,我如何在Qt5.4.2 或visual studio 2010以及Qt-addin ?有没有人这样做过?
答案 0 :(得分:0)
load_extension() documentation说:
出于安全原因,默认情况下已关闭扩展程序。
您必须使用C函数sqlite3_enable_load_extension()或sqlite3_db_config(... SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION ...)启用它。 当您无论如何都要调用C函数时,也可以使用sqlite3_load_extension()。
如果您无法直接从Qt应用程序调用SQLite库函数,那么您唯一的选择是重新编译Qt(或Qt插件)。
答案 1 :(得分:0)
非常感谢你的帮助,特别是@Marco和@CL ..
以下是我的两个解决方案:
PS: 首先,从http://www.gaia-gis.it/gaia-sins/windows-bin-x86/下载mod_spatialite-4.3.0a-win-x86.7z。然后,将名为mod_spatialite.dll的文件复制到项目的执行内容(等于.exe程序文件)。接下来,编写Qt项目并运行此Qt项目进行测试。
我的机器运行时: Window 10 + Qt5.4.2 + Sqlite3
第一个解决方案:
作为@CL。说,
如果您无法直接从Qt应用程序调用SQLite库函数,那么您唯一的选择是重新编译Qt(或Qt插件)。
所以我重新编译了sqlite Qt插件(文件路径是C:\ Qt \ Qt5.4.2 \ 5.4 \ Src \ qtbase \ src \ plugins \ sqldrivers)。然后修改两个位置:
在sqlite.pro中添加DEFINES -= SQLITE_OMIT_LOAD_EXTENSION
;
在名为open of qsql_sqlite.cpp的函数中添加以下代码块:
if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) {
...
char* zErrMsg = 0;
char* spatialiteDll = "mod_spatialite";
sqlite3_enable_load_extension(d->access, 1);
sqlite3_load_extension(d->access, spatialiteDll, 0, &zErrMsg);
...
}
第二个解决方案:参考链接:https://www.sqlite.org/quickstart.html
正如@Marco所说,
QSqlQuery是一个c ++ / Qt类,用于从sqlite数据库获取数据,但Qt也是c ++,因此您可以自由使用任何c ++ sqlite库打开您的sqlite数据库。 sqlite.org/quickstart.html
因此,我得到以下代码来执行SQL语句以及Qt5中的spatialite函数。
示例代码:
#include <QCoreApplication>
#include <stdio.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char **argv){
QCoreApplication a(argc, argv);
sqlite3 *db;
char *zErrMsg = 0;
int rc;
if( argc!=3 ){
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
char* spatialiteDll = "mod_spatialite";
sqlite3_enable_load_extension(db, 1);
sqlite3_load_extension(db, spatialiteDll, 0, &zErrMsg);
fprintf(stderr, "sqlite3 error: %s\n", zErrMsg);
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return a.exec();
}