Skip to main content

Description

pg_clickhouse est une extension PostgreSQL qui permet d’exécuter des requêtes à distance sur des bases de données ClickHouse, et inclut un foreign data wrapper. Elle est compatible avec PostgreSQL 14 et versions ultérieures, ainsi qu’avec ClickHouse 23.3 et versions ultérieures.

Prise en main

Le moyen le plus simple de tester pg_clickhouse est d’utiliser l’Docker image, qui contient l’image Docker PostgreSQL standard avec les extensions pg_clickhouse et [re2][re2 extension] :
Consultez le tutoriel pour commencer à importer des tables ClickHouse et à déporter l’exécution des requêtes.

Utilisation

Politique de versionnage

pg_clickhouse se conforme au [versionnement sémantique] pour ses versions publiques.
  • La version majeure est incrémentée en cas de modification de l’API
  • La version mineure est incrémentée en cas de modifications SQL rétrocompatibles
  • La version de correctif est incrémentée pour les modifications portant uniquement sur le binaire
Une fois installée, PostgreSQL distingue deux variantes de version :
  • La version de la bibliothèque (définie par PG_MODULE_MAGIC sur PostgreSQL 18 et versions ultérieures) inclut la version sémantique complète, visible dans la sortie de la fonction pgch_version() ou de la fonction Postgres pg_get_loaded_modules().
  • La version de l’extension (définie dans le fichier de contrôle) inclut uniquement les versions majeure et mineure, visibles dans la table pg_catalog.pg_extension, la sortie de la fonction pg_available_extension_versions() et \dx pg_clickhouse.
En pratique, cela signifie qu’une version qui incrémente la version de correctif, par ex. de v0.1.0 à v0.1.1, bénéficie à toutes les bases de données qui ont chargé v0.1 et n’ont pas besoin d’exécuter ALTER EXTENSION pour profiter de la mise à niveau. En revanche, une version qui incrémente la version mineure ou majeure sera accompagnée de scripts de mise à niveau SQL, et toutes les bases de données existantes qui contiennent l’extension doivent exécuter ALTER EXTENSION pg_clickhouse UPDATE pour bénéficier de la mise à niveau.

Référence SQL DDL

Les expressions SQL DDL suivantes utilisent pg_clickhouse.

CREATE EXTENSION

Utilisez CREATE EXTENSION pour ajouter pg_clickhouse à une base de données :
Utilisez WITH SCHEMA pour l’installer dans un schéma spécifique (recommandé) :

ALTER EXTENSION

Utilisez ALTER EXTENSION pour modifier l’extension pg_clickhouse. Exemples :
  • Après l’installation d’une nouvelle version de pg_clickhouse, utilisez la clause UPDATE :
  • Utilisez SET SCHEMA pour déplacer l’extension vers un nouveau schéma :

DROP EXTENSION

Utilisez DROP EXTENSION pour supprimer pg_clickhouse d’une base de données :
Cette commande échoue si des objets dépendent de pg_clickhouse. Utilisez la clause CASCADE pour les supprimer également :

CREATE SERVER

Utilisez CREATE SERVER pour créer un serveur distant connecté à un serveur ClickHouse. Exemple :
Les options prises en charge sont :
  • driver : Le pilote de connexion ClickHouse à utiliser, soit “binary”, soit “http”. Obligatoire.
  • compression : Compression du protocole natif pour le pilote “binary”, parmi “none”, “lz4” ou “zstd”. La valeur par défaut est “lz4”. Ignoré par le pilote “http”.
  • dbname : La base de données ClickHouse à utiliser lors de la connexion. La valeur par défaut est “default”.
  • host : Le nom d’hôte du serveur ClickHouse. La valeur par défaut est “localhost” ;
  • port : Le port auquel se connecter sur le serveur ClickHouse. Les valeurs par défaut sont les suivantes :
    • 9440 si driver vaut “binary” et que host est un hôte ClickHouse Cloud
    • 9004 si driver vaut “binary” et que host n’est pas un hôte ClickHouse Cloud
    • 8443 si driver vaut “http” et que host est un hôte ClickHouse Cloud
    • 8123 si driver vaut “http” et que host n’est pas un hôte ClickHouse Cloud
  • min_tls_version : Version minimale du protocole TLS à négocier sur les connexions qui utilisent TLS. L’une de TLSv1, TLSv1.1, TLSv1.2 ou TLSv1.3. La valeur par défaut est la version minimale propre à la bibliothèque TLS. S’applique aux deux pilotes.
  • secure : Contrôle l’utilisation de TLS pour la connexion. L’une des valeurs suivantes :
    • auto (par défaut) : utilise TLS lorsque host est un hôte ClickHouse Cloud ou que port est un port sécurisé ; en clair sinon.
    • on (ou true/yes/1) : utilise toujours TLS. La valeur par défaut de port est 8443 (“http”) ou 9440 (“binary”).
    • off (ou false/no/0) : n’utilise jamais TLS. La valeur par défaut de port est 8123 (“http”) ou 9000 (“binary”).
  • encoding_check : Définit le traitement des caractères invalides au regard de l’[encodage de la base de données] lors de la conversion des valeurs String et JSON de ClickHouse. L’une des valeurs suivantes :
    • fail (par défaut) : lève une erreur
    • remove : supprime les octets invalides
    • replace : avec l’encodage UTF-8, remplace les octets invalides par le caractère de remplacement Unicode (�) ; équivaut à remove pour les autres encodages
    • truncate : tronque le texte au premier octet invalide

ALTER SERVER

Utilisez ALTER SERVER pour modifier un serveur distant. Exemple :
Les options sont les mêmes que pour CREATE SERVER.

DROP SERVER

