Sqlite:在Qt5.4.2或vs2010中执行Spatialite函数以及Qt-addin

时间:2017-02-28 08:48:07

标签: c++ qt sqlite

有人知道是否可以在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 ?有没有人这样做过?

2 个答案:

答案 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)。然后修改两个位置:

  1. 在sqlite.pro中添加DEFINES -= SQLITE_OMIT_LOAD_EXTENSION;

  2. 在名为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);
    
     ...
    

    }

  3. 第二个解决方案:参考链接: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();
      }