> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Descubrimiento de esquemas

> Cómo Fetcher lee las tablas y los campos de un datasource, cuándo sirve un snapshot en caché y cómo valida un mapeo de extracción antes de la primera consulta.

Fetcher lee la forma de un datasource por ti. Un **snapshot de esquema** lista las tablas de un datasource y los nombres de campo de cada tabla. No mantienes ningún catálogo aparte, y no subes ningún archivo de esquema.

Dos tareas dependen de un snapshot. Un llamador lee uno para saber qué campos existen. Fetcher revisa un mapeo de extracción contra uno antes de que corra la primera consulta.

## Qué guarda un snapshot

***

| Elemento     | Contenido                                                     |
| ------------ | ------------------------------------------------------------- |
| `configName` | La conexión que describe el snapshot.                         |
| Tablas       | Una entrada por tabla o colección, bajo su nombre calificado. |
| Campos       | Los nombres de campo de cada tabla, en orden alfabético.      |

Los nombres llegan calificados cuando la tabla está fuera del espacio de nombres por defecto. PostgreSQL devuelve `accounting.invoices` para una tabla en otro esquema y `users` a secas para una en `public`. SQL Server aplica la misma regla alrededor de `dbo`. Oracle devuelve `OWNER.TABLE` cuando el propietario difiere del usuario conectado.

Un snapshot lleva nombres y nada más. No guarda filas, ni credenciales, ni cadena de conexión. Las tablas de sistema nunca llegan a él: el adaptador de base de datos descarta `pg_*`, `information_schema` y las vistas del diccionario de Oracle antes de que el snapshot salga del adaptador.

## Descubrimiento en vivo y descubrimiento en caché

***

El Manager expone dos superficies de esquema, y difieren a propósito.

| Operación                                         | Frescura                                                                                       |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `GET /v1/management/connections/{id}/schema`      | Siempre en vivo. Nunca lee la caché ni escribe en ella.                                        |
| `POST /v1/management/connections/validate-schema` | Caché primero. Sirve un snapshot en caché cuando existe, y descubre en vivo en caso contrario. |

La división sigue los dos casos de uso. Quien pide un esquema quiere la verdad actual, a menudo justo después de que una migración agregó una columna. La validación corre en la entrada de cada job, así que una ida y vuelta a la base de datos en cada llamada costaría mucho más de lo que devuelve.

El descubrimiento sigue un orden fijo, y cada barrera corre antes de que la siguiente adquiera nada:

<Steps>
  <Step title="Revisar el tenant">
    Fetcher valida el alcance de tenant antes de tocar cualquier recurso.
  </Step>

  <Step title="Resolver la conexión">
    Fetcher resuelve la conexión dentro de ese alcance. Una conexión desconocida — o una que pertenece a otro tenant — se detiene aquí como `404 Not Found`.
  </Step>

  <Step title="Consultar la caché">
    En el camino de caché primero, un acierto devuelve de inmediato. Fetcher no construye ningún conector y no abre ninguna sesión de base de datos.
  </Step>

  <Step title="Abrir el datasource">
    Ante un fallo de caché, Fetcher resuelve el driver del tipo de datasource, abre un conector y lee el catálogo. Cierra el conector en todos los casos, con éxito o con fallo.
  </Step>

  <Step title="Escribir en caché">
    Fetcher almacena el snapshot bajo el tenant y el nombre de configuración, y después lo devuelve.
  </Step>
</Steps>

## Qué te da la caché de esquemas

***

La caché convierte una ida y vuelta a la base de datos en una búsqueda. Un acierto evita la construcción del conector y la lectura del catálogo a la vez, así que un job que valida veinte tablas en tres datasources no paga por ninguna una segunda vez dentro de la ventana.

* **Clave.** Cada lectura y cada escritura tienen alcance de tenant y de nombre de configuración. Un tenant nunca ve el snapshot de otro tenant ni lo contamina.
* **Vigencia.** Cinco minutos por defecto. `SCHEMA_CACHE_TTL_SECONDS` la define en el Manager.
* **Almacén de respaldo.** El Manager guarda la caché en Valkey o Redis, y recurre a la memoria del proceso cuando ese almacén está inalcanzable.

<Note>
  La caché es una optimización, y Fetcher la trata como tal. Una lectura de caché fallida degrada a un descubrimiento en vivo. Una escritura de caché fallida igual devuelve al llamador el snapshot descubierto. Ninguno de los dos fallos llega a tu respuesta.
</Note>

### Correr sin caché

Un host embebido conecta la caché de esquemas como un puerto opcional, y muchos hosts la dejan fuera. Sin ella, cada llamada de esquema descubre en vivo desde el datasource. La validación sigue siendo igual de correcta — simplemente paga la ida y vuelta cada vez.

Agrega una caché cuando el tráfico de validación se repite contra esquemas estables. Déjala fuera cuando el host corre extracciones ocasionales, o cuando una lectura en vivo en cada llamada es el comportamiento que quieres.

## Descubrimiento por base de datos

***