Utilisez DROP SERVER pour supprimer un serveur distant :
Cette commande échoue si d’autres objets dépendent du serveur. Utilisez CASCADE pour supprimer également ces objets dépendants :

CREATE USER MAPPING

Utilisez CREATE USER MAPPING pour associer un utilisateur PostgreSQL à un utilisateur ClickHouse. Par exemple, pour associer l’utilisateur PostgreSQL actuel à l’utilisateur ClickHouse distant lors de la connexion au serveur distant taxi_srv :
Les options prises en charge sont :
  • user : Le nom de l’utilisateur ClickHouse. La valeur par défaut est “default”.
  • password : Le mot de passe de l’utilisateur ClickHouse.

ALTER USER MAPPING

Utilisez ALTER USER MAPPING pour modifier la définition d’un mappage d’utilisateur :
Les options sont les mêmes que celles de CREATE USER MAPPING.

DROP USER MAPPING

Utilisez DROP USER MAPPING pour supprimer un mappage d’utilisateur :

IMPORT FOREIGN SCHEMA

Utilisez IMPORT FOREIGN SCHEMA pour importer toutes les tables définies dans une base de données ClickHouse en tant que tables étrangères dans un schéma PostgreSQL :
Utilisez LIMIT TO pour restreindre l’importation à certaines tables :
Utilisez EXCEPT pour exclure des tables :
pg_clickhouse récupère la liste de toutes les tables de la base de données ClickHouse spécifiée (« demo » dans les exemples ci-dessus), récupère la définition des colonnes de chacune d’elles et exécute des commandes CREATE FOREIGN TABLE pour créer les tables étrangères. Les colonnes sont définies à l’aide des types de données pris en charge et, lorsqu’elles sont détectables, des options prises en charge par CREATE FOREIGN TABLE. Quelques points à garder à l’esprit :
  • Les colonnes importées conservent le modificateur du type ClickHouse, y compris à l’intérieur des Array. Autrement dit, Array(Decimal(12,6)) est importé en tant que numeric(12,6)[].
  • Les colonnes Nullable sont importées sans NOT NULL ; ce n’est pas le cas de Nullable à l’intérieur d’un Array, car les tableaux PostgreSQL acceptent toujours les éléments NULL.
  • Les colonnes AggregateFunction et SimpleAggregateFunction sont importées sans NOT NULL, quelle que soit leur déclaration dans ClickHouse ; voir Colonnes d’état et NOT NULL.
  • Les colonnes Tuple sont importées en tant que text[]. Les colonnes Map et les colonnes Nested créées avec flatten_nested=0 sont importées en tant que text[][]. Chaque conversion émet un NOTICE. Le pseudo-type record de PostgreSQL ne pouvant pas servir à définir une colonne de table, chaque tuple devient un tableau de valeurs, chaque map devient un tableau à deux dimensions de paires clé-valeur, et chaque valeur Nested devient un tableau à deux dimensions de lignes. Pour lire les champs sous forme d’enregistrements, convertissez la colonne en tableau d’un type composé correspondant ; voir Mappages de types manuels pour un exemple.
  • Les colonnes DateTime64 et Time64 dont la précision est supérieure à 6 (microsecondes) déclenchent également un NOTICE, car PostgreSQL limite la précision à timestamp(6) et time(6).
  • Les types de colonnes sans équivalent dans PostgreSQL, y compris l’ancien type Object('json'), antérieur au type JSON de ClickHouse, déclenchent une erreur.
Préservation de la casse des identifiants importésIMPORT FOREIGN SCHEMA exécute quote_identifier() sur les noms de table et de colonne qu’il importe, ce qui entoure de guillemets doubles les identifiants contenant des majuscules ou des espaces. Ces noms de table et de colonne doivent donc être entourés de guillemets doubles dans les requêtes PostgreSQL. Les noms entièrement en minuscules et sans espace n’ont pas besoin d’être mis entre guillemets.Par exemple, étant donnée cette table ClickHouse :
IMPORT FOREIGN SCHEMA crée cette table étrangère :
Les requêtes doivent donc utiliser les guillemets de manière appropriée, par exemple :
Pour créer des objets avec des noms différents ou entièrement en minuscules (et donc insensibles à la casse), utilisez CREATE FOREIGN TABLE.

CREATE FOREIGN TABLE

Utilisez CREATE FOREIGN TABLE pour créer une table étrangère permettant d’interroger les données d’une base de données ClickHouse :
Les options de table prises en charge sont :
  • database : Le nom de la base de données distante. Par défaut, il s’agit de la base de données définie pour le serveur distant.
  • table_name : Le nom de la table distante. Par défaut, il s’agit du nom spécifié pour la table étrangère.
  • engine : Le [moteur de table] utilisé par la table ClickHouse. Pour CollapsingMergeTree() et AggregatingMergeTree(), pg_clickhouse applique automatiquement les paramètres aux expressions de fonction exécutées sur la table.
Utilisez le type de données adapté au type de données ClickHouse distant de chaque colonne. Les options de colonne prises en charge sont :
  • column_name : Le nom de la colonne côté ClickHouse, utilisé de préférence au nom d’attribut PostgreSQL lors de la régénération des requêtes et des insertions. Utile pour faire correspondre des noms de colonnes PostgreSQL non quotés en minuscules à des colonnes ClickHouse sensibles à la casse, par exemple :
  • AggregateFunction : Le nom de la fonction d’agrégation appliquée à une colonne de [type AggregateFunction]. Faites correspondre le type de données au type ClickHouse passé à la fonction et spécifiez le nom de la fonction d’agrégation via l’option de colonne appropriée ; pg_clickhouse ajoutera automatiquement Merge à la fonction d’agrégation qui évalue la colonne. Déclarez la colonne comme nullable afin d’éviter les problèmes décrits dans Colonnes d’état et NOT NULL.
  • SimpleAggregateFunction : Le nom de la fonction d’agrégation appliquée à une colonne de [type SimpleAggregateFunction]. Faites correspondre le type de données au type ClickHouse passé à la fonction et spécifiez le nom de la fonction d’agrégation via l’option de colonne appropriée.

