4456d58abe
Demo nuevo en demos_sql.cpp: abre registry.db en SQLITE_OPEN_READONLY (resolviendo via FN_REGISTRY_ROOT o cwd ascendente), monta fn::SqlWorkbenchState con readonly=true y query inicial sobre la tabla functions. Wire-up: entry en k_demos[] tras process_runner; declaracion en demos.h; sources sql_workbench.cpp + demos_sql.cpp + link SQLite::SQLite3 en CMakeLists.txt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
130 lines
3.7 KiB
C++
130 lines
3.7 KiB
C++
// Demo de sql_workbench (Core, issue 0032).
|
|
//
|
|
// Abre `registry.db` en modo readonly y deja que el componente liste sus
|
|
// tablas en la sidebar. La idea es probar el ciclo Run + tabla + historial
|
|
// contra una DB real sin riesgo de mutarla.
|
|
|
|
#include "demos.h"
|
|
#include "demo.h"
|
|
|
|
#include "core/sql_workbench.h"
|
|
#include "core/tokens.h"
|
|
|
|
#include <imgui.h>
|
|
#include <sqlite3.h>
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
namespace gallery {
|
|
|
|
namespace {
|
|
|
|
struct SqlDemoState {
|
|
sqlite3* db = nullptr;
|
|
fn::SqlWorkbenchState wb;
|
|
bool tried_open = false;
|
|
std::string db_path;
|
|
std::string open_error;
|
|
};
|
|
|
|
SqlDemoState& state() {
|
|
static SqlDemoState s;
|
|
return s;
|
|
}
|
|
|
|
// Resuelve la ruta a registry.db: env FN_REGISTRY_ROOT/registry.db si existe,
|
|
// si no, prueba ./registry.db, ../registry.db, ../../registry.db (build tree).
|
|
std::string resolve_registry_db() {
|
|
if (const char* env = std::getenv("FN_REGISTRY_ROOT")) {
|
|
std::string p = std::string(env) + "/registry.db";
|
|
if (FILE* f = std::fopen(p.c_str(), "rb")) { std::fclose(f); return p; }
|
|
}
|
|
const char* candidates[] = {
|
|
"registry.db",
|
|
"../registry.db",
|
|
"../../registry.db",
|
|
"../../../registry.db",
|
|
"../../../../registry.db",
|
|
};
|
|
for (const char* c : candidates) {
|
|
if (FILE* f = std::fopen(c, "rb")) { std::fclose(f); return c; }
|
|
}
|
|
return "";
|
|
}
|
|
|
|
void ensure_open() {
|
|
auto& s = state();
|
|
if (s.tried_open) return;
|
|
s.tried_open = true;
|
|
|
|
s.db_path = resolve_registry_db();
|
|
if (s.db_path.empty()) {
|
|
s.open_error = "registry.db not found (tried FN_REGISTRY_ROOT and parent dirs)";
|
|
return;
|
|
}
|
|
int rc = sqlite3_open_v2(s.db_path.c_str(), &s.db,
|
|
SQLITE_OPEN_READONLY, nullptr);
|
|
if (rc != SQLITE_OK) {
|
|
s.open_error = sqlite3_errmsg(s.db);
|
|
if (s.db) { sqlite3_close(s.db); s.db = nullptr; }
|
|
return;
|
|
}
|
|
s.wb.readonly = true;
|
|
// Query inicial mas util para el demo: lista de funciones del registry.
|
|
s.wb.query =
|
|
"SELECT id, kind, purity, domain\n"
|
|
"FROM functions\n"
|
|
"ORDER BY id\n"
|
|
"LIMIT 50;";
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void demo_sql_workbench() {
|
|
using namespace fn_tokens;
|
|
|
|
demo_header("sql_workbench", "v1.0.0",
|
|
"Workbench SQL: editor con highlighting, schema sidebar, tabla de "
|
|
"resultados e historial. Ejecuta queries contra una sqlite3* del caller. "
|
|
"En este demo, registry.db abierto en modo readonly.");
|
|
|
|
ensure_open();
|
|
auto& s = state();
|
|
|
|
if (!s.open_error.empty()) {
|
|
ImGui::PushStyleColor(ImGuiCol_Text, colors::error);
|
|
ImGui::TextWrapped("could not open registry.db: %s", s.open_error.c_str());
|
|
ImGui::PopStyleColor();
|
|
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted);
|
|
ImGui::TextWrapped("Set FN_REGISTRY_ROOT to the repo root or run from the repo cwd.");
|
|
ImGui::PopStyleColor();
|
|
return;
|
|
}
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_dim);
|
|
ImGui::Text("db: %s (readonly)", s.db_path.c_str());
|
|
ImGui::PopStyleColor();
|
|
|
|
section("workbench");
|
|
{
|
|
ImVec2 avail = ImGui::GetContentRegionAvail();
|
|
// Reserva un pelin para el code_block de abajo.
|
|
float h = avail.y - 110.0f;
|
|
if (h < 320.0f) h = 320.0f;
|
|
fn::sql_workbench("##gallery_sql", s.db, s.wb, ImVec2(-1, h));
|
|
}
|
|
|
|
code_block(
|
|
"sqlite3* db = nullptr;\n"
|
|
"sqlite3_open_v2(\"registry.db\", &db, SQLITE_OPEN_READONLY, nullptr);\n"
|
|
"fn::SqlWorkbenchState st;\n"
|
|
"st.readonly = true;\n"
|
|
"fn::sql_workbench(\"##sql\", db, st, ImVec2(-1, -1));"
|
|
);
|
|
}
|
|
|
|
} // namespace gallery
|