/* * 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 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 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 lock(mLock); int rval = 0; if (mHandle != NULL) { rval = sqlite3_close(mHandle); mHandle = NULL; } return rval; } void CSqlite::setHandle(sqlite3 *h) { std::lock_guard lock(mLock); mHandle = h; } sqlite3 *CSqlite::getHandle() { std::lock_guard lock(mLock); return mHandle; } int CSqlite::select(const char *sql, CSqlite::Cursor &c) { std::lock_guard 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 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 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(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(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 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 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 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 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 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 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 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 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 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 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; }