Colonnes d’état et NOT NULL

Laissez les colonnes AggregateFunction et SimpleAggregateFunction nullables. Pour les colonnes d’état NOT NULL, PostgreSQL 19 remplace count(column) par count(*), ce qui compte les lignes au lieu de fusionner les états. Prenons une table ClickHouse contenant un état count par utilisateur, chaque état étant construit à partir de 1 000 événements :
Avec NOT NULL, PostgreSQL compte les états, ce qui donne un résultat incorrect :
Sans NOT NULL, pg_clickhouse utilise countMerge() pour fusionner les états, ce qui donne le décompte correct de 1000 :
Utilisez ALTER FOREIGN TABLE pour supprimer la contrainte d’une table étrangère existante :
NOT NULL ne concerne que PostgreSQL. C’est pourquoi IMPORT FOREIGN SCHEMA importe les colonnes d’état comme nullables.

ALTER FOREIGN TABLE

Utilisez ALTER FOREIGN TABLE pour modifier la définition d’une table étrangère :
Les options de table et de colonne prises en charge sont identiques à celles de CREATE FOREIGN TABLE.

DROP FOREIGN TABLE

Utilisez DROP FOREIGN TABLE pour supprimer une table étrangère :
Cette commande échoue s’il existe des objets dépendant de la table étrangère. Utilisez la clause CASCADE pour les supprimer également :

Référence SQL DML

Les expressions SQL DML ci-dessous peuvent utiliser pg_clickhouse. Les exemples s’appuient sur ces tables ClickHouse :

EXPLAIN

La commande EXPLAIN fonctionne comme prévu, mais l’option VERBOSE provoque l’affichage de la requête ClickHouse “Remote SQL” :
Cette requête est exécutée dans ClickHouse via un nœud de plan “Foreign Scan”, le SQL exécuté à distance.

SELECT

Utilisez l’instruction SELECT pour exécuter des requêtes sur les tables pg_clickhouse, comme sur n’importe quelle autre table :
pg_clickhouse s’efforce de déléguer autant que possible l’exécution des requêtes à ClickHouse, y compris les fonctions d’agrégation. Utilisez EXPLAIN pour déterminer dans quelle mesure le pushdown s’applique. Pour la requête ci-dessus, par exemple, toute l’exécution est déléguée à ClickHouse
pg_clickhouse délègue également les JOIN entre des tables provenant du même serveur distant :
Une jointure avec une table locale générera des requêtes moins efficaces sans un ajustement fin. Dans cet exemple, nous créons une copie locale de la table nodes et effectuons la jointure avec celle-ci plutôt qu’avec la table distante :
Dans ce cas, nous pouvons confier une plus grande part de l’agrégation à ClickHouse en regroupant par node_id plutôt que par la colonne locale, puis en effectuant la jointure avec la table de correspondance plus tard :
Le nœud “Foreign Scan” délègue désormais l’agrégation par node_id, réduisant le nombre de lignes devant être rapatriées dans Postgres de 1000 (la totalité d’entre elles) à seulement 8, une pour chaque nœud.

Tables partitionnées

Une [table partitionnée] PostgreSQL peut combiner des partitions locales et des partitions étrangères stockées dans ClickHouse. Une configuration courante consiste à déporter les données plus anciennes vers ClickHouse, tandis que les données récentes restent dans PostgreSQL :
Pour savoir comment déplacer des données de partitions locales vers des partitions étrangères, consultez l’exemple offload-partition.sql. Les agrégats couvrant à la fois des partitions locales et étrangères nécessitent l’[agrégation par partition], que PostgreSQL désactive par défaut :
Lorsque enable_partitionwise_aggregate est activé, PostgreSQL calcule un agrégat partiel sous Append, puis un agrégat de finalisation au-dessus, qui combine ces résultats partiels. pg_clickhouse délègue l’agrégat partiel de la partition étrangère à ClickHouse :

Quand les agrégats partiels sont délégués

PostgreSQL représente un agrégat partiel par un état de transition que l’étape de finalisation combine entre les partitions. pg_clickhouse ne peut déléguer l’agrégat partiel d’une partition que s’il peut l’exprimer sous la forme d’une valeur ClickHouse :
  • Les agrégats décomposables dont l’état de transition correspond déjà à la valeur finale sont délégués directement : count, sum, min, max, bool_and/every, bool_or, bit_and, bit_or et bit_xor.
  • avg sur des integer délègue son état {count, sum} sous forme de tableau.
  • avg, var_pop, var_samp, stddev_pop et stddev_samp sur des nombres à virgule flottante délèguent leur état {N, sum, sum of squared deviations} sous forme de tableau.
FILTER (WHERE …) est délégué avec ces fonctions d’agrégation.

Lorsqu’ils basculent vers une solution de repli

Les agrégats dont l’état de transition correspond au type opaque internal de PostgreSQL ne disposent d’aucune représentation portable ; la partition étrangère récupère donc leurs lignes et les agrège localement. Cela concerne tout ce qui utilise numeric, ainsi que avg(bigint) et avg(interval). Les agrégats DISTINCT, à ensemble ordonné et variadiques basculent également vers une solution de repli.

PREPARE, EXECUTE, DEALLOCATE

