如何使用本机sqlite库而不是QSql从sqlite插入和检索QString

时间:2015-02-06 13:39:22

标签: c++ qt sqlite

我在使用Qt的C ++项目中使用本机sqlite库(amalgamation 1file),我创建了一个简单的包装器,但是我在插入和选择长UTF-8文本时遇到了麻烦。

我使用此代码插入数据:

SqlResult *result = new SqlResult();
sqlite3_stmt *statement;
int current_parameter = 1;
this->LastStatement = sql;
int x = sqlite3_prepare_v2(this->db, sql.toUtf8().constData(), sql.length() + 1, &statement, NULL);
foreach (QString text, parameter)
{
    ////////////// here is problem ///////////////
    x = sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC);
    if (!this->Evaluate(x))
    ...

正如您所看到的,我正在使用SQL变量?,其中的文本绑定使用函数sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC),该函数应取值QString文本并将其转换为utf8 const char *。但是我在数据库中获得的文本部分是垃圾(当我使用一些sqlite浏览器应用程序时,我可以看到一些奇怪的符号)。

这是我用来转换const char *

sqlite3_column_text代码
static QString StringFromUnsignedChar( const unsigned char *str )
{
    std::string temp = std::string(reinterpret_cast<const char*>(str));
    return QString::fromUtf8(temp.c_str());
}

我得到的文字与我在sqlite manager中看到的“垃圾”相同。所以我想问题是在插入期间,选择可能有效。怎么了?如何将sqlite3_bind_text功能正确地用于QString

P.S。我宁愿不使用Qt自己的sqlite sqlite实现,主要是为了兼容性目的(在linux上我使用Qt4和Windows Qt5,我想在各处都有相同的sqlite库以便于移植)

1 个答案:

答案 0 :(得分:2)

在我的情况下问题是我自己的代码,用法是正确的但实现不是。这一行:

sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC);

需要

sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_TRANSIENT);

正如文件所述:

  

BLOB和字符串绑定接口的第五个参数是a   用于在SQLite之后处理BLOB或字符串的析构函数   完成它。析构函数被调用以处理BLOB或   字符串,即使对绑定API的调用失败。如果第五个参数是   特殊值SQLITE_STATIC,然后SQLite假定   信息在静态的非托管空间中,不需要   释放。如果第五个参数的值为SQLITE_TRANSIENT,那么   SQLite在之前立即制作了自己的数据私有副本   sqlite3_bind _ *()例程返回。

因此使用QString和sqlite使用其原生API的正确方法是:

// Create and evaluate a statement
sqlite3_stmt *statement;
// Note: return value should be checked for error here
sqlite3_prepare_v2(pointer_to_sqlite_db, sql.toUtf8().constData(), sql.length() + 1, &statement, NULL);
// Bind QString to SQL statement - it must be transient so that sql text persist even after function call is over and data is destructed
sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_TRANSIENT);
// step
sqlite3_step(statement);
// clean up
sqlite3_finalize(statement);

如何将const char *转换回QString

static QString StringFromUnsignedChar( const unsigned char *str )
{
    return QString::fromUtf8(reinterpret_cast<const char*>(str));
}

QString result = StringFromUnsignedChar(sqlite3_column_text(statement, column));