Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38c489caec | ||
|
|
b77dc8cf5a |
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 + ");";
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
bool migrate();
|
||||
bool createTableInternal(const std::string& tableName, const std::string& columns);
|
||||
bool createAllTablesUnlocked();
|
||||
bool migrateColumnsUnlocked();
|
||||
|
||||
// 列描述:名称 + SQL 类型 + 绑定器(无捕获函数指针)
|
||||
struct Column {
|
||||
|
||||
Reference in New Issue
Block a user