À partir de la version v0.1.2, pg_clickhouse prend en charge les requêtes paramétrées, principalement créées par la commande PREPARE :
Utilisez EXECUTE comme d’habitude pour exécuter une requête préparée :
pg_clickhouse délègue les agrégations, comme d’habitude, comme on peut le voir dans la sortie détaillée de EXPLAIN :
Notez qu’il a envoyé les valeurs de date complètes, et non les marqueurs de paramètres. Ceci vaut pour les cinq premières requêtes, comme décrit dans les [notes sur PREPARE] de PostgreSQL. Lors de la sixième exécution, il envoie des [paramètres de requête] ClickHouse au format {param:type} :
Utilisez DEALLOCATE pour libérer une requête préparée :

INSERT

Utilisez la commande INSERT pour insérer des valeurs dans une table ClickHouse distante :

COPY

Utilisez la commande COPY pour insérer un lot de lignes dans une table ClickHouse distante :
⚠️ Limitations de l’API Batch pg_clickhouse n’a pas encore implémenté la prise en charge de l’API d’insertion par lot du FDW de PostgreSQL. Par conséquent, COPY utilise actuellement des instructions INSERT pour insérer les enregistrements. Cela sera amélioré dans une prochaine version.

LOAD

Utilisez LOAD pour charger la bibliothèque partagée pg_clickhouse :
Il n’est généralement pas nécessaire d’utiliser LOAD, car Postgres chargera automatiquement pg_clickhouse la première fois que l’une de ses fonctionnalités (fonctions, tables étrangères, etc.) est utilisée. Le seul cas où il peut être utile de LOAD pg_clickhouse est pour SET les paramètres de pg_clickhouse avant d’exécuter des requêtes qui en dépendent.

SET

Utilisez SET pour définir les paramètres de configuration personnalisés de pg_clickhouse.

pg_clickhouse.session_settings

Le paramètre pg_clickhouse.session_settings configure les [paramètre ClickHouse] à appliquer aux requêtes suivantes. Exemple :
Par défaut, la valeur est
Définissez-la sur une chaîne vide pour revenir aux paramètres du serveur ClickHouse — mais notez que la validité du pushdown dépend de certaines de ces valeurs par défaut : join_use_nulls pour les jointures externes et transform_null_in pour la famille IN (voir IN et sémantique NULL).
La syntaxe est une liste de paires clé/valeur délimitées par des virgules et séparées par un ou plusieurs espaces. Les clés doivent correspondre aux [paramètre ClickHouse]. Faites précéder les espaces, les virgules et les barres obliques inverses dans les valeurs d’une barre oblique inverse :
Ou utilisez des valeurs entre guillemets simples pour éviter d’avoir à échapper les espaces et les virgules ; envisagez d’utiliser le dollar quoting pour éviter d’avoir à utiliser des guillemets doubles :
Si la lisibilité est importante pour vous et que vous devez définir de nombreux paramètres, utilisez plusieurs lignes, par exemple :
Certains paramètres seront ignorés lorsqu’ils risqueraient d’interférer avec le fonctionnement de pg_clickhouse lui-même. Il s’agit des paramètres suivants :
  • date_time_output_format : le pilote « http » exige qu’il soit défini sur “iso”
  • format_tsv_null_representation : le pilote « http » exige la valeur par défaut
  • output_format_tsv_crlf_end_of_line le pilote « http » exige la valeur par défaut
Sinon, pg_clickhouse ne valide pas les paramètres, mais les transmet à ClickHouse pour chaque requête. Il prend donc en charge tous les paramètres de chaque version de ClickHouse. Notez que pg_clickhouse doit être chargé avant de définir pg_clickhouse.session_settings ; utilisez soit le [préchargement de bibliothèque partagée], soit simplement l’un des objets de l’extension pour garantir son chargement.

pg_clickhouse.pushdown_regex

Le paramètre pg_clickhouse.pushdown_regex contrôle si pg_clickhouse déporte les fonctions et les opérateurs d’expressions régulières. C’est le comportement par défaut ; définissez ce paramètre sur false pour éviter qu’ils ne soient déportés :
Voir Expressions régulières pour plus de détails.

ALTER ROLE

Utilisez la commande SET d’ALTER ROLE pour précharger pg_clickhouse et/ou SET ses paramètres pour certains rôles :
Utilisez la commande RESET de ALTER ROLE pour réinitialiser le préchargement de pg_clickhouse et/ou les paramètres :

Préchargement

Si presque toutes les connexions Postgres doivent utiliser pg_clickhouse, envisagez d’utiliser le [préchargement de bibliothèque partagée] pour le charger automatiquement :

session_preload_libraries

Charge la bibliothèque partagée à chaque nouvelle connexion à PostgreSQL :
Utile pour profiter des mises à jour sans redémarrer le serveur : il suffit de se reconnecter. Peut aussi être défini pour des utilisateurs ou des rôles spécifiques via ALTER ROLE.

shared_preload_libraries

Charge la bibliothèque partagée dans le processus parent de PostgreSQL au démarrage :
Utile pour économiser de la mémoire et réduire la surcharge de chargement à chaque session, mais nécessite le redémarrage du cluster lors de la mise à jour de la bibliothèque.

Types de données

