Estado: ✅ Aceptada Fecha: 2026-05-07 Contexto que la motiva: continuación de Fase 5 (AI-native) en ROADMAP.md. Implementación entregada como tool nueva en src/bin/gabysql-mcp.rs.

🧭 Contexto

El uso de bases por agentes LLM trae con él la expectativa de búsqueda semántica: dada una consulta en lenguaje natural, embeberla con un modelo y traer las filas cuyo vector está más cerca. Hoy el patrón estándar para resolverlo es:

  1. Tener un tipo VECTOR(n) nativo en el motor (ej. pgvector en Postgres).
  2. Indexarlo con un algoritmo aproximado (HNSW, IVF) para no escanear toda la tabla.
  3. Exponer operadores de distancia (<->, <=>, <#> en pgvector).

gabysql no tiene nada de eso, y meterlo bien implica:

Eso es un proyecto grande, riesgoso y con superficie de error alta, especialmente para un motor cuyo eje es estabilidad y compatibilidad del formato (ver ADR-0007). Hacerlo “para validar el use case” es exactamente la trampa que ROADMAP.md advierte: “crecer features antes de consolidar recovery, constraints y compatibilidad del storage”.

Restricciones del proyecto:

Pregunta práctica: ¿se puede entregar búsqueda vectorial usable hoy sin tocar el motor?

💡 Decisión

Implementar búsqueda vectorial en el gateway MCP (gabysql-mcp), no en el motor. Concretamente:

  1. Los vectores se almacenan como columna TEXT que contiene un array JSON de floats: "[0.1, 0.2, ..., 0.768]". El motor no sabe que es un vector — solo ve texto.
  2. El gateway expone una nueva tool MCP gabysql_vector_search con argumentos:
    • db (opcional)
    • table (requerido)
    • pk_column (default "id")
    • vector_column (requerido)
    • query (requerido — array JSON de floats)
    • top_k (default 10)
    • metric (default "cosine"; acepta también "euclidean"/"l2" y "dot"/"ip")
  3. La tool ejecuta SELECT <pk>, <vec_col> FROM <table> vía el HTTP existente (tras validar que los identificadores son [A-Za-z0-9_]+ para evitar inyección), parsea cada fila del lado del gateway, computa la distancia en Rust contra el vector de consulta y devuelve top-k por heap selection.
  4. Los identificadores se validan con safe_ident; cualquier carácter fuera de [A-Za-z0-9_] o que empiece con dígito hace fallar la tool antes de pegar al server.
  5. Filas con vector mal formado o de dimensión distinta a la query se cuentan en el campo skipped de la respuesta (el agente sabe que las saltó, no se silencia el problema).

Resultado: el agente puede pedir “tráeme las 5 filas más parecidas a este vector” sin que el motor sepa nada de vectores ni distancias.

🔄 Alternativas consideradas

Tipo VECTOR(n) nativo con bump de formato

Vectores como TEXT, distancias en SQL puro (UDFs)

Sidecar service en otro proceso

Vectores como TEXT, distancias en el gateway (decisión)

📊 Consecuencias

Positivas

Negativas

Neutras

🚪 Condiciones de salida (cuándo promover a VECTOR(n) nativo)

Esta ADR queda superseded por una ADR futura cuando se cumpla al menos uno de estos criterios:

Hasta entonces, esta solución es la entrega correcta.

🔗 Referencias