C++封装SQLite实例

第一次结识SQLite是在上学期,有一个软工的同学在看有关安卓应用的书籍,正好在实验室碰到了他,他正在看的就是SQLite这个数据库在安卓上的使用。从那以后就再也没有了解过有关SQLite的信息,上星期学长们的CDIO组在做一个游戏,要用到这个数据库,正好我也在这个组里,于是就分配我去学习如何封装这个数据库中的原生态函数,以便于访问数据库。学了一个星期,根据外文网站上的一个例子逐步的去拆解过程函数与变量将其放置在不同的类中,这其中也百度了很多网页,可都是一些不完整的或是未封装的。就想把这一个星期的学习心得分享给大家,于是就有了接下来的博客。写这些心得之前也思考了一下该怎么组织语言能更好的将这个简化的几个类展现在大家面前。

从这几天的学习SQLite来看,应该把用到的最多的也是最简单的一个类先讲,那就是异常类。

SQLite本来提供有关抛出错误的函数:

SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
头两个是返回操作异常的宏定义,后两个是返回错误的具体代码,他们的参数都是数据库指针对象,这里将其sqlite3*说成是对象是有道理的,因为在后面的使用中,指针就体现出了一个数据库对象的职责与特点。

具体的错误代码宏定义如下:

#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* Database is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT  19   /* Abort due to constraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Auxiliary database format error */
#define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* File opened that is not a database file */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

在封装这个异常类的时候考虑更多的是自己程序中可能出现的很多意外情况,比如最多的就是对于参数合法性的判断了,并且在此抛出异常再合适不过了。在这里有必要说一下一个函数,这个函数和C语言库中的free类似,SQLITE_API void sqlite3_free(void*);在sqlite库函数中起到的也是释放空间作用。


下面直接贴代码:

#pragma once
#include 
#include 
#include "sqlite3.h"

#define CPPSQLITE_ERROR 1000  //这个宏定义是为了区分库函数中定义的错误代码,专用于自己程序中的异常标示

class CppSQLite3Exception
{
private:
	int mnErrCode;
	char *mpszErrMessage;

public:
	CppSQLite3Exception(const int nErrNode,
		                const char *szErrMess,
		                bool bDeleteMess);
	CppSQLite3Exception(const CppSQLite3Exception &e);
	~CppSQLite3Exception();

	const int ErrorCode() { return mnErrCode; }
	const char *ErrorMessage() { return mpszErrMessage; }

	static const char* ErrorCodeAsString(const int nErrCode);
};
#include "CppSQLite3.h"
#include 

static const bool DONT_DELETE_MSG=false;

CppSQLite3Exception::CppSQLite3Exception(const int nErrNode,
	const char *szErrMess,
	bool bDeleteMess)
{
	mnErrCode = nErrNode;
	mpszErrMessage = sqlite3_mprintf("%s[%d]: %s",
		                             ErrorCodeAsString(nErrNode),
									 mnErrCode,
									 szErrMess ? szErrMess : "");
	if (bDeleteMess && szErrMess)
	{
		sqlite3_free(mpszErrMessage);
	}
}

CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception &e)
{
	mnErrCode = e.mnErrCode;
	mpszErrMessage = 0;
	if (e.mpszErrMessage)
	{
		mpszErrMessage = sqlite3_mprintf("%s", e.mpszErrMessage);
	}
}

const char* CppSQLite3Exception::ErrorCodeAsString(const int nErrCode)
{
	switch (nErrCode)
	{
	case SQLITE_OK          : return "SQLITE_OK";
	case SQLITE_ERROR       : return "SQLITE_ERROR";
	case SQLITE_INTERNAL    : return "SQLITE_INTERNAL";
	case SQLITE_PERM        : return "SQLITE_PERM";
	case SQLITE_ABORT       : return "SQLITE_ABORT";
	case SQLITE_BUSY        : return "SQLITE_BUSY";
	case SQLITE_LOCKED      : return "SQLITE_LOCKED";
	case SQLITE_NOMEM       : return "SQLITE_NOMEM";
	case SQLITE_READONLY    : return "SQLITE_READONLY";
	case SQLITE_INTERRUPT   : return "SQLITE_INTERRUPT";
	case SQLITE_IOERR       : return "SQLITE_IOERR";
	case SQLITE_CORRUPT     : return "SQLITE_CORRUPT";
	case SQLITE_NOTFOUND    : return "SQLITE_NOTFOUND";
	case SQLITE_FULL        : return "SQLITE_FULL";
	case SQLITE_CANTOPEN    : return "SQLITE_CANTOPEN";
	case SQLITE_PROTOCOL    : return "SQLITE_PROTOCOL";
	case SQLITE_EMPTY       : return "SQLITE_EMPTY";
	case SQLITE_SCHEMA      : return "SQLITE_SCHEMA";
	case SQLITE_TOOBIG      : return "SQLITE_TOOBIG";
	case SQLITE_CONSTRAINT  : return "SQLITE_CONSTRAINT";
	case SQLITE_MISMATCH    : return "SQLITE_MISMATCH";
	case SQLITE_MISUSE      : return "SQLITE_MISUSE";
	case SQLITE_NOLFS       : return "SQLITE_NOLFS";
	case SQLITE_AUTH        : return "SQLITE_AUTH";
	case SQLITE_FORMAT      : return "SQLITE_FORMAT";
	case SQLITE_RANGE       : return "SQLITE_RANGE";
	case SQLITE_ROW         : return "SQLITE_ROW";
	case SQLITE_DONE        : return "SQLITE_DONE";
	case CPPSQLITE_ERROR    : return "CPPSQLITE_ERROR";
	default: return "UNKNOWN_ERROR";
	}
}

CppSQLite3Exception::~CppSQLite3Exception()
{
	if (mpszErrMessage)
	{
		sqlite3_free(mpszErrMessage);
		mpszErrMessage = 0;
	}
}
接下来会有其他的针对于查询与无返回执行语句的封装等。。。


你可能感兴趣的:(C/C++)