> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-vortex-format.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentation de référence complète du module chdb_hook pour Postgres

# Documentation de référence du module chdb_hook

<h2 id="synopsis">
  Synopsis
</h2>

```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
```

<h2 id="description">
  Description
</h2>

Le module chdb\_hook s'intègre à la commande PostgreSQL [COPY](#copy-overloading)
afin d'utiliser [chDB] pour copier des données `TO` ou `FROM` l'un des
[formats de données pris en charge par chDB][formats], dans des fichiers locaux, des buckets [AWS S3],
[Google Cloud Storage], et bien d'autres. Il s'intègre également à [CREATE TABLE], si bien qu'une
table peut déduire ses colonnes et charger ses lignes depuis n'importe laquelle de ces mêmes
cibles.

<h2 id="loading">
  Chargement
</h2>

Chargez chdb\_hook de l'une des façons suivantes en tant que superutilisateur. Utilisez
celle qui correspond le mieux à votre cas d'utilisation :

* Explicitement, via la commande [LOAD] ; valable pour la durée d'une session :

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

  <Note>
    La SQL Console de ClickHouse Cloud ne prend pas encore en charge la commande
    `LOAD 'chdb_hook'`, mais celle-ci peut être exécutée via psql ou toute autre
    connexion à la base de données. Sinon, contactez votre interlocuteur Support pour
    l'ajouter à la configuration de votre service Postgres ; elle pourra ensuite être
    utilisée dans la SQL Console.
  </Note>

* Pour toutes les sessions, via le paramètre \[session\_preload\_libraries], dans
  `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';
  ```

  Ce paramètre peut également être défini base de données par base de données via [ALTER DATABASE] :

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

  Ou pour des utilisateurs et des groupes spécifiques via [ALTER ROLE] :

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

* Au démarrage du serveur, via le paramètre \[shared\_preload\_libraries], afin qu'il soit
  toujours disponible pour toutes les sessions et toutes les bases de données :

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

<Warning>
  Notez que le chargement de chdb\_hook permet aux utilisateurs disposant des rôles
  `pg_read_server_files` ou `pg_write_server_files` d'effectuer des opérations `COPY`
  depuis et vers des fichiers du serveur Postgres, ainsi que vers du stockage cloud.
</Warning>

<h2 id="copy-overloading">
  Surcharge de COPY
</h2>

Lors du [chargement](#loading), chdb\_hook se greffe sur la commande Postgres [COPY]
pour copier des données `TO` ou `FROM` l'un quelconque des [formats de données pris en
charge par chDB][formats], dans des fichiers locaux, des buckets [AWS S3],
[Google Cloud Storage], et bien plus encore. Pour charger une table depuis un CSV file
dans S3, par exemple, créez la table puis appelez `COPY` avec une 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';
```

<h3 id="privileges">
  Privilèges
</h3>

Un `COPY` chdb\_hook requiert les mêmes privilèges que le [COPY] qu'il remplace :
`SELECT` sur la relation ou sur chaque colonne copiée pour `COPY TO`, et `INSERT`
pour `COPY FROM`. Une URL `file://` lit ou écrit un fichier sur le serveur, et
requiert donc également l'appartenance à `pg_read_server_files` ou `pg_write_server_files`.
`COPY FROM` requiert une transaction en lecture-écriture.

<h3 id="url-schemes">
  Schémas d'URL
</h3>

chdb\_hook ne s'exécute que pour les cibles `COPY` de type URL utilisant l'un des
schémas suivants :