Ce tableau présente la correspondance recommandée entre les types de données ClickHouse et PostgreSQL. IMPORT FOREIGN SCHEMA s’appuie sur ces correspondances et en déduit les modificateurs de type et les dimensions de tableau appropriés. Utilisez CREATE FOREIGN TABLE pour déclarer d’autres types PostgreSQL. Les cibles de lecture supplémentaires indiquent les conversions prises en charge par le driver binary, en plus des conversions explicites de PostgreSQL. Les cellules vides n’empêchent pas ces conversions. Les valeurs doivent tenir dans les types cibles. Ces cibles s’appliquent aux lectures ; les écritures obéissent à des règles de conversion distinctes. Toute colonne peut également être lue dans text, varchar ou un autre type chaîne. La valeur prend le type PostgreSQL indiqué ci-dessus, puis est rendue au moyen de la fonction de sortie de ce type. Une chaîne ClickHouse lue dans un type texte est validée par rapport à l’encodage de la base de données : les octets que PostgreSQL ne peut pas lire déclenchent donc une erreur. Déclarez une colonne String, FixedString, Enum ou JSON en BYTEA pour lire ses octets tels que ClickHouse les a écrits. Les types compatibles en entrée peuvent lire des chaînes de caractères à l’aide de leur fonction d’entrée PostgreSQL. Les types composites doivent comporter des champs correspondants, dans le même ordre. Pour lire un tuple sous forme de tableau, chaque champ doit pouvoir être converti dans le type d’élément du tableau, et aucun champ ne peut lui-même être un tableau. Lorsqu’ils sont lus sous forme de tableaux, Map produit une ligne par paire clé-valeur et Nested une ligne par enregistrement imbriqué. Pour lire un tuple en tant que box, fournissez deux points ; pour circle, un point et un rayon ; pour line, trois coefficients. Vous trouverez ci-dessous des remarques et des précisions supplémentaires.

Coercition de types

Avec le driver binary, les autres types scalaires utilisent les conversions explicites de PostgreSQL lorsqu’elles existent, et les éléments de tableau sont convertis dans le type d’élément déclaré. Les conversions non prises en charge et les valeurs hors plage génèrent des erreurs. Quel que soit le driver, mappez les types ClickHouse Interval vers smallint, integer ou bigint pour lire et écrire leur nombre d’unités. Par exemple, une valeur IntervalDay de 3 correspond à l’integer 3. Mapper IntervalNanosecond vers bigint conserve les nanosecondes, tandis que le mapper vers interval tronque la valeur à la microseconde.

BYTEA

ClickHouse ne fournit pas l’équivalent du type PostgreSQL BYTEA, mais permet de stocker n’importe quels octets dans le type [String]. En général, les chaînes ClickHouse doivent être associées au type PostgreSQL [TEXT], mais pour les données binaires, utilisez BYTEA. Exemple :
Cette dernière requête SELECT produira :
Une table externe utilisant des colonnes [TEXT] ne peut généralement pas lire ces valeurs en tant que texte, car pg_clickhouse valide les octets ClickHouse par rapport à l’encodage de la base de données :
Affichera :
Un digest contient des octets arbitraires, qui forment rarement un texte valide. PostgreSQL réserve en outre le caractère nul : une colonne [TEXT] ne peut donc jamais lire une string ClickHouse qui en contient un. L’insertion de valeurs binaires dans des colonnes [TEXT] réussira et fonctionnera comme prévu :
Les colonnes de texte contiendront les valeurs correctes :
Mais pas si vous les lisez comme BYTEA :
Une colonne FixedString(N) complète les valeurs courtes avec des octets nuls. Une colonne de texte supprime ce remplissage final, alors qu’une colonne BYTEA conserve chaque octet.
En règle générale, utilisez les colonnes [TEXT] uniquement pour les chaînes encodées et les colonnes BYTEA uniquement pour les données binaires, sans jamais passer de l’une à l’autre.

Types composites

Array

Les [Array]s ClickHouse correspondent directement aux tableaux PostgreSQL, avec une sémantique équivalente. La principale différence tient au fait que, dans Postgres, les tableaux multidimensionnels doivent contenir des expressions de tableau de dimensions identiques. Toute tentative de lecture d’un tableau ClickHouse de dimensions différentes, comme [[1], [2,3]], déclenche une erreur. L’accès par index aux tableaux est délégué au système distant lorsque c’est pertinent, y compris l’accès par index multidimensionnel. Exemples :
Les secteurs de tableaux (secteurs) sont également poussés vers la source distante via la fonction [arraySlice], bien que l’accès par secteur multidimensionnel ne soit pas encore pris en charge :

Map

PostgreSQL ne propose aucun type correspondant au type [Map] de ClickHouse. pg_clickhouse fait donc correspondre les colonnes [Map] au type text[][], chaque paire clé-valeur formant son propre tableau. IMPORT FOREIGN SCHEMA utilise cette correspondance. Il est également possible d’insérer des maps sous forme de tableaux avec INSERT. Par exemple :
Chaque tableau imbriqué doit contenir exactement deux valeurs textuelles. Toute valeur incompatible avec les types de clé ou de valeur ClickHouse correspondants déclenche une erreur.
L’insertion d’un Map nécessite le driver binary, qui déduit les types de colonnes à partir du serveur ClickHouse. Le driver http ne le fait pas : il ne dispose donc pas des informations nécessaires pour formater et insérer la valeur appropriée.

Tuple

De même, les colonnes ClickHouse de type [Tuple] sont mappées vers text[] et prennent en charge les INSERT via le binary driver. IMPORT FOREIGN SCHEMA émet un NOTICE lorsqu’il effectue un tel mappage.

Nested