| Datasource | Cómo lee Fetcher el catálogo                                                                                                                                                                             |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PostgreSQL | Lee `information_schema` para las tablas base y sus columnas. Recurre al esquema `public` cuando la conexión no nombra ninguno.                                                                          |
| MySQL      | Lee `information_schema` para tablas, columnas y restricciones de clave primaria.                                                                                                                        |
| Oracle     | Lee las vistas de diccionario `ALL_TABLES` y `ALL_TAB_COLUMNS` para los propietarios que nombras, y las tablas del propio usuario en caso contrario. El usuario conectado es el propietario por defecto. |
| SQL Server | Lee `information_schema` y recurre al esquema `dbo`.                                                                                                                                                     |
| MongoDB    | Infiere la forma. Una colección no declara ninguna.                                                                                                                                                      |

Las lecturas de catálogo llevan un timeout de 30 segundos.

### Inferencia en MongoDB

MongoDB no tiene esquema declarado, así que Fetcher construye uno en dos pasadas. Una agregación sobre la colección produce los nombres de campo. Una muestra de hasta 50 documentos da después su tipo a cada campo.

La pasada de nombres de campo está acotada por el tamaño de la colección. En una colección de hasta 10.000 documentos, Fetcher lee como máximo los primeros 1.000. Por encima de 10.000 documentos, toma una muestra aleatoria:

| Tamaño de la colección  | Documentos leídos para nombres de campo |
| ----------------------- | --------------------------------------- |
| Hasta 1.000             | Todos                                   |
| De 1.001 a 10.000       | Los primeros 1.000                      |
| De 10.001 a 100.000     | Una muestra aleatoria de 2.000          |
| De 100.001 a 1.000.000  | Una muestra aleatoria de 5.000          |
| Por encima de 1.000.000 | Una muestra aleatoria de 10.000         |

El snapshot nombra los campos que llevan esos documentos. Un campo que aparece solo fuera de la lectura — después de los primeros 1.000 documentos, o fuera de la muestra aleatoria — no está en el snapshot.

Nombra ese campo en el `mappedFields` del trabajo cuando lo necesites. La extracción proyecta los nombres que envías contra la colección misma, así que un campo que el snapshot omite se extrae igual. `POST /v1/management/connections/validate-schema` responde desde el snapshot, así que reporta ese campo como `FIELD_NOT_FOUND`.

Cuando la agregación falla en una colección, Fetcher recurre al muestreo para esa colección y continúa. El descubrimiento de las colecciones restantes sigue adelante.

## Validación antes de la extracción

***

`POST /v1/management/connections/validate-schema` toma el mismo mapa `mappedFields` que lleva un job de extracción. Envíalo antes de mandar el job.

```json theme={null}
{
  "mappedFields": {
    "my_postgres": {
      "accounts": ["id", "email", "created_at"]
    }
  }
}
```

Fetcher revisa tres cosas, en este orden:

1. **Forma y conteos.** La solicitud permite 10 datasources, 20 tablas por datasource y 50 campos por tabla. Un exceso se reporta antes de que Fetcher toque una base de datos.
2. **Conexiones.** Cada datasource nombrado debe resolver a una conexión dentro del alcance del tenant.
3. **Pertenencia.** Cada tabla y cada campo deben existir en el snapshot del datasource.

Un mapeo limpio responde `success`. Un mapeo con problemas responde `failure` y nombra cada uno:

```json theme={null}
{
  "status": "failure",
  "message": "Schema validation found inconsistencies.",
  "errors": [
    {
      "type": "FIELD_NOT_FOUND",
      "dataSourceId": "my_postgres",
      "table": "accounts",
      "field": "external_id"
    }
  ]
}
```

| Tipo                    | Significado                                                           |
| ----------------------- | --------------------------------------------------------------------- |
| `DATA_SOURCE_NOT_FOUND` | Ninguna conexión lleva ese nombre de configuración en este tenant.    |
| `TABLE_NOT_FOUND`       | El datasource no tiene esa tabla.                                     |
| `FIELD_NOT_FOUND`       | La tabla no tiene ese campo.                                          |
| `DATA_SOURCE_DOWN`      | Fetcher alcanzó el registro de conexión pero no pudo leer el esquema. |

<Note>
  Un nombre de campo coincide con una columna exacta, o con el padre de una ruta con puntos. Una solicitud de `natural_person` valida cuando el snapshot guarda `natural_person.mother_name`. MongoDB aplana los documentos anidados en nombres con puntos, así que las referencias al padre son un patrón común ahí.
</Note>

La validación separa dos desenlaces que un solo código de estado mezclaría. Un problema de mapeo vuelve dentro del informe, una entrada por problema, y el informe completo llega de una vez. Un datasource que Fetcher no puede alcanzar vuelve como `DATA_SOURCE_DOWN` contra ese datasource solamente, y los demás datasources igual se validan.

## Próximos pasos

***

<CardGroup cols={2}>
  <Card title="Jobs de extracción" icon="play" href="/es/fetcher/fetcher-extraction-jobs">
    Envía un job, síguelo y lee el resultado.
  </Card>

  <Card title="Conexiones" icon="plug" href="/es/fetcher/fetcher-connections">
    Registra, prueba, actualiza y elimina una conexión a un datasource.
  </Card>

  <Card title="Fuentes de datos" icon="database" href="/es/fetcher/fetcher-datasources">
    Qué hace distinto cada uno de los cinco motores de base de datos.
  </Card>

  <Card title="Conceptos centrales" icon="cube" href="/es/fetcher/fetcher-core-concepts">
    El modelo de Fetcher en un solo lugar.
  </Card>
</CardGroup>