| Schémas | Cible | Fonction chDB |
| - | - | - |
| `file` | Chemin absolu sur le serveur 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()`] |

<h3 id="url-formats">
  Formats d'URL
</h3>

Le format des URL varie selon le target.

<h4 id="file">
  File
</h4>

Doit être un chemin absolu sur le serveur Postgres. Un chemin relatif provoque une
erreur. L'utilisateur Postgres doit être membre du rôle `pg_read_server_files` ou
`pg_write_server_files`, selon le cas. L'utilisateur système Postgres doit
disposer d'un accès en lecture ou en écriture au fichier, selon le cas. Pour `COPY TO`, si le
chemin n'existe pas, chdb\_hook créera les répertoires parents manquants ; il
doit pour cela disposer des permissions nécessaires sur le système de fichiers. Exemple :

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

<h4 id="http">
  HTTP
</h4>

Toute URL HTTP ordinaire, y compris dans un stockage cloud public. Pour `COPY TO`,
chdb\_hook tentera d'envoyer les données à l'URL via `POST`. Exemple :

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

<h4 id="s3">
  S3
</h4>

Les URL S3 peuvent prendre la forme d'un URI S3

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

Ou d'une URL d'objet :

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

<h4 id="GCS">
  GCS
</h4>

Les URL GCS prennent la forme d'une URL publique :

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

Ou un URI Cloud Storage, que chdb\_hook convertit en URL publique :

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

<h4 id="azure-blob-storage">
  Azure Blob Storage
</h4>

Utilisez une URL `blob.windows.net` avec un nom de compte comme sous-domaine :

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

Ou utilisez un autre nom d'hôte :

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

<h4 id="azure-abfs">
  Azure ABFS
</h4>

Les URL ABFS doivent utiliser ce format :

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

<h4 id="hdfs-urls">
  URL HDFS
</h4>

Les URL HDFS peuvent adopter la forme classique des URL de type HTTP, avec un port optionnel :

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

<h3 id="path-wildcards">
  Caractères génériques dans les chemins
</h3>

Les chemins d'URL peuvent contenir des globs dans les commandes `COPY FROM`. Les fichiers doivent correspondre au
motif de chemin complet, et non seulement au suffixe ou au préfixe. Seule exception : lorsque le
chemin désigne un répertoire existant et n'utilise pas de globs, un `*` est
implicitement ajouté au chemin afin de sélectionner tous les fichiers du répertoire.

Les caractères génériques pris en charge :

* `*` : correspond à un nombre quelconque de caractères, à l'exception de `/`, y compris la chaîne vide.
* `?` : correspond à un seul caractère quelconque.
* `{groucho,harpo,chico}` : substitue l'une des chaînes "groucho", "harpo" ou
  "chico". Ces chaînes peuvent contenir `/`.
* `{N..M}` : correspond à tout nombre `>= N` et `<= M`.
* `**` : correspond de manière récursive à tous les fichiers d'un répertoire.

Par exemple, pour charger les données de ces fichiers en une seule commande :

* [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)

Utilisez `{some,another}_prefix` pour faire correspondre les deux noms de répertoire et
`some_file_{1..3}.csv'` pour faire correspondre les fichiers, comme ceci :

```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';
```

<h3 id="options">
  Options
</h3>

La commande `COPY` de chdb\_hook prend en charge les options suivantes :

<h4 id="format">
  `format` :
</h4>

Le format à lire ou à écrire. Doit être l'un des [formats] proposés par [chDB],
parmi lesquels TSV, CSV, Parquet, Iceberg, JSON, et bien d'autres. Omettez-le ou définissez-le sur
`auto` pour laisser chDB déduire le format à partir de l'extension du nom de fichier figurant à la fin
de l'URL.

<h4 id="structure">
  `structure`
</h4>

