feat(0035a): tipo Group + columna group_id en entities
Plumbing para issue 0035 — agrupacion de resultados de enrichers cuando exceden umbral. Sin cambios visibles para el usuario todavia. - Migracion idempotente: ALTER TABLE entities ADD COLUMN group_id si no existe (detectado via PRAGMA table_info). Se ejecuta al abrir el proyecto en switch_to_project y en el bootstrap inicial. - Tipo Group en examples/types.yaml (template) y en el types.yaml del proyecto default activo en Windows. - shape=square (regla en types_registry.cpp extendida a Group), color=#94A3B8, icon=ti-stack-2. - Fields: name (req), count (int), enricher (string), batch_id (string). Refs: issues/0035a-group-type-and-schema.md
This commit is contained in:
@@ -55,6 +55,7 @@ CREATE TABLE IF NOT EXISTS entities (
|
||||
source TEXT NOT NULL DEFAULT 'graph_explorer',
|
||||
metadata TEXT NOT NULL DEFAULT '{}',
|
||||
notes TEXT NOT NULL DEFAULT '',
|
||||
group_id TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
|
||||
);
|
||||
@@ -300,6 +301,76 @@ static bool bootstrap_operations_db(const std::string& path, std::string* error_
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Migraciones idempotentes de operations.db existente
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Cada migracion es un check + ALTER TABLE / CREATE ... condicional. Se
|
||||
// ejecuta una vez al abrir un proyecto (project_migrate_schema). Detecta el
|
||||
// estado actual via PRAGMA table_info y ejecuta solo lo que falta. No-op si
|
||||
// la BD ya esta al dia.
|
||||
//
|
||||
// Issue 0035a: anade columna entities.group_id (TEXT NULL) si no existe.
|
||||
|
||||
// Devuelve true si la columna `column` existe en la tabla `table`.
|
||||
static bool table_has_column(sqlite3* db, const char* table, const char* column) {
|
||||
std::string sql = "PRAGMA table_info(";
|
||||
sql += table;
|
||||
sql += ");";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
return false;
|
||||
}
|
||||
bool found = false;
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const unsigned char* name = sqlite3_column_text(stmt, 1);
|
||||
if (name && std::strcmp(reinterpret_cast<const char*>(name), column) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool project_migrate_schema(const std::string& path, std::string* error_msg) {
|
||||
sqlite3* db = nullptr;
|
||||
int rc = sqlite3_open_v2(path.c_str(), &db,
|
||||
SQLITE_OPEN_READWRITE, nullptr);
|
||||
if (rc != SQLITE_OK) {
|
||||
if (error_msg) {
|
||||
*error_msg = "sqlite3_open failed: ";
|
||||
*error_msg += db ? sqlite3_errmsg(db) : sqlite3_errstr(rc);
|
||||
}
|
||||
if (db) sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 0035a: entities.group_id
|
||||
if (!table_has_column(db, "entities", "group_id")) {
|
||||
char* errmsg = nullptr;
|
||||
rc = sqlite3_exec(db,
|
||||
"ALTER TABLE entities ADD COLUMN group_id TEXT",
|
||||
nullptr, nullptr, &errmsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
if (error_msg) {
|
||||
*error_msg = "ALTER TABLE entities ADD COLUMN group_id failed: ";
|
||||
*error_msg += errmsg ? errmsg : "(unknown)";
|
||||
}
|
||||
if (errmsg) sqlite3_free(errmsg);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
if (errmsg) sqlite3_free(errmsg);
|
||||
std::fprintf(stdout,
|
||||
"[project_manager] migrated %s: ALTER TABLE entities ADD COLUMN group_id\n",
|
||||
path.c_str());
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// project_create
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user