我在使用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库以便于移植)
答案 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));