La structure de données [chDB] d'une ligne. Elle se compose d'une liste de noms de colonnes,
de [ClickHouse data types] et de modificateurs. Si elle est omise, chdb\_hook fait correspondre les
types de données Postgres à des types ClickHouse généralement appropriés ; voir [Postgres vers
chDB](#postgres-to-chdb) pour plus de détails. Si la valeur est `auto`, chDB tente d'inférer
les types.

Exemple :

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

<h4 id="access_key-and-access_secret">
  `access_key` et `access_secret`
</h4>

Credentials à long terme de l'utilisateur du compte AWS permettant d'authentifier les requests.

* **S3 :** un \[access key ID et access secret] AWS, souvent définis à l'aide des
  environment variables `AWS_ACCESS_KEY_ID` et `AWS_SECRET_ACCESS_KEY`
* **GCS :** un [HMAC key and secret] GCP
* **Azure :** un nom de storage account Azure et une [access key]

<h4 id="session_token">
  `session_token`
</h4>

Token de session AWS à utiliser avec `access_key` et `access_secret`, souvent
défini par la variable d'environnement `AWS_SESSION_TOKEN`. Utilisé uniquement pour les
URL S3.

<h4 id="compression">
  `compression`
</h4>

Format de compression du fichier. À utiliser lorsque la compression ne peut pas
être déduite du nom du fichier. Valeurs prises en charge :

* `auto` (par défaut)
* `none`
* `gzip` ou `gz`
* `brotli` ou `br`
* `xz` ou `LZMA`
* `zstd` ou `zst`
* `lz4`
* `bz2`
* `snappy`

<h4 id="timeout">
  `timeout`
</h4>

Timeout de requête en millisecondes. S'applique aux URL HTTP, S3, GCS et Azure.
Valeur par défaut : `30000` (30 s).

<h3 id="debugging">
  Débogage
</h3>

En cas d'erreur, la commande `COPY` de chdb\_hook inclut la requête [chDB] qu'elle
a tenté d'exécuter dans le contexte de l'erreur :

```
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');
```

chdb\_hook utilise des placeholders de la forme `{name:Type}` pour les query parameters afin de se prémunir contre les vulnérabilités d'injection SQL et de limiter le risque de consigner des données sensibles telles que des credentials.

Si vous avez toutefois besoin de consulter le contenu de ces parameters pour déboguer un issue, définissez temporairement le GUC Postgres \[log\_min\_messages] sur `DEBUG1` ou une valeur supérieure : chdb\_hook enverra alors la query et les parameters dans le log Postgres (jamais au client), où ils apparaîtront ainsi :

```
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>
  Ne laissez pas \[log\_min\_messages] réglé sur un niveau de débogage au-delà
  d'une seule session de débogage, afin d'éviter de consigner des informations
  sensibles telles que des credentials, et parce que PostgreSQL journalise lui
  aussi des informations de débogage et peut rapidement saturer le log.
</Warning>

<h2 id="create-table-overloading">
  Surcharge de CREATE TABLE
</h2>

chdb\_hook s'accroche également à [CREATE TABLE], ce qui permet à une table de dériver ses
colonnes et de charger ses lignes depuis une URL.

Pour créer une table dont la structure est dérivée d'une URL, passez l'URL dans
l'option `structure_from` et laissez la liste de colonnes vide :

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

Utilisez `copy_from` pour charger les lignes ainsi que les colonnes :

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

`copy_from` n'infère les colonnes que lorsque le statement n'en nomme aucune
lui-même. Une column list, une clause `INHERITS`, un type `OF` ou une partition
définissent chacun des colonnes : `copy_from` ne copie alors que :

```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');
```

Les deux options prennent en charge les mêmes [schémas d’URL](#url-schemes) et
[options](#options) que `COPY` : credentials, format, compression, timeout et
même une [structure](#structure) explicite, tout s'applique. Postgres conserve
les paramètres de stockage restants :

```sql theme={null}
CREATE TABLE users () WITH (
    copy_from     = 's3://my-bucket/users.csv',
    access_key    = 'AKIAIOSFODNN7EXAMPLE',
    access_secret = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
    format        = 'CSVWithNames',
    fillfactor    = 90
);
```

Ni `structure_from` ni `copy_from` ne fonctionnent avec `IF NOT EXISTS`. Utilisez
[COPY] pour charger une relation existante.

<h2 id="limitations">
  Limitations
</h2>

En raison de quelques problèmes connus et de différences de comportement des types de données
entre Postgres et chDB, chdb\_hook présente les limitations suivantes :

* Impossible d'effectuer un `COPY` sur des relations dont les politiques de [row-level security] s'appliquent
  au rôle effectuant la copie. Postgres applique ces politiques en réécrivant `COPY TO` sous forme de
  requête, ce que chdb\_hook ne prend pas en charge.
* ClickHouse ne dispose pas de tableau NULL : `COPY TO` stocke donc un tableau vide (`[]`) pour
  un `NULL`.
* ClickHouse représente les équivalents de `lseg`, `path` ou `polygon` sous forme de
  tableaux ; les valeurs NULL de ces types sont donc elles aussi converties par `COPY TO` en tableau vide
  (`[]`).
* Les valeurs NULL produites pour une [structure](#structure) spécifiée qui ne
  définit pas la colonne comme Nullable seront émises sous forme de valeurs par défaut. Définissez toujours
  explicitement les colonnes nullables dans la [structure](#structure) pour éviter
  cette conversion.
* Un `path` ouvert dont le dernier point est identique au premier est émis comme un chemin fermé.
* Protobuf n'admet pas de valeur null dans un champ répété : il omet donc les valeurs NULL dans les tableaux.
* Le [JSON type] de chDB ne prend en charge que les objets JSON ; ne remplacez le mappage
  `String` par défaut de `json` et `jsonb` par `JSON` que si toutes les valeurs sont
  des objets JSON. (ClickHouse/ClickHouse#68428)
* Le [JSON type] de chDB ignore les `null` ; les clés d'objet dont la valeur est NULL seront
  omises en sortie. Ne remplacez le mappage `String` par défaut de `json` et
  `jsonb` par `JSON` que si les valeurs des objets ne sont pas `null` ou si leur perte est
  acceptable. (ClickHouse/ClickHouse#68428)
* Les formats JSON, JSONCompact et JSONColumnsWithMetadata valident toujours
  l'UTF-8 ; ils émettent donc les valeurs bytea avec des caractères de remplacement.
* `COPY FROM` interprète un champ Protobuf `Nullable` contenant une chaîne vide ou
  un zéro comme `NULL`. (chdb-io/chdb-core#152)
* `COPY TO` en Parquet supprime les `NULL` du null map propre à un Tuple Nullable.
  (ClickHouse/ClickHouse#112427)
* Les formats Parquet, Arrow, ArrowStream, ORC, Avro, Protobuf, ProtobufList, MsgPack
  et BSONEachRow n'ont aucun type correspondant au type `time` de Postgres ou
  `Time64` de chDB. Configurez les colonnes `time` comme des `String` dans une
  [structure](#structure) explicite pour préserver leurs valeurs.
* La sortie Protobuf tronque les valeurs timestamp à la seconde.
* La sortie Protobuf ne prend pas en charge les dates antérieures au 1970-01-01. Configurez les colonnes `time`
  comme des `String` dans une [structure](#structure) explicite pour préserver
  leurs valeurs. (ClickHouse/ClickHouse#111860)
* Les formats CSVWithNames et CSVWithNamesAndTypes ne peuvent actuellement pas importer
  de valeurs box ou circle `NULL`. (ClickHouse/ClickHouse#115523)

<h2 id="data-types">
  Types de données
</h2>

[COPY](#copy-overloading) fait correspondre les types Postgres d'une relation aux types chDB,
tandis que [CREATE TABLE](#create-table-overloading) fait correspondre les types chDB d'une URL
aux types Postgres.

<h3 id="postgres-to-chdb">
  Postgres vers chDB
</h3>

En l'absence d'une option [structure](#structure) explicite, chdb\_hook fait
correspondre les types Postgres à des équivalents chDB raisonnables. Lorsque ceux-ci ne
conviennent pas à votre cas d'usage, précisez la [structure](#structure) afin de remplacer les types générés par
ceux dont vous avez besoin.

| Postgres | chDB | Notes |
| - | - | - |
| boolean | Bool | |
| name | String | |
| text | String | |
| inet | String | Remplacez par `IPv4` ou `IPv6` si les données ne contiennent que l'un des deux. |
| cidr | String | |
| macaddr | String | |
| macaddr8 | String | |
| interval | String | Remplacez par une unité `Interval` telle que `IntervalDay`. |
| tsvector | String | |
| tsquery | String | |
| jsonpath | String | |
| money | String | |
| enum | String | |
| varchar | String | |
| varbit | String | |
| char | FixedString | |
| bit | FixedString | |
| bpchar | String | |
| int2 | Int16 | |
| int4 | Int32 | |
| int8 | Int64 | |
| oid | UInt32 | |
| oid8 | UInt64 | |
| xid8 | UInt64 | |
| json | String | Remplacez par `JSON` si les données ne contiennent que des objets. |
| jsonb | String | Remplacez par `JSON` si les données ne contiennent que des objets. |
| float4 | Float32 | |
| float8 | Float64 | |
| date | Date32 | |
| time | Time64(6) | Remplacez par `String` pour les formats qui ne prennent pas en charge les heures. |
| timetz | String | |
| timestamp | DateTime64(6) | Déclaré avec la time zone `UTC`, converti depuis la session time zone. |
| timestamptz | DateTime64(6) | Déclaré avec la time zone `UTC`. |
| numeric | Decimal | |
| uuid | UUID | |
| point | `Point` | Les deux mêmes coordonnées que dans Postgres. |
| lseg | `LineString` | Une line composée d'exactement deux points. |
| path | `LineString` | Un path fermé répète son premier point. |
| polygon | `Ring` | Un ring se ferme implicitement, comme un polygon. |
| box | `Tuple(high Point, low Point)` | Les deux coins, triés comme le fait Postgres. |
| circle | `Tuple(center Point, radius Float64)` | |
| line | `Tuple(a Float64, b Float64, c Float64)` | L'équation `Ax + By + C = 0`. |

Les types Array correspondent à des `Array` du type d'élément associé. ClickHouse contraint
la nullabilité par column, tandis que Postgres la contraint par array : les elements sont
donc toujours `Nullable`.

Aucun type Postgres ne correspond à `Map` ou `Tuple`, mais la [structure](#structure) peut
en désigner un. Un `Map` peut être converti en array de paires clé-valeur, et un `Tuple`
en array. Utilisez `text[]` pour une prise en charge hétérogène.

<h3 id="timestamp-conversion">
  Conversion des timestamps
</h3>

Dans les formats texte brut (TSV, CSV, etc.), le hook `COPY` émet les valeurs DateTime et
DateTime64 au format ISO-8601, `YYYY-MM-DDThh:mm:ssZ`, sans tenir compte
du paramètre `datestyle` courant. Cela garantit que les valeurs timestamptz
restent cohérentes, même si une source qui importe ces valeurs utilise une time zone
différente. L'utilisation d'un type différent dans la sortie `structure`, tel que `Datetime64(3,
'America/Los_Angeles')`, n'a aucun effet sur le décalage de la sortie, mais
modifie la precision.

Exemples 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` |

Le hook `COPY` convertit également les valeurs timestamp de la session time zone vers
UTC, ce qui garantit qu'elles sont émises par rapport à cette time zone. Une fois chargées
dans un nouveau système, celui-ci devrait les convertir vers sa time zone locale. Les
valeurs différeront donc si la time zone diffère, mais resteront identiques
compte tenu de l'écart entre les time zones.

Exemple de l'effet du paramètre `timezone` sur le timestamp
`2026-08-28T12:00:00` :

| paramètre 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` |

<h3 id="chdb-to-postgres">
  chDB vers Postgres
</h3>

chdb\_hook fait correspondre les types ClickHouse renvoyés par [`DESCRIBE`] aux types
Postgres suivants :

| chDB | Postgres | Notes |
| - | - | - |
| Array(T) | T\[] | Un type tableau PG par niveau de profondeur |
| BFloat16 | real | L'écriture supprime les bits de poids faible de la mantisse |
| Bool | boolean | |
| Date | date | |
| Date32 | date | |
| DateTime | timestamp with time zone | |
| DateTime64(P) | timestamp(P) with time zone | Un P supérieur à 6 est plafonné à 6 |
| Decimal(P,S) | numeric(P,S) | |
| Decimal32(S) | numeric(9,S) | |
| Decimal64(S) | numeric(18,S) | |
| Decimal128(S) | numeric(38,S) | |
| Decimal256(S) | numeric(76,S) | |
| Enum8 | text | |
| Enum16 | text | |
| FixedString(N) | text | N compte des octets côté CH, des caractères côté PG |
| Float32 | real | |
| Float64 | double precision | |
| IPv4 | inet | |
| IPv6 | inet | |
| Int8 | smallint | |
| Int16 | smallint | |
| Int32 | integer | |
| Int64 | bigint | |
| Int128 | numeric(39,0) | |
| Int256 | numeric(77,0) | |
| IntervalDay | interval | |
| IntervalHour | interval | |
| IntervalMicrosecond | interval | |
| IntervalMillisecond | interval | |
| IntervalMinute | interval | |
| IntervalMonth | interval | |
| IntervalNanosecond | interval | Tronqué à la microseconde |
| IntervalQuarter | interval | |
| IntervalSecond | interval | |
| IntervalWeek | interval | |
| IntervalYear | interval | |
| JSON | jsonb | |
| LineString | path | |
| LowCardinality(T) | T | |
| Map(K,V) | text\[]\[] | Une ligne d'éléments text par paire |
| MultiLineString | path\[] | |
| MultiPolygon | polygon\[]\[] | |
| Nullable(T) | T | Rend la colonne nullable |
| Point | point | |
| Polygon | polygon\[] | |
| Ring | polygon | |
| String | text | |
| Time | time without time zone | |
| Time64(P) | time(P) without time zone | Un P supérieur à 6 est plafonné à 6 |
| Tuple(...) | text\[] | Les champs deviennent des éléments text |
| UInt8 | smallint | |
| UInt16 | integer | |
| UInt32 | bigint | |
| UInt64 | numeric(20,0) | |
| UInt128 | numeric(39,0) | |
| UInt256 | numeric(78,0) | |
| UUID | uuid | |

Tout type chDB absent de ce tableau lève une erreur, notamment `Nested`,
`Variant` et `Dynamic`. Utilisez une [structure](#structure) qui les associe à
`String` pour les lire sous forme de texte.

Pour certains de ces types, Postgres couvre une plage plus étroite que chDB ; la copie
lève donc une erreur sur un `Time` ou un `Time64` dépassant 24 heures, ainsi que sur un `Date32`
situé en dehors de la plage de dates de Postgres.

<h3 id="text-encoding">
  Encodage du texte
</h3>

chDB lit `String`, `FixedString`, `Enum` et `JSON` sous forme d'octets, sans
aucune garantie quant à l'encodage. La copie d'une telle colonne vers `text`, ou vers
tout autre type non binaire, vérifie les octets au regard de l'encodage de la base de données et lève une erreur
pour les données qui ne peuvent pas être représentées :

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

Chaque encoding rejette les caractères NUL, que Postgres ne peut pas stocker dans `text`.

Copiez dans `bytea` pour conserver les octets tels que chDB les a écrits. Nommez-les ainsi, car
[CREATE TABLE](#create-table-overloading) dérive `text` pour ces types :

```sql theme={null}
CREATE TABLE logs (id bigint, payload bytea) WITH (
    copy_from = 's3://my-bucket/logs.parquet'
);
```

`FixedString(N)` complète les valeurs plus courtes avec des octets NUL. La copie vers `text` supprime les NUL de fin, tandis que `bytea` conserve la totalité des N octets.

<h2 id="settings">
  Paramètres
</h2>

<h3 id="chdb_hookmax_memory">
  `chdb_hook.max_memory`
</h3>

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

Définit la quantité maximale de mémoire allouée à une requête chDB ; sert à renseigner le paramètre chDB
[`max_memory_usage`]. Nécessite les privileges de superuser. Indiquez un integer
correspondant au nombre de mégaoctets, ou une valeur suivie de l'une des unités de mémoire suivantes :

* `B` (octets)
* `kB` (kilooctets)
* `MB` (mégaoctets)
* `GB` (gigaoctets)
* `TB` (téraoctets)

Vaut `0` par défaut, ce qui signifie aucune limite de mémoire.

<h3 id="chdb_hookmax_threads">
  `chdb_hook.max_threads`
</h3>

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

Le nombre maximal de threads de query processing pour une requête chDB, utilisé pour définir le paramètre chDB [`max_threads`]. Nécessite le privilège de superuser. La valeur par défaut est `0`, ce qui laisse chDB déterminer la valeur.

Nous recommandons vivement de définir `chdb_hook.max_threads` avant d'exécuter un `COPY` volumineux, afin d'éviter que chDB ne sature le CPU au détriment de PostgreSQL.

<h3 id="chdb_hookmax_parsing_threads">
  `chdb_hook.max_parsing_threads`
</h3>

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

Le nombre maximal de threads que chDB peut utiliser pour parser des données dans les formats d'entrée qui prennent en charge le parsing parallèle ; il sert à définir le paramètre chDB [`max_parsing_threads`]. Nécessite les privilèges de superuser. La valeur par défaut est `0`, ce qui laisse chDB déterminer la valeur.

Nous recommandons de définir `chdb_hook.max_parsing_threads` avant d'effectuer un `COPY` sur un grand volume de données, afin d'éviter que chDB ne sature l'utilisation du CPU au détriment de PostgreSQL.

<h2 id="versioning-policy">
  Politique de versionnage
</h2>

chdb\_hook respecte le [Semantic Versioning] pour ses releases publiques.

* La major version est incrémentée en cas de changements d'API
* La minor version est incrémentée en cas de changements SQL rétrocompatibles
* La version de patch est incrémentée en cas de changements portant uniquement sur le binary

Une fois installé, PostgreSQL la version via la fonction
[`pg_get_loaded_modules()`] de Postgres 18.

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

<h2 id="authors">
  Auteurs
</h2>

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

<h2 id="copyright">
  Droits d'auteur
</h2>

Copyright (c) 2026, ClickHouse

[chDB]: https://clickhouse.com/chdb "chDB - base de données in-process rapide, fiable et évolutive"

[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 "Documentation Postgres : COPY"

[CREATE TABLE]: https://www.postgresql.org/docs/current/sql-createtable.html "Documentation Postgres : CREATE TABLE"

[`DESCRIBE`]: https://clickhouse.com/docs/sql-reference/statements/describe-table "ClickHouse Docs : DESCRIBE TABLE"

[formats]: https://github.com/chdb-io/chdb/blob/main/refs/clickhouse-formats-settings.md#complete-format-names-table "Documentation chDB : tableau complet des noms de formats"

[access key ID and access secret]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html "AWS Identity and Access Management : gérer les clés d'accès des utilisateurs IAM"

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

[access key]: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-cli "Azure : gérer les clés d'accès d'un compte de stockage"

[row-level security]: https://www.postgresql.org/docs/current/ddl-rowsecurity.html "Documentation Postgres : politiques de sécurité au niveau des lignes"

[JSON type]: /reference/data-types/newjson "ClickHouse Docs : type de données JSON"

[LOAD]: https://www.postgresql.org/docs/current/sql-load.html "Documentation Postgres : LOAD"

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

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

[ALTER SYSTEM]: https://www.postgresql.org/docs/18/sql-altersystem.html "Documentation Postgres : ALTER SYSTEM"

[ALTER DATABASE]: https://www.postgresql.org/docs/current/sql-alterdatabase.html "Documentation Postgres : ALTER DATABASE"

[ALTER ROLE]: https://www.postgresql.org/docs/18/sql-alterrole.html "Documentation 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 "ClickHouse Docs : table function file"

[`url()`]: https://clickhouse.com/docs/sql-reference/table-functions/url "ClickHouse Docs : table function url"

[`s3()`]: https://clickhouse.com/docs/sql-reference/table-functions/s3 "ClickHouse Docs : table function s3"

[`gcs()`]: https://clickhouse.com/docs/sql-reference/table-functions/gcs "ClickHouse Docs : 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 "Utiliser l'URI Azure Data Lake Storage (ABFS) - Azure Storage"

[`azureBlobStorage()`]: https://clickhouse.com/docs/sql-reference/table-functions/azureBlobStorage "ClickHouse Docs : table function azureBlobStorage"

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

[`hdfs()`]: https://clickhouse.com/docs/sql-reference/table-functions/hdfs "ClickHouse Docs : table function hdfs"

[ClickHouse data types]: https://clickhouse.com/docs/reference/data-types/index "ClickHouse Docs : types de données dans ClickHouse"

[log_min_messages]: https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES "Documentation 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 "ClickHouse Docs : session settings max_memory_usage_*"

[`max_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max-threads "ClickHouse Docs : session settings max_threads_*"

[`max_parsing_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max#max_parsing_threads "ClickHouse Docs : paramètre de session max_parsing_threads"