Par défaut, ClickHouse découpe une colonne Nested en une colonne Array par champ (flatten_nested=1). IMPORT FOREIGN SCHEMA lit ces colonnes dans le catalogue system.columns de ClickHouse et crée des colonnes de type tableau PostgreSQL distinctes, en conservant les noms avec point, tels que items.a et items.b. Par exemple, pour la table externe suivante :
Son schéma importé comporte trois colonnes au lieu de deux :
Interrogez les colonnes Nested en plaçant les noms de colonnes entre guillemets doubles, par exemple :
Et filtrer les valeurs dans une clause WHERE à l’aide des fonctionnalités habituelles des tableaux, notamment la syntaxe d’accès par indice :
Une colonne [Nested] créée avec flatten_nested=0 correspond à un tableau comportant un élément par ligne imbriquée. Chaque élément du tableau contient les valeurs de la ligne correspondante :
Le schéma obtenu est alors le suivant :
Composez les enregistrements imbriqués sous forme de tableau à deux dimensions, dont les valeurs textuelles sont formatées selon chaque type défini par la colonne ClickHouse. Pour c2 Nested(id Int64, name String) dans cet exemple, on obtiendrait :
Le pushdown des colonnes text[][] vers des types Nested échoue toutefois :
En effet, pg_clickhouse ne peut pas distinguer une colonne de type tableau de texte reposant sur une colonne Array ClickHouse d’une colonne reposant sur une colonne Nested ; il ne peut donc pas la réécrire dans la syntaxe Nested de ClickHouse. Toutefois, un tableau d’un type composite correspondant peut également représenter ces éléments (voir Correspondances de types manuelles pour plus de détails). Dans ce cas, le pushdown fonctionne, à condition que les noms des champs du type composite soient identiques aux noms des champs Nested :

Correspondances de types manuelles

IMPORT FOREIGN SCHEMA utilise des types PostgreSQL génériques. Prenons par exemple une table ClickHouse comportant des colonnes [Enum], [Tuple], Map et [Nested] non aplaties (flatten_nested = 0), comme celle-ci :
Pour conserver la structure ou restreindre les valeurs, définissez des types PostgreSQL composites ou enum et créez manuellement une table externe :
Veillez à toujours rendre les libellés d’enum et les noms de champs des types composites identiques aux libellés d’enum ClickHouse et aux noms de champs Nested ou Tuple, afin que le pushdown utilise les bons noms.
Faites correspondre l’ordre et les types des champs composites aux déclarations ClickHouse. Les clés et les valeurs d’une [Map] deviennent respectivement le premier et le deuxième champ (ici, key et value). Nested et Map deviennent des tableaux de composites, tandis que Tuple devient une seule valeur composite :
Vous pouvez bien sûr aussi utiliser les noms de champs du type composite, à la fois dans une liste SELECT :
Et, pour les types [Nested] dans une clause WHERE --- à condition que les noms des champs soient identiques :
L’INSERT avec de tels types composites n’est pas encore pris en charge.

Référence des fonctions et des opérateurs

Fonctions

Ces fonctions constituent l’interface permettant d’interroger une base de données ClickHouse.

clickhouse_server_version

Renvoie la version du serveur ClickHouse, au format major.minor.patch, pour le serveur externe spécifié, en s’y connectant si nécessaire à l’aide des options du serveur et du user mapping de l’utilisateur courant :
Lit la version lors du handshake de la connexion via le protocole natif ou, via HTTP, à l’aide d’une unique requête SELECT version(), puis la met en cache pendant toute la durée de vie de la connexion.

clickhouse_query

Exécute une requête sur un serveur externe déjà configuré et renvoie ses lignes sous forme de relation, en associant chaque colonne de résultat ClickHouse au type PostgreSQL indiqué dans la liste de définition des colonnes. Elle réutilise le driver du serveur, ses informations d’identification, sa base de données et le cache de connexion. Le premier argument est le nom d’un serveur créé avec CREATE SERVER. Une liste de définition des colonnes (AS name(col type, ...)) est obligatoire : PostgreSQL doit connaître la structure du résultat avant de récupérer les lignes, et elle doit correspondre aux colonnes renvoyées par la requête. Les valeurs sont converties de ClickHouse vers les types déclarés, comme le seraient celles d’une colonne de table externe. Les instructions qui ne renvoient aucun résultat, telles que les DDL, n’ont rien à déclarer ; exécutez-les plutôt avec clickhouse_perform. Aucun rôle ne dispose par défaut de l’autorisation EXECUTE ; accordez GRANT à un rôle pour lui permettre d’utiliser la fonction.

clickhouse_perform

Exécute une instruction sur un serveur externe déjà configuré et ignore tout résultat. Utilisez-la pour les instructions qui ne renvoient aucune ligne, telles que les DDL, lorsque clickhouse_query n’a aucune forme de résultat à déclarer. Elle résout le serveur de la même manière que clickhouse_query, en réutilisant son driver, ses informations d’identification, sa base de données et le cache de connexions. En tant que procédure, elle doit être appelée avec CALL, et non avec SELECT, et ne renvoie aucune ligne. Par défaut, aucun rôle ne dispose de l’autorisation EXECUTE ; utilisez GRANT pour autoriser un rôle à utiliser la procédure.

Fonctions de pushdown

pg_clickhouse applique le pushdown à un sous-ensemble des fonctions intégrées de PostgreSQL utilisées dans les expressions conditionnelles (clauses HAVING et WHERE). Ce sous-ensemble correspond aux équivalents ClickHouse suivants :

Opérateurs de pushdown

Sémantique de IN et NULL

