我正在尝试在qSqlite(Qt 5.9)中加载Spatialite作为扩展,我在使用Qt4.8之前已经完成了,但是我在QT5.9中失败了。
我通过删除" SQLITE_OMIT_LOAD_EXTENSION"来更改sqlite.pri,并通过删除" #define SQLITE_OMIT_LOAD_EXTENSION 1
"并添加"来对sqlite.c做了一些更改。 #define SQLITE_ENABLE_LOAD_EXTENSION 1
&#34 ;.
我还将以下行添加到openDatabase(....)
#if defined(SQLITE_ENABLE_LOAD_EXTENSION)
| SQLITE_LoadExtension|SQLITE_LoadExtFunc
#endif
现在" requet.setQuery(" SELECT load_extension(' spatialite')",dbProject);"功能被识别,但我得到了这样的信息: 错误"找不到指定的过程。\ r \ n无法获取行" 如果我查看MSVC14中的调试输出,我可以看到已经加载了spatialite.dll及其所有依赖项。
注意:我使用我的Spatialite以及从网站下载的mod_spatialite进行了测试。
有关此问题的任何想法? 提前谢谢。
答案 0 :(得分:3)
根据示例here我在sqlite中启用了spatialite,该函数启用该模块。为此,您必须链接sqlite3库。
所做的修改是:
将"SELECT load_extension('libspatialite.so')"
更改为"SELECT load_extension('mod_spatialite')"
将"SELECT InitSpatialMetadata()"
更改为"SELECT InitSpatialMetadata(1)"
#include <sqlite3.h>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QSqlError>
int enable_spatialite(QSqlDatabase db){
QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0)
{
sqlite3_initialize();
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) {
sqlite3_enable_load_extension(db_handle, 1);
QSqlQuery query;
query.exec("SELECT load_extension('mod_spatialite')");
if (query.lastError() .isValid())
{
qDebug() << "Error: cannot load the Spatialite extension (" << query.lastError().text()<<")";
return 0;
}
qDebug()<<"**** SpatiaLite loaded as an extension ***";
query.exec("SELECT InitSpatialMetadata(1)");
if (query.lastError() .isValid())
{
qDebug() << "Error: cannot load the Spatialite extension (" << query.lastError().text()<<")";
return 0;
}
qDebug()<<"**** InitSpatialMetadata successful ***";
return 1;
}
}
return 0;
}
示例:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("memory.db");
if (!db.open()) {
qDebug()<<"not open";
}
qDebug()<<enable_spatialite(db);
QSqlQuery query;
qDebug()<<query.exec("CREATE TABLE test_geom (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, measured_value DOUBLE NOT NULL);");
qDebug()<<query.exec("SELECT AddGeometryColumn('test_geom', 'the_geom', 4326, 'POINT', 'XY');");
for(int i=0; i< 10; i++){
QString q = QString("INSERT INTO test_geom(id, name, measured_value, the_geom) VALUES (%1,'point %2', %3, GeomFromText('POINT(1.01 2.02)', 4326))")
.arg("NULL").arg(i).arg(i);
query.prepare(q);
qDebug()<< i<<query.exec();
}
qDebug()<<query.exec("SELECT id, name, measured_value, AsText(the_geom), ST_GeometryType(the_geom), ST_Srid(the_geom) FROM test_geom");
while (query.next()) {
QString str;
for(int i=0; i < query.record().count(); i++)
str += query.value(i).toString() + " ";
qDebug()<<str;
}
return a.exec();
}
输出:
**** SpatiaLite loaded as an extension ***
**** InitSpatialMetadata successful ***
1
true
true
0 true
1 true
2 true
3 true
4 true
5 true
6 true
7 true
8 true
9 true
true
"1 point 0 0 POINT(1.01 2.02) POINT 4326 "
"2 point 1 1 POINT(1.01 2.02) POINT 4326 "
"3 point 2 2 POINT(1.01 2.02) POINT 4326 "
"4 point 3 3 POINT(1.01 2.02) POINT 4326 "
"5 point 4 4 POINT(1.01 2.02) POINT 4326 "
"6 point 5 5 POINT(1.01 2.02) POINT 4326 "
"7 point 6 6 POINT(1.01 2.02) POINT 4326 "
"8 point 7 7 POINT(1.01 2.02) POINT 4326 "
"9 point 8 8 POINT(1.01 2.02) POINT 4326 "
"10 point 9 9 POINT(1.01 2.02) POINT 4326 "
可以找到完整的示例here。
此代码已在linux Arch Linux 4.11.3-1-ARCH,Qt 5.8
上测试过答案 1 :(得分:2)
感谢eyllanesc,由于您的解释和建议,我找到了解决方案。
问题在于我编译的库(我还不知道为什么?),还有我下载的mod_spatialite。当我们在visual studio中使用它时,最后一个需要替换diag(p)[1]
,因为它会导致崩溃。
我的问题在这里,我使用的那个不是好的,并且导致了libstdc++_64-6.dll
,所以我下载了The specified procedure could not be found
并且我使用了x86_64-5.3.0-release-win32-seh-rt_v4-rev0
(我更改了)使用libstdc++-6.dll
的{{1}})名称。我还用我之前编译的另一个更改了libstdc++_64-6.dll
。
然后我使用了以下解决方案之一:
解决方案1:
我之前使用过代码进行修改,因为libgcc_s_seh-1.dll
导致了崩溃,我也通过参数发送了db,因为它不像以前的代码那样工作。
所以我现在的工作代码是:
libxml2-2.dll
还有一件重要的事情,就是我重新编译了qsqlite驱动程序以删除SQLITE_OMIT_LOAD_EXTENSION
解决方案2 :(直接解决方案)
打开&#34; Qt5.9.0 \ 5.9 \ Src \ qtbase \ src \ 3rdparty \ sqlite \&#34;文件夹并更改sqlite3.c如下:
评论或删除ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
添加:
#include <QtCore/QCoreApplication>
#include <QtSql/QtSql>
#include "sqlite3.h"
int enable_spatialite(QSqlDatabase db) {
QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0)
{
sqlite3_initialize();
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) {
sqlite3_enable_load_extension(db_handle, 1);
QSqlQueryModel sql;
sql.setQuery("SELECT load_extension('mod_spatialite')", db);
if (sql.lastError().isValid())
{
qDebug() << "Error: cannot load the Spatialite extension (" << sql.lastError().text()<<")";
return 0;
}
else return 1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "Project");
db.setDatabaseName("dbTest.db");
if (!db.open())
{
qDebug()<<"Critical"<< "Impossible to intialize the database !\n" + db.lastError().text();
return 0;
}
qDebug()<<enable_spatialite(db);
//just a test
QSqlQueryModel sql;
sql.setQuery("SELECT HEX(GeomFromText('POINT(10 20)'));", db);
qDebug() << sql.index(0, 0).data().toString();
return a.exec();
}
#define SQLITE_OMIT_LOAD_EXTENSION 1
功能并将#ifndef SQLITE_ENABLE_LOAD_EXTENSION
#define SQLITE_ENABLE_LOAD_EXTENSION 1
#endif
添加到static int openDatabase( const char *zFilename,sqlite3 **ppDb, unsigned int flags, const char *zVfs)
,如下所示:| SQLITE_LoadExtFunc
使用编译器(在我的例子中为nmake)在Qt5.9.0 \ 5.9 \ Src \ qtbase \ src \ plugins \ sqldrivers \ sqlite \ sqlite.pro
调用以下代码加载您的spaceite:
SQLITE_ENABLE_LOAD_EXTENSION