Files
fn_registry/cpp/functions/viz/graph_sources.h
T
egutierrez 54cee13e8e feat(viz): graph_sources lector operations.db + streaming (issue 0049g)
- graph_load_from_operations: SQLite read-only, schema-detect (type_ref/type,
  from_entity/source, to_entity/target, name/type, weight, updated_at).
- 16-color indigo palette por hash FNV1a32 del nombre de tipo. user_data
  por nodo es FNV1a64(entity.id) — deterministico entre cargas.
- Label pool interno: metadata.name (JSON simple) > entities.name > id.
- graph_free libera nodes/edges/types/rel_types/labels/strdup'd names via
  arena_map (GraphData* -> arena).
- Streaming pull-based con tiebreak (updated_at, id) y crecimiento x2 de
  capacidad. Tipos nuevos descubiertos en stream se anaden a types.
- Tests: fixture in-memory (3 entity types, 2 rel types, 10 entities,
  15 relations) + smoke contra apps/script_navegador/operations.db.
- Issue movido a completed/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:12:31 +02:00

58 lines
2.4 KiB
C++

#pragma once
#include <cstdint>
#include "graph_types.h"
// Lectores de grafos para `GraphData` (issue 0049g). Disenado como un set de
// funciones con la misma firma `GraphLoadFn` para que anadir un backend nuevo
// (JSON, JSONL, GraphML, etc.) sea declarar otra funcion compatible — el
// resto del codigo (apps, viewport, force layout) no cambia.
//
// Esquema soportado de operations.db:
// entities (id, type_ref|type, name?, metadata?, updated_at)
// relations (id, from_entity|source, to_entity|target, name?, type?,
// weight?, updated_at)
// La funcion detecta los nombres reales via `PRAGMA table_info` y mapea:
// - entity.type_ref / entity.type → EntityType (color por hash de nombre)
// - relation.name (o type) → RelationType
// - entity.id → user_data (FNV1a 64), label
// - entity.metadata.name (json) → label si existe, else id
namespace graph {
struct GraphLoadStats {
int nodes_loaded;
int edges_loaded;
int types_discovered;
int rel_types_discovered;
int errors;
char error_msg[256];
};
// Firma uniforme para todos los backends. `uri` es opaco — para
// `graph_load_from_operations` es el path de un fichero SQLite.
typedef bool (*GraphLoadFn)(const char* uri, GraphData* out, GraphLoadStats* stats);
// Carga sincrona de operations.db. Allocs propios en out (nodes/edges/types/
// rel_types + string pool interno). El caller libera con graph_free.
bool graph_load_from_operations(const char* db_path, GraphData* out, GraphLoadStats* stats);
// Libera toda la memoria alocada por graph_load_from_operations (incluyendo
// los nombres de tipos y el label pool). Deja la struct a cero.
void graph_free(GraphData* graph);
// Devuelve el label de un nodo. Si label_idx == 0 o no hay pool, retorna "".
const char* graph_label(const GraphData* graph, uint32_t label_idx);
// --- Streaming --------------------------------------------------------------
// Pull-based: el caller invoca pull cada N ms y la fuente devuelve cuantas
// entidades/relaciones nuevas anadio in-place al GraphData. Si no hay sitio
// (capacity), corta y devuelve cuanto pudo escribir; el caller decide si
// reallocar.
struct GraphStreamSource;
GraphStreamSource* graph_stream_operations_open(const char* db_path, int poll_ms);
int graph_stream_pull(GraphStreamSource* src, GraphData* graph);
void graph_stream_close(GraphStreamSource* src);
} // namespace graph