我正在尝试减少对象中的重复sqlite代码。为此,我想要一个具有sqlite交互的方法,只返回一个sqlite3_stmt。我的问题是sqlite3_stmt指针始终为null。我的问题是,我做错了什么还是不能用sqlite做的?
用法:
SqliteIO sqldb;
string GET_CONFIG = "select* from config; ";
sqlite3_stmt *statement;
assert(sqldb.sqlForResults(GET_CONFIG, statement));
assert(statement != NULL); //this fails
方法:
bool SqliteIO::sqlForResults(string pSql, sqlite3_stmt *statement ){
bool lbRetVal=false;
if(mDB == NULL){
cerr << "No database to query";
Logger::error("SqlliteIO::getAllScheuled() null database handle");
} else {
sqlite3_busy_timeout(mDB, 2000);
if(sqlite3_prepare_v2(mDB, pSql.c_str(), -1, &statement, 0) == SQLITE_OK) {
lbRetVal = true;
}
string error = sqlite3_errmsg(mDB);
if(error != "not an error"){
cerr << pSql << " " << error << endl;
Logger::error("SqlliteIO::sqlForResults() "+ error + " " +pSql );
}
}
return lbRetVal;
答案 0 :(得分:1)
sqlite3_stmt *statement; // this never gets initialized
assert(sqldb.sqlForResults(GET_CONFIG, statement));
assert(statement != NULL); //this fails
该代码块中的语句变量永远不会被初始化(您将它的副本传递给sqlForResults())。
坦率地说,你很幸运断言失败了,因为语句可能有任何垃圾值(我猜测变量在编译器的调试模式下是零初始化的)答案 1 :(得分:0)
SqliteIO :: sqlForResults()的statement参数需要具有sqlite3_stmt**
类型,而不是sqlite3_stmt*
。所以呼叫网站现在看起来像:
SqliteIO sqldb;
string GET_CONFIG = "select* from config; ";
sqlite3_stmt *statement = NULL;
assert(sqldb.sqlForResults(GET_CONFIG, &statement));
如果在语句之前没有引用/ address-of运算符&
(就像在原始问题中那样),那么您将statement
的值传递给{{1} },在这种情况下为sqlForResults
或0。 NULL
中的相关更改为:
sqlForResults
参数列表现在接受bool SqliteIO::sqlForResults(string pSql, sqlite3_stmt **statement ){
bool lbRetVal=false;
if(mDB == NULL){
// ...
} else {
// ...
if(sqlite3_prepare_v2(mDB, pSql.c_str(), -1, statement, 0) == SQLITE_OK) {
// ...
}
// ...
}
return lbRetVal;
arg,我们将其直接传递给sqlite_stmt**
。在原始问题中,sqlite3_prepare_v2
已将sqlForResults
传递给&statement
- 这是此sqlite3_prepare_v2
方法调用的statement
参数的地址 - 这不是什么你想要的。
我知道这是一个老问题,但我希望这会有所帮助。
编辑:为了清楚起见并从sqlForResults中躲避更多代码