2 Commits
4 changed files with 59 additions and 1 deletions
+3
View File
@@ -246,6 +246,9 @@ bool PowerManger::OnStartUp()
loguru::add_file(logPath.c_str(), loguru::Append, loguru::Verbosity_MAX);
LOG_F(INFO, "日志文件路径: %s", logPath.c_str());
// 网页日志监控使用同一文件(默认相对路径在 systemd WorkingDirectory 下打不开)
if (m_httpServer) m_httpServer->setLogFilePath(logPath);
// 初始化数据库:dbpath 未配置则默认当前目录
if (dbPath.empty()) dbPath = "power_data.db";
LOG_F(INFO, "数据库存储路径: %s", dbPath.c_str());
+5
View File
@@ -86,6 +86,11 @@ private:
static const size_t MAX_CACHE_SIZE = 1000; // 最大缓存条数
static const size_t MAX_WS_BACKLOG = 256 * 1024; // WebSocket发送积压阈值,超过则跳过推送
public:
// 设置被监控的日志文件路径(须与 logpath 配置一致;
// 默认相对路径在 systemd WorkingDirectory 下会打开失败)
void setLogFilePath(const std::string& path) { m_logFilePath = path; }
};
#endif // HTTP_SERVER_H
+50 -1
View File
@@ -7,7 +7,7 @@
#include "../logc/loguru.hpp"
namespace {
const int SCHEMA_VERSION = 1;
const int SCHEMA_VERSION = 2;
}
//====================================================================
@@ -463,6 +463,10 @@ bool SQLite::migrate()
if (!createAllTablesUnlocked()) return false;
// 老库缺列自动补齐(协议演进新增字段后,旧表由 CREATE TABLE IF NOT EXISTS
// 创建、不会带新列,导致 INSERT prepare 失败、该表数据无法落库)
if (!migrateColumnsUnlocked()) return false;
if (version < SCHEMA_VERSION) {
std::string sql = "PRAGMA user_version = " + std::to_string(SCHEMA_VERSION) + ";";
sqlite3_exec(m_db, sql.c_str(), nullptr, nullptr, nullptr);
@@ -470,6 +474,51 @@ bool SQLite::migrate()
return true;
}
//====================================================================
// migrateColumnsUnlocked:按注册表逐一对比表现有列,缺哪列补哪列
// (ALTER TABLE ADD COLUMN,新增列对旧行取默认值 0/NULL)。
//====================================================================
bool SQLite::migrateColumnsUnlocked()
{
for (const TableDesc& t : allTables()) {
// 读取现有列(PRAGMA table_info 第 2 列为列名)
std::vector<std::string> existing;
sqlite3_stmt* stmt = nullptr;
std::string pragma = std::string("PRAGMA table_info(") + t.name + ");";
if (sqlite3_prepare_v2(m_db, pragma.c_str(), -1, &stmt, nullptr) == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
const unsigned char* name = sqlite3_column_text(stmt, 1);
if (name) existing.push_back(reinterpret_cast<const char*>(name));
}
sqlite3_finalize(stmt);
}
if (existing.empty()) continue; // 表不存在(新库),建表时已含全部列
for (const Column& c : t.columns) {
bool found = false;
for (const std::string& e : existing) {
if (e == c.name) { found = true; break; }
}
if (found) continue;
std::string sql = std::string("ALTER TABLE ") + t.name +
" ADD COLUMN " + c.name + " " + c.sqlType + ";";
char* errMsg = nullptr;
int rc = sqlite3_exec(m_db, sql.c_str(), nullptr, nullptr, &errMsg);
if (rc == SQLITE_OK) {
LOG_F(INFO, "SQLite 迁移: 表 %s 新增列 %s", t.name, c.name);
} else {
// 记录失败但不中断打开:其余列/表继续尝试,
// 未补齐列的 insert 仍会按原样报 prepare 错误
m_lastError = errMsg ? errMsg : "alter table failed";
LOG_F(ERROR, "SQLite 迁移失败: %s (%s)", sql.c_str(), m_lastError.c_str());
if (errMsg) sqlite3_free(errMsg);
}
}
}
return true;
}
bool SQLite::createTableInternal(const std::string& tableName, const std::string& columns)
{
std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName + " (" + columns + ");";
+1
View File
@@ -65,6 +65,7 @@ private:
bool migrate();
bool createTableInternal(const std::string& tableName, const std::string& columns);
bool createAllTablesUnlocked();
bool migrateColumnsUnlocked();
// 列描述:名称 + SQL 类型 + 绑定器(无捕获函数指针)
struct Column {