sqlite3,c ++连接,runnning查询,sqlite3_prepare_v2()

时间:2016-04-28 04:00:41

标签: c++ sqlite

我遇到的情况是我们与sqlite3的连接没有通过。这是我的队友代码,但他离开了团队,现在我正在尝试解决代码中的问题,但我很丢失。程序编译,我只能在QtCreator中找到调试工具的问题位置。调试器工具将我带到sqlite_prepare_v2来解决问题。

调试器输出是:(我发布这个因为它可能有用)

        nByte   84  size_t
        query   "SELECT username,password FROM users WHERE username='dilsizk' AND password='12345678'"  std::string
        return_matrix   <not accessible>    std::vector<std::vector<std::string>>
        return_value    32745   int
        this    @0x7fe90ab23f5f DBHandler
            columns_    -1282717696 int
            db_connection_  0x740000800003f7da  sqlite3 * *
            log @0x7fe90ab23f5f Log
                count   -1064971727 int
            query_  0x401f0fc35bd08908  sqlite3_stmt * *
            return_matrix_  0xc748eb7501046e83  std::vector<std::vector<std::string>> *
        unusedSQL   "12345678"  char *

该方法的代码是:

//query must be nul-terminated (ending in \0)
//if an error code is returned, method returns what it has processed to that point
std::vector<std::vector<std::string>>* DBHandler::runQuery(std::string query) {
    //get byte size of query
    size_t nByte = std::strlen(query.c_str());
    //log
    log << "DBHandler: Query size is " + std::to_string((int)nByte) +" bytes";
    //make junk variable for potential unused sql
    const char **unusedSQL;
    //prepare the statement
    sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,unusedSQL);
    //log
    log << "DBHandler: Query formatted into prepared statement";
    //perform first step, grab return value
    int return_value = sqlite3_step(*query_);
    //log
    log << "DBHandler: First evaluation step completed";
    //check if done, and if it is because of an error or that there is only 1 row
    if(return_value != SQLITE_ROW) {
        //log
        log << "DBHandler: Query returns only 1 row";
        if(return_value != SQLITE_DONE) {
            //log
            log << "DBHandler: Error handling query, code 1";
            return (new std::vector<std::vector<std::string>>);
        }
    }

该方法还有更多内容但我并不想发布整个内容,因为程序无法进入后面的步骤

sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,unusedSQL);

另外,让我为变量提供dbhandler.h的头文件。

#include <algorithm>
#include <sqlite3.h>
#include <vector>
#include <cstring>
#include "log.h"

#include <iostream>

/* Class to handle interaction with the local test database in the /db_tools directory.  Run ./newDB.sh in that directory prior to use. */
class DBHandler {

public:
    /* Constructor to create DBHandler object. */
    /*!
     * This object should ALWAYS be destroyed by its destructor when use is done.  The constructor only opens a connection to the local database.
     */
    DBHandler();
    /* Destructor to prevent memory leaks from this object. */
    /*!
     * Important that this is called, as it is otherwise vulnerable to causing multiple memory leaks.
     */
    ~DBHandler();
    /* Runs a query to the database and returns the output in a formatted vector. */
    /*!
     * This method formats the query, passed as a string, into a prepared statement to be processed.
     * \param query The query to the database. Must be nul-terminated (ending in \0) with no whitespace between the end of the query and the zero-terminator.
     * \return Returns a vector, where each index holds a vector per column, whose 0 index is the column name and all following indices are entries in order of their row.
     */
    std::vector<std::vector<std::string>>* runQuery(std::string query);

private:
    Log log;
    sqlite3** db_connection_;   /** Database connection object. **/
    sqlite3_stmt** query_;  /** Prepared statement object. **/
    int columns_;   /** Number of columns in the prepared statement after 1 step. **/
    std::vector<std::vector<std::string>>* return_matrix_;  /** Pointer to the matrix containing the evaluation of the prepared statement. **/
    /* Fills the return matrix with the names of the columns in the prepared statement. */
    void fillColName();
    /* Fills each column vector in the return matrix with the entries from the most recent step of the prepared statement. */
    void fillRow();
};

我很抱歉很多文字,但我认为这些输出在尝试解决问题时很有用。

如果我还能提供其他任何内容,或者我的问题遗失了,请告诉我。我是一个相当新的网站。只是试图能够提出格式正确的问题。

感谢。

1 个答案:

答案 0 :(得分:0)

根据documentationsqlite_prepare_v2的最后一个参数是接收SQL语句其余部分的指针的位置(因为prepare只编译查询中的第一个sql语句)。 / p>

您的代码将未初始化的变量作为该参数传递,因此当sqlite_prepare_v2尝试更改指针的值时,它会覆盖一些随机内存。

使用类似的东西:

const char *unusedSQL = NULL;
//prepare the statement
sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte,query_,&unusedSQL);

sqlite3_prepare_v2的第四个参数应该是指向将接收已编译语句的变量的指针,您的代码正在传递_query,这是您班级的成员变量,但是您还没有& #39; t显示了它是如何初始化的。我怀疑这与unusedSQL具有相同的问题。

您应该将声明更改为

sqlite3_stmt* query_

并传递指向query_参数的指针:

const char *unusedSQL = NULL;
query_ = NULL;
//prepare the statement
sqlite3_prepare_v2(*db_connection_,query.c_str(),(int)nByte, &query_, &unusedSQL);

另请注意:sqlite3_prepare_v2有一个返回值 - 您应该检查它是否一切正常。