Files
registry_dashboard/data.cpp
T

189 lines
6.2 KiB
C++

#include "data.h"
#include <sqlite3.h>
#include <cstdio>
// Helper: execute a query and call row_fn for each row
template<typename F>
static bool query(sqlite3* db, const char* sql, F row_fn) {
sqlite3_stmt* stmt = nullptr;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n query: %s\n", sqlite3_errmsg(db), sql);
return false;
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
row_fn(stmt);
}
sqlite3_finalize(stmt);
return true;
}
static std::string col_str(sqlite3_stmt* s, int i) {
const char* t = reinterpret_cast<const char*>(sqlite3_column_text(s, i));
return t ? t : "";
}
static int col_int(sqlite3_stmt* s, int i) {
return sqlite3_column_int(s, i);
}
void RegistryData::prepare_chart_data() {
lang_labels.clear(); lang_values.clear();
for (auto& lc : by_lang) {
lang_labels.push_back(lc.lang);
lang_values.push_back(static_cast<float>(lc.count));
}
domain_labels.clear(); domain_values.clear();
for (auto& dc : by_domain) {
domain_labels.push_back(dc.domain);
domain_values.push_back(static_cast<float>(dc.count));
}
kind_labels.clear(); kind_values.clear();
for (auto& kc : by_kind) {
kind_labels.push_back(kc.kind);
kind_values.push_back(static_cast<float>(kc.count));
}
date_labels.clear(); date_values.clear();
for (auto& dc : by_date) {
date_labels.push_back(dc.date);
date_values.push_back(static_cast<float>(dc.count));
}
}
bool load_registry_data(const char* db_path, RegistryData& out) {
sqlite3* db = nullptr;
if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) {
fprintf(stderr, "Cannot open %s: %s\n", db_path, sqlite3_errmsg(db));
return false;
}
// --- Counts ---
query(db, "SELECT COUNT(*) FROM functions", [&](sqlite3_stmt* s) {
out.stats.total_functions = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM types", [&](sqlite3_stmt* s) {
out.stats.total_types = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM apps", [&](sqlite3_stmt* s) {
out.stats.total_apps = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM analysis", [&](sqlite3_stmt* s) {
out.stats.total_analysis = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM unit_tests", [&](sqlite3_stmt* s) {
out.stats.total_unit_tests = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM proposals", [&](sqlite3_stmt* s) {
out.stats.total_proposals = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM functions WHERE tested = 1", [&](sqlite3_stmt* s) {
out.stats.tested_functions = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM functions WHERE purity = 'pure'", [&](sqlite3_stmt* s) {
out.stats.pure_functions = col_int(s, 0);
});
query(db, "SELECT COUNT(*) FROM functions WHERE purity = 'impure'", [&](sqlite3_stmt* s) {
out.stats.impure_functions = col_int(s, 0);
});
// --- By language ---
out.by_lang.clear();
query(db, "SELECT lang, COUNT(*) as cnt FROM functions GROUP BY lang ORDER BY cnt DESC",
[&](sqlite3_stmt* s) {
out.by_lang.push_back({col_str(s, 0), col_int(s, 1)});
});
// --- By domain ---
out.by_domain.clear();
query(db, "SELECT domain, COUNT(*) as cnt FROM functions GROUP BY domain ORDER BY cnt DESC",
[&](sqlite3_stmt* s) {
out.by_domain.push_back({col_str(s, 0), col_int(s, 1)});
});
// --- By kind ---
out.by_kind.clear();
query(db, "SELECT kind, COUNT(*) as cnt FROM functions GROUP BY kind ORDER BY cnt DESC",
[&](sqlite3_stmt* s) {
out.by_kind.push_back({col_str(s, 0), col_int(s, 1)});
});
// --- By date (last 30 days) ---
out.by_date.clear();
query(db,
"SELECT date(created_at) as d, COUNT(*) as cnt FROM functions "
"WHERE created_at >= date('now', '-30 days') "
"GROUP BY d ORDER BY d",
[&](sqlite3_stmt* s) {
out.by_date.push_back({col_str(s, 0), col_int(s, 1)});
});
// --- Recent functions (last 20) ---
out.recent_funcs.clear();
query(db,
"SELECT id, name, lang, domain, kind, purity, description, created_at, tested "
"FROM functions ORDER BY created_at DESC LIMIT 20",
[&](sqlite3_stmt* s) {
FunctionRow r;
r.id = col_str(s, 0);
r.name = col_str(s, 1);
r.lang = col_str(s, 2);
r.domain = col_str(s, 3);
r.kind = col_str(s, 4);
r.purity = col_str(s, 5);
r.description = col_str(s, 6);
r.created_at = col_str(s, 7);
r.tested = col_int(s, 8) != 0;
out.recent_funcs.push_back(std::move(r));
});
// --- Apps ---
out.apps.clear();
query(db,
"SELECT id, name, lang, domain, description, framework FROM apps ORDER BY name",
[&](sqlite3_stmt* s) {
AppRow r;
r.id = col_str(s, 0);
r.name = col_str(s, 1);
r.lang = col_str(s, 2);
r.domain = col_str(s, 3);
r.description = col_str(s, 4);
r.framework = col_str(s, 5);
out.apps.push_back(std::move(r));
});
// --- Analysis ---
out.analyses.clear();
query(db,
"SELECT id, name, domain, description FROM analysis ORDER BY name",
[&](sqlite3_stmt* s) {
AnalysisRow r;
r.id = col_str(s, 0);
r.name = col_str(s, 1);
r.domain = col_str(s, 2);
r.description = col_str(s, 3);
out.analyses.push_back(std::move(r));
});
// --- Types ---
out.types.clear();
query(db,
"SELECT id, name, lang, domain, algebraic, description FROM types ORDER BY name",
[&](sqlite3_stmt* s) {
TypeRow r;
r.id = col_str(s, 0);
r.name = col_str(s, 1);
r.lang = col_str(s, 2);
r.domain = col_str(s, 3);
r.algebraic = col_str(s, 4);
r.description = col_str(s, 5);
out.types.push_back(std::move(r));
});
sqlite3_close(db);
out.prepare_chart_data();
return true;
}