Files
2026-08-24 10:03:24 +08:00

720 lines
16 KiB
C++

/*
* Copyright (c) 2014 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description: c++ file
*/
#define LOG_MODULE_TAG "PQ"
#define LOG_CLASS_TAG "CSqlite"
#include "CSqlite.h"
CSqlite::Cursor::Cursor()
{
mData = NULL;
mCurRowIndex = 0;
mRowNums = 0;
mColNums = 0;
mIsClosed = false;
}
CSqlite::Cursor::~Cursor()
{
close();
}
void CSqlite::Cursor::Init(char **data, int cow, int col)
{
if (mData != NULL) {
sqlite3_free_table(mData);
}
mData = data;
mCurRowIndex = 0;
mRowNums = cow;
mColNums = col;
mIsClosed = false;
}
int CSqlite::Cursor::getCount()
{
return mRowNums;
}
int CSqlite::Cursor::getPosition()
{
return 0;
}
bool CSqlite::Cursor::move(int offset)
{
return false;
}
bool CSqlite::Cursor::moveToPosition(int position)
{
return false;
}
bool CSqlite::Cursor::moveToFirst()
{
if (mRowNums <= 0) {
return false;
} else {
mCurRowIndex = 0;
return true;
}
}
bool CSqlite::Cursor::moveToLast()
{
return false;
}
bool CSqlite::Cursor::moveToNext()
{
if (mCurRowIndex >= mRowNums - 1) {
return false;
} else {
mCurRowIndex++;
return true;
}
}
bool CSqlite::Cursor::moveToPrevious()
{
return false;
}
int CSqlite::Cursor::getColumnIndex(const char *columnName)
{
int index = 0;
for (int i = 0; i < mColNums; i++) {
if (strcmp(columnName, mData[i]) == 0)
return index;
index++;
}
return -1;
}
int CSqlite::Cursor::getColumnCount()
{
return -1;
}
std::string CSqlite::Cursor::getString(int columnIndex)
{
if (columnIndex >= mColNums) {
return std::string("");
} else {
return std::string(mData[mColNums * (mCurRowIndex + 1) + columnIndex]);
}
}
int CSqlite::Cursor::getInt(int columnIndex)
{
return atoi(mData[mColNums * (mCurRowIndex + 1) + columnIndex]);
}
unsigned long int CSqlite::Cursor::getUInt(int columnIndex)
{
return strtoul(mData[mColNums * (mCurRowIndex + 1) + columnIndex], NULL, 10);
}
double CSqlite::Cursor::getF(int columnIndex)
{
return atof(mData[mColNums * (mCurRowIndex + 1) + columnIndex]);
}
int CSqlite::Cursor::getType(int columnIndex)
{
return -1;
}
void CSqlite::Cursor::close()
{
if (mData != NULL) {
sqlite3_free_table(mData);
}
mData = NULL;
mCurRowIndex = 0;
mRowNums = 0;
mIsClosed = true;
}
bool CSqlite::Cursor::isClosed()
{
return mIsClosed;
}
CSqlite::CSqlite()
{
mHandle = NULL;
m_pStmtSelect = NULL;
m_pStmtUpdate = NULL;
m_pStmtDelete = NULL;
}
CSqlite::~CSqlite()
{
std::lock_guard<std::mutex> lock(mLock);
if (mHandle != NULL) {
sqlite3_close(mHandle);
mHandle = NULL;
}
}
int CSqlite::sqlite3_exec_callback(void *data __unused, int nColumn, char **colValues __unused, char **colNames __unused)
{
LOGD("%s: nums = %d", __FUNCTION__, nColumn);
return 0;
}
int CSqlite::openDb(const char *path)
{
std::lock_guard<std::mutex> lock(mLock);
if (sqlite3_open(path, &mHandle) != SQLITE_OK) {
LOGD("open db(%s) error", path);
mHandle = NULL;
return -1;
}
return 0;
}
int CSqlite::closeDb()
{
std::lock_guard<std::mutex> lock(mLock);
int rval = 0;
if (mHandle != NULL) {
rval = sqlite3_close(mHandle);
mHandle = NULL;
}
return rval;
}
void CSqlite::setHandle(sqlite3 *h)
{
std::lock_guard<std::mutex> lock(mLock);
mHandle = h;
}
sqlite3 *CSqlite::getHandle()
{
std::lock_guard<std::mutex> lock(mLock);
return mHandle;
}
int CSqlite::select(const char *sql, CSqlite::Cursor &c)
{
std::lock_guard<std::mutex> lock(mLock);
int col, row;
char **pResult = NULL;
char *errmsg;
assert(mHandle && sql);
if (strncmp(sql, "select", 6)) {
return -1;
}
if (sqlite3_get_table(mHandle, sql, &pResult, &row, &col, &errmsg) != SQLITE_OK) {
LOGE("errmsg=%s.\n", errmsg);
if (pResult != NULL)
sqlite3_free_table(pResult);
return -1;
}
c.Init(pResult, row, col);
return 0;
}
void CSqlite::insert()
{
}
bool CSqlite::exeSql(const char *sql)
{
std::lock_guard<std::mutex> lock(mLock);
char *errmsg = NULL;
if (sql == NULL) {
return false;
}
int result = sqlite3_exec(mHandle, sql, NULL, NULL, &errmsg);
if (result != SQLITE_OK) {
SYS_LOGE("exeSql=: %s error=%s, error code = %d", sql, errmsg ? errmsg : "Unknown", result);
if (errmsg) {
sqlite3_free(errmsg);
}
return false;
}
return true;
}
bool CSqlite::EnableBatchHighSpeedMode(void)
{
std::lock_guard<std::mutex> lock(mLock);
if (SqlBatchHighSpeedMode) {
printf("SQL at Batch High Speed mode\n");
return true;
}
// 保存当前设置
char* errMsg = nullptr;
int ret = SQLITE_OK;
ret = sqlite3_exec(mHandle, "PRAGMA journal_mode;", [](void* data, int argc, char** argv, char** colName) -> int {
if (argc > 0 && argv[0]) {
*static_cast<std::string*>(data) = argv[0];
}
return 0;
}, &m_originalJournalMode, &errMsg);
if (ret != SQLITE_OK) {
printf("Error getting original journal mode: %d - %s\n", ret, errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
return false;
}
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
ret = sqlite3_exec(mHandle, "PRAGMA synchronous;", [](void* data, int argc, char** argv, char** colName) -> int {
if (argc > 0 && argv[0]) {
*static_cast<std::string*>(data) = argv[0];
}
return 0;
}, &m_originalSyncMode, &errMsg);
if (ret != SQLITE_OK) {
printf("Error getting original sync mode: %d - %s\n", ret, errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
}
return false;
}
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
// 启用高性能设置
ret = sqlite3_exec(mHandle, "PRAGMA journal_mode = WAL;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error setting WAL mode: %d - %s\n", ret, errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
}
return false;
}
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
ret = sqlite3_exec(mHandle, "PRAGMA synchronous = NORMAL;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error setting synchronous mode: %d - %s\n", ret, errMsg ? errMsg : "Unknown error");
char* rollbackErrMsg = nullptr;
int rollbackRet = sqlite3_exec(mHandle, ("PRAGMA journal_mode = " + m_originalJournalMode + ";").c_str(),
nullptr, nullptr, &rollbackErrMsg);
if (rollbackRet != SQLITE_OK) {
printf("Error rolling back journal mode: %d - %s\n",
rollbackRet, rollbackErrMsg ? rollbackErrMsg : "Unknown error");
}
if (rollbackErrMsg) {
sqlite3_free(rollbackErrMsg);
}
ret =sqlite3_exec(mHandle, ("PRAGMA journal_mode = " + m_originalJournalMode + ";").c_str(),
nullptr, nullptr, nullptr);
if (ret != SQLITE_OK) {
printf("Error setting WAL mode: %d - %s\n", ret, errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
}
return false;
}
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
return false;
}
/*
// 设置buff 10M 如果需要
ret = sqlite3_exec(m_pDB, "PRAGMA cache_size = -10000;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error setting cache size: %s\n", errMsg);
sqlite3_free(errMsg);
}
*/
SqlBatchHighSpeedMode = true;
return true;
}
bool CSqlite::DisableBatchHighSpeedMode(void)
{
std::lock_guard<std::mutex> lock(mLock);
if (!SqlBatchHighSpeedMode) {
printf("SQL not at Batch High Speed mode\n");
return true;
}
bool success = true;
char* errMsg = nullptr;
//确保所有WAL中的数据都已写入主数据库
int ret = sqlite3_exec(mHandle, "PRAGMA wal_checkpoint(TRUNCATE);", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error during checkpoint: %s\n", errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
success = false;
}
// 恢复原始日志模式
std::string pragmaJournal = "PRAGMA journal_mode = " + m_originalJournalMode + ";";
ret = sqlite3_exec(mHandle, pragmaJournal.c_str(), nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error restoring journal mode: %s\n", errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
success = false;
}
// 恢复原始同步模式
std::string pragmaSync = "PRAGMA synchronous = " + m_originalSyncMode + ";";
ret = sqlite3_exec(mHandle, pragmaSync.c_str(), nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error restoring sync mode: %s\n", errMsg ? errMsg : "Unknown error");
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
success = false;
}
if (errMsg) {
sqlite3_free(errMsg);
errMsg = nullptr;
}
/*
//恢复 buff 2M
ret = sqlite3_exec(m_pDB, "PRAGMA cache_size = -2000;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error restoring cache size: %s\n", errMsg);
sqlite3_free(errMsg);
}
*/
SqlBatchHighSpeedMode = false;
return success;
}
bool CSqlite::beginTransaction()
{
std::lock_guard<std::mutex> lock(mLock);
if (!mHandle) {
printf("Database handle is invalid\n");
return false;
}
if (sqlite3_get_autocommit(mHandle) == 0) {
printf("Already in transaction\n");
return false;
}
char* errMsg = nullptr;
int ret = sqlite3_exec(mHandle, "BEGIN TRANSACTION;", nullptr, nullptr, &errMsg);
bool success = (ret == SQLITE_OK);
if (!success) {
fprintf(stderr, "Error beginning transaction (code %d): %s\n", ret, errMsg ? errMsg : "Unknown error");
}
if (errMsg) {
sqlite3_free(errMsg);
}
return success;
}
bool CSqlite::commitTransaction()
{
std::lock_guard<std::mutex> lock(mLock);
char* errMsg = nullptr;
int ret = sqlite3_exec(mHandle, "COMMIT;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
const char* errorDescription = "Unknown error";
switch (ret) {
case SQLITE_BUSY: errorDescription = "Database is busy"; break;
case SQLITE_READONLY: errorDescription = "Database is read-only"; break;
case SQLITE_IOERR: errorDescription = "Disk I/O error"; break;
case SQLITE_CORRUPT: errorDescription = "Database is corrupt"; break;
default: break;
}
fprintf(stderr, "Error committing transaction (code %d): %s - %s\n",
ret, errorDescription, errMsg ? errMsg : "No details");
if (errMsg != nullptr) {
sqlite3_free(errMsg);
}
return false;
}
if (errMsg != nullptr) {
sqlite3_free(errMsg);
}
return true;
}
bool CSqlite::rollbackTransaction()
{
std::lock_guard<std::mutex> lock(mLock);
char* errMsg = nullptr;
int ret = sqlite3_exec(mHandle, "ROLLBACK;", nullptr, nullptr, &errMsg);
if (ret != SQLITE_OK) {
printf("Error rolling back transaction: %s\n", errMsg);
sqlite3_free(errMsg);
return false;
}
return true;
}
void CSqlite::del()
{
}
void CSqlite::update()
{
}
void CSqlite::xxtable()
{
}
bool CSqlite::PrepareSqlSelect(const char *msql)
{
std::lock_guard<std::mutex> lock(mLock);
if (m_pStmtSelect) {
sqlite3_finalize(m_pStmtSelect);
m_pStmtSelect = nullptr;
}
int ret = sqlite3_prepare_v2(mHandle, msql, -1, &m_pStmtSelect, 0);
if (ret != SQLITE_OK || !m_pStmtSelect) {
printf("ret: %d, msql =%s, errorCode=%d\n", ret, msql, sqlite3_errcode(mHandle));
sqlite3_finalize(m_pStmtSelect);
m_pStmtSelect = 0;
assert(0 && "Failed to prepare SELECT statement");
}
return true;
}
bool CSqlite::PrepareSqlUpdate(const char *msql)
{
std::lock_guard<std::mutex> lock(mLock);
if (m_pStmtUpdate) {
sqlite3_finalize(m_pStmtUpdate);
m_pStmtUpdate = nullptr;
}
int ret = sqlite3_prepare_v2(mHandle, msql, -1, &m_pStmtUpdate, 0);
if (ret != SQLITE_OK || !m_pStmtUpdate) {
printf("ret: %d, msql =%s, errorCode=%d\n", ret, msql, sqlite3_errcode(mHandle));
sqlite3_finalize(m_pStmtUpdate);
m_pStmtUpdate = 0;
assert(0 && "Failed to prepare UPDATE statement");
}
return true;
}
bool CSqlite::PrepareSqlDelete(const char *msql)
{
std::lock_guard<std::mutex> lock(mLock);
if (m_pStmtDelete) {
sqlite3_finalize(m_pStmtDelete);
m_pStmtDelete = nullptr;
}
int ret = sqlite3_prepare_v2(mHandle, msql, -1, &m_pStmtDelete, 0);
if (ret != SQLITE_OK || !m_pStmtDelete) {
const char* errMsg = sqlite3_errmsg(mHandle);
printf("Prepare DELETE failed: ret=%d, sql=%s, error=%s\n", ret, msql, errMsg);
if (m_pStmtDelete) {
sqlite3_finalize(m_pStmtDelete);
m_pStmtDelete = nullptr;
}
assert(0 && "Failed to prepare DELETE statement");
return false;
}
return true;
}
bool CSqlite::SetBlobValueToTable(const char *Key, void *pData, int iSize)
{
std::lock_guard<std::mutex> lock(mLock);
if (Key == nullptr || pData == nullptr) {
printf("Error: Key or pData is null\n");
return false;
}
if (iSize < 0) {
printf("Error: Invalid blob size %d\n", iSize);
return false;
}
if (!m_pStmtUpdate) {
printf("m_pStmtUpdateINVALID VALUES");
return false;
}
sqlite3_reset(m_pStmtUpdate);
sqlite3_clear_bindings(m_pStmtUpdate);
if (sqlite3_bind_text(m_pStmtUpdate, 1, Key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
return false;
}
if (sqlite3_bind_blob(m_pStmtUpdate, 2, pData, iSize, SQLITE_TRANSIENT) != SQLITE_OK) {
return false;
}
int ret = sqlite3_step(m_pStmtUpdate);
if (ret != SQLITE_DONE) {
return false;
}
return true;
}
bool CSqlite::GetBlobValueFromTable(const char *Key, void *pData, int iSize)
{
std::lock_guard<std::mutex> lock(mLock);
if (Key == nullptr || pData == nullptr) {
printf("Error: Key or pData is null\n");
return false;
}
if (iSize <= 0) {
printf("Error: Invalid buffer size %d\n", iSize);
return false;
}
if (!m_pStmtSelect) {
printf("Error: Select statement null\n");
return false;
}
sqlite3_reset(m_pStmtSelect);
sqlite3_clear_bindings(m_pStmtSelect);
if (sqlite3_bind_text(m_pStmtSelect, 1, Key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
return false;
}
int ret = sqlite3_step(m_pStmtSelect);
if (ret == SQLITE_DONE) {
return false;
}
if (ret != SQLITE_ROW) {
return false;
}
int valSize = sqlite3_column_bytes(m_pStmtSelect, 0);
if (valSize <= 0) {
return false;
}
const void* blob = sqlite3_column_blob(m_pStmtSelect, 0);
if (!blob) {
return false;
}
if (valSize > iSize) {
return false;
}
memcpy(pData, blob, valSize);
return true;
}
bool CSqlite::DeleteValueFromTable(const char *Key)
{
std::lock_guard<std::mutex> lock(mLock);
if (Key == nullptr) {
printf("Error: Key is null\n");
return false;
}
if (!m_pStmtDelete) {
printf("Error: Delete statement not prepared (m_pStmtDelete is null)\n");
return false;
}
sqlite3_reset(m_pStmtDelete);
sqlite3_clear_bindings(m_pStmtDelete);
if (sqlite3_bind_text(m_pStmtDelete, 1, Key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
return false;
}
int ret = sqlite3_step(m_pStmtDelete);
if (ret != SQLITE_DONE) {
return false;
}
return true;
}