C++封装SQLite实例<三>
前一篇博客中介绍的是怎样依据sqlite3_get_table()函数来获取一张表的内容,就是一股脑的把表中的内容所有存储起来放在一个一维数组中,这其中的规则已经介绍过了。接下来讲的是怎样依据一个SQL查询语句来挑选出合乎选择条件的记录,被挑选出的记录事先是不知道的。你不知道这个查询的结果中有几行更不知道每一行中详细的记录值是什么,所以没办法用给定行值和列值的方式来获取数据,所有之前的用数组存储表的方式即可不通了。想要灵活的管理一个查询返回的结果这就会复杂多了,用到的SQLite原生函数也非常多。
这个CppSQLite3Query类中有四个字段,各自是
sqlite3 *mpDB; sqlite3_stmt *mpStmt; bool mbEof; //因为查询的结果须要一行一行的訪问,所以设置一个bool值来表示是否达到最后一行的结尾 int mnCols; //表示这个查询结果的列数,行数是无法得知的第一个參数:查询要连接的数据库
第二个參数:
** CAPI3REF: SQL Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement. ** This object is variously known as a "prepared statement" or a ** "compiled SQL statement" or simply as a "statement". ** ** The life of a statement object goes something like this: ** ** <ol> ** <li> Create the object using [sqlite3_prepare_v2()] or a related ** function. ** <li> Bind values to [host parameters] using the sqlite3_bind_*() ** interfaces. ** <li> Run the SQL by calling [sqlite3_step()] one or more times. ** <li> Reset the statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. ** <li> Destroy the object using [sqlite3_finalize()]. ** </ol>是一个SQL语句对象,或是说一条原生的SQL查询语句select * from XXX;经过SQLite处理后就生成了一个sqlite3_stmt对象。以后就能够不用原生的语句来做查询,就直接使用这个sqlite3_stmt*就能够查询了,当查询结束后,要将sqlite3_stmt*指针对象释放掉。
释放函数sqlite3_finalize()和sqlite3_free();函数功能类似,仅仅只是后者是释放sqlite3*对象的,而前者是释放sqlite3_stmt*对象的。
函数原型 SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
函数说明:
/* ** CAPI3REF: Destroy A Prepared Statement Object ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors ** or if the statement is never been evaluated, then sqlite3_finalize() returns ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then ** sqlite3_finalize(S) returns the appropriate [error code] or ** [extended error code]. ** ** ^The sqlite3_finalize(S) routine can be called at any point during ** the life cycle of [prepared statement] S: ** before statement S is ever evaluated, after ** one or more calls to [sqlite3_reset()], or after any call ** to [sqlite3_step()] regardless of whether or not the statement has ** completed execution. ** ** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. ** ** The application must finalize every [prepared statement] in order to avoid ** resource leaks. It is a grievous error for the application to try to use ** a prepared statement after it has been finalized. Any use of a prepared ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */
用来初始化mnCols字段的函数是:
SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);函数说明:
/* ** CAPI3REF: Number Of Columns In A Result Set ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL ** statement that does not return data (for example an [UPDATE]). ** ** See also: [sqlite3_data_count()] */
在依据列索引值获取当前列的列名用到的函数:
函数原型:SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
在推断数据是否为空的时候要用到检測数据类型的函数:
函数原型:SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);这个函数返回的是一个整型,当中不同的数值代表不同的已定义好的宏,以下是各种类型:
#define SQLITE_INTEGER 1 #define SQLITE_FLOAT 2 #define SQLITE_BLOB 4 #define SQLITE_NULL 5 #ifdef SQLITE_TEXT # undef SQLITE_TEXT #else # define SQLITE_TEXT 3 #endif #define SQLITE3_TEXT 3
另一种查询数据类型的函数
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);他返回的直接是类型名称。
在获取各种不同类型数据的时候用到各种函数,他们返回不同的数据类型的值:
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);上面的一些函数可能没有出如今这个封装的C++类中。
以下直接贴代码:
class CppSQLite3Query { private: sqlite3 *mpDB; sqlite3_stmt *mpStmt; bool mbEof; int mnCols; void CheckStmt(); public: CppSQLite3Query(); CppSQLite3Query(sqlite3 *pdb, sqlite3_stmt *pStmt, bool bEof); CppSQLite3Query(const CppSQLite3Query &rQuery); CppSQLite3Query& operator= (const CppSQLite3Query &rQuery); ~CppSQLite3Query(); int FieldNums(); int FieldIndex(const char* szField); const char* FieldName(int nField); int FieldDataType(int nField); const char* FieldDeclType(int nField); const char* FieldValue(int nField); const char* FieldValue(const char *szField); bool FieldIsNull(int nField); bool FieldIsNull(const char *szField); bool GetIntValue(int nField, int &rDest); bool GetIntValue(const char *szField, int &rDest); bool GetFloatValue(int nField, double &rDest); bool GetFloatValue(const char *szField, double &rDest); bool GetStringValue(int nField, char *&rDest); bool GetStringValue(const char *szField, char *&rDest); bool Eof(); void NextRow(); void Finalize(); };
CppSQLite3Query::CppSQLite3Query() { mpDB = 0; mpStmt = 0; mnCols = 0; mbEof = true; } CppSQLite3Query::CppSQLite3Query(sqlite3 *pdb, sqlite3_stmt *pStmt, bool bEof) { mpDB = pdb; mpStmt = pStmt; mbEof = bEof; mnCols = sqlite3_column_count(pStmt); } CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query &rQuery) { mpStmt = rQuery.mpStmt; const_cast<CppSQLite3Query &>(rQuery).mpStmt = 0; mnCols = rQuery.mnCols; mbEof = rQuery.mbEof; } CppSQLite3Query& CppSQLite3Query::operator =(const CppSQLite3Query &rQuery) { mpStmt = rQuery.mpStmt; const_cast<CppSQLite3Query &>(rQuery).mpStmt = 0; mnCols = rQuery.mnCols; mbEof = rQuery.mbEof; return *this; } CppSQLite3Query::~CppSQLite3Query() { Finalize(); } void CppSQLite3Query::CheckStmt() { if (mpStmt == 0) { throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid Stmt Pointer", DONT_DELETE_MSG); } } int CppSQLite3Query::FieldNums() { CheckStmt(); return mnCols; } //依据字段名返回列索引 int CppSQLite3Query::FieldIndex(const char* szField) { CheckStmt(); if (szField) { for (int nField = 0; nField < mnCols; nField++) { //后面还有非常多相似的函数,參数差点儿相同,须要一个sqlite3_stmt*和列索引值,这应该是内部查询了之后返回的结果,而不是事先保存的 const char *szTemp = sqlite3_column_name(mpStmt, nField); if (strcmp(szTemp, szField) == 0) { return nField; } } } throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid field name requested", DONT_DELETE_MSG); } const char* CppSQLite3Query::FieldName(int nField) { CheckStmt(); if (nField < 0 || nField > mnCols-1) { throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid field index requested", DONT_DELETE_MSG); } return sqlite3_column_name(mpStmt, nField); } int CppSQLite3Query::FieldDataType(int nField) { CheckStmt(); if (nField < 0 || nField > mnCols-1) { throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid field index requested", DONT_DELETE_MSG); } return sqlite3_column_type(mpStmt, nField); } const char* CppSQLite3Query::FieldDeclType(int nField) { CheckStmt(); if (nField < 0 || nField > mnCols-1) { throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid field index requested", DONT_DELETE_MSG); } return sqlite3_column_decltype(mpStmt, nField); } const char* CppSQLite3Query::FieldValue(int nField) { CheckStmt(); if (nField < 0 || nField > mnCols-1) { throw CppSQLite3Exception(CPPSQLITE_ERROR, "Invalid field index requested", DONT_DELETE_MSG); } return (const char*)sqlite3_column_text(mpStmt, nField); } const char* CppSQLite3Query::FieldValue(const char *szField) { int nField = FieldIndex(szField); return FieldValue(nField); } bool CppSQLite3Query::FieldIsNull(int nField) { return (FieldDataType(nField) == SQLITE_NULL); } bool CppSQLite3Query::FieldIsNull(const char *szField) { int nField = FieldIndex(szField); return (FieldDataType(nField) == SQLITE_NULL); } bool CppSQLite3Query::GetIntValue(int nField, int &rDest) { if (FieldDataType(nField) == SQLITE_NULL) { return false; } else { rDest = sqlite3_column_int(mpStmt, nField); return true; } } bool CppSQLite3Query::GetIntValue(const char *szField, int &rDest) { int nField = FieldIndex(szField); return GetIntValue(nField, rDest); } bool CppSQLite3Query::GetFloatValue(int nField, double &rDest) { if (FieldDataType(nField) == SQLITE_NULL) { return false; } else { rDest = sqlite3_column_double(mpStmt, nField); return true; } } bool CppSQLite3Query::GetFloatValue(const char *szField, double &rDest) { int nField = FieldIndex(szField); return GetFloatValue(nField, rDest); } bool CppSQLite3Query::GetStringValue(int nField, char *&rDest) { if (FieldDataType(nField) == SQLITE_NULL) { return false; } else { rDest = const_cast<char *>((const char*)sqlite3_column_text(mpStmt, nField)); return true; } } bool CppSQLite3Query::GetStringValue(const char *szField, char *&rDest) { int nField = FieldIndex(szField); return GetStringValue(nField, rDest); } bool CppSQLite3Query::Eof() { CheckStmt(); return mbEof; } void CppSQLite3Query::NextRow() { CheckStmt(); int nRet = sqlite3_step(mpStmt); if (nRet == SQLITE_DONE) { // no rows mbEof = true; } else if (nRet == SQLITE_ROW) { // more rows, nothing to do } else { nRet = sqlite3_finalize(mpStmt); mpStmt = 0; const char* szError = sqlite3_errmsg(mpDB); throw CppSQLite3Exception(nRet, szError, DONT_DELETE_MSG); } } void CppSQLite3Query::Finalize() { if (mpStmt) { int nRet = sqlite3_finalize(mpStmt); mpStmt = 0; if (nRet != SQLITE_OK) { const char* szError = sqlite3_errmsg(mpDB); throw CppSQLite3Exception(nRet, szError, DONT_DELETE_MSG); } } }