> ## 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.

# Descoberta de esquema

> Como o Fetcher lê as tabelas e os campos de uma fonte de dados, quando serve um snapshot em cache e como valida um mapeamento de extração antes de a primeira consulta rodar.

O Fetcher lê o formato de uma fonte de dados por você. Um **snapshot de esquema** lista as tabelas de uma fonte de dados e os nomes dos campos de cada tabela. Você não mantém catálogo separado, e não envia arquivo de esquema algum.

Dois trabalhos dependem de um snapshot. Quem chama lê um para saber que campos existem. O Fetcher confere um mapeamento de extração contra um antes de a primeira consulta rodar.

## O que um snapshot guarda

***

| Elemento     | Conteúdo                                                        |
| ------------ | --------------------------------------------------------------- |
| `configName` | A conexão que o snapshot descreve.                              |
| Tabelas      | Uma entrada por tabela ou coleção, sob o nome qualificado dela. |
| Campos       | Os nomes dos campos de cada tabela, em ordem alfabética.        |

Os nomes chegam qualificados quando a tabela fica fora do namespace padrão. O PostgreSQL retorna `accounting.invoices` para uma tabela em outro esquema e apenas `users` para uma no `public`. O SQL Server aplica a mesma regra em torno do `dbo`. O Oracle retorna `OWNER.TABLE` quando o owner difere do usuário conectado.

Um snapshot carrega nomes e nada além disso. Ele não guarda linhas, nem credenciais, nem string de conexão. Tabelas de sistema nunca chegam a ele: o adaptador do banco descarta `pg_*`, `information_schema` e as views de dicionário do Oracle antes de o snapshot sair do adaptador.

## Descoberta ao vivo e descoberta em cache

***

O Manager expõe duas superfícies de esquema, e elas diferem de propósito.

| Operação                                          | Atualidade                                                                                          |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `GET /v1/management/connections/{id}/schema`      | Sempre ao vivo. Ela nunca lê o cache e nunca escreve nele.                                          |
| `POST /v1/management/connections/validate-schema` | Cache primeiro. Ela serve um snapshot em cache quando existe um, e descobre ao vivo caso contrário. |

A separação segue os dois casos de uso. Quem pede um esquema quer a verdade atual, muitas vezes logo depois de uma migração adicionar uma coluna. A validação roda na entrada de todo job, então uma ida ao banco de dados a cada chamada custaria muito mais do que devolve.

A descoberta segue uma ordem fixa, e cada portão roda antes de o próximo adquirir qualquer coisa:

<Steps>
  <Step title="Checar o tenant">
    O Fetcher valida o escopo do tenant antes de tocar em qualquer recurso.
  </Step>

  <Step title="Resolver a conexão">
    O Fetcher resolve a conexão dentro desse escopo. Uma conexão desconhecida — ou uma que pertence a outro tenant — para aqui como `404 Not Found`.
  </Step>

  <Step title="Consultar o cache">
    No caminho que usa cache primeiro, um acerto retorna de imediato. O Fetcher não constrói conector e não abre sessão de banco de dados.
  </Step>

  <Step title="Abrir a fonte de dados">
    Em uma falha de cache, o Fetcher resolve o driver do tipo de fonte de dados, abre um conector e lê o catálogo. Ele fecha o conector em todo caminho, sucesso ou falha.
  </Step>

  <Step title="Gravar no cache">
    O Fetcher armazena o snapshot sob o tenant e o nome da configuração, e então o retorna.
  </Step>
</Steps>

## O que o cache de esquema entrega

***

O cache transforma uma ida ao banco de dados em uma consulta local. Um acerto pula a construção do conector e a leitura do catálogo juntas, então um job que valida vinte tabelas em três fontes de dados não paga por nenhuma delas uma segunda vez dentro da janela.

* **Chave.** Toda leitura e toda escrita têm escopo no tenant e no nome da configuração. Um tenant nunca vê o snapshot de outro tenant e nunca o contamina.
* **Duração.** Cinco minutos por padrão. `SCHEMA_CACHE_TTL_SECONDS` define isso no Manager.
* **Armazenamento de apoio.** O Manager mantém o cache no Valkey ou no Redis, e cai para a memória do processo quando esse armazenamento está inacessível.

<Note>
  O cache é uma otimização, e o Fetcher o trata como tal. Uma leitura de cache que falha degrada para uma descoberta ao vivo. Uma escrita de cache que falha ainda retorna o snapshot descoberto para quem chamou. Nenhuma das duas falhas chega à sua resposta.
</Note>

### Rodar sem cache

Um hospedeiro que incorpora o Engine liga o cache de esquema como uma porta opcional, e muitos hospedeiros a deixam de fora. Sem ela, toda chamada de esquema descobre ao vivo na fonte de dados. A validação continua exatamente igual de correta — ela apenas paga a ida ao banco a cada vez.

Adicione um cache quando o tráfego de validação se repete contra esquemas estáveis. Deixe-o de fora quando o hospedeiro roda extrações ocasionais, ou quando uma leitura ao vivo a cada chamada é o comportamento que você quer.

## Descoberta por banco de dados

***

| Fonte de dados | Como o Fetcher lê o catálogo                                                                                                                                                     |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PostgreSQL     | Lê o `information_schema` para tabelas base e as colunas delas. Cai para o esquema `public` quando a conexão não nomeia nenhum.                                                  |
| MySQL          | Lê o `information_schema` para tabelas, colunas e constraints de chave primária.                                                                                                 |
| Oracle         | Lê as views de dicionário `ALL_TABLES` e `ALL_TAB_COLUMNS` para os owners que você nomeia, e as tabelas do próprio usuário caso contrário. O usuário conectado é o owner padrão. |
| SQL Server     | Lê o `information_schema` e cai para o esquema `dbo`.                                                                                                                            |
| MongoDB        | Infere o formato. Uma coleção não declara nenhum.                                                                                                                                |

As leituras de catálogo carregam um tempo limite de 30 segundos.

### Inferência no MongoDB

O MongoDB não tem esquema declarado, então o Fetcher constrói um em duas passagens. Uma agregação sobre a coleção produz os nomes de campos. Uma amostra de até 50 documentos então dá a cada campo o tipo dele.

A passagem de nomes de campos é limitada pelo tamanho da coleção. Em uma coleção de até 10.000 documentos, o Fetcher lê no máximo os primeiros 1.000. Acima de 10.000 documentos, ele usa uma amostra aleatória:

| Tamanho da coleção     | Documentos lidos para nomes de campos |
| ---------------------- | ------------------------------------- |
| Até 1.000              | Todos eles                            |
| De 1.001 a 10.000      | Os primeiros 1.000                    |
| De 10.001 a 100.000    | Uma amostra aleatória de 2.000        |
| De 100.001 a 1.000.000 | Uma amostra aleatória de 5.000        |
| Acima de 1.000.000     | Uma amostra aleatória de 10.000       |

O snapshot nomeia os campos que esses documentos carregam. Um campo que aparece apenas fora da leitura — depois dos primeiros 1.000 documentos, ou fora da amostra aleatória — não está no snapshot.

Nomeie esse campo no `mappedFields` do trabalho quando precisar dele. A extração projeta os nomes que você envia contra a própria coleção, então um campo que o snapshot omite é extraído mesmo assim. `POST /v1/management/connections/validate-schema` responde a partir do snapshot, então reporta esse campo como `FIELD_NOT_FOUND`.

Quando a agregação falha em uma coleção, o Fetcher cai para amostragem naquela coleção e continua. A descoberta das demais coleções segue em frente.

## Validação antes da extração

***

`POST /v1/management/connections/validate-schema` recebe o mesmo mapa `mappedFields` que um job de extração carrega. Envie-o antes de submeter o job.

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

O Fetcher confere três coisas, nesta ordem:

1. **Formato e contagens.** A requisição permite 10 fontes de dados, 20 tabelas por fonte de dados e 50 campos por tabela. Uma violação é reportada antes de o Fetcher tocar em um banco de dados.
2. **Conexões.** Toda fonte de dados nomeada precisa resolver para uma conexão dentro do escopo do tenant.
3. **Existência.** Toda tabela e todo campo precisam existir no snapshot da fonte de dados.

Um mapeamento limpo responde `success`. Um mapeamento com problemas responde `failure` e nomeia cada um:

```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` | Nenhuma conexão carrega esse nome de configuração neste tenant.            |
| `TABLE_NOT_FOUND`       | A fonte de dados não tem essa tabela.                                      |
| `FIELD_NOT_FOUND`       | A tabela não tem esse campo.                                               |
| `DATA_SOURCE_DOWN`      | O Fetcher alcançou o registro da conexão, mas não conseguiu ler o esquema. |

<Note>
  Um nome de campo casa com uma coluna exata, ou com o pai de um caminho pontuado. Uma requisição por `natural_person` valida quando o snapshot guarda `natural_person.mother_name`. O MongoDB achata documentos aninhados em nomes pontuados, então referências ao pai são um padrão comum ali.
</Note>

A validação separa dois desfechos que um único código de status misturaria. Um problema de mapeamento volta dentro do relatório, uma entrada por problema, e o relatório inteiro chega de uma vez. Uma fonte de dados que o Fetcher não consegue alcançar volta como `DATA_SOURCE_DOWN` contra aquela fonte de dados apenas, e as demais fontes de dados continuam sendo validadas.

## Próximos passos

***

<CardGroup cols={2}>
  <Card title="Jobs de extração" icon="play" href="/pt/fetcher/fetcher-extraction-jobs">
    Submeta um job, acompanhe-o e leia o resultado.
  </Card>

  <Card title="Conexões" icon="plug" href="/pt/fetcher/fetcher-connections">
    Registre, teste, atualize e exclua uma conexão com uma fonte de dados.
  </Card>

  <Card title="Fontes de dados" icon="database" href="/pt/fetcher/fetcher-datasources">
    O que cada um dos cinco motores de banco de dados faz de diferente.
  </Card>

  <Card title="Conceitos centrais" icon="cube" href="/pt/fetcher/fetcher-core-concepts">
    O modelo do Fetcher em um só lugar.
  </Card>
</CardGroup>
