LAPTOP-SNT8I5JK\Boounion
2025-02-14 2fc5bbfe88adefb0d2f8ba55d800fe074264a539
SourceCode/Bond/Servo/SECSRuntimeManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,682 @@
#include "stdafx.h"
#include "SECSRuntimeManager.h"
// å¸¸é‡
const std::string DATABASE_FILE = R"(SECSDataManager.db)";
// é™æ€æˆå‘˜åˆå§‹åŒ–
std::mutex SECSRuntimeManager::m_mutex;
// èŽ·å–å•ä¾‹å®žä¾‹
SECSRuntimeManager& SECSRuntimeManager::getInstance() {
    static SECSRuntimeManager instance;
    return instance;
}
// æž„造函数
SECSRuntimeManager::SECSRuntimeManager() {
    m_pDB = new BL::SQLiteDatabase();
}
// æžæž„函数
SECSRuntimeManager::~SECSRuntimeManager() {
    termRuntimeSetting();
    if (m_pDB != nullptr) {
        delete m_pDB;
        m_pDB = nullptr;
    }
}
// ä»Žæ•°æ®åº“中获取整数
int SECSRuntimeManager::getIntFromDB(const std::string& query) {
    auto results = m_pDB->fetchResults(query);
    if (!results.empty() && !results[0].empty()) {
        // è½¬æ¢ç¬¬ä¸€ä¸ªæŸ¥è¯¢ç»“果为整数
        return std::stoi(results[0][0]);
    }
    return 0;
}
// åˆ¤æ–­VID是否重复
bool SECSRuntimeManager::isIDDuplicate(int nID) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
      return false;
    }
    // å®šä¹‰è¦æ£€æŸ¥çš„表
    std::vector<std::string> tables = { "SystemSV", "EqpSV", "SystemDV", "EqpDV", "SystemEC", "EqpEC" };
    // éåŽ†è¡¨ï¼Œæ£€æŸ¥æ˜¯å¦æœ‰é‡å¤çš„ ID
    for (const auto& table : tables) {
        // åˆ›å»º SQL æŸ¥è¯¢
        std::string checkSQL = "SELECT COUNT(*) FROM " + table + " WHERE ID = " + std::to_string(nID) + ";";
        // æ‰§è¡ŒæŸ¥è¯¢
        auto results = m_pDB->fetchResults(checkSQL);
        int count = (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0;
        // å¦‚果找到了重复的 ID,则返回 true
        if (count > 0) {
            return true;
        }
    }
    // å¦‚果没有重复,返回 false
    return false;
}
// åˆ¤æ–­åç§°æ˜¯å¦é‡å¤
bool SECSRuntimeManager::isNameDuplicate(const std::string& sName) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return false;
    }
    // å®šä¹‰è¦æ£€æŸ¥çš„表
    std::vector<std::string> tables = { "SystemSV", "EqpSV", "SystemDV", "EqpDV", "SystemEC", "EqpEC" };
    // éåŽ†è¡¨ï¼Œæ£€æŸ¥æ˜¯å¦æœ‰é‡å¤çš„ Name
    for (const auto& table : tables) {
        // åˆ›å»º SQL æŸ¥è¯¢
        std::string checkSQL = "SELECT COUNT(*) FROM " + table + " WHERE Name = '" + sName + "';";
        // æ‰§è¡ŒæŸ¥è¯¢
        auto results = m_pDB->fetchResults(checkSQL);
        int count = (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0;
        // å¦‚果找到了重复的 Name,则返回 true
        if (count > 0) {
            return true;
        }
    }
    // å¦‚果没有重复,返回 false
    return false;
}
// è®¾ç½®æ•°æ®åº“连接
void SECSRuntimeManager::setDatabase(BL::Database* db) {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_pDB = db;
}
// åˆå§‹åŒ–SECS设置管理库
bool SECSRuntimeManager::initRuntimeSetting() {
    char path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
    std::string exePath(path);
    std::string dbFileDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
    if (!CreateDirectory(dbFileDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError()) {
        throw std::runtime_error("Failed to create database directory.");
    }
    std::string dbFilePath = dbFileDir + "\\" + DATABASE_FILE;
    if (!m_pDB->connect(dbFilePath, true)) {
        return false;
    }
   // åˆå§‹åŒ– SystemSV è¡¨
   initSystemSVTable();
   // åˆå§‹åŒ– EqpSV è¡¨
   initEqpSVTable();
   // åˆå§‹åŒ– SystemDV è¡¨
    initSystemDVTable();
   // åˆå§‹åŒ– EqpDV è¡¨
   initEqpDVTable();
   // åˆå§‹åŒ– SystemEC è¡¨
   initSystemECTable();
   // åˆå§‹åŒ– EqpEC è¡¨
   initEqpECTable();
   // åˆå§‹åŒ– SystemECID è¡¨
   initSystemEventTable();
   // åˆå§‹åŒ– EqpECID è¡¨
   initEqpEventTable();
   // åˆå§‹åŒ– SystemEventLink è¡¨
   initEventLinkTable();
   // åˆå§‹åŒ– PPID è¡¨
   initPPIDTable();
   // åˆå§‹åŒ– RPTID è¡¨
   initRPTIDTable();
    return true;
}
// é”€æ¯SECS设置管理库
void SECSRuntimeManager::termRuntimeSetting() {
    if (m_pDB != nullptr) {
        m_pDB->disconnect();
    }
}
// åˆå§‹åŒ– SystemSV è¡¨
void SECSRuntimeManager::initSystemSVTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º SystemSV è¡¨ï¼ˆå¦‚果不存在)
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS SystemSV ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "Length INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SystemID INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create SystemSV table.");
    }
    // é¢„定义的 SV æ•°æ®
    std::vector<std::tuple<int, std::string, std::string, int, std::string, std::string, int>> svData = {
        {1, "SYS_LICENSE_CODE", "ASCII", 0, "NULL", "License code (Formal; Evaluation; NoLicense)", 1},
        {2, "SYS_LICENSE_STATUS", "UINT_1", 0, "NULL", "License status(0:Unauthorized; 1:Authorized; 2:Evaluation; 3:Evaluation Expiring; 4:Trial; 5:Trial End)", 2},
        {3, "GEM_CLOCK", "ASCII", 0, "NULL", "System Clock", 3},
        {4, "SYS_SECS_COMM_MODE", "UINT_1", 0, "NULL", "SECS Communication Mode(0:HSMS Mode; 1:SECSI Mode)", 4},
        {5, "SYS_SECS_DRIVER_CONNECT_STATE", "UINT_1", 0, "NULL", "Initial SECS Driver Connect State(0:Stop; 1:Start)", 5}
    };
    for (const auto& entry : svData) {
        int nID, nLength, nSystemID;
        std::string sName, sDataType, sRemark, sUnit;
        std::tie(nID, sName, sDataType, nLength, sUnit, sRemark, nSystemID) = entry;
        // æ£€æŸ¥ Name æ˜¯å¦å·²å­˜åœ¨
        int count = getIntFromDB("SELECT COUNT(*) FROM SystemSV WHERE Name = '" + sName + "';");
        if (count == 0) {
            // æ’入数据
            std::string insertSQL = "INSERT INTO SystemSV (ID, Name, DataType, Length, Unit, Remark, SystemID) VALUES ("
                + std::to_string(nID) + ", '"
                + sName + "', '"
                + sDataType + "', "
                + (nLength > 0 ? std::to_string(nLength) : "NULL") + ", "
                + ((sUnit == "NULL") ? "NULL" : "'" + sUnit + "'") + ", '"
                + sRemark + "', "
                + std::to_string(nSystemID) + ");";
            if (!m_pDB->executeQuery(insertSQL)) {
                throw std::runtime_error("Failed to insert SystemSV data.");
            }
        }
    }
}
// æ·»åŠ  SystemSV æ•°æ®
int SECSRuntimeManager::addSystemSV(int nID, const std::string& sName, const std::string& sDataType, int nLength, const std::string& sUnit, const std::string& sRemark, int nSystemID) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    if (isIDDuplicate(nID)) {
      return 2;
    }
    if (isNameDuplicate(sName)) {
        return 3;
    }
    // å¦‚æžœ Unit æ˜¯ "NULL" å­—符串或者为空,则插入 NULL å€¼
    std::string insertSQL = "INSERT INTO SystemSV (ID, Name, DataType, Length, Unit, Remark, SystemID) VALUES ("
        + std::to_string(nID) + ", '"
        + sName + "', '"
        + sDataType + "', "
        + (nLength > 0 ? std::to_string(nLength) : "NULL") + ", "
        + ((sUnit == "NULL" || sUnit.empty()) ? "NULL" : "'" + sUnit + "'") + ", '"
        + sRemark + "', "
        + std::to_string(nSystemID) + ");";
    if (!m_pDB->executeQuery(insertSQL)) {
        return 4;
    }
    return 0;
}
// æ›´æ–°æŒ‡å®š ID çš„ SystemSV æ•°æ®
int SECSRuntimeManager::updateIDSystemSV(int nID, int sNewID) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    // æ£€æŸ¥æ˜¯å¦å­˜åœ¨è¯¥ ID
    if (!isIDDuplicate(nID)) {
        return 2;
    }
    if (isIDDuplicate(sNewID)) {
        return 3;
    }
    // æž„建更新的 SQL è¯­å¥
    std::string updateSQL = "UPDATE SystemSV SET ID = " + std::to_string(sNewID) + " WHERE ID = " + std::to_string(nID) + ";";
    if (!m_pDB->executeQuery(updateSQL)) {
        return 4;
    }
    return 0;
}
// æ›´æ–°æ‰€æœ‰ SystemSV æ•°æ®
int SECSRuntimeManager::updateAllSystemSV(int nID, int sNewID, const std::string& sName, const std::string& sDataType, int nLength, const std::string& sUnit, const std::string& sRemark, int nSystemID) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    // æ£€æŸ¥æ˜¯å¦å­˜åœ¨è¯¥ ID
    if (!isIDDuplicate(nID)) {
        return 2;
    }
    // æ£€æŸ¥æ–°çš„ ID æ˜¯å¦å·²å­˜åœ¨ï¼Œå¦‚果已存在,则返回错误代码 3。
    if (isIDDuplicate(sNewID)) {
        return 3;
    }
    // æž„建更新的 SQL è¯­å¥
    std::string updateSQL = "UPDATE SystemSV SET ";
    bool firstField = true;
    // å¦‚果新的 ID è¢«æä¾›ï¼Œæ›´æ–° ID
    if (sNewID > 0) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "ID = " + std::to_string(sNewID);
        firstField = false;
    }
    // æ›´æ–° Name
    if (!sName.empty()) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "Name = '" + sName + "'";
        firstField = false;
    }
    // æ›´æ–° DataType
    if (!sDataType.empty()) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "DataType = '" + sDataType + "'";
        firstField = false;
    }
    // æ›´æ–° Length
    if (nLength > 0) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "Length = " + std::to_string(nLength);
        firstField = false;
    }
    // æ›´æ–° Unit
    if (sUnit != "NULL" && !sUnit.empty()) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "Unit = '" + sUnit + "'";
        firstField = false;
    }
    else if (sUnit == "NULL") {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "Unit = NULL";
        firstField = false;
    }
    // æ›´æ–° Remark
    if (!sRemark.empty()) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "Remark = '" + sRemark + "'";
        firstField = false;
    }
    // æ›´æ–° SystemID
    if (nSystemID > 0) {
        if (!firstField) {
            updateSQL += ", ";
        }
        updateSQL += "SystemID = " + std::to_string(nSystemID);
    }
    // æ·»åŠ  WHERE å­å¥æ¥æŒ‡å®šæ›´æ–°å“ªä¸ªè®°å½•
    updateSQL += " WHERE ID = " + std::to_string(nID) + ";";
    // æ‰§è¡Œæ›´æ–°æ“ä½œ
    if (!m_pDB->executeQuery(updateSQL)) {
      return 4;
    }
    return 0;
}
// åˆ é™¤æŒ‡å®š ID çš„ SystemSV æ•°æ®
int SECSRuntimeManager::deleteSystemSVByID(int nID) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    // æ£€æŸ¥æ˜¯å¦å­˜åœ¨è¯¥ ID
    if (!isIDDuplicate(nID)) {
        return 2;
    }
    // æž„建删除的 SQL è¯­å¥
    std::string deleteSQL = "DELETE FROM SystemSV WHERE ID = " + std::to_string(nID) + ";";
    if (!m_pDB->executeQuery(deleteSQL)) {
        return 3;
    }
    return 0;
}
int SECSRuntimeManager::deleteAllSystemSV() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    // æž„建删除所有数据的 SQL è¯­å¥
    std::string deleteSQL = "DELETE FROM SystemSV;";
    if (!m_pDB->executeQuery(deleteSQL)) {
        return 2;
    }
    return 0; // åˆ é™¤æˆåŠŸï¼Œè¿”å›ž 0 è¡¨ç¤ºæ“ä½œæˆåŠŸå®Œæˆã€‚
}
// åˆå§‹åŒ– EqpSV è¡¨
void SECSRuntimeManager::initEqpSVTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º EqpSV è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS EqpSV ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "Length INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SeqNo INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create EqpSV table.");
    }
}
// æ·»åŠ  EqpSV æ•°æ®
int SECSRuntimeManager::addEqpSV(int nID, const std::string& sName, const std::string& sDataType, int nLength, const std::string& sUnit, const std::string& sRemark, int nSeqNo) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        return 1;
    }
    if (isIDDuplicate(nID)) {
        return 2;
    }
    if (isNameDuplicate(sName)) {
        return 3;
    }
    // æž„建 SQL æ’入语句,插入数据到 EqpSV è¡¨ä¸­ã€‚
    std::string insertSQL = "INSERT INTO EqpSV (ID, Name, DataType, Length, Unit, Remark, SeqNo) VALUES ("
        + std::to_string(nID) + ", '"
        + sName + "', '"
        + sDataType + "', "
        + ((nLength <= 0) ? "NULL" : std::to_string(nLength))+", "
        + ((sUnit == "NULL" || sUnit.empty()) ? "NULL" : "'" + sUnit + "'")+", '"
        + sRemark + "', "
        + std::to_string(nSeqNo) + ");";
    // æ‰§è¡Œæ’入操作,若失败则抛出异常。
    if (!m_pDB->executeQuery(insertSQL)) {
        return 4;
    }
    return 0; // æ’入成功,返回 0 è¡¨ç¤ºæ“ä½œæˆåŠŸå®Œæˆã€‚
}
// åˆå§‹åŒ– SystemDV è¡¨
void SECSRuntimeManager::initSystemDVTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º SystemDV è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS SystemDV ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "Length INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SystemID INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create SystemDV table.");
    }
}
// åˆå§‹åŒ– EqpDV è¡¨
void SECSRuntimeManager::initEqpDVTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º EqpDV è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS EqpDV ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "Length INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SeqNo INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create EqpDV table.");
    }
}
// åˆå§‹åŒ– SystemEC è¡¨
void SECSRuntimeManager::initSystemECTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º SystemEC è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS SystemEC ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "MinValue INTEGER NULL, "
        "MaxValue INTEGER NULL, "
        "DefaultVal INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SystemID INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create SystemEC table.");
    }
}
// åˆå§‹åŒ– EqpEC è¡¨
void SECSRuntimeManager::initEqpECTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º EqpEC è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS EqpEC ("
        "ID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "DataType TEXT NOT NULL, "
        "MinValue INTEGER NULL, "
        "MaxValue INTEGER NULL, "
        "DefaultValue INTEGER NULL, "
        "Unit TEXT NULL, "
        "Remark TEXT, "
        "SeqNo INTEGER NOT NULL, "
        "Length INTEGER NOT NULL, "
        "CanUpdateByHost INTEGER NOT NULL);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create EqpEC table.");
    }
}
// åˆå§‹åŒ– SystemEvent è¡¨
void SECSRuntimeManager::initSystemEventTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º SystemEvent è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS SystemEvent ("
        "CEID INTEGER PRIMARY KEY, "
        "Name TEXT UNIQUE NOT NULL, "
        "Remark TEXT, "
        "SystemID INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create SystemEvent table.");
    }
}
// åˆå§‹åŒ– EqpEvent è¡¨
void SECSRuntimeManager::initEqpEventTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º EqpEvent è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS EqpEvent ("
        "CEID INTEGER PRIMARY KEY AUTOINCREMENT, "
        "Name TEXT UNIQUE NOT NULL, "
        "Remark TEXT, "
        "BitNo INTEGER);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create EqpEvent table.");
    }
}
// åˆå§‹åŒ– EventLink è¡¨
void SECSRuntimeManager::initEventLinkTable() {
   std::lock_guard<std::mutex> lock(m_mutex);
   if (m_pDB == nullptr) {
      throw std::runtime_error("Database not connected.");
   }
    // åˆ›å»º EventLink è¡¨
    std::string createEventLinkSQL =
        "CREATE TABLE IF NOT EXISTS EventLink ("
        "CEID INTEGER, "
        "RPTID INTEGER, "
        "FOREIGN KEY (CEID) REFERENCES EqpEvent(CEID));";
    if (!m_pDB->executeQuery(createEventLinkSQL)) {
        throw std::runtime_error("Failed to create EventLink table.");
    }
}
// åˆå§‹åŒ– PPID è¡¨
void SECSRuntimeManager::initPPIDTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º EqpPPID è¡¨
    std::string createTableSQL =
        "CREATE TABLE IF NOT EXISTS EqpPPID ("
        "BitNo INTEGER PRIMARY KEY AUTOINCREMENT, "
        "PPID INTEGER NULL);";
    if (!m_pDB->executeQuery(createTableSQL)) {
        throw std::runtime_error("Failed to create EqpPPID table.");
    }
    // å…ˆæ£€æŸ¥è¡¨æ˜¯å¦ä¸ºç©º
    int nCount = getIntFromDB("SELECT COUNT(*) FROM EqpPPID;");
    if (nCount == 0) {
        // æ’入初始数据(512 è¡Œï¼‰
        for (int nBitNo = 0; nBitNo < 512; ++nBitNo) {
            std::string insertSQL = "INSERT INTO EqpPPID (BitNo) VALUES (" + std::to_string(nBitNo) + ");";
            if (!m_pDB->executeQuery(insertSQL)) {
                throw std::runtime_error("Failed to insert data into EqpPPID table.");
            }
        }
    }
}
// åˆå§‹åŒ– RPTID è¡¨
void SECSRuntimeManager::initRPTIDTable() {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_pDB == nullptr) {
        throw std::runtime_error("Database not connected.");
    }
    // åˆ›å»º RPTID ç›¸å…³è¡¨
    std::string createReportTableSQL =
        "CREATE TABLE IF NOT EXISTS Report ("
        "RPTID INTEGER PRIMARY KEY);";
    std::string createReportVIDsTableSQL =
        "CREATE TABLE IF NOT EXISTS ReportVIDs ("
        "ID INTEGER PRIMARY KEY AUTOINCREMENT, "
        "RPTID INTEGER NOT NULL, "
        "VID INTEGER NOT NULL, "
        "FOREIGN KEY (RPTID) REFERENCES Report(RPTID));";
    if (!m_pDB->executeQuery(createReportTableSQL)) {
        throw std::runtime_error("Failed to create Report table.");
    }
    if (!m_pDB->executeQuery(createReportVIDsTableSQL)) {
        throw std::runtime_error("Failed to create ReportVIDs table.");
    }
}