54cee13e8e
- 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>
58 lines
2.4 KiB
C++
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
|