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] :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
- La version de la bibliothèque (définie par
PG_MODULE_MAGICsur PostgreSQL 18 et versions ultérieures) inclut la version sémantique complète, visible dans la sortie de la fonctionpgch_version()ou de la fonction Postgrespg_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 fonctionpg_available_extension_versions()et\dx pg_clickhouse.
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 :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 SCHEMApour déplacer l’extension vers un nouveau schéma :
DROP EXTENSION
Utilisez DROP EXTENSION pour supprimer pg_clickhouse d’une base de données :CASCADE pour les supprimer également :
CREATE SERVER
Utilisez CREATE SERVER pour créer un serveur distant connecté à un serveur ClickHouse. Exemple :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
drivervaut “binary” et quehostest un hôte ClickHouse Cloud - 9004 si
drivervaut “binary” et quehostn’est pas un hôte ClickHouse Cloud - 8443 si
drivervaut “http” et quehostest un hôte ClickHouse Cloud - 8123 si
drivervaut “http” et quehostn’est pas un hôte ClickHouse Cloud
- 9440 si
min_tls_version: Version minimale du protocole TLS à négocier sur les connexions qui utilisent TLS. L’une deTLSv1,TLSv1.1,TLSv1.2ouTLSv1.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 lorsquehostest un hôte ClickHouse Cloud ou queportest un port sécurisé ; en clair sinon.on(outrue/yes/1) : utilise toujours TLS. La valeur par défaut deportest 8443 (“http”) ou 9440 (“binary”).off(oufalse/no/0) : n’utilise jamais TLS. La valeur par défaut deportest 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 erreurremove: supprime les octets invalidesreplace: avec l’encodage UTF-8, remplace les octets invalides par le caractère de remplacement Unicode (�) ; équivaut àremovepour les autres encodagestruncate: tronque le texte au premier octet invalide
ALTER SERVER
Utilisez ALTER SERVER pour modifier un serveur distant. Exemple :DROP SERVER
Utilisez DROP SERVER pour supprimer un serveur distant :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 distanttaxi_srv :
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 :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 :LIMIT TO pour restreindre l’importation à certaines tables :
EXCEPT pour exclure des tables :
-
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 quenumeric(12,6)[]. -
Les colonnes
Nullablesont importées sansNOT NULL; ce n’est pas le cas deNullableà l’intérieur d’unArray, car les tableaux PostgreSQL acceptent toujours les éléments NULL. -
Les colonnes
AggregateFunctionetSimpleAggregateFunctionsont importées sansNOT NULL, quelle que soit leur déclaration dans ClickHouse ; voir Colonnes d’état etNOT NULL. -
Les colonnes
Tuplesont importées en tant quetext[]. Les colonnesMapet les colonnesNestedcréées avecflatten_nested=0sont importées en tant quetext[][]. Chaque conversion émet unNOTICE. Le pseudo-typerecordde 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
DateTime64etTime64dont la précision est supérieure à 6 (microsecondes) déclenchent également unNOTICE, car PostgreSQL limite la précision àtimestamp(6)ettime(6). -
Les types de colonnes sans équivalent dans PostgreSQL, y compris l’ancien type
Object('json'), antérieur au typeJSONde ClickHouse, déclenchent une erreur.
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 :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. PourCollapsingMergeTree()etAggregatingMergeTree(), pg_clickhouse applique automatiquement les paramètres aux expressions de fonction exécutées sur la table.
-
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 automatiquementMergeà 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 etNOT 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 :
NOT NULL, PostgreSQL compte les états, ce qui donne un résultat incorrect :
NOT NULL, pg_clickhouse utilise countMerge() pour fusionner les états, ce qui donne
le décompte correct de 1000 :
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 :DROP FOREIGN TABLE
Utilisez DROP FOREIGN TABLE pour supprimer une table étrangère :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’optionVERBOSE provoque l’affichage de la
requête ClickHouse “Remote SQL” :
SELECT
Utilisez l’instruction SELECT pour exécuter des requêtes sur les tables pg_clickhouse, comme sur n’importe quelle autre table :nodes et effectuons la jointure avec celle-ci plutôt qu’avec la table distante :
node_id plutôt que par la colonne locale, puis en effectuant la jointure
avec la table de correspondance plus tard :
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 :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_oretbit_xor. avgsur des integer délègue son état{count, sum}sous forme de tableau.avg,var_pop,var_samp,stddev_popetstddev_sampsur 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 opaqueinternal 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 :{param:type} :
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 :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 :
join_use_nulls pour les jointures externes et transform_null_in pour la famille IN
(voir IN et sémantique NULL).
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éfautoutput_format_tsv_crlf_end_of_linele pilote « http » exige la valeur par défaut
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 :
ALTER ROLE
Utilisez la commandeSET d’ALTER ROLE pour précharger pg_clickhouse
et/ou SET ses paramètres pour certains rôles :
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 :
shared_preload_libraries
Charge la bibliothèque partagée dans le processus parent de PostgreSQL au démarrage :
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 driverbinary, 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 driverbinary, 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 :SELECT produira :
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.
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 :
Map
PostgreSQL ne propose aucun type correspondant au type [Map] de ClickHouse. pg_clickhouse fait donc correspondre les colonnes [Map] au typetext[][], 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 :
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 verstext[] 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 colonneNested 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 :
WHERE à l’aide des fonctionnalités habituelles des tableaux,
notamment la syntaxe d’accès par indice :
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 :
c2 Nested(id Int64, name String) dans cet exemple, on obtiendrait :
text[][] vers des types Nested échoue toutefois :
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 :
key et value).
Nested et Map deviennent des tableaux de composites, tandis que Tuple
devient une seule valeur composite :
SELECT :
WHERE --- à condition que les noms des champs soient
identiques :
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
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 :
SELECT version(), puis la met en cache pendant toute la durée de vie de la
connexion.
clickhouse_query
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
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 (clausesHAVING et WHERE). Ce sous-ensemble correspond aux
équivalents ClickHouse suivants :
abs: absfactorial: factorialmod(int2/int4/int8/numeric) : modulopow&power(float8, pas numeric) : powround: roundsin,cos,tan,atan,atan2,sinh,cosh,tanh,asinh,degrees,radians,pi: fonctions mathématiques ClickHouse portant le même nom.asin,acos,atanh,acoshne sont pas poussées vers le bas : PG renvoie une erreur sur une entrée hors intervalle, là où CH renvoieNaN.date_part:date_part('day'): toDayOfMonthdate_part('doy'): toDayOfYeardate_part('dow'): toDayOfWeekdate_part('year'): toYeardate_part('month'): toMonthdate_part('hour'): toHourdate_part('minute'): toMinutedate_part('second'): toSeconddate_part('quarter'): toQuarterdate_part('isoyear'): toISOYeardate_part('week'): toISOYeardate_part('epoch'): toISOYear
date_trunc:date_trunc('week'): toMondaydate_trunc('second'): toStartOfSeconddate_trunc('minute'): toStartOfMinutedate_trunc('hour'): toStartOfHourdate_trunc('day'): toStartOfDaydate_trunc('month'): toStartOfMonthdate_trunc('quarter'): toStartOfQuarterdate_trunc('year'): toStartOfYear
extract(field FROM source): mêmes correspondances quedate_partdate(timestamp)&date(timestamptz): toDate (restitué sous forme d’alias CHdate)array_position: indexOf avec nullIf pour convertir0enNULLet arraySlice lorsqu’un troisième argument indique l’index de début de la recherche ; notez quenanne correspond actuellement pasarray_cat: arrayConcatarray_append: arrayPushBackarray_prepend: arrayPushFrontarray_remove: arrayRemovecardinality: arrayFlattenedLength à partir de ClickHouse 26.9, sinon length, qui ne compte que les éléments du tableau externearray_length(array, 1):nullIf(length(array), 0)array_length&cardinality: lengtharray_to_string: arrayStringConcatstring_to_array: splitByStringsplit_part: splitByString + indexation de tableautrim_array: arrayResizearray_fill: arrayWithConstantarray_reverse: arrayReversearray_shuffle: arrayShufflearray_sample: arrayRandomSamplearray_sort: arraySort / arrayReverseSortbtrim: trimBothltrim: trimLeftrtrim: trimRightconcat_ws: concatWithSeparatorlower(text): lowerUTF8upper(text): upperUTF8substring(text, ...)&substr(text, ...): substringUTF8substring(bytea, ...)&substr(bytea, ...): substringlength(text): lengthUTF8length(bytea)&octet_length: lengthreverse(text): reverseUTF8reverse(bytea): reversestrpos: positionUTF8regexp_like: matchregexp_match: extractGroups si l’expression régulière contient des sous-expressions entre parenthèses ; sinon extractAll puis découpé avec arraySlice.regexp_replace: replaceRegexpOne ou replaceRegexpOne lorsque l’indicateurgest présentregexp_split_to_array: splitByRegexpmd5: MD5sha224,sha256,sha384etsha512: fonctions SHA correspondantes de ClickHouseencode(bytea, fmt)lorsquefmtest une constante de chaîne (sans distinction entre majuscules et minuscules) :encode(bytea, 'hex'): hex enveloppé dans lower, car PostgreSQL produit des valeurs hexadécimales en minuscules.encode(bytea, 'base64'): base64Encode enveloppé dans replaceRegexpAll afin de reproduire les sauts de ligne MIME (RFC 2045) de PostgreSQL toutes les 76 caractères.encode(bytea, 'base64url')(PostgreSQL 19+) : base64URLEncode, qui utilise l’alphabet d’URL RFC 4648 de PostgreSQL sans remplissage.
json_extract_path_text: syntaxe des sous-colonnesjson_extract_path: toJSONString + syntaxe des sous-colonnesjsonb_extract_path_text: syntaxe des sous-colonnesjsonb_extract_path: toJSONString + syntaxe des sous-colonnesbit_count(bytea): bitCountto_timestamp(float8): toDateTime64to_char(timestamp[tz], fmt): formatDateTime lorsquefmtest une constante de chaîne dont chaque mot-clé possède un équivalent fidèle dans ClickHouse. Voir to_char() dans les Notes de compatibilité pour les mots-clés pris en charge. Sinon, la fonction est évaluée localement dans PostgreSQL.statement_timestamp,transaction_timestamp, &clock_timestamp: nowInBlock64 (nowInBlock64(9, $session_timezone))CURRENT_DATE: now et toDate (toDate(now($session_timezone)))now,CURRENT_TIMESTAMP, &LOCALTIMESTAMP: now64 (now64(9, $session_timezone))CURRENT_TIMESTAMP(n)&LOCALTIMESTAMP(n): now64 (now64(n, $session_timezone))CURRENT_DATABASE: Transmise comme valeur par la fonction PostgreSQL.CURRENT_SCHEMA: Transmise comme valeur par la fonction PostgreSQL.CURRENT_CATALOG: Transmise comme valeur par la fonction PostgreSQL.CURRENT_USER: Transmise comme valeur par la fonction PostgreSQL.USER: transmis comme valeur par la fonction PostgreSQL.CURRENT_ROLE: transmis comme valeur par la fonction PostgreSQL.SESSION_USER: transmis comme valeur par la fonction PostgreSQL.
Opérateurs de pushdown
- Tranche d’Array (
arr[L:U]) : arraySlice @>(le tableau contient) : hasAll<@(tableau contenu dans) : hasAll&&(chevauchement de tableaux) : hasAny~(correspondance regexp) : match!~(absence de correspondance regexp) : match~*(absence de correspondance regexp insensible à la casse) : match!~*(absence de correspondance regexp insensible à la casse) : match->>(extraction d’un élément JSON/JSONB sous forme de texte) : syntaxe des sous-colonnes->(extraction JSON/JSONB) : toJSONString + syntaxe des sous-colonnes
Sémantique de IN et NULL
ClickHouse évalueIN 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 :@~→ matchre2match→ matchre2extract→ extractre2extractall→ extractAllre2regexpextract→ regexpExtractre2extractgroups→ extractGroupsre2replaceregexpone→ replaceRegexpOnere2replaceregexpall→ replaceRegexpAllre2countmatches→ countMatchesre2countmatchescaseinsensitive→ countMatchesCaseInsensitivere2multimatchany→ multiMatchAnyre2multimatchanyindex→ multiMatchAnyIndexre2multimatchallindices→ multiMatchAllIndices
intarray
Une fonction [intarray] fait l’objet d’un pushdown vers ClickHouse :idx→ indexOf
fuzzystrmatch
Deux fonctions [fuzzystrmatch] sont déléguées à ClickHouse :soundex: soundexlevenshtein(à 2 arguments) : editDistanceUTF8
pgcyrpto
digest(text, text)etdigest(bytea, text): fonction de hachage ClickHouse correspondante lorsque l’algorithme est une constantemd5,sha1,sha224,sha256,sha384ousha512(sans tenir compte de la casse).
Conversions de type avec pushdown
pg_clickhouse prend en charge le pushdown de conversions de type telles queCAST(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.- any_value
- array_agg
- avg
- bit_and
- bit_or
- bit_xor
- bool_and / every
- bool_or
- count
- corr
- covarpop
- covarsamp
- min
- max
- stddev_pop
- stddev_samp / stddev
- string_agg
- sum
- var_op
- var_samp /variance
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 expressionsORDER BY comme arguments. Par exemple, cette requête PostgreSQL :
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.
percentile_cont(double): quantilepercentile_cont(double[]): quantilespercentile_disc(double): quantileExactLowpercentile_disc(double[]): quantilesExactLow
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.quantile(double): quantilequantileExact(double): quantileExact
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 clausesOVER (PARTITION BY ... ORDER BY ...), y compris des spécifications de cadre
le cas échéant.
- row_number
- rank
- dense_rank
- ntile
- cume_dist
- percent_rank
- lead
- lag
- first_value
- last_value
- nth_value
min/max(avec une clauseOVER)
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 clauseSELECT). -
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,metpempê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 flagg. Lorsquegest activé, pg_clickhouse utilisereplaceRegexpAll()au lieu dereplaceRegexpOne()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\0pour la correspondance complète. Veillez à utiliser\0lorsque la fonction fait l’objet d’un pushdown vers ClickHouse. -
Postgres
regexp_matchrenvoieNULLlorsqu’il n’y a aucune correspondance, tandis que les expressions dont l’exécution est déléguée renvoient un tableau vide. UtilisezCOALESCE()pour renvoyer un tableau vide au lieu deNULLafin de comparer les valeurs de retour de manière compatible. Par exemple :
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. WheelerDroits d’auteur
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_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”