#include "GdSQLite3.h" /////////////////////////////////////////////////////////////////////////// /// \brief GdSQLite3::GdSQLite3 /// GdSQLite3::GdSQLite3() { m_pDB = nullptr; m_bOpen = false; m_strDBName = ""; m_strLastQueryResult = ""; } GdSQLite3::~GdSQLite3() { CloseDB(); } bool GdSQLite3::OpenDB(const QString& strDBName) { CloseDB(); if(SQLITE_OK != sqlite3_open(strDBName.toStdString().c_str(), &m_pDB) ) { return false; } m_strDBName = strDBName; m_bOpen = true; return true; } void GdSQLite3::CloseDB() { if(m_bOpen) { sqlite3_close(m_pDB); m_pDB = nullptr; m_bOpen = false; } } bool GdSQLite3::IsOpen() { return m_bOpen; } sqlite3* GdSQLite3::GetDB() { return m_pDB; } bool GdSQLite3::Execute(const QString& strSQL) { if(!m_bOpen) { return false; } char* lpszErrMsg = nullptr; if(SQLITE_OK != sqlite3_exec(m_pDB, strSQL.toStdString().c_str(), &GdSQLite3::CallBack_Execute, nullptr, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; return false; } return true; } // 每查询到1条记录,调用一次 int GdSQLite3::CallBack_Execute(void* pOwner, int nColCount, char** lpszValue, char** lpszColName) { GdSQLite3* pThis = reinterpret_cast(pOwner); if(nullptr == pThis) { return -1; } return pThis->DoExecute(nColCount, lpszValue, lpszColName); } int GdSQLite3::DoExecute(int nColCount, char** lpszValue, char** lpszColName) { m_strLastQueryResult = ""; for(int i = 0; i < nColCount; i++) { m_strLastQueryResult += lpszColName[i]; m_strLastQueryResult += ":"; m_strLastQueryResult += lpszValue[i] ? lpszValue[i] : "NULL"; m_strLastQueryResult += "$"; //printf("%s = %s\n", lpszColName[i], lpszValue[i] ? lpszValue[i] : "NULL"); } //printf("\n"); return 0; } bool GdSQLite3::QueryAllTableInfo(QString& strResult, const QString& strTable) { /* * sqlite3_get_table * 第1个参数不再多说,看前面的例子。 * 第2个参数是 sql 语句,跟 sqlite3_exec 里的 sql 是一样的。是一个很普通的以/0结尾的char *字符串。 * 第3个参数是查询结果,它依然一维数组(不要以为是二维数组,更不要以为是三维数组)。 * 它内存布局是:resultp的字段值是连续的,第一行是字段名称,后面是紧接着是每个字段的值。 * 从第0索引到第 nColumn - 1索引都是字段名称,从第nColumn 索引开始,后面都是字段值, * 它把一个二维的表(传统的行列表示法)用一个扁平的形式来表示。 * //第n列的名称,存放于resultp [nrow] * //第n行第m列的数据,存放于resultp [(nrow+ 1) * nColumn + m] * 第4个参数是查询出多少条记录(即查出多少行)。 * 第5个参数是多少个字段(多少列)。 * 第6个参数是错误信息。 */ QString strSQL = "select * from " + strTable; char** lpszResult = nullptr; char* lpszErrMsg = nullptr; int nRow = 0, nCol = 0; if(!m_bOpen) { return false; } if(SQLITE_OK != sqlite3_get_table(m_pDB, strSQL.toStdString().c_str(), &lpszResult, &nRow, &nCol, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; return false; } // strResult = ""; int nIndex = nCol; // 第一列为表头 for(int i = 0; i < nRow; i++) { for(int j = 0; j < nCol; j++) { strResult += lpszResult[j]; strResult += ":"; strResult += lpszResult[nIndex]; if (j < (nCol - 1)) { strResult += ","; } nIndex++; } strResult += ";"; } sqlite3_free_table(lpszResult); lpszResult = nullptr; return true; } bool GdSQLite3::EgTransaction() { if(!m_bOpen) { return false; } char* lpszErrMsg = nullptr; /* // eg 1 if(SQLITE_OK != sqlite3_exec(m_pDB, "BEGIN;", nullptr, nullptr, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; return false; } for(int i = 0; i < 1000; i++) { QString strSQL = "insert into MyTable(MyText, MyDate, MyTime, MyFloat)" " VALUES('--上班好远!', '2022-03-24', '9:00:00', 1000);"; if(SQLITE_OK != sqlite3_exec(m_pDB, strSQL.toStdString().c_str(), nullptr, nullptr, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; } } if(SQLITE_OK != sqlite3_exec(m_pDB, "COMMIT;", nullptr, nullptr, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; return false; } // eg 2 QString strSQL = ""; strSQL += "begin;\n"; for(int i = 0; i < 1000; i++) { strSQL += "insert into MyTable values(null, 'test msg');\n"; } strSQL += "commit;\n"; if(SQLITE_OK != sqlite3_exec(m_pDB, strSQL.toStdString().c_str(), nullptr, nullptr, &lpszErrMsg) ) { sqlite3_free(lpszErrMsg); lpszErrMsg = nullptr; return false; } */ return true; } /////////////////////////////////////////////////////////////////////////// /// \brief GdSQLite3RecordSet::GdSQLite3RecordSet /// \param pGdSQLite3 /// GdSQLite3RecordSet::GdSQLite3RecordSet(GdSQLite3* pGdSQLite3) : m_pGdSQLite3(pGdSQLite3) { m_pStmt = nullptr; m_bOpen = false; m_bValueReady = false; } GdSQLite3RecordSet::~GdSQLite3RecordSet() { Close(); } bool GdSQLite3RecordSet::Open(const QString& strQuerySQL) { Close(); if(nullptr == m_pGdSQLite3) { return false; } if(!m_pGdSQLite3->IsOpen() ) { return false; } const char* lpszTail = nullptr; if(SQLITE_OK != sqlite3_prepare_v2(m_pGdSQLite3->GetDB(), strQuerySQL.toStdString().c_str(), -1, &m_pStmt, &lpszTail) ) { return false; } m_bOpen = true; return true; } void GdSQLite3RecordSet::Close() { if(m_bOpen) { if(nullptr != m_pStmt) { sqlite3_finalize(m_pStmt); m_pStmt = nullptr; } m_bOpen = false; m_bValueReady = false; } } bool GdSQLite3RecordSet::Next() { if(!m_bOpen) { return false; } m_bValueReady = false; if(SQLITE_ROW != sqlite3_step(m_pStmt) ) { return false; } m_bValueReady = true; return true; } bool GdSQLite3RecordSet::GetValue(QVariant& varVal, int nCol, GdSQLite3RecordSet::eDataType eDT) { if(!m_bValueReady) { return false; } switch(eDT) { case eDT_Int: { varVal = sqlite3_column_int(m_pStmt, nCol); break; } case eDT_Int64: { varVal = sqlite3_column_int64(m_pStmt, nCol); break; } case eDT_Double: { varVal = sqlite3_column_double(m_pStmt, nCol); break; } case eDT_Text: { varVal = (char*)sqlite3_column_text(m_pStmt, nCol); break; } case eDT_Blob: { varVal = QVariant(QByteArray((char*)sqlite3_column_text(m_pStmt, nCol) ) ); break; } default: { return false; } } return true; }