ClickHouse évalue IN selon une logique à deux valeurs : lorsqu’aucune correspondance n’est trouvée, il renvoie 0 même si un NULL est impliqué, tandis que PostgreSQL renvoie NULL. Pour préserver la sémantique de PostgreSQL, pg_clickhouse pousse systématiquement vers ClickHouse la famille IN appliquée à une liste ou un tableau constant (IN, NOT IN, = ANY, = ALL, <> ANY, <> ALL) : sous sa forme native ou peu coûteuse lorsqu’il peut prouver que ni la valeur testée ni un élément du tableau ne peuvent être NULL, ou sinon sous une forme CASE protégée qui vérifie les valeurs NULL à l’exécution et calcule la réponse exacte à trois valeurs de PostgreSQL (TRUE, FALSE, NULL) dans tous les contextes, y compris dans des positions de valeur telles qu’une liste SELECT ou GROUP BY. Un filtre NOT IN (SELECT ...) sur des colonnes Nullable est également poussé vers ClickHouse, puis déparsé avec des protections compensatoires qui préservent le comportement de PostgreSQL : un ensemble contenant un NULL exclut chaque ligne, et une valeur testée NULL ne passe que face à un ensemble vide. Chaque protection est omise lorsqu’une déclaration NOT NULL prouve qu’elle est inutile. Contrairement aux formes tableau ci-dessus, cette protection ne s’applique que dans une simple condition de filtre (ou sous NOT) ; nous ne poussons toujours pas IN (SELECT ...) vers ClickHouse lorsqu’il est utilisé dans une position de valeur, ni les corps de sous-requêtes groupés ou agrégés. Déclarer les colonnes NOT NULL maximise le pushdown en permettant d’envoyer à la place la forme non protégée, moins coûteuse ; IMPORT FOREIGN SCHEMA le fait automatiquement pour les colonnes ClickHouse non-Nullable. La preuve s’appuie sur les constantes non-NULL, les colonnes NOT NULL et l’arithmétique de base (+, -, *, unary -) appliquée à celles-ci. Ces règles supposent que transform_null_in = 0 conserve sa valeur par défaut dans ClickHouse, que pg_clickhouse définit pour chaque requête via la valeur par défaut du paramètre pg_clickhouse.session_settings, afin qu’un profil de serveur ClickHouse ne puisse pas la modifier silencieusement. Définir transform_null_in = 1 rompt la sémantique de chaque IN poussé vers ClickHouse.

Fonctions personnalisées

Ces fonctions personnalisées créées par pg_clickhouse assurent le pushdown des requêtes externes pour certaines fonctions ClickHouse n’ayant pas d’équivalent dans PostgreSQL. Si l’une de ces fonctions ne peut pas être poussée down, elle déclenchera une exception.

Pushdown des extensions

pg_clickhouse reconnaît les fonctions de certaines extensions de base et tierces, et effectue leur pushdown vers leurs équivalents dans ClickHouse.

re2

Tous les opérateurs et fonctions de l’[extension re2] font l’objet d’un pushdown 1:1 à ClickHouse :

intarray

Une fonction [intarray] fait l’objet d’un pushdown vers ClickHouse :

fuzzystrmatch

Deux fonctions [fuzzystrmatch] sont déléguées à ClickHouse :

pgcyrpto

  • digest(text, text) et digest(bytea, text) : fonction de hachage ClickHouse correspondante lorsque l’algorithme est une constante md5, sha1, sha224, sha256, sha384 ou sha512 (sans tenir compte de la casse).

Conversions de type avec pushdown

pg_clickhouse prend en charge le pushdown de conversions de type telles que CAST(x AS bigint) pour les types de données compatibles. Pour les types incompatibles, le pushdown échoue ; si x dans cet exemple est un UInt64 de ClickHouse, ClickHouse refusera de convertir la valeur. Pour effectuer le pushdown de conversions vers des types de données incompatibles, pg_clickhouse fournit les fonctions suivantes. Elles lèvent une exception dans PostgreSQL si elles ne sont pas pushed down.

Agrégats en pushdown

Ces fonctions d’agrégation PostgreSQL sont déléguées à ClickHouse via le pushdown.

Agrégats personnalisés

Ces fonctions d’agrégation personnalisées créées par pg_clickhouse assurent le pushdown des requêtes externes pour certaines fonctions d’agrégation ClickHouse sans équivalent dans PostgreSQL. Si l’une de ces fonctions ne peut pas faire l’objet d’un pushdown, une exception sera levée.

Agrégats d’ensemble ordonné en pushdown

Ces [fonctions d’agrégation d’ensemble ordonné] sont associées aux [fonctions d’agrégation paramétriques] de ClickHouse en passant leur argument direct comme paramètre et leurs expressions ORDER BY comme arguments. Par exemple, cette requête PostgreSQL :
Correspond à la requête ClickHouse suivante :
Notez que les suffixes DESC et NULLS FIRST non définis par défaut pour ORDER BY ne sont pas pris en charge et génèrent une erreur.

Agrégats d’ensemble ordonné personnalisés

Ces [fonctions d’agrégation d’ensemble ordonné] personnalisées créées par pg_clickhouse permettent le pushdown de requêtes externes pour sélectionner des [fonctions d’agrégation paramétriques] de ClickHouse. Si l’une de ces fonctions ne peut pas être exécutée en pushdown, elle génère une exception.

Agrégats d’ensembles ordonnés personnalisés

Ces [fonctions d’agrégation d’ensembles ordonnés] personnalisées, créées par pg_clickhouse, permettent le pushdown de requête externe pour sélectionner des [fonctions d’agrégation paramétriques] ClickHouse. Si l’une de ces fonctions ne peut pas être déléguée, elle génère une exception.

Fonctions de fenêtre prises en charge par le pushdown

Ces [fonctions de fenêtre] PostgreSQL font l’objet d’un pushdown vers ClickHouse avec des clauses OVER (PARTITION BY ... ORDER BY ...), y compris des spécifications de cadre le cas échéant. Les fonctions de classement (row_number, rank, dense_rank, ntile, cume_dist, percent_rank) omettent leur clause de cadre lors du pushdown, car ClickHouse rejette les spécifications de cadre pour ces fonctions.

Notes de compatibilité

Expressions régulières

Bien que pg_clickhouse délègue les expressions régulières à leurs équivalents ClickHouse lorsque pg_clickhouse.pushdown_regex vaut true (par défaut), et s’efforce d’assurer un minimum de compatibilité, gardez à l’esprit les différences entre les deux et la manière dont pg_clickhouse les gère.
  • PostgreSQL prend en charge les [expressions régulières POSIX], tandis que ClickHouse prend en charge les [expressions régulières RE2][RE2]. Tenez compte des différences de comportement : utilisez RE2 lorsque l’expression régulière est évaluée par ClickHouse (par exemple, dans une clause WHERE) et POSIX lorsqu’elle est évaluée par Postgres (par exemple, dans une clause SELECT).
  • pg_clickhouse répercute les [options Postgres] en les ajoutant en préfixe à l’expression régulière ClickHouse dans (?). Par exemple :
    Devient
  • Les seules options prises en charge par les deux, et qui peuvent donc être utilisées lorsqu’elles sont évaluées par ClickHouse, sont : RE2 ne prend en charge que ces options ; n’utilisez pas d’autres [options Postgres].
  • Ce tableau résume les effets des différents modificateurs (et de l’absence de modificateur, qui revient au même que s) pour la correspondance des sauts de ligne et des fins de ligne. Notez que dans Postgres, m et p empêchent les classes de caractères négatives ([^xyz]) de correspondre à un saut de ligne, alors que les équivalents de ClickHouse ne le font pas. Sinon, les comportements sont les mêmes dans ClickHouse que dans Postgres :
  • Tout autre flag transmis aux fonctions d’expression régulière empêchera le pushdown de la fonction.
  • L’exception est regexp_replace(), qui prend aussi en charge le flag g. Lorsque g est activé, pg_clickhouse utilise replaceRegexpAll() au lieu de replaceRegexpOne() et supprime le flag avant d’ajouter les autres flags en préfixe.
  • L’argument de remplacement de regexp_replace() dans Postgres prend en charge \& pour désigner la correspondance complète, tandis que ClickHouse utilise \0 pour la correspondance complète. Veillez à utiliser \0 lorsque la fonction fait l’objet d’un pushdown vers ClickHouse.
  • Postgres regexp_match renvoie NULL lorsqu’il n’y a aucune correspondance, tandis que les expressions dont l’exécution est déléguée renvoient un tableau vide. Utilisez COALESCE() pour renvoyer un tableau vide au lieu de NULL afin de comparer les valeurs de retour de manière compatible. Par exemple :
Pour lever toute ambiguïté, envisagez de définir pg_clickhouse.pushdown_regex pour empêcher le pushdown des expressions régulières Postgres vers ClickHouse, et d’utiliser l’ [extension re2], pour laquelle pg_clickhouse prend en charge le pushdown direct des expressions régulières [RE2] compatibles avec ClickHouse.

to_char()

Le [to_char()] de PostgreSQL pour timestamp et timestamp with time zone ne fait l’objet d’un pushdown vers ClickHouse [formatDateTime] que lorsque l’argument de format est une constante de chaîne non-NULL dont chaque mot-clé PostgreSQL a un équivalent ClickHouse strictement identique, octet pour octet. Si le format est dynamique ou s’il contient un mot-clé ou un modificateur non pris en charge, l’appel retombe sur une évaluation locale dans PostgreSQL. pg_clickhouse ne fait jamais l’objet d’un pushdown pour une traduction partielle, de sorte que le résultat reste compatible. Les formes à deux arguments de to_char() appliquées à numeric, interval et à d’autres types autres que timestamp ne font jamais l’objet d’un pushdown ; ClickHouse [formatDateTime] ne formate que les valeurs de date et d’heure.

Mots-clés traduits

Texte entre guillemets et littéraux

Le texte placé entre "..." est transmis tel quel, avec chaque % littéral doublé en %% pour échapper au préfixe de spécificateur de ClickHouse. Un \" en dehors des guillemets est également transmis comme un ". À l’intérieur de "...", l’antislash n’échappe que " ; les autres séquences avec antislash sont traitées comme du texte littéral.

Auteurs

David E. Wheeler Copyright (c) 2025-2026, ClickHouse [Array] https://clickhouse.com/docs/reference/data-types/array “ClickHouse Docs: Array(T)” [Map]: https://clickhouse.com/docs/sql-reference/data-types/map “ClickHouse Docs: Map” [Tuple]: https://clickhouse.com/docs/reference/data-types/tuple “ClickHouse Docs: Tuple(T1, T2, …)” [Nested]: https://clickhouse.com/docs/sql-reference/data-types/nested-data-structures/nested “ClickHouse Docs: Nested” [Enum]: https://clickhouse.com/docs/reference/data-types/enum “ClickHouse Docs: Enum” [String]: /reference/data-types/string “ClickHouse Docs: String” [TEXT]: https://www.postgresql.org/docs/current/datatype-character.html “PostgreSQL Docs: Types de caractères” [window functions]: https://www.postgresql.org/docs/current/functions-window.html “PostgreSQL Docs: Fonctions de fenêtre” [POSIX Regular Expressions]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP “PostgreSQL Docs: Expressions régulières POSIX” [Postgres flags]: https://www.postgresql.org/docs/current/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE “PostgreSQL Docs: Lettres d’option intégrées ARE” [RE2]: https://github.com/google/re2/wiki/Syntax “Syntaxe RE2” [re2 extension]: https://github.com/ClickHouse/pg&#95;re2 “pg_re2 : fonctions regex compatibles avec ClickHouse utilisant RE2” [intarray]: https://www.postgresql.org/docs/current/intarray.html “PostgreSQL Docs: intarray” [fuzzystrmatch]: https://www.postgresql.org/docs/current/fuzzystrmatch.html “PostgreSQL Docs: fuzzystrmatch” [to_char()]: https://www.postgresql.org/docs/current/functions-formatting.html “PostgreSQL Docs: Fonctions de formatage des types de données” [formatDateTime]: /reference/functions/regular-functions/date-time-functions#formatDateTime “ClickHouse Docs: formatDateTime”