Sqlite   发布时间:2022-05-22  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了SQLite3简单C++包装类源码示例大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
一个比较好的sqlite3 C++ wrapper包装类的通常思路是这样的
数据库连接类,包含连接池和sqlite3*,负责与@R_450_9345@的连接问题;
一些create table,insert,update,delete等操作都在这里定义,直接使用sqlite3_exec()函数进行就可以,对它的回调函数可以定义为空。
如果对数据库执行查询操作,则需要一个单独的操作类, CQuery它调用更具体的接口,先获取结果集,再逐行解析字段名和值,最后删除结果集
这里的重点是,首次将列字段名保存下来,再每次获取一行记录,将字段值记录到一个向量中,使用 sqlite3_column_text()将每个字段统一存为一个字符串,在需要处理时再分别转换为具体的数据类型。
当进行下一行解析时,先要将原来的数据清除,在存放当前行的数据。注意存放的是const char*,这和
const unsigned char *sqlite3_column_text(sqlite3_stmt*,int iCol);
定义是相符合的。
上面是两种完全不同的处理方法。
目前我通过实践,摸透了两个例子
https://github.com/wrmsr/sqliteDB

这个例子我比较欣赏,准备在它的基础上编写一个简单的sqlite C++ wrapper类。参见下面的代码:

//
//

#ifndef __sqlite3_WRAPPER_H__
#define __sqlite3_WRAPPER_H__

#include <map>
#include <String>
#include <sstream>
#include <vector>
#include <memory>

#include <stdlib.h>
#include <stdio.h>
#include <sqlite3.h>

class CException: std::exception {
    public:
        CException(int _rC): rc(_rC) {
            Stringstream ss;
            ss << rc;
            msg = ss.str();
        }
        CException(const char* _msg): msg(_msg) {}
        ~CException() throw(){}

        int getCode() const { return rc; }
        const char* getmessage() const { return msg.c_str(); }

    protected:
        int rc;
        String msg;
};


class Csqlite3;
class CQuery{
    public:
        CQuery(Csqlite3& _db,const char* sql);
        ~CQuery();

        Csqlite3& getDB() const { return db; }
        size_t  getPos() const { return pos; }
        size_t getNumCols() const { return cols.size(); }

        //最核心的函数,会被反复调用,每次从结果集中读取出一行(IE.一条记录),存放在vals向量中
        bool read_one_row();

        int getColIDx(const char* col) const;
        const char* getVal(size_t IDX) const;
        const char* getVal(const char* col) const;
        const char* operator[](int idX) const;
        const char* operator[](const char* col) const;

        int getVals(map<String,String>& pair) const;

    private:
        CQuery(const cquery& src);

        Csqlite3& db;  //database connection object
        sqlite3_stmt* stmt; //prepared statement object

        size_t pos; //用于区分出列名而非记录
        vector<const char*> cols; //列名组成的向量
        vector<const char*> vals; //每次只保存一条记录(也就是一行)的数据,下次处理时会首先清空再存放下一条记录
        map<String,int> colIDxs; //列名和索引对应的记录
};

class Csqlite3{
    public:
        Csqlite3(const char* path,int flags = @R_467_5607@OPEN_READWRITE | @R_467_5607@OPEN_CREATE,const char* zVfs = null);
        ~Csqlite3();

        sqlite3* getConn() const { return conn; }

        typedef int (*CallBACk)(void*,int,char**,char**);
        voID exec(const char* sql,CallBACk cb = NulL,void* arg = null);
        String execStr(const char* sql);
        long long execInt(const char* sql);
        unsigned long long execUInt(const char* sql);
        std::auto_ptr<CQuery> execCQuery(const char* sql);
        int execOne(const char* sql,map<String,String>& pair);

    private:
        sqlite3* conn;
};

#endif
下面是源文件

#include "sqlite3_wrapper.h"

CQuery::CQuery(Csqlite3& _db,const char* sql): db(_db),stmt(NulL),pos(0) {
    int rc = sqlite3_prepare_v2(db.getConn(),sql,-1,&stmt,null);
    if(rC)
        throw CException(rc);
}

CQuery::~CQuery(){
    if(stmt)
        sqlite3_finalize(stmt);
}

//该函数会反复调用,每次只保存一行的值
bool CQuery::read_one_row() {
  int rc = sqlite3_step(stmt);
  if(rc != @R_467_5607@ROW && rc != @R_467_5607@DONE)
    throw CException(rc);

  //仅在开始获取列名向量,以后直接跳过
  if(pos++ < 1) {
    size_t numCols = sqlite3_column_count(stmt);

    cols.reserve(numCols);
    vals.reserve(numCols);

    for(size_t i = 0; i < numCols; i++) {
      const char* col = sqlite3_column_name(stmt,i);

      cols.push_BACk(col);
      colIDxs[std::string(col)] = i;
    }
  }

  //如果没有下一条记录就返回,这说明我们已经读完了
  if(rc == @R_467_5607@DONE)
    return false;

  //还有下一条记录可以读,先清空存放该记录值的向量
  vals.clear();

  for(size_t i = 0; i < getNumCols(); i++) {
    const char* val = (const char*)sqlite3_column_text(stmt,i);

    vals.push_BACk(val);
  }

  return true;
}

//找出列名在向量中对应的索引值
int CQuery::getColIDx(const char* col) const {
  std::map<std::string,int>::const_iterator i = colIDxs.find(std::string(col));

  if(i != colIDxs.end())
    return (*i).second;

  return -1;
}

const char* CQuery::getVal(size_t IDX) const {
  if(IDx < 0 || IDx > getNumCols())
    return NulL;

  return vals[IDx];
}

const char* CQuery::getVal(const char* col) const {
  return getVal(getColIDx(col));
}

const char* CQuery::operator[](int idX) const {
  return getVal(IDX);
}

const char* CQuery::operator[](const char* col) const {
  return getVal(col);
}

int CQuery::getVals(map<String,String>& pair) const {
  for(size_t i = 0; i < getNumCols(); i++)
     pair[std::string(cols[i])] = getVal(i);

  return 0;
}



Csqlite3::Csqlite3(const char* path,int flags,const char* zVfs): conn(NulL) {
    int rc = sqlite3_open_v2(path,&conn,flags,zVfs);
    if(rC)
        throw CException(rc);
}

Csqlite3::~Csqlite3(){
    if(conn)
        sqlite3_close(conn);
}

voID Csqlite3::exec(const char* sql,CallBACk cb,void* arg) {
    char* error = NulL;
    int rc = sqlite3_exec(conn,cb,arg,&error);
    if(error) {
      CException ex(error);
      sqlite3_free(error);
      throw ex;
    }
    if(rC)
      throw CException(rc);
}

String Csqlite3::execStr(const char* sql) {
    std::string ret;

    CQuery c(*this,sql);

    if(c.read_one_row() && c.getNumCols() > 0)
      ret = c[0];

    return ret;
}

long long Csqlite3::execInt(const char* sql) {
    CQuery c(*this,sql);

    if(!c.read_one_row() || c.getNumCols() < 1)
      return -1;

    return strtoll(c[0],NulL,10);
}

unsigned long long Csqlite3::execUInt(const char* sql) {
     CQuery c(*this,sql);

    if(!c.read_one_row() || c.getNumCols() < 1)
      return -1;

    return strtoull(c[0],10);
}

std::auto_ptr<CQuery> Csqlite3::execCQuery(const char* sql) {
    return std::auto_ptr<CQuery>(new CQuery(*this,sql));
}

//成功返回0,失败返回1
int Csqlite3::execOne(const char* sql,String>& pair) {
    CQuery c(*this,sql);

    if(!c.read_one_row()) {
      return 1;
    }

    return c.getVals(pair);
}
下面是测试文件
//g++ -g test_sqlite3.cpp sqlite3_wrapper.cpp -o test_sqlite3 -lsqlite3
//
#include <iostream>
#include <unistd.h>

#include "sqlite3_wrapper.h"

int main() {
  try {
    unlink("test.db");
    Csqlite3 db("test.db");

    db.exec("create table test(ID int priMary key,value int);");

    for(int i = 0; i < 100; i++) {
      std::stringstream sql;
      sql << "insert into test values(" << i << "," << i * 2 << ");";
      db.exec(sql.str().c_str());
    }

    std::cout << "Max: " << db.execInt("SELEct max(value) from test;") << std::endl;

    CQuery query(db,"SELEct * FROM test order by value desc;");
    while(query.read_one_row())
      std::cout << querY["ID"] << " = " << querY["value"] << std::endl;

    //some arbitrary op to show that you can easily get the sqlite3 object and do whatever to it directly
    sqlite3_interrupt(db.getConn());
  }
  catch(CException eX) {
    std::cout << "sqlite exception: " << ex.getmessage() << std::endl;
  }

  return 0;
}
注意:
需要先安装sqlite3动态库,在Ubuntu 14.04 64bit上输入如下命令
sudo apt-get install sqlite3 libsqlite3-dev
在CentOS上面安装
yum -y install sqlite-devel
下面是运行截图

文献
[1]. https://github.com/wrmsr/sqliteDB

大佬总结

以上是大佬教程为你收集整理的SQLite3简单C++包装类源码示例全部内容,希望文章能够帮你解决SQLite3简单C++包装类源码示例所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。