先看一段使用方法:
另外,关于代码中的字符串动态加密,可使用x2lib中的MixPool类
SqliteDB.h
#ifndef _20266D69_1291_4C2A_8708_56BE03DB0B74
#define _20266D69_1291_4C2A_8708_56BE03DB0B74
#include "depends/incfile.h"
#include "../../../sqlite3xx/include/sqlite3xx.h"
#include "xCores.h"
数据库操作失败重试次数
//#define DBVALUENUBER 10
//
回调函数指针
//#define DB_Password _T("J5A4M6E819840917");
namespace x2lib
{
/*==============================================================================
* 描述:数据库操作简易封装类
=============================================================================*/
class SqliteDB
{
public:
SqliteDB();
virtual ~SqliteDB(void);
/*------------------------------------------------------------------------------
* 描 述:初始化数据库
* 参 数:[in] pszFile 数据库文件名,全路径,若为nullptr则创建内存数据库
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool Init(const char* pszFile, const char* pszPwd = nullptr);
/*------------------------------------------------------------------------------
* 描 述:反初始化数据库
* 参 数:
* 返回值:无
*----------------------------------------------------------------------------*/
void UnInit();
/*------------------------------------------------------------------------------
* 描 述:获取数据库文件
* 参 数:
* 返回值:返回nullptr表示为内存数据库
*----------------------------------------------------------------------------*/
const char* GetFile();
/*------------------------------------------------------------------------------
* 描 述:删除数据库表
* 参 数:[in] szTableName 数据库表名
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool DropTable(const char* pszTable);
/*------------------------------------------------------------------------------
* 描 述:清空数据库表
* 参 数:[in] szTableName 数据库表名
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool CleanTable(const char* pszTable);
/*------------------------------------------------------------------------------
* 描 述:判断数据库表是否存在
* 参 数:[in] szTableName 数据库表名
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool IsTableExist(const char* szTable);
/*------------------------------------------------------------------------------
* 描 述:判断数据库表指定字段是否存在
* 参 数:[in] szTableName 数据库表名
* 参 数:[in] szFiledName 数据库表字段名
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool IsFiledExist(const char* pszTable, char* pszFiled);
/*------------------------------------------------------------------------------
* 描 述:增加数据库表字段
* 参 数:[in] szTableName 数据库表名
* 参 数:[in] szFiledName 数据库表字段名
* 参 数:[in] szKeyType 数据库表字段类型
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool AppendFiled(const char* pszTable, const char* pszFiled, const char* pszKeyType);
/*------------------------------------------------------------------------------
* 描 述:执行一条sql语句
* 参 数:[in] szSql 语句
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool ExecuteSql(const char* pszSql, int(*callback)(void*, int, char**, char**) = nullptr, void* p = nullptr);
bool ExecuteSql(int(*callback)(void*, int, char**, char**), const char* pszSqlFmt, ...);
/*------------------------------------------------------------------------------
* 描 述:插入一条数据
* 参 数:[in] pszTable 目标表名
* 参 数:[in] ... 键值对序列,【键名】格式必须为“I:aaa”“F:bbb”“S:ccc”,
** 其中IFS固定,分别代表字段数据类型,aaa,bbb,ccc为任意字段名;
** 【键值】紧跟键名;最后一个参数必须为nullptr,即可变参为奇数个
** 如:InsertItem("UserInfo", "S:userName","小王", "I:age",18, nullptr)
* 返回值:TRUE/FALSE 是否执行成功
*----------------------------------------------------------------------------*/
bool InsertItem(const char *pszTable, ...);
bool insertItem(const char *pszTable, va_list va);
//准备废弃,推荐使用ExecuteSql(szCreateSql)创建
//bool CreateTable(const char* pszTable, ...);
// callback可以为nullptr
// coMethod = true 表示或, false表示与
int SelectItems(const char* pszTable, bool coMethod, int(*callback)(void*, int, char**, char**), ...);
int selectItems(const char* pszTable, bool coMethod, int(*callback)(void*, int, char**, char**), va_list va);
static bool Convert2(sqlite3xx::sqlite3db* pMemDB, const char* pszFile, bool toFile);
private:
char m_szFile[1024]; // 数据库文件名称( 路径)
sqlite3xx::sqlite3db * m_pDB;
xCores::Mutex m_mutex;
};
}
SqliteDB.cpp
// sqlite3.3.1后貌似是线程安全的
#include "SqliteDB.h"
using namespace sqlite3xx;
namespace x2lib
{
SqliteDB::SqliteDB()
{
m_pDB = nullptr;
memset(m_szFile, 0, sizeof(m_szFile));
}
SqliteDB::~SqliteDB(void)
{
}
bool SqliteDB::Init(const char* pszFile, const char* pszPwd)
{
if (m_pDB && (!pszFile || 0 == strcmp(m_szFile, pszFile)))
{
return true;
}
if (m_pDB)
{
sqlite3xx_close(m_pDB);
}
if (pszFile)
{
strcpy(m_szFile, pszFile);
}
else
{
strcpy(m_szFile, ":memory:");
}
int nRet = 0;
if (SQLITE_OK != sqlite3xx_open(m_szFile, &m_pDB))
{
m_pDB = nullptr;
return false;
}
#if 0 // 仅供SqlCipher使用
if (pszPwd && pszPwd[0] && SQLITE_OK != sqlite3xx_key(m_pDB, pszPwd, strlen(pszPwd)))
{
sqlite3xx_close(m_pDB);
m_pDB = nullptr;
return false;
}
#endif
return true;
}
void SqliteDB::UnInit()
{
if (m_pDB)
{
sqlite3xx_close(m_pDB);
m_pDB = nullptr;
}
}
const char* SqliteDB::GetFile()
{
return m_szFile[0] ? m_szFile : nullptr;
}
bool SqliteDB::InsertItem(const char *pszTable, ...)
{
va_list body;
va_start(body, pszTable);
bool isSucc = InsertItem(pszTable, body);
va_end(body);
return isSucc;
}
bool SqliteDB::insertItem(const char *pszTable, va_list va)
{
char szKeys[1024] = { 0 };
char* pszValues = (char*)calloc(1, 1024 * 8);
for (int i = 0;; ++i)
{
char* pkv = va_arg(va, char*);
if (pkv == nullptr) { break; }
sprintf(szKeys, "%s,%s", szKeys, &pkv[2]);
if (pkv[0] == 'I' || pkv[0] == 'B')
{
sprintf(pszValues, "%s,%d", pszValues, va_arg(va, int));
}
else if (pkv[0] == 'F')
{
sprintf(pszValues, "%s,%f", pszValues, va_arg(va, double));
}
else if (pkv[0] == 'S')
{
sprintf(pszValues, "%s,'%s'", pszValues, va_arg(va, char*));
}
}
char* pszSql = (char*)calloc(1, 1024 * 10);
if (pszValues[0] && szKeys[0])
{
sprintf(pszSql, "INSERT INTO %s (%s) VALUES (%s);", pszTable, &szKeys[1], &pszValues[1]);
}
else
{
sprintf(pszSql, "INSERT INTO %s DEFAULT VALUES;", pszTable);
}
bool isSucc = ExecuteSql(pszSql);
free(pszValues);
free(pszSql);
return isSucc;
}
//bool SqliteDB::CreateTable(const char* pszTable, ...)
//{
// char szCols[1024] = { 0 };
// va_list body;
// va_start(body, pszTable);
// for (int i = 0;; ++i)
// {
// char* pkv = va_arg(body, char*);
// if (pkv == nullptr) { break; }
// if (pkv[0] == 'I' || pkv[0] == 'B')
// {
// sprintf(szCols, "%s INT", szCols, &pkv[2]);
// }
// else if (pkv[0] == 'F')
// {
// sprintf(szCols, "%s REAL", szCols, &pkv[2]);
// }
// else if (pkv[0] == 'S')
// {
// sprintf(szCols, "%s TEXT", szCols, &pkv[2]);
// }
// }
// va_end(body);
// char szSql[1024] = { 0 };
// sprintf(szSql, "CREATE TABLE %s(%s);", pszTable, szCols);
// return ExecuteSql(szSql);
//}
int SqliteDB::SelectItems(const char* pszTable, bool coMethod, int(*callback)(void*, int, char**, char**), ...)
{
va_list va;
va_start(va, callback);
int nCount = SelectItems(pszTable, coMethod, callback, va);
va_end(va);
return nCount;
}
int SqliteDB::selectItems(const char* pszTable, bool coMethod, int(*callback)(void*, int, char**, char**), va_list va)
{
int nCount = 0;
if (!m_pDB) { return 0; }
const char* pszCoMethod = nullptr;
if (coMethod) { pszCoMethod = "OR "; }
else { pszCoMethod = "AND "; }
va_list body;
va_start(body, callback);
char* pszWhere = (char*)calloc(1, 1024 * 8);
for (int i = 0;; ++i)
{
char* pkv = va_arg(va, char*);
if (pkv == nullptr) { break; }
if (pkv[0] == 'I' || pkv[0] == 'B')
{
sprintf(pszWhere, "%s%s=%d ", pszWhere, &pkv[2], va_arg(va, int));
}
else if (pkv[0] == 'F')
{
sprintf(pszWhere, "%s%s=%f ", pszWhere, &pkv[2], va_arg(va, double));
}
else if (pkv[0] == 'S')
{
sprintf(pszWhere, "%s%s='%s' ", pszWhere, &pkv[2], va_arg(va, char*));
}
strcat(pszWhere, pszCoMethod);
}
va_end(body);
pszWhere[strlen(pszCoMethod) - strlen(pszCoMethod) + 1] = 0;
char szSql[1024] = { 0 };
sprintf(szSql, "SELECT COUNT(*) FROM %s WHERE %s;", pszTable, pszWhere);
m_mutex.Lock();
sqlite3xx_exec(m_pDB, szSql, [](void* pVoid, int, char**, char**)->int {
++(*(int*)pVoid);
return 0;
}, &nCount, nullptr);
m_mutex.Unlock();
if (callback)
{
sprintf(szSql, "SELECT * FROM %s WHERE %s;", pszTable, pszWhere);
char *pszErr = nullptr;
m_mutex.Lock();
sqlite3xx_exec(m_pDB, szSql, callback, 0, &pszErr);
if (pszErr) { sqlite3xx_free(pszErr); }
m_mutex.Unlock();
}
return nCount;
}
bool SqliteDB::IsTableExist(const char* szTable)
{
char *pErrmsg = nullptr;
char szSql[512] = { 0 };
int nRow = 0;
int nColumn = 0;
char **pDBResult = nullptr;
sprintf(szSql, "SELECT * FROM sqlite_master WHERE type='table' AND name = '%s';", szTable);
m_mutex.Lock();
int nRet = sqlite3xx_get_table(m_pDB, szSql, &pDBResult, &nRow, &nColumn, &pErrmsg);
if (pDBResult) { sqlite3xx_free_table(pDBResult); }
if (pErrmsg) { sqlite3xx_free(pErrmsg); }
m_mutex.Unlock();
return (nRet == SQLITE_OK && nRow > 0);
}
//表字段是否存在
bool SqliteDB::IsFiledExist(const char* pszTable, char* pszFiled)
{
char* pErrmsg = nullptr;
char szSql[1024] = { 0 };
int nRow = 0;
int nColumn = 0;
char **pDBResult = nullptr;
sprintf(szSql, "SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table';", pszTable);
m_mutex.Lock();
int nRet = sqlite3xx_get_table(m_pDB, szSql, &pDBResult, &nRow, &nColumn, &pErrmsg);
if (pErrmsg) { sqlite3xx_free(pErrmsg); }
m_mutex.Unlock();
bool bFind = false;
do
{
if (nRet != SQLITE_OK || nRow <= 0 || pDBResult == nullptr)
break;
char* pColumValue = pDBResult[1];
if (pColumValue == nullptr)
break;
if (nullptr == strstr(pColumValue, pszFiled))
break;
bFind = true;
} while (0);
sqlite3xx_free_table(pDBResult);
return bFind;
}
bool SqliteDB::AppendFiled(const char* pszTable, const char* pszFiled, const char* pszKeyType)
{
char szSql[1024] = { 0 };
sprintf(szSql, "ALTER TABLE '%s' ADD '%s' %s;", pszTable, pszFiled, pszKeyType);
return ExecuteSql(szSql);
}
bool SqliteDB::DropTable(const char* pszTable) //删除表
{
char szSql[1024] = { 0 };
sprintf(szSql, "DROP TABLE '%s';", pszTable);
return ExecuteSql(szSql);
}
bool SqliteDB::CleanTable(const char* pszTable) //清空表
{
char szSql[1024] = { 0 };
sprintf(szSql, "DELETE FROM '%s';", pszTable);
return ExecuteSql(szSql);
}
bool SqliteDB::ExecuteSql(const char* szSql, int(*callback)(void*, int, char**, char**), void* p)
{
char * pErrmsg = nullptr;
m_mutex.Lock();
int iRet = sqlite3xx_exec(m_pDB, szSql, callback, p, &pErrmsg);
if (pErrmsg) { sqlite3xx_free(pErrmsg); }
m_mutex.Unlock();
return (iRet == SQLITE_OK);
}
bool SqliteDB::ExecuteSql(int(*callback)(void*, int, char**, char**), const char* pszSqlFmt, ...)
{
char* pszSql = (char*)calloc(1, 1024 * 10);
va_list body;
va_start(body, pszSqlFmt);
vsprintf(pszSql, pszSqlFmt, body);
va_end(body);
bool isSucc = ExecuteSql(pszSql, callback);
free(pszSql);
return isSucc;
}
bool SqliteDB::Convert2(sqlite3db* pMemDB, const char* pszFile, bool toFile)
{
sqlite3db *pFileDB = nullptr;
if (SQLITE_OK == sqlite3xx_open(pszFile, &pFileDB))
{
sqlite3db *pFrom = (toFile ? pMemDB : pFileDB);
sqlite3db *pTo = (toFile ? pFileDB : pMemDB);
sqlite3xx_backup *pBackup = sqlite3xx_backup_init(pTo, "main", pFrom, "main");
if (pBackup)
{
sqlite3xx_backup_step(pBackup, -1);
sqlite3xx_backup_finish(pBackup);
}
bool isSucc = (SQLITE_OK == sqlite3xx_errcode(pFileDB));
sqlite3xx_close(pFileDB);
return isSucc;
}
return false;
}
}