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

> Documentação de referência completa do módulo chdb_hook do Postgres

# Documentação de referência do módulo chdb_hook

## Sinopse

```psql theme={null}
# LOAD 'chdb_hook';
LOAD

# CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
);
CREATE TABLE

# COPY times FROM 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv';
COPY 18
```

## Descrição

O módulo chdb\_hook se integra ao comando [COPY](#copy-overloading) do PostgreSQL
para usar o [chDB] e copiar dados `TO` ou `FROM` qualquer um dos
[formatos de dados fornecidos pelo chDB][formats] em arquivos locais, buckets do [AWS S3],
[Google Cloud Storage], entre outros. Ele também se integra ao [CREATE TABLE], permitindo que uma
tabela derive suas colunas e carregue suas linhas a partir de qualquer um desses mesmos
destinos.

## Carregamento

Carregue o chdb\_hook de uma das seguintes maneiras como super user. Use a que
fizer mais sentido para o seu caso de uso:

* Explicitamente, via comando [LOAD]; permanece ativo pelo tempo de duração de uma session:

  ```sql theme={null}
  LOAD 'chdb_hook';
  ```

  > [!NOTE]
  >
  > O SQL Console do ClickHouse Cloud ainda não oferece suporte ao comando
  > `LOAD 'chdb_hook'`, mas ele pode ser executado via psql ou qualquer outra database connection.
  > Caso contrário, entre em contato com seu representante de Support para adicioná-lo à
  > configuration do seu service Postgres, e depois disso ele poderá ser usado no SQL Console.

* Para todas as sessions, pela configuração \[session\_preload\_libraries], no
  `postgresql.conf`:

  ```ini theme={null}
  session_preload_libraries = chdb_hook
  ```

  Ou via [ALTER SYSTEM]:

  ```sql theme={null}
  ALTER SYSTEM SET session_preload_libraries = 'chdb_hook';
  ```

  Essa configuração também pode ser definida individualmente por database, via [ALTER DATABASE]:

  ```sql theme={null}
  ALTER DATABASE name SET session_preload_libraries = 'chdb_hook';
  ```

  Ou para usuários e grupos específicos, via [ALTER ROLE]:

  ```sql theme={null}
  ALTER ROLE name SET session_preload_libraries = 'chdb_hook';
  ```

* Na inicialização do servidor, pela configuração \[shared\_preload\_libraries], de modo que fique sempre
  disponível para todas as sessions e databases:

  ```ini theme={null}
  shared_preload_libraries = chdb_hook
  ```

> [!WARNING]
>
> Atenção: carregar o chdb\_hook permite que usuários nas roles `pg_read_server_files`
> ou `pg_write_server_files` executem `COPY` de dados de e para arquivos no
> servidor Postgres, bem como para cloud storage.

## Sobrecarga do COPY

Durante o [carregamento](#loading), o chdb\_hook se integra ao comando [COPY] do Postgres para
copiar dados `TO` ou `FROM` qualquer um dos [formatos de dados suportados pelo
chDB][formats] em arquivos locais, buckets do [AWS S3], [Google Cloud Storage] e
outros. Para carregar uma tabela a partir de um arquivo CSV no S3, por exemplo, crie a tabela
e depois chame `COPY` com uma URL `s3://`:

```sql theme={null}
CREATE TABLE times (
    id     INT PRIMARY KEY,
    months INT NOT NULL,
    days   INT NOT NULL
);

COPY times FROM 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv';
```

### Privilégios

Um `COPY` do chdb\_hook exige os mesmos privilégios do [COPY] que ele substitui:
`SELECT` na relação ou em cada coluna copiada, no caso do `COPY TO`, e `INSERT`
no caso do `COPY FROM`. Uma URL `file://` lê ou grava um arquivo no servidor, portanto também
exige participação em `pg_read_server_files` ou `pg_write_server_files`.
O `COPY FROM` exige uma transação de leitura e gravação.

### Esquemas de URL

O chdb\_hook só é executado para destinos de `COPY` do tipo URL que usam um dos
esquemas a seguir:

| Esquemas | Destino | Função chDB |
| - | - | - |
| `file` | Caminho absoluto no servidor Postgres | [`file()`] |
| `http`, `https` | URL HTTP | [`url()`] |
| `s3` | [AWS S3] | [`s3()`] |
| `gs`, `gcs`, `oss` | [Google Cloud Storage] | [`gcs()`] |
| `az`, `azure`, `abfss`, `abfs` | [Azure Blob Storage] ou [Azure ABFS] | [`azureBlobStorage()`] |
| `hdfs` | [Hadoop Distributed File System] | [`hdfs()`] |

### Formatos de URL

O formato das URLs varia conforme o target.

#### File

O esquema `file://` não é compatível com o ClickHouse Cloud.

Deve ser um caminho absoluto no servidor Postgres. Um caminho relativo resulta em
erro. O usuário do Postgres deve ser membro da role `pg_read_server_files` ou
`pg_write_server_files`, conforme apropriado. O usuário de sistema do Postgres deve
ter acesso de leitura ou escrita ao arquivo, conforme apropriado. No caso de `COPY TO`, se o
caminho não existir, o chdb\_hook criará os diretórios pais que estiverem ausentes; para isso, ele
precisa ter permissão no sistema de arquivos. Exemplo:

```
file:///tmp/users.parquet
```

#### HTTP

Qualquer URL HTTP comum, inclusive em armazenamento em nuvem público. Para `COPY TO`,
o chdb\_hook tentará fazer um `POST` dos dados para a URL. Exemplo:

```
https://datasets-documentation.s3.eu-west-3.amazonaws.com/my-test-bucket-768/some_prefix/some_file_1.csv
```

#### S3

URLs do S3 podem assumir o formato de um URI do S3

```
s3://{bucket}/{path}
```

Ou de uma URL de object:

```
s3://{bucket}.s3.{region}.amazonaws.com/{path}
```

#### GCS

As URLs do GCS têm o formato de uma URL pública:

```
gs://storage.googleapis.com/{bucket}/{path}
```

Ou uma URI do Cloud Storage, que o chdb\_hook converte em uma URL pública:

```
gs://{bucket}/{path}
```

#### Azure Blob Storage

Use uma URL `blob.windows.net` com o nome da account como subdomínio:

```
az://{account}.blob.core.windows.net/{container}/{blob}
```

Ou use algum outro host name:

```
az://{host}/{container}/{blob}
```

#### Azure ABFS

URLs ABFS devem usar este formato:

```
abfs://{container}@{account}.dfs.core.windows.net/{blob}
```

#### URLs HDFS

URLs HDFS podem usar URLs típicas no estilo HTTP, com uma porta opcional:

```
hdfs://{host}/{path}
hdfs://{host}:{port}/{path}
```

### Wildcards em paths

Os paths de URL podem conter globs em comandos `COPY FROM`. Os arquivos devem corresponder ao
padrão completo do path, não apenas ao suffix ou ao prefix. Há uma única exceção: quando o
path se refere a um directory existente e não usa globs, um `*` é
adicionado implicitamente ao path para selecionar todos os arquivos do directory.

Os wildcards suportados:

* `*`: Corresponde a uma quantidade arbitrária de characters, exceto `/`, incluindo a empty string.
* `?`: Corresponde a um único character arbitrário.
* `{groucho,harpo,chico}`: Substitui qualquer uma das strings "groucho", "harpo" e
  "chico". As strings podem conter `/`.
* `{N..M}`: Corresponde a qualquer número `>= N` e `<= M`.
* `**`: Corresponde recursivamente a todos os arquivos de um directory.

Por exemplo, para carregar dados destes arquivos em um único comando:

* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;1.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;1.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;2.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;2.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;3.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;3.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;1.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;1.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;2.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;2.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;3.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;3.csv)

Use `{some,another}_prefix` para corresponder aos dois nomes de directory e
`some_file_{1..3}.csv'` para corresponder aos arquivos, assim:

```sql theme={null}
CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
);

COPY times FROM 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv';
```

### Opções

O comando `COPY` do chdb\_hook oferece suporte às seguintes opções:

#### `format`:

O formato de leitura ou escrita. Deve ser um dos [formats] fornecidos pelo [chDB],
que incluem TSV, CSV, Parquet, Iceberg, JSON, entre outros. Omita ou defina como
`auto` para que o chDB determine o formato a partir da extensão do nome do arquivo ao final
da URL.

#### `structure`

A estrutura de dados do [chDB] para uma linha. Consiste em uma lista de nomes de colunas,
\[tipos de dados do ClickHouse] e modificadores. Se omitido, o chdb\_hook mapeia os tipos de dados
do Postgres para tipos do ClickHouse geralmente apropriados; consulte [Postgres para
chDB](#postgres-to-chdb) para mais detalhes. Se definido como `auto`, o chDB tenta inferir
os tipos.

Exemplo:

```sql theme={null}
COPY users TO 'file:///tmp/users.parquet' (
    structure 'id Int64, name String, age Nullable(UInt8), attributes JSON'
);
```

#### `access_key` e `access_secret`

Credenciais de longo prazo do usuário da AWS account para autenticar requisições.

* **S3:** Um \[access key ID e access secret] da AWS, geralmente definidos pelas
  variáveis de ambiente `AWS_ACCESS_KEY_ID` e `AWS_SECRET_ACCESS_KEY`
* **GCS:** Uma [HMAC key and secret] do GCP
* **Azure:** Um nome de Azure storage account e [access key]

#### `session_token`

Token de sessão da AWS a ser usado com `access_key` e `access_secret`, geralmente
definido pela variável de ambiente `AWS_SESSION_TOKEN`. Usado apenas para URLs
do S3.

#### `compression`

Formato de compressão do arquivo. Use quando a compressão não puder ser inferida
pelo nome do arquivo. Valores suportados:

* `auto` (padrão)
* `none`
* `gzip` ou `gz`
* `brotli` ou `br`
* `xz` ou `LZMA`
* `zstd` ou `zst`
* `lz4`
* `bz2`
* `snappy`

#### `timeout`

Tempo limite da requisição em milissegundos. Aplica-se a URLs HTTP, S3, GCS e Azure.
O padrão é `30000` (30s).

#### `encoding_check`

Define como tratar caracteres inválidos na [codificação do banco de dados][database encoding] ao
converter valores String e JSON do chDB. Aceita um dos seguintes valores:

* `fail` (padrão): gera um erro
* `remove`: remove os bytes inválidos
* `replace`: na codificação UTF-8, substitui os bytes inválidos pelo
  caractere de substituição Unicode (`�`); nas demais codificações,
  equivale a `remove`
* `truncate`: trunca o texto no primeiro byte inválido

### Depuração

Em caso de erro, o comando `COPY` do chdb\_hook inclui no contexto do erro a consulta [chDB] que ele tentou
executar:

```
ERROR:  chdb: error executing chDB query
DETAIL:  Code: 53. DB::Exception: Requested type of column p doesn't match parquet schema
CONTEXT:  query: SELECT * FROM file({path:String}, {format:String}, {structure:String})
STATEMENT:  COPY "users" FROM 'file:///tmp/users.data' (format 'Parquet');
```

O chdb\_hook usa placeholders no estilo `{name:Type}` para query parameters, a fim de
proteger contra vulnerabilidades de injection de SQL e minimizar o risco de
registrar dados sensíveis em log, como credenciais.

Se, no entanto, você precisar ver o conteúdo desses parameters para depurar
um issue, defina temporariamente o GUC \[log\_min\_messages] do Postgres como `DEBUG1` ou
superior, para que o chdb\_hook envie a consulta e os parameters ao log do Postgres
(nunca ao client), onde aparecerão assim:

```
2026-08-08 09:41:06.842 EDT [59940] LOG:  executing chDB query
2026-08-08 09:41:06.842 EDT [59940] DETAIL:  query: SELECT * FROM file({path:String}, {format:String}, {structure:String})
2026-08-08 09:41:06.842 EDT [59940] CONTEXT:  params: { path: "/tmp/users.data", format: "Parquet", structure: "user_id Nullable(Int64), username Nullable(String), password Nullable(String)" }
2026-08-08 09:41:06.842 EDT [59940] STATEMENT:  COPY "users" FROM 'file:///tmp/users.data' (format 'Parquet');
```

> [!WARNING]
>
> Não mantenha \[log\_min\_messages] em um nível de depuração por mais tempo do que
> uma única sessão de depuração, para evitar o registro de informações sensíveis como
> credenciais, e porque o próprio PostgreSQL também registra informações de depuração
> e pode encher o log rapidamente.

## Sobrecarga de CREATE TABLE

O chdb\_hook também se integra a [CREATE TABLE], de modo que uma tabela possa derivar suas
colunas e carregar suas linhas a partir de uma URL.

Para criar uma tabela com a estrutura derivada de uma URL, passe a URL na
opção `structure_from` e deixe a lista de colunas vazia (atenção: este arquivo de dados
público contém 41 milhões de linhas):

```sql theme={null}
CREATE TABLE reviews () WITH (
    encoding_check = 'replace',
    structure_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'
);
```

Use `copy_from` para carregar as linhas, além das colunas:

```sql theme={null}
CREATE TABLE reviews () WITH (
    encoding_check = 'replace',
    copy_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'
);
```

O `copy_from` infere as colunas apenas quando a instrução não define nenhuma
coluna própria. Uma lista de colunas, uma cláusula `INHERITS`, um tipo `OF` ou uma
partição definem colunas e, nesse caso, o `copy_from` copia apenas:

```sql theme={null}
CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
) WITH (copy_from = 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv');
```

Quando o `copy_from` infere as colunas, ele usa o schema da origem retornado por `DESCRIBE`.
Isso permite que valores `Map`, `Tuple` e `Nested` sejam carregados como colunas de array de texto,
que não identificam seus tipos originais do ClickHouse.

Ambas as opções suportam os mesmos [esquemas de URL](#url-schemes) e
[options](#options) que `COPY`; credenciais, format, compressão, tempo limite e
até mesmo uma [structure](#structure) explícita se aplicam. O Postgres mantém
os parâmetros de armazenamento que restarem:

```sql theme={null}
CREATE TABLE logs () WITH (
    copy_from  = 's3://chdb-lakedata-public/logs/logs-2026-08-26.csv',
    format     = 'CSVWithNames',
    timeout    = 60000,
    fillfactor = 90
);
```

Nem `structure_from` nem `copy_from` funcionam com `IF NOT EXISTS`. Use
[COPY] para carregar uma relação existente.

## Limitações

Devido a alguns problemas conhecidos e a variações no comportamento dos tipos de dados
entre o Postgres e o chDB, o chdb\_hook apresenta as seguintes limitações:

* Não é possível executar `COPY` em relações com policies de [row-level security] aplicáveis à
  role que faz a cópia. O Postgres aplica essas policies reescrevendo o `COPY TO` como uma
  consulta, o que o chdb\_hook não suporta.
* Não é possível executar `COPY FROM` a partir de uma URL com uma cláusula `WHERE`.
* O chDB não possui array NULL, portanto o `COPY TO` armazena um array vazio (`[]`) no lugar de um
  NULL.
* O chDB representa os equivalentes de `lseg`, `path` ou `polygon` como arrays;
  assim, valores NULL desses tipos também são gravados pelo `COPY TO` como um array vazio (`[]`).
* O ClickHouse não possui array NULL, portanto o `COPY TO` armazena um array vazio (`[]`) no lugar de
  um `NULL`.
* O ClickHouse representa os equivalentes de `lseg`, `path` ou `polygon` como
  arrays; assim, valores NULL desses tipos também são gravados pelo `COPY TO` como um array vazio
  (`[]`).
* Valores NULL emitidos para uma [structure](#structure) especificada que não
  defina a coluna como Nullable serão emitidos como seus valores default. Defina sempre
  explicitamente as colunas nullable na [structure](#structure) para evitar
  essa conversão.
* Um `path` aberto cujo último ponto é igual ao primeiro é emitido como um path fechado.
* O Protobuf não possui null em campos repetidos, portanto valores NULL em arrays são omitidos.
* O [JSON type] do chDB suporta apenas JSON objects; substitua o mapeamento padrão
  `String` de `json` e `jsonb` por `JSON` somente se todos os valores forem
  JSON object. (ClickHouse/ClickHouse#68428)
* O [JSON type] do chDB ignora `null`s; chaves de objeto com valores NULL serão
  omitidas na saída. Substitua o mapeamento padrão `String` de `json` e
  `jsonb` por `JSON` somente se os valores do objeto não forem `null` ou se sua
  perda for aceitável. (ClickHouse/ClickHouse#68428)
* Os formatos JSON, JSONCompact e JSONColumnsWithMetadata sempre validam
  UTF-8, portanto emitem valores bytea com caracteres de substituição.
* O `COPY FROM` lê um campo `Nullable` do Protobuf que contenha uma string vazia ou
  zero como `NULL`. (chdb-io/chdb-core#152)
* O `COPY TO` em Parquet descarta os `NULL`s do null map próprio de um Tuple Nullable.
  (ClickHouse/ClickHouse#112427)
* Os formatos Parquet, Arrow, ArrowStream, ORC, Avro, Protobuf, ProtobufList, MsgPack
  e BSONEachRow não possuem tipo correspondente ao `time` do Postgres nem ao
  `Time64` do chDB. Configure as colunas `time` como `String`s em uma
  [structure](#structure) explícita para preservar seus valores.
* A saída em Protobuf trunca os valores de timestamp para o segundo.
* A saída em Protobuf não suporta datas anteriores a 1970-01-01. Configure as colunas `time`
  como `String`s em uma [structure](#structure) explícita para preservar
  seus valores. (ClickHouse/ClickHouse#111860)

## Tipos de dados

O [COPY](#copy-overloading) mapeia os tipos do Postgres de uma relação para tipos do chDB,
enquanto o [CREATE TABLE](#create-table-overloading) mapeia os tipos do chDB de uma URL
para tipos do Postgres.

### Postgres para chDB

Na ausência de uma opção [structure](#structure) explícita, o chdb\_hook mapeia
os tipos do Postgres para equivalentes adequados no chDB. Quando eles não atenderem
ao seu caso de uso, especifique a opção [structure](#structure) para substituir os tipos
gerados pelos tipos de que você precisa.

| PostgreSQL | chDB | Observações |
| - | - | - |
| boolean | Bool | |
| smallint | Int16 | |
| integer | Int32 | |
| bigint | Int64 | |
| oid | UInt32 | |
| xid8 | UInt64 | |
| oid8 | UInt64 | |
| real | Float32 | |
| double precision | Float64 | |
| numeric | Decimal256(38) | Também quando a precisão excede 76 dígitos. |
| numeric(12,6) | Decimal(12,6) | A precisão e a escala são preservadas. |
| text | String | |
| bytea | String | |
| date | Date32 | |
| time | Time64(6) | Substitua por `String` para formatos que não suportam horários. |
| timestamp | DateTime64(6, 'UTC') | Convertido a partir do fuso horário da sessão. |
| timestamptz | DateTime64(6, 'UTC') | |
| interval | String | Substitua por uma unidade de `Interval`, como `IntervalDay`. |
| uuid | UUID | |
| json | String | Substitua por `JSON` se os dados contiverem apenas objetos. |
| jsonb | String | Substitua por `JSON` se os dados contiverem apenas objetos. |
| inet | String | Substitua por `IPv4` ou `IPv6` se os dados contiverem apenas um ou outro. |
| point | Point | As mesmas duas coordenadas do Postgres. |
| lseg | LineString | Uma linha de exatamente dois pontos. |
| path | LineString | Um caminho fechado repete seu primeiro ponto. |
| polygon | Ring | Um anel se fecha implicitamente, assim como um polígono. |
| box | Tuple(high Point, low Point) | Os dois cantos, ordenados da mesma forma que no Postgres. |
| circle | Tuple(center Point, radius Float64) | |
| line | Tuple(a Float64, b Float64, c Float64) | A equação `Ax + By + C = 0`. |

Tipos ausentes desta tabela, como `name`, `varchar`, `char`, `bit`,
`timetz`, `money` e enums, são mapeados para `String`.

Tipos de array são mapeados para `Array`s do tipo de elemento mapeado. O ClickHouse restringe
a nulidade por coluna, enquanto o Postgres a restringe por array; por isso, os elementos são
sempre `Nullable`.

Nenhum tipo do Postgres é mapeado diretamente para `Map`, `Tuple` ou `Nested`, mas uma opção
[structure](#structure) ou um arquivo de origem pode especificá-los. Uma `Tuple` pode ser lida
como `text[]`, com um elemento por campo da tupla, ou como um \[tipo
composto] correspondente, para preservar os tipos dos campos. Um `Map` ou `Nested` pode ser lido como
`text[][]`, com um array interno por par chave-valor ou tupla aninhada, ou como
um array de um tipo composto correspondente. Consulte [Mapeamentos manuais de
tipos](#manual-type-mappings) para ver exemplos.

### Conversão de timestamp

Em formatos de texto simples (TSV, CSV, etc.), o hook `COPY` emite valores DateTime e
DateTime64 no formato ISO-8601, `YYYY-MM-DDThh:mm:ssZ`, independentemente
da configuração `datestyle` atual. Isso garante que os valores timestamptz
permaneçam consistentes, mesmo que a origem que importa os valores use um fuso
horário diferente. Usar um tipo diferente na saída de `structure`, como `Datetime64(3,
'America/Los_Angeles')`, não altera o deslocamento da saída, mas
altera a precisão.

Exemplos de Timestamp TZ:

| timestamptz | `DateTime64(6, 'UTC')` | `DateTime64(3 'Japan')` |
| - | - | - |
| `2026-08-28T12:00:00Z` | `2026-08-28T12:00:00.000000Z` | `2026-08-28T12:00:00.000Z` |
| `2026-08-28T11:00:00 America/Los_Angeles` | `2026-08-28T18:00:00.000000Z` | `2026-08-28T18:00:00.000Z` |
| `2026-08-28T10:00:00.723923 Asia/Tokyo` | `2026-08-28T01:00:00.723923Z` | `2026-08-28T01:00:00.723Z` |

O hook `COPY` também converte valores de timestamp do fuso horário da sessão para
UTC, garantindo assim que a saída seja relativa a esse fuso horário. Ao serem carregados
em um novo sistema, este deve convertê-los para o seu fuso horário local. Portanto, os
valores serão diferentes se o fuso horário for diferente, mas equivalentes considerando
a diferença entre os fusos.

Exemplo do efeito da configuração `timezone` sobre o timestamp
`2026-08-28T12:00:00`:

| configuração timezone | `DateTime64(6, 'UTC')` | `DateTime64(3 'Japan')` |
| - | - | - |
| `UTC` | `2026-08-28T12:00:00.000000Z` | `2026-08-28T12:00:00.000Z` |
| `America/Los_Angeles` | `2026-08-28T19:00:00.000000Z` | `2026-08-28T19:00:00.000Z` |
| `America/New_York` | `2026-08-28T16:00:00.000000Z` | `2026-08-28T16:00:00.000Z` |
| `Japan` | `2026-08-28T03:00:00.000000Z` | `2026-08-28T03:00:00.000Z` |

### chDB para Postgres

Para tabelas existentes, os valores são convertidos para os tipos de coluna declarados.
Tipos escalares alternativos usam os casts explícitos do PostgreSQL quando disponíveis, e
os elementos de array são convertidos para o tipo de elemento declarado. Conversões
sem suporte e valores fora do intervalo permitido geram erros.

Mapeie os tipos `Interval` do chDB para `smallint`, `integer` ou `bigint` para ler e
gravar a quantidade de suas unidades. Por exemplo, um valor `IntervalDay` igual a `3` é mapeado
para o inteiro `3`. Mapear `IntervalNanosecond` para `bigint` preserva
os nanossegundos, enquanto mapear para `interval` trunca o valor para microssegundos.

O chdb\_hook usa os tipos padrão do Postgres listados abaixo ao criar tabelas a partir dos
tipos do ClickHouse informados por [`DESCRIBE`]. Os destinos de leitura adicionais se aplicam a
colunas declaradas explicitamente e incluem conversões que vão além dos casts explícitos do
PostgreSQL. Células vazias continuam permitindo esses casts. Esses destinos se referem a leituras;
as gravações seguem regras de conversão próprias.

| chDB | PostgreSQL padrão | Destinos de leitura adicionais | Observações |
| - | - | - | - |
| Array(T) | T\[] | | Um tipo de array do PG por nível de profundidade |
| BFloat16 | real | | |
| Bool | boolean | | |
| Date | date | | |
| Date32 | date | | |
| DateTime | timestamp with time zone | time | |
| DateTime64(P) | timestamp(P) with time zone | time | P acima de 6 é limitado a 6 |
| Decimal(P,S) | numeric(P,S) | xid8, oid8 | |
| Decimal32(S) | numeric(9,S) | xid8, oid8 | |
| Decimal64(S) | numeric(18,S) | xid8, oid8 | |
| Decimal128(S) | numeric(38,S) | xid8, oid8 | |
| Decimal256(S) | numeric(76,S) | xid8, oid8 | |
| Enum8 | text | bytea; tipos compatíveis com a entrada | Decodifica o rótulo; enums do PG com rótulos correspondentes também são aceitos |
| Enum16 | text | bytea; tipos compatíveis com a entrada | Decodifica o rótulo; enums do PG com rótulos correspondentes também são aceitos |
| FixedString(N) | text | bytea; tipos compatíveis com a entrada | Apenas bytea preserva os NULs finais |
| Float32 | real | | |
| Float64 | double precision | | |
| IPv4 | inet | | |
| IPv6 | inet | | |
| Int8 | smallint | boolean | Zero é false; qualquer valor diferente de zero é true |
| Int16 | smallint | boolean | Zero é false; qualquer valor diferente de zero é true |
| Int32 | integer | | |
| Int64 | bigint | | |
| Int128 | numeric(39,0) | xid8, oid8 | |
| Int256 | numeric(77,0) | xid8, oid8 | |
| IntervalDay | interval | smallint, integer, bigint | Inteiros recebem a quantidade de unidades |
| IntervalHour | interval | smallint, integer, bigint | Inteiros recebem a quantidade de unidades |
| IntervalMicrosecond | interval | smallint, integer, bigint | Inteiros recebem a quantidade de unidades |
| IntervalMillisecond | interval | smallint, integer, bigint | Inteiros recebem a quantidade de unidades |
| IntervalMinute | interval | smallint, integer, bigint | Inteiros recebem a quantidade de unidades |
| IntervalMonth | interval | smallint, integer, bigint | Inteiros recebem a contagem de unidades |
| IntervalNanosecond | interval | smallint, integer, bigint | Inteiros mantêm ns; interval trunca para us |
| IntervalQuarter | interval | smallint, integer, bigint | Inteiros recebem a contagem de unidades |
| IntervalSecond | interval | smallint, integer, bigint | Inteiros recebem a contagem de unidades |
| IntervalWeek | interval | smallint, integer, bigint | Inteiros recebem a contagem de unidades |
| IntervalYear | interval | smallint, integer, bigint | Inteiros recebem a contagem de unidades |
| JSON | jsonb | json, text, bytea; tipos compatíveis com a entrada | jsonb normaliza o documento |
| LineString | path | lseg | lseg exige dois pontos |
| LowCardinality(T) | T | | |
| Map(K,V) | text\[]\[] | composite\[], T\[]\[], text | Uma linha de itens de texto por par |
| MultiLineString | path\[] | | |
| MultiPolygon | polygon\[]\[] | | |
| Nested(...) | text\[]\[] | composite\[], T\[]\[], text | Uma linha de itens de texto por linha aninhada |
| Nullable(T) | T | | Define a coluna como nullable |
| Point | point | | |
| Polygon | polygon\[] | | |
| Ring | polygon | lseg | lseg exige dois pontos |
| SimpleAggregateFunction(f,T) | T | | Armazena os valores como T |
| String | text | bytea; tipos compatíveis com a entrada | bytea preserva os bytes brutos |
| Time | time without time zone | | |
| Time64(P) | time(P) without time zone | | P acima de 6 é limitado a 6 |
| Tuple(...) | text\[] | composite, T\[], text; box, circle, line | Os campos viram itens de texto |
| UInt8 | smallint | boolean | Zero é false; qualquer valor diferente de zero é true |
| UInt16 | integer | | |
| UInt32 | bigint | | |
| UInt64 | numeric(20,0) | xid8, oid8 | |
| UInt128 | numeric(39,0) | xid8, oid8 | |
| UInt256 | numeric(78,0) | xid8, oid8 | |
| UUID | uuid | | |

Tipos compatíveis com entrada podem ler strings usando sua função de entrada do PostgreSQL.
Tipos compostos devem ter campos correspondentes na mesma ordem. Para ler uma tupla
como array, cada campo deve ser convertível para o tipo de elemento do array, e nenhum campo
pode ser, ele próprio, um array.

Quando lidos como array, `Map` usa uma linha por par chave-valor e `Nested` usa
uma linha por linha aninhada. Para ler uma tupla como `box`, forneça dois pontos; para
`circle`, forneça um ponto e um raio; para `line`, forneça três coeficientes.

Todo tipo do chDB omitido desta tabela gera um erro, entre eles `Variant`,
`Dynamic` e `AggregateFunction`. Use uma [structure](#structure) que os mapeie
para `String` para lê-los como texto.

O Postgres admite um intervalo mais restrito que o chDB em alguns desses tipos; por isso, a cópia
gera um erro em um `Time` ou `Time64` superior a 24 horas, e em um `Date32`
fora do intervalo de datas do Postgres.

### Mapeamentos manuais de tipos

A inferência de colunas usa `text` para enums e arrays de texto para valores `Tuple`, `Map`
e `Nested`. Para preservar os tipos dos campos ou restringir os valores de enum, crie
tipos enum e compostos no PostgreSQL e, em seguida, declare as colunas com esses tipos.
Especifique os tipos do chDB com [structure](#structure) ou use `structure 'auto'`
para inferi-los a partir dos dados de origem, em vez da tabela do Postgres. Por
exemplo, use estes tipos para carregar status de eventos, coordenadas, labels e
itens aninhados:

```sql theme={null}
CREATE TYPE event_status AS ENUM ('new', 'done');
CREATE TYPE event_point AS (x integer, y integer);
CREATE TYPE event_label AS (key text, value bigint);
CREATE TYPE event_item AS (id integer, name text);

CREATE TABLE events (
    status event_status,
    point  event_point,
    labels event_label[],
    items  event_item[]
);

COPY events FROM 's3://chdb-lakedata-public/examples/events.parquet' (
    structure $$
        status Enum8('new' = 1, 'done' = 2),
        point  Tuple(Int32, Int32),
        labels Map(String, Int64),
        items  Array(Tuple(id Int32, name String))
    $$
);
```

Declare os campos compostos na ordem de campos do chDB, usando tipos
PostgreSQL compatíveis. Para valores `Map`, declare um campo de chave seguido de um campo de valor. Cada
`Tuple` se torna um valor composto; cada par de `Map` ou linha de `Nested` se torna
um elemento de um array composto.

Em uma `structure` explícita, o chDB divide `Nested` em uma coluna `Array` para cada
campo. Use `Array(Tuple(...))` para ler linhas aninhadas em uma única coluna de
array composto, como mostrado acima, ou use `structure 'auto'` com um formato de origem do chDB
que inclua informações de tipo.

### Codificação de texto

O chDB lê `String`, `FixedString`, `Enum` e `JSON` como bytes, sem qualquer
garantia de codificação. Ao copiar uma coluna desse tipo para `text`, ou para qualquer outro
tipo não binário, os bytes são verificados contra a codificação do banco de dados e é gerado um erro
para os dados que não podem ser representados:

```
ERROR:  invalid byte sequence for encoding "UTF8": 0x00
```

Todas as codificações rejeitam NULs, que o Postgres não consegue armazenar em `text`.

Copie para `bytea` para manter os bytes exatamente como o chDB os escreveu. Nomeie-os dessa forma, pois o
[CREATE TABLE](#create-table-overloading) deriva `text` para esses tipos:

```sql theme={null}
CREATE TABLE logs (req_id numeric(20,0), resource bytea) WITH (
    copy_from = 's3://chdb-lakedata-public/logs/logs-2026-08-26.parquet'
);
```

`FixedString(N)` preenche valores mais curtos com bytes NUL. Ao copiar para `text`, os NULs finais são descartados, enquanto `bytea` mantém todos os N bytes.

## Configurações

### `chdb_hook.max_memory`

```sql theme={null}
SET chdb_hook.max_memory = '1 GB';
```

Define a quantidade máxima de memória para uma consulta chDB, usada para definir a configuração
[`max_memory_usage`] do chDB. Requer privilégios de superusuário. Use um número inteiro
para indicar a quantidade de megabytes ou uma das seguintes unidades de memória:

* `B` (bytes)
* `kB` (kilobytes)
* `MB` (megabytes)
* `GB` (gigabytes)
* `TB` (terabytes)

O padrão é `0`, que não impõe limite de memória.

### `chdb_hook.max_threads`

```sql theme={null}
SET chdb_hook.max_threads = 4;
```

O número máximo de threads de processamento de consultas para uma consulta chDB, usado para definir a configuração [`max_threads`] do chDB. Requer privilégios de superusuário. O padrão é `0`, que deixa o próprio chDB determinar o valor.

Recomendamos fortemente definir `chdb_hook.max_threads` antes de executar um `COPY` de grande porte, para evitar que o chDB consuma toda a CPU em detrimento do PostgreSQL.

### `chdb_hook.max_parsing_threads`

```sql theme={null}
SET chdb_hook.max_parsing_threads = 2;
```

O número máximo de threads que o chDB pode usar para fazer o parsing de dados em input formats que
suportam parallel parsing, utilizado para definir a configuração [`max_parsing_threads`]
do chDB. Requer privilégios de superusuário. O padrão é `0`, o que deixa o próprio chDB
determinar o valor.

Recomendamos definir `chdb_hook.max_parsing_threads` antes de executar `COPY` com grandes volumes de
dados, para evitar que o chDB consuma todo o uso de CPU em detrimento do
PostgreSQL.

## Política de versionamento

O chdb\_hook segue o [Semantic Versioning] em seus lançamentos públicos.

* A major version é incrementada em mudanças de API
* A minor version é incrementada em mudanças de SQL compatíveis com versões anteriores
* A versão de patch é incrementada em mudanças apenas no binary

Uma vez instalado, o PostgreSQL a versão por meio da função
[`pg_get_loaded_modules()`] do Postgres 18.

```sql theme={null}
SELECT version FROM pg_get_loaded_modules() WHERE module_name = 'chdb_hook';
```

## Autores

* [David E. Wheeler](https://justatheory.com/)
* [serprex](https://github.com/serprex)

## Direitos autorais

Copyright (c) 2026, ClickHouse

[chDB]: https://clickhouse.com/chdb "chDB - banco de dados in-process rápido, confiável e escalável"

[Semantic Versioning]: https://semver.org/spec/v2.0.0.html "Semantic Versioning 2.0.0"

[COPY]: https://www.postgresql.org/docs/current/sql-copy.html "Documentação do Postgres: COPY"

[CREATE TABLE]: https://www.postgresql.org/docs/current/sql-createtable.html "Documentação do Postgres: CREATE TABLE"

[`DESCRIBE`]: https://clickhouse.com/docs/sql-reference/statements/describe-table "Documentação do ClickHouse: DESCRIBE TABLE"

[formats]: https://github.com/chdb-io/chdb/blob/main/refs/clickhouse-formats-settings.md#complete-format-names-table "Documentação do chDB: tabela completa de nomes de formatos"

[access key ID and access secret]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html "AWS Identity and Access Management: gerenciar chaves de acesso para usuários do IAM"

[HMAC key and secret]: https://docs.cloud.google.com/storage/docs/authentication/hmackeys "Google Cloud Storage: chaves HMAC"

[access key]: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-cli "Azure: gerenciar chaves de acesso de contas de armazenamento"

[row-level security]: https://www.postgresql.org/docs/current/ddl-rowsecurity.html "Documentação do Postgres: políticas de segurança em nível de linha"

[JSON type]: https://clickhouse.com/docs/reference/data-types/newjson.md "Documentação do ClickHouse: tipo de dado JSON"

[LOAD]: https://www.postgresql.org/docs/current/sql-load.html "Documentação do Postgres: LOAD"

[session_preload_libraries]: https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SESSION-PRELOAD-LIBRARIES "Documentação do Postgres: `session_preload_libraries`"

[shared_preload_libraries]: https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SESSION-PRELOAD-LIBRARIES "Documentação do Postgres: `shared_preload_libraries`"

[ALTER SYSTEM]: https://www.postgresql.org/docs/18/sql-altersystem.html "Documentação do Postgres: ALTER SYSTEM"

[ALTER DATABASE]: https://www.postgresql.org/docs/current/sql-alterdatabase.html "Documentação do Postgres: ALTER DATABASE"

[ALTER ROLE]: https://www.postgresql.org/docs/18/sql-alterrole.html "Documentação do Postgres: ALTER ROLE"

[AWS S3]: https://aws.amazon.com/s3/ "Cloud Object Storage - Amazon S3 - Amazon Web Services"

[Google Cloud Storage]: https://cloud.google.com/storage "Cloud Storage - Google Cloud"

[`file()`]: https://clickhouse.com/docs/sql-reference/table-functions/file "Documentação do ClickHouse: table function file"

[`url()`]: https://clickhouse.com/docs/sql-reference/table-functions/url "Documentação do ClickHouse: table function url"

[`s3()`]: https://clickhouse.com/docs/sql-reference/table-functions/s3 "Documentação do ClickHouse: table function s3"

[`gcs()`]: https://clickhouse.com/docs/sql-reference/table-functions/gcs "Documentação do ClickHouse: table function gcs"

[Azure Blob Storage]: https://azure.microsoft.com/en-us/products/storage/blobs/

[Azure ABFS]: https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction-abfs-uri "Usar a URI do Azure Data Lake Storage (ABFS) - Azure Storage"

[`azureBlobStorage()`]: https://clickhouse.com/docs/sql-reference/table-functions/azureBlobStorage "Documentação do ClickHouse: table function azureBlobStorage"

[Hadoop Distributed File System]: https://en.wikipedia.org/wiki/Apache_Hadoop#Overview "Wikipedia: visão geral do Apache Hadoop"

[`hdfs()`]: https://clickhouse.com/docs/sql-reference/table-functions/hdfs "Documentação do ClickHouse: table function hdfs"

[ClickHouse data types]: https://clickhouse.com/docs/reference/data-types/index.md "Documentação do ClickHouse: tipos de dados no ClickHouse"

[composite type]: https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-DECLARING "Documentação do PostgreSQL: declaração de tipos compostos"

[log_min_messages]: https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES "Documentação do PostgreSQL: log_min_messages"

[`pg_get_loaded_modules()`]: https://pgpedia.info/g/pg_get_loaded_modules.html "pgPedia: pg_get_loaded_modules()"

[`max_memory_usage`]: https://clickhouse.com/docs/reference/settings/session-settings/max-memory-usage "Documentação do ClickHouse: configurações de sessão max_memory_usage_*"

[`max_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max-threads "Documentação do ClickHouse: configurações de sessão max_threads_*"

[`max_parsing_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max#max_parsing_threads "Documentação do ClickHouse: configuração de sessão max_parsing_threads"

[database encoding]: https://www.postgresql.org/docs/current/multibyte.html "Documentação do PostgreSQL: Suporte a conjuntos de caracteres"
