355 lines
7.3 KiB
C++
355 lines
7.3 KiB
C++
|
|
#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<GdSQLite3*>(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;
|
|||
|
|
}
|