Dev User 1 ヶ月 前
コミット
e833d72122
2 ファイル変更64 行追加7 行削除
  1. 27 4
      src/store/store.cpp
  2. 37 3
      src/weblog/weblog.cpp

+ 27 - 4
src/store/store.cpp

@@ -46,6 +46,29 @@ bool exec_sql(const std::string& sql) {
     return true;
 }
 
+bool column_exists(const std::string& table, const std::string& column) {
+    SQLITE_RESULT rows;
+    if (!g_db.query("PRAGMA table_info(" + table + ")", rows)) {
+        return false;
+    }
+    for (const auto& row : rows) {
+        auto it = row.find("name");
+        if (it != row.end() && it->second == column) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool add_column_if_missing(const std::string& table, const std::string& column,
+                           const std::string& decl) {
+    if (column_exists(table, column)) {
+        return true;
+    }
+    return exec_sql("ALTER TABLE " + table + " ADD COLUMN " + column + " " +
+                    decl);
+}
+
 bool ensure_schema() {
     const char* ddl = R"SQL(
 CREATE TABLE IF NOT EXISTS websites (
@@ -75,10 +98,10 @@ CREATE TABLE IF NOT EXISTS meta (
         return false;
     }
     // Best-effort migrations for existing DBs.
-    exec_sql("ALTER TABLE websites ADD COLUMN ssl_enable INTEGER NOT NULL DEFAULT 0");
-    exec_sql("ALTER TABLE websites ADD COLUMN ssl_cert TEXT NOT NULL DEFAULT ''");
-    exec_sql("ALTER TABLE websites ADD COLUMN ssl_key TEXT NOT NULL DEFAULT ''");
-    exec_sql("ALTER TABLE websites ADD COLUMN ssl_port INTEGER NOT NULL DEFAULT 443");
+    add_column_if_missing("websites", "ssl_enable", "INTEGER NOT NULL DEFAULT 0");
+    add_column_if_missing("websites", "ssl_cert", "TEXT NOT NULL DEFAULT ''");
+    add_column_if_missing("websites", "ssl_key", "TEXT NOT NULL DEFAULT ''");
+    add_column_if_missing("websites", "ssl_port", "INTEGER NOT NULL DEFAULT 443");
     return true;
 }
 

+ 37 - 3
src/weblog/weblog.cpp

@@ -297,6 +297,31 @@ bool exec_db(ylib::sqlite3& db, const std::string& sql) {
     return true;
 }
 
+bool column_exists(ylib::sqlite3& db, const std::string& table,
+                   const std::string& column) {
+    SQLITE_RESULT rows;
+    if (!db.query("PRAGMA table_info(" + table + ")", rows)) {
+        return false;
+    }
+    for (const auto& row : rows) {
+        auto it = row.find("name");
+        if (it != row.end() && it->second == column) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool add_column_if_missing(ylib::sqlite3& db, const std::string& table,
+                           const std::string& column,
+                           const std::string& decl) {
+    if (column_exists(db, table, column)) {
+        return true;
+    }
+    return exec_db(db, "ALTER TABLE " + table + " ADD COLUMN " + column + " " +
+                           decl);
+}
+
 bool ensure_schema(ylib::sqlite3& db) {
     const char* ddl = R"SQL(
 CREATE TABLE IF NOT EXISTS access_log (
@@ -341,9 +366,18 @@ CREATE TABLE IF NOT EXISTS ingest_meta (
     if (!exec_db(db, ddl)) {
         return false;
     }
-    // Migrations for older per-site DBs.
-    exec_db(db, "ALTER TABLE access_log ADD COLUMN time_ms INTEGER NOT NULL DEFAULT 0");
-    exec_db(db, "ALTER TABLE access_log ADD COLUMN bytes_recv INTEGER NOT NULL DEFAULT 0");
+    // Older per-site DBs may lack columns that CREATE TABLE IF NOT EXISTS
+    // will not add. Only ALTER when missing.
+    add_column_if_missing(db, "access_log", "time_ms",
+                          "INTEGER NOT NULL DEFAULT 0");
+    add_column_if_missing(db, "access_log", "bytes_recv",
+                          "INTEGER NOT NULL DEFAULT 0");
+    add_column_if_missing(db, "access_log", "bytes_sent",
+                          "INTEGER NOT NULL DEFAULT 0");
+    add_column_if_missing(db, "access_log", "request_time",
+                          "REAL NOT NULL DEFAULT 0");
+    add_column_if_missing(db, "error_log", "time_ms",
+                          "INTEGER NOT NULL DEFAULT 0");
     return true;
 }