自己整理的一个访问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
 
 
 

猜你喜欢

转载自www.cnblogs.com/blogpro/p/11426881.html