zoukankan      html  css  js  c++  java
  • 自己整理的一个访问SQLite3数据库的C++类

    原文地址:自己整理的一个访问SQLite3数据库的C++类作者:vigra
    近日,对SQLite3的使用进行了研究。真不愧是优秀的嵌入数据库,API接口也极其简捷。基本上只要使用以下几个接口就能完成数据库的操作:
     
    sqlite3_open()
    sqlite3_prepare()
    sqlite3_step()
    sqlite3_column()
    sqlite3_finalize()
    sqlite3_close()
    但是,API方式不太符合数据库开发的习惯。我们是C++程序员,封装一下吧。
     
    多网上找到了一份Rob Groves在2004写的“C++ wrapper around the SQLite3 embedded database library.”基本可用,但太复杂了,不利于学习。
     
    所以,我对其进行了简化,只保留了3个类:
     
    TSQLite3Exception 用于异常处理
     
    TSQLite3Query 用于处理带返回数据的SQL语句
     
    TSQLite3DB 用于对数据库本身的操作
     
    经过这样的简化,在保证基本数据库操作的前提下,代码行数变成的原来的1/3,简捷、易用,推荐给大家。
     
    还附上一些应用示例代码,方便大家上手。我测试用的SQLite3版本是3.7.3
     
    //---------------------------------------------------------------------------
    int __fastcall TDataModule1::UpdateFounds(String sCode, String sName, String sDate, String sValue)
    {
    char SqlStr[500];
    TSQLite3DB *db;
    // open the database file
    db = new TSQLite3DB();
     
    try
    {
    try
    {
    db->open("data.s3db");
    //更新记录
    sprintf(SqlStr, "UPDATE FOUNDS SET FOUND_NAME='%s', DATE='%s', VALUE='%s' WHERE CODE='%s'",
    AnsiString(sName).c_str(), AnsiString(sDate).c_str(), AnsiString(sValue).c_str(), AnsiString(sCode).c_str());
    db->execDML(SqlStr);
    }
    catch(const TSQLite3Exception &e)
    {
    ShowMessage(String("更新记录失败!") + e.errorMessage());
    }
    catch(...)
    {
    return -1;
    }
     
    return 0;
    }
     
    __finally
    {
    delete db;
    }
    }
    //---------------------------------------------------------------------------
    int __fastcall TDataModule1::FillListViewFirst(TListView *ListView)
    {
    TListItem *pItem = NULL;
    TSQLite3DB *db;
    // open the database file
    db = new TSQLite3DB();
     
    try
    {
    try
    {
    db->open("data.s3db");
    TSQLite3Query Results = db->execQuery("SELECT * FROM FOUNDS ORDER BY CODE");
    ListView->Items->Clear();
     
    for( ; !Results.eof(); Results.nextRow())
    {
    //如果不需要显示,则跳过
    if(strncmp("是", Results.getStringField(4, ""), 2) == 0)
    {
    pItem = ListView->Items->Add();
    //第1列
    pItem->Caption = String(Results.getStringField(0, ""));
    //第2列
    pItem->SubItems->Add(Results.getStringField(1, ""));
    //第3列
    pItem->SubItems->Add(Results.getStringField(2, ""));
    //第4列
    pItem->SubItems->Add(Results.getStringField(3, ""));
    }
    }
    }
    catch(const TSQLite3Exception &e)
    {
    ShowMessage(String("查询记录失败!") + e.errorMessage());
    }
    catch(...)
    {
    return -1;
    }
     
    return 0;
    }
     
    __finally
    {
    delete db;
    }
    }
     
     
     
     
    //---------------------------------------------------------------------------
     
    #include <string.h>
    #include <time.h>
    #pragma hdrstop
     
    #include "SQLite3_unit.h"
    #pragma package(smart_init)
     
    // Named constant for passing to TSQLite3Exception when passing it a string
    // that cannot be deleted.
    static const bool DONT_DELETE_MSG = false;
    // Timeout values on busy or lock conditions
    static const int SQLTM_TIMEOUT = 6000; // 6 seconds
     
    ////////////////////////////////////////////////////////////////////////////////
     
    TSQLite3Exception::TSQLite3Exception(const int nErrCode,
    char *szErrMess,
    bool bDeleteMsg) :
    mnErrCode(nErrCode)
    {
    mpszErrMess = sqlite3_mprintf("%s[%d]: %s",
    errorCodeAsString(nErrCode),
    nErrCode,
    szErrMess ? szErrMess : "");
     
    if(bDeleteMsg && szErrMess)
    {
    sqlite3_free(szErrMess);
    }
    }
    //---------------------------------------------------------------------------
     
     
    TSQLite3Exception::TSQLite3Exception(const TSQLite3Exception &e) :
    mnErrCode(e.mnErrCode)
    {
    mpszErrMess = 0;
     
    if(e.mpszErrMess)
    {
    mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess);
    }
    }
    //---------------------------------------------------------------------------
     
     
    const char *TSQLite3Exception::errorCodeAsString(int nErrCode)
    {
    switch(nErrCode)
    {
    case SQLITE_OK :
    return "Successful result";
    case SQLITE_ERROR :
    return "SQL error or missing database";
    case SQLITE_INTERNAL :
    return "Internal logic error in SQLite ";
    case SQLITE_PERM :
    return "Access permission denied";
    case SQLITE_ABORT :
    return "Callback routine requested an abort";
    case SQLITE_BUSY :
    return "The database file is locked";
    case SQLITE_LOCKED :
    return "A table in the database is locked";
    case SQLITE_NOMEM :
    return "A malloc() failed";
    case SQLITE_READONLY :
    return "Attempt to write a readonly database";
    case SQLITE_INTERRUPT :
    return "Operation terminated by sqlite3_interrupt()";
    case SQLITE_IOERR :
    return "Some kind of disk I/O error occurred ";
    case SQLITE_CORRUPT :
    return "The database disk image is malformed";
    case SQLITE_NOTFOUND :
    return "NOT USED. Table or record not found";
    case SQLITE_FULL :
    return "Insertion failed because database is full";
    case SQLITE_CANTOPEN :
    return "Unable to open the database file";
    case SQLITE_PROTOCOL :
    return "Database lock protocol error";
    case SQLITE_EMPTY :
    return "Database is empty";
    case SQLITE_SCHEMA :
    return "The database schema changed";
    case SQLITE_TOOBIG :
    return "String or BLOB exceeds size limit";
    case SQLITE_CONSTRAINT :
    return "Abort due to constraint violation";
    case SQLITE_MISMATCH :
    return "Data type mismatch";
    case SQLITE_MISUSE :
    return "Library used incorrectly";
    case SQLITE_NOLFS :
    return "Uses OS features not supported on host";
    case SQLITE_AUTH :
    return "Authorization denied";
    case SQLITE_FORMAT :
    return "Auxiliary database format error";
    case SQLITE_RANGE :
    return "2nd parameter to sqlite3_bind out of range";
    case SQLITE_NOTADB :
    return "File opened that is not a database file";
    case SQLITE_ROW :
    return "sqlite3_step() has another row ready";
    case SQLITE_DONE :
    return "sqlite3_step() has finished executing";
    case TSQLITE_ERROR :
    return "TSQLITE_ERROR";
    default:
    return "UNKNOWN_ERROR";
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Exception::~TSQLite3Exception()
    {
    if(mpszErrMess)
    {
    sqlite3_free(mpszErrMess);
    mpszErrMess = 0;
    }
    }
    ////////////////////////////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query()
    {
    mpDB = 0;
    mpVM = 0;
    mbEof = true;
    mnCols = 0;
    mbOwnVM = false;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query(const TSQLite3Query &rQuery)
    {
    mpDB = rQuery.mpDB;
    mpVM = rQuery.mpVM;
    // Only one object can own the VM
    const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
    mbEof = rQuery.mbEof;
    mnCols = rQuery.mnCols;
    mbOwnVM = rQuery.mbOwnVM;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query(sqlite3 *pDB,
    sqlite3_stmt *pVM,
    bool bEof,
    bool bOwnVM)
    {
    mpDB = pDB;
    mpVM = pVM;
    mbEof = bEof;
    mnCols = sqlite3_column_count(mpVM);
    mbOwnVM = bOwnVM;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::~TSQLite3Query()
    {
    try
    {
    finalize();
    }
    catch(...)
    {
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Query &TSQLite3Query::operator=(const TSQLite3Query &rQuery)
    {
    try
    {
    finalize();
    }
    catch(...)
    {
    }
     
    mpDB = rQuery.mpDB;
    mpVM = rQuery.mpVM;
    // Only one object can own the VM
    const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
    mbEof = rQuery.mbEof;
    mnCols = rQuery.mnCols;
    mbOwnVM = rQuery.mbOwnVM;
    return *this;
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::numFields()
    {
    checkVM();
    return mnCols;
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldValue(int nField)
    {
    checkVM();
     
    if(nField < 0 || nField > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldValue(const char *szField)
    {
    int nField = fieldIndex(szField);
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::getIntField(int nField, int nNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return nNullValue;
    }
    else
    {
    return sqlite3_column_int(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::getIntField(const char *szField, int nNullValue)
    {
    int nField = fieldIndex(szField);
    return getIntField(nField, nNullValue);
    }
    //---------------------------------------------------------------------------
    double TSQLite3Query::getFloatField(int nField, double fNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return fNullValue;
    }
    else
    {
    return sqlite3_column_double(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    double TSQLite3Query::getFloatField(const char *szField, double fNullValue)
    {
    int nField = fieldIndex(szField);
    return getFloatField(nField, fNullValue);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::getStringField(int nField, const char *szNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return szNullValue;
    }
    else
    {
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::getStringField(const char *szField, const char *szNullValue)
    {
    int nField = fieldIndex(szField);
    return getStringField(nField, szNullValue);
    }
    //---------------------------------------------------------------------------
    const unsigned char *TSQLite3Query::getBlobField(int nField, int &nLen)
    {
    checkVM();
     
    if(nField < 0 || nField > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    nLen = sqlite3_column_bytes(mpVM, nField);
    return (const unsigned char *)sqlite3_column_blob(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    const unsigned char *TSQLite3Query::getBlobField(const char *szField, int &nLen)
    {
    int nField = fieldIndex(szField);
    return getBlobField(nField, nLen);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::fieldIsNull(int nField)
    {
    return (fieldDataType(nField) == SQLITE_NULL);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::fieldIsNull(const char *szField)
    {
    int nField = fieldIndex(szField);
    return (fieldDataType(nField) == SQLITE_NULL);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::fieldIndex(const char *szField)
    {
    checkVM();
     
    if(szField)
    {
    for(int nField = 0; nField < mnCols; nField++)
    {
    const char *szTemp = sqlite3_column_name(mpVM, nField);
     
    if(strcmp(szField, szTemp) == 0)
    {
    return nField;
    }
    }
    }
     
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field name requested",
    DONT_DELETE_MSG);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldName(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_name(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldDeclType(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_decltype(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::fieldDataType(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_type(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::eof()
    {
    checkVM();
    return mbEof;
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::nextRow()
    {
    checkVM();
    int nRet = sqlite3_step(mpVM);
     
    if(nRet == SQLITE_DONE)
    {
    // no rows
    mbEof = true;
    }
    else if(nRet == SQLITE_ROW)
    {
    // more rows, nothing to do
    }
    else
    {
    nRet = sqlite3_reset(mpVM);
    mpVM = 0;
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet,
    (char *)szError,
    DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::finalize()
    {
    if(mpVM && mbOwnVM)
    {
    int nRet = sqlite3_finalize(mpVM);
    mpVM = 0;
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
    }
    else if(mpVM && !mbOwnVM)
    {
    sqlite3_reset(mpVM);
    }
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::checkVM()
    {
    if(mpVM == 0)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Null Virtual Machine pointer",
    DONT_DELETE_MSG);
    }
    }
    ////////////////////////////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------
    TSQLite3DB::TSQLite3DB()
    {
    mpDB = 0;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    }
    //---------------------------------------------------------------------------
    TSQLite3DB::TSQLite3DB(const TSQLite3DB &db)
    {
    mpDB = db.mpDB;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    }
    //---------------------------------------------------------------------------
    TSQLite3DB::~TSQLite3DB()
    {
    close();
    }
    //---------------------------------------------------------------------------
    TSQLite3DB &TSQLite3DB::operator=(const TSQLite3DB &db)
    {
    mpDB = db.mpDB;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    return *this;
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::open(const char *szFile)
    {
    int nRet = sqlite3_open(szFile, &mpDB);
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
     
    setBusyTimeout(mnBusyTimeoutMs);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::close()
    {
    if(mpDB)
    {
    int Result = sqlite3_close(mpDB);
     
    if(Result != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(Result, (char *)szError, DONT_DELETE_MSG);
    }
     
    mpDB = 0;
    }
    }
    //---------------------------------------------------------------------------
    int TSQLite3DB::execDML(const char *szSQL)
    {
    checkDB();
    char *szError = 0;
    int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError);
     
    if(nRet == SQLITE_OK)
    {
    return sqlite3_changes(mpDB);
    }
    else
    {
    throw TSQLite3Exception(nRet, szError);
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Query TSQLite3DB::execQuery(const char *szSQL)
    {
    checkDB();
    sqlite3_stmt *pVM = compile(szSQL);
    int nRet = sqlite3_step(pVM);
     
    if(nRet == SQLITE_DONE)
    {
    // no rows
    return TSQLite3Query(mpDB, pVM, true);
    }
    else if(nRet == SQLITE_ROW)
    {
    // at least 1 row
    return TSQLite3Query(mpDB, pVM, false);
    }
    else
    {
    nRet = sqlite3_finalize(pVM);
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    sqlite_int64 TSQLite3DB::lastRowId()
    {
    return sqlite3_last_insert_rowid(mpDB);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::setBusyTimeout(int nMillisecs)
    {
    mnBusyTimeoutMs = nMillisecs;
    sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::checkDB()
    {
    if(!mpDB)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Database not open",
    DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    sqlite3_stmt *TSQLite3DB::compile(const char *szSQL)
    {
    checkDB();
    const char *szTail = 0;
    sqlite3_stmt *pVM;
    int nRet;
    nRet = sqlite3_prepare_v2(mpDB, szSQL, -1, &pVM, &szTail);
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet,
    (char *)szError,
    DONT_DELETE_MSG);
    }
     
    return pVM;
    }
    //---------------------------------------------------------------------------
     
     
    //---------------------------------------------------------------------------
     
    #ifndef SQLite3_unitH
    #define SQLite3_unitH
     
    #include "sqlite3.h"
     
    #define TSQLITE_ERROR 1000
     
    //---------------------------------------------------------------------------
    class TSQLite3Exception
    {
    public:
     
    TSQLite3Exception(const int nErrCode,
    char *szErrMess,
    bool bDeleteMsg = true);
     
    TSQLite3Exception(const TSQLite3Exception &e);
     
    virtual ~TSQLite3Exception();
     
    int errorCode() const
    {
    return mnErrCode;
    }
     
    char *errorMessage() const
    {
    return mpszErrMess;
    }
     
    static const char *errorCodeAsString(int nErrCode);
     
    private:
     
    int mnErrCode;
    char *mpszErrMess;
    };
    //---------------------------------------------------------------------------
    class TSQLite3Query
    {
    public:
     
    TSQLite3Query();
     
    TSQLite3Query(const TSQLite3Query &rQuery);
     
    TSQLite3Query(sqlite3 *pDB,
    sqlite3_stmt *pVM,
    bool bEof,
    bool bOwnVM = true);
     
    TSQLite3Query &operator=(const TSQLite3Query &rQuery);
     
    virtual ~TSQLite3Query();
     
    int numFields();
     
    int fieldIndex(const char *szField);
    const char *fieldName(int nCol);
     
    const char *fieldDeclType(int nCol);
    int fieldDataType(int nCol);
     
    const char *fieldValue(int nField);
    const char *fieldValue(const char *szField);
     
    int getIntField(int nField, int nNullValue = 0);
    int getIntField(const char *szField, int nNullValue = 0);
     
    double getFloatField(int nField, double fNullValue = 0.0);
    double getFloatField(const char *szField, double fNullValue = 0.0);
     
    const char *getStringField(int nField, const char *szNullValue = "");
    const char *getStringField(const char *szField, const char *szNullValue = "");
     
    const unsigned char *getBlobField(int nField, int &nLen);
    const unsigned char *getBlobField(const char *szField, int &nLen);
     
    bool fieldIsNull(int nField);
    bool fieldIsNull(const char *szField);
     
    bool eof();
    void nextRow();
    void finalize();
     
    private:
     
    void checkVM();
     
    sqlite3 *mpDB;
    sqlite3_stmt *mpVM;
    bool mbEof;
    int mnCols;
    bool mbOwnVM;
    };
    //---------------------------------------------------------------------------
    class TSQLite3DB
    {
    public:
    TSQLite3DB();
    virtual ~TSQLite3DB();
    void open(const char *szFile);
    void close();
    int execDML(const char *szSQL);
    TSQLite3Query execQuery(const char *szSQL);
    void setBusyTimeout(int nMillisecs);
    sqlite_int64 lastRowId();
     
    void interrupt()
    {
    sqlite3_interrupt(mpDB);
    }
     
    bool isAutoCommit()
    {
    return sqlite3_get_autocommit(mpDB) != 0;
    }
     
    static const char *SQLiteVersion()
    {
    return SQLITE_VERSION;
    }
     
    sqlite3 *getDB()
    {
    return mpDB;
    }
    private:
     
    TSQLite3DB(const TSQLite3DB &db);
    TSQLite3DB &operator=(const TSQLite3DB &db);
     
    sqlite3_stmt *compile(const char *szSQL);
     
    void checkDB();
     
    sqlite3 *mpDB;
    int mnBusyTimeoutMs;
    };
     
    //---------------------------------------------------------------------------
     
    #endif
     
     
     
  • 相关阅读:
    gain 基尼系数
    luogu P5826 【模板】子序列自动机 主席树 vector 二分
    牛客挑战赛39 树与异或 离线 树上莫队 树状数组 约数
    4.22 省选模拟赛 三元组 manacher 回文自动机
    4.22 省选模拟赛 最优价值 网络流 最大权闭合子图
    4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列
    luogu P4008 [NOI2003]文本编辑器 splay 块状链表
    牛客挑战赛39 密码系统 后缀数组
    luogu P1526 [NOI2003]智破连环阵 搜索+最大匹配+剪枝
    luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
  • 原文地址:https://www.cnblogs.com/blogpro/p/11426881.html
Copyright © 2011-2022 走看看