Saltar al contenido principal

Descripción

pg_clickhouse es una extensión de PostgreSQL que permite ejecutar consultas de forma remota en bases de datos de ClickHouse e incluye un foreign data wrapper. Es compatible con PostgreSQL 13 y versiones posteriores, y con ClickHouse 23 y versiones posteriores.

Primeros pasos

La forma más sencilla de probar pg_clickhouse es la imagen de Docker, que contiene la imagen de Docker estándar de PostgreSQL con las extensiones pg_clickhouse y [re2][re2 extension]:
Consulta el tutorial para empezar a importar tablas de ClickHouse y delegar la ejecución de consultas.

Uso

Política de versionado

pg_clickhouse sigue el [versionado semántico] para sus versiones públicas.
  • La versión mayor se incrementa por cambios en la API
  • La versión menor se incrementa por cambios de SQL compatibles con versiones anteriores
  • La versión de parche se incrementa por cambios únicamente en el binario
Una vez instalado, PostgreSQL realiza un seguimiento de dos variantes de la versión:
  • La versión de la biblioteca (definida por PG_MODULE_MAGIC en PostgreSQL 18 y posteriores) incluye la versión semántica completa, visible en la salida de la función pgch_version() o de la función de Postgres pg_get_loaded_modules().
  • La versión de la extensión (definida en el archivo de control) incluye solo las versiones mayor y menor, visibles en la tabla pg_catalog.pg_extension, en la salida de la función pg_available_extension_versions() y en \dx pg_clickhouse.
En la práctica, esto significa que una versión que incrementa la versión de parche, por ejemplo, de v0.1.0 a v0.1.1, beneficia a todas las bases de datos que han cargado v0.1 y no necesitan ejecutar ALTER EXTENSION para beneficiarse de la actualización. Por otro lado, una versión que incrementa la versión menor o mayor irá acompañada de scripts de actualización de SQL, y todas las bases de datos existentes que contengan la extensión deben ejecutar ALTER EXTENSION pg_clickhouse UPDATE para beneficiarse de la actualización.

Referencia de SQL DDL

Las siguientes expresiones SQL DDL usan pg_clickhouse.

CREATE EXTENSION

Utiliza CREATE EXTENSION para añadir pg_clickhouse a una base de datos:
Utiliza WITH SCHEMA para instalarlo en un esquema específico (recomendado):

ALTER EXTENSION

Utilice ALTER EXTENSION para modificar pg_clickhouse. Ejemplos:
  • Después de instalar una nueva versión de pg_clickhouse, use la cláusula UPDATE:
  • Use SET SCHEMA para mover la extensión a un nuevo esquema:

DROP EXTENSION

Utiliza DROP EXTENSION para eliminar pg_clickhouse de una base de datos:
Este comando falla si hay algún objeto que dependa de pg_clickhouse. Use la cláusula CASCADE para eliminarlos también:

CREATE SERVER

Use CREATE SERVER para crear un servidor foráneo que se conecte a un servidor de ClickHouse. Ejemplo:
Las opciones admitidas son:
  • driver: El controlador de conexión de ClickHouse que se usará, ya sea “binary” o “http”. Obligatorio.
  • dbname: La base de datos de ClickHouse que se usará al conectarse. El valor predeterminado es “default”.
  • fetch_size: Tamaño aproximado del lote en bytes para HTTP streaming. Los lotes se dividen en los límites de las filas. El valor predeterminado es 50000000 (50 MB). 0 desactiva el streaming y almacena en búfer la respuesta completa. Las tablas foráneas pueden sobrescribir este valor.
  • host: El nombre de host del servidor de ClickHouse. El valor predeterminado es “localhost”;
  • port: El puerto del servidor de ClickHouse al que conectarse. Los valores predeterminados son los siguientes:
    • 9440 si driver es “binary” y host es un host de ClickHouse Cloud
    • 9004 si driver es “binary” y host no es un host de ClickHouse Cloud
    • 8443 si driver es “http” y host es un host de ClickHouse Cloud
    • 8123 si driver es “http” y host no es un host de ClickHouse Cloud

ALTER SERVER

Utilice ALTER SERVER para modificar un servidor foráneo. Ejemplo:
Las opciones son las mismas que en CREATE SERVER.

DROP SERVER

Use DROP SERVER para eliminar un servidor foráneo:
Este comando falla si algún otro objeto depende del servidor. Use CASCADE para eliminar también esas dependencias:

CREATE USER MAPPING

Use CREATE USER MAPPING para asignar un usuario de PostgreSQL a un usuario de ClickHouse. Por ejemplo, para asignar el usuario actual de PostgreSQL al usuario remoto de ClickHouse al conectarse al servidor foráneo taxi_srv:
Las opciones admitidas son:
  • user: El nombre del usuario de ClickHouse. El valor predeterminado es “default”.
  • password: La contraseña del usuario de ClickHouse.

ALTER USER MAPPING

Use ALTER USER MAPPING para cambiar la definición de una asignación de usuario:
Las opciones son las mismas que las de CREATE USER MAPPING.

DROP USER MAPPING

Utilice DROP USER MAPPING para eliminar una asignación de usuario:

IMPORT FOREIGN SCHEMA

Use IMPORT FOREIGN SCHEMA para importar todas las tablas definidas en una base de datos de ClickHouse como tablas foráneas en un esquema de PostgreSQL:
Usa LIMIT TO para limitar la importación a tablas concretas:
Usa EXCEPT para excluir tablas:
pg_clickhouse obtendrá una lista de todas las tablas de la base de datos de ClickHouse especificada (“demo” en los ejemplos anteriores), recuperará las definiciones de las columnas de cada una y ejecutará comandos CREATE FOREIGN TABLE para crear las tablas externas. Las columnas se definirán mediante los tipos de datos compatibles y, cuando sea posible detectarlas, las opciones compatibles con CREATE FOREIGN TABLE.
Conservación del uso de mayúsculas y minúsculas en los identificadores importadosIMPORT FOREIGN SCHEMA ejecuta quote_identifier() sobre los nombres de las tablas y columnas que importa, lo que pone entre comillas dobles los identificadores que contienen caracteres en mayúsculas o espacios en blanco. Por lo tanto, esos nombres de tablas y columnas deben ir entre comillas dobles en las consultas de PostgreSQL. Los nombres compuestos únicamente por minúsculas y sin espacios en blanco no necesitan comillas.Por ejemplo, dada esta tabla de ClickHouse:
IMPORT FOREIGN SCHEMA crea esta tabla externa:
Por lo tanto, las consultas deben entrecomillar los identificadores de forma adecuada; por ejemplo:
Para crear objetos con nombres distintos o completamente en minúsculas (y, por tanto, que no distingan entre mayúsculas y minúsculas), use CREATE FOREIGN TABLE.

CREATE FOREIGN TABLE

Use CREATE FOREIGN TABLE para crear una tabla foránea que permite consultar datos de una base de datos de ClickHouse:
Las opciones de tabla compatibles son:
  • database: El nombre de la base de datos remota. De forma predeterminada, usa la base de datos definida para el servidor foráneo.
  • fetch_size: Tamaño aproximado del lote en bytes para HTTP streaming. Anula el fetch_size a nivel de servidor. El valor predeterminado es 50000000 (50 MB). 0 desactiva el streaming y almacena en el búfer la respuesta completa.
  • table_name: El nombre de la tabla remota. De forma predeterminada, usa el nombre especificado para la tabla foránea.
  • engine: El motor de tabla usado por la tabla de ClickHouse. Para CollapsingMergeTree() y AggregatingMergeTree(), pg_clickhouse aplica automáticamente los parámetros a las expresiones de función ejecutadas en la tabla.
Use el tipo de dato adecuado para el tipo de dato remoto de ClickHouse de cada columna. Las opciones de columna compatibles son:
  • column_name: El nombre de la columna en ClickHouse, que se usa con preferencia sobre el nombre del atributo de PostgreSQL al reconstruir consultas e inserciones. Es útil para asignar nombres de columna de PostgreSQL en minúsculas y sin comillas a columnas de ClickHouse sensibles a mayúsculas y minúsculas; por ejemplo:
  • AggregateFunction: El nombre de la función de agregación aplicada a una columna de [AggregateFunction Type]. Asigne el tipo de dato al tipo de ClickHouse pasado a la función y especifique el nombre de la función de agregación mediante la opción de columna correspondiente; pg_clickhouse añadirá automáticamente Merge a la función de agregación que evalúe la columna.
  • SimpleAggregateFunction: El nombre de la función de agregación aplicada a una columna de [SimpleAggregateFunction Type]. Asigne el tipo de dato al tipo de ClickHouse pasado a la función y especifique el nombre de la función de agregación mediante la opción de columna correspondiente.

ALTER FOREIGN TABLE

Utilice ALTER FOREIGN TABLE para cambiar la definición de una tabla foránea:
Las opciones de tabla y columna admitidas son las mismas que para CREATE FOREIGN TABLE.

DROP FOREIGN TABLE

Utilice DROP FOREIGN TABLE para eliminar una tabla foránea:
Este comando produce un error si hay algún objeto que dependa de la tabla foránea. Use la cláusula CASCADE para eliminarlos también:

Referencia de SQL DML

Las expresiones SQL DML que se muestran a continuación pueden usar pg_clickhouse. Los ejemplos dependen de estas tablas de ClickHouse:

EXPLAIN

El comando EXPLAIN funciona como es de esperar, pero la opción VERBOSE provoca que se emita la consulta “Remote SQL” de ClickHouse:
Esta consulta se envía a ClickHouse a través de un nodo de plan “Foreign Scan”, el SQL remoto.

SELECT

Use la instrucción SELECT para ejecutar consultas en las tablas de pg_clickhouse igual que en cualquier otra tabla:
pg_clickhouse procura trasladar la ejecución de la consulta a ClickHouse tanto como sea posible, incluidas las funciones de agregado. Use EXPLAIN para determinar hasta qué punto se aplica el pushdown. Para la consulta anterior, por ejemplo, toda la ejecución se traslada a ClickHouse
pg_clickhouse también aplica pushdown a JOINs entre tablas que provienen del mismo servidor remoto:
Hacer JOIN con una tabla local generará consultas menos eficientes sin una configuración cuidadosa. En este ejemplo, hacemos una copia local de la tabla nodes y hacemos JOIN con ella en lugar de con la tabla remota:
En este caso, podemos trasladar una mayor parte de la agregación a ClickHouse agrupando por node_id en lugar de por la columna local, y luego unirnos a la tabla de búsqueda más adelante:
El nodo “Foreign Scan” ahora aplica la agregación por node_id en origen, lo que reduce el número de filas que deben traerse de vuelta a Postgres de 1000 (todas ellas) a solo 8, una por cada nodo.

PREPARE, EXECUTE, DEALLOCATE

A partir de la versión v0.1.2, pg_clickhouse admite consultas parametrizadas, creadas principalmente mediante el comando PREPARE:
Use EXECUTE como de costumbre para ejecutar una sentencia preparada:
La ejecución parametrizada impide que el http driver convierta correctamente las zonas horarias de DateTime en versiones de ClickHouse anteriores a la 25.8, donde se [corrigió] el error subyacente. Ten en cuenta que, a veces, PostgreSQL usa un plan de consulta parametrizado incluso sin usar PREPARE. Para las consultas que requieran una conversión precisa de la zona horaria, si actualizar a la 25.8 o una versión posterior no es una opción, utiliza en su lugar el binary driver.
pg_clickhouse delega las agregaciones, como es habitual, como se ve en la salida detallada de EXPLAIN:
Tenga en cuenta que ha enviado los valores de fecha completos, no los marcadores de posición de los parámetros. Esto se cumple en las primeras cinco solicitudes, como se describe en las notas sobre PREPARE de PostgreSQL. En la sexta ejecución, envía los parámetros de consulta de ClickHouse con el formato {param:type}: parámetros:
Use DEALLOCATE para liberar una sentencia preparada:

INSERT

Utilice el comando INSERT para insertar valores en una tabla remota de ClickHouse:

COPY

Usa el comando COPY para insertar un lote de filas en una tabla remota de ClickHouse:
⚠️ Limitaciones de la API de inserción por lotes pg_clickhouse aún no ha implementado compatibilidad con la API de inserción por lotes del FDW de PostgreSQL. Por lo tanto, COPY actualmente usa sentencias INSERT para insertar registros. Esto se mejorará en una versión futura.

LOAD

Utilice LOAD para cargar la biblioteca compartida pg_clickhouse:
No suele ser necesario usar LOAD, ya que Postgres cargará automáticamente pg_clickhouse la primera vez que se utilice alguna de sus funcionalidades (funciones, tablas foráneas, etc.). La única ocasión en la que puede resultar útil LOAD pg_clickhouse es para SET los parámetros de pg_clickhouse antes de ejecutar consultas que dependan de ellos.

SET

Use SET para definir los parámetros de configuración personalizados de pg_clickhouse.

pg_clickhouse.session_settings

El parámetro pg_clickhouse.session_settings permite establecer la configuración de ClickHouse que se aplicará a las consultas posteriores. Ejemplo:
El valor predeterminado es join_use_nulls 1, group_by_use_nulls 1, final 1. Establézcalo en una cadena vacía para volver a usar la configuración del servidor de ClickHouse.
La sintaxis es una lista de pares clave/valor delimitados por comas y separados por uno o más espacios. Las claves deben corresponder a la configuración de ClickHouse. Use una barra invertida para escapar los espacios, las comas y las barras invertidas en los valores:
O bien use valores entre comillas simples para evitar escapar los espacios y las comas; considere usar [dollar quoting] para evitar tener que usar comillas dobles:
Si te importa la legibilidad y necesitas establecer muchos parámetros, usa varias líneas, por ejemplo:
Algunos ajustes se ignorarán en los casos en que interfieran con el funcionamiento de pg_clickhouse. Entre ellos se incluyen:
  • date_time_output_format: el driver HTTP requiere que sea “iso”
  • format_tsv_null_representation: el driver HTTP requiere el valor predeterminado
  • output_format_tsv_crlf_end_of_line el driver HTTP requiere el valor predeterminado
Por lo demás, pg_clickhouse no valida estos ajustes, sino que los pasa a ClickHouse en cada consulta. Por tanto, admite todos los ajustes de cada versión de ClickHouse. Ten en cuenta que pg_clickhouse debe cargarse antes de configurar pg_clickhouse.session_settings; usa precarga de bibliotecas compartidas o simplemente uno de los objetos de la extensión para asegurarte de que se cargue.

pg_clickhouse.pushdown_regex

El parámetro pg_clickhouse.pushdown_regex controla si pg_clickhouse transfiere las funciones y los operadores de expresiones regulares. Lo hace de forma predeterminada; establezca este parámetro en false para evitarlo:
Consulta Expresiones regulares para obtener más detalles.

ALTER ROLE

Use el comando SET de ALTER ROLE para precargar pg_clickhouse y/o SET sus parámetros para roles específicos:
Utilice el comando RESET de ALTER ROLE para restablecer la precarga de pg_clickhouse y/o los parámetros:

Precarga

Si todas o casi todas las conexiones a Postgres necesitan usar pg_clickhouse, considere usar la precarga de bibliotecas compartidas para cargarlo automáticamente:

session_preload_libraries

Carga la biblioteca compartida en cada nueva conexión a PostgreSQL:
Útil para aplicar las actualizaciones sin reiniciar el servidor: basta con volver a conectarse. También puede establecerse para usuarios o roles específicos mediante ALTER ROLE.

shared_preload_libraries

Carga la biblioteca compartida en el proceso padre de PostgreSQL al iniciarse:
Útil para ahorrar memoria y reducir la sobrecarga en cada sesión, pero requiere que se reinicie el clúster cuando se actualiza la biblioteca.

Tipos de datos

pg_clickhouse asigna los siguientes tipos de datos de ClickHouse a tipos de datos de PostgreSQL. IMPORT FOREIGN SCHEMA usa el primer tipo indicado en la columna de PostgreSQL al importar columnas; se pueden usar tipos adicionales en las sentencias CREATE FOREIGN TABLE: A continuación se ofrecen notas y detalles adicionales.

BYTEA

ClickHouse no ofrece un equivalente al tipo BYTEA de PostgreSQL, pero permite almacenar cualquier secuencia de bytes en el tipo String. En general, las cadenas de ClickHouse deben mapearse al tipo TEXT de PostgreSQL; sin embargo, cuando se trabaja con datos binarios, mapéelas a BYTEA. Ejemplo:
Esa consulta SELECT final producirá como salida:
Tenga en cuenta que si hay bytes nulos en las columnas de ClickHouse, una tabla externa que use columnas TEXT no mostrará los valores correctos:
Producirá la siguiente salida:
Tenga en cuenta que las filas dos y tres contienen valores truncados. Esto se debe a que PostgreSQL utiliza cadenas terminadas en nul y no admite nuls en sus cadenas. Intentar insertar valores binarios en columnas TEXT funcionará correctamente y dará el resultado esperado:
Las columnas de texto serán correctas:
Pero leerlos como BYTEA no funcionará:
Por regla general, usa las columnas TEXT solo para cadenas codificadas y las columnas BYTEA solo para datos binarios, y no alternes nunca entre ellas.

Referencia de funciones y operadores

Funciones

Estas funciones sirven de interfaz para consultar una base de datos de ClickHouse.

clickhouse_raw_query

Conéctese a un servicio de ClickHouse a través de su interfaz HTTP, ejecute una sola consulta y desconéctese. El segundo argumento opcional especifica una cadena de conexión cuyo valor predeterminado es host=localhost port=8123. Los parámetros de conexión admitidos son:
  • host: El host al que conectarse; obligatorio.
  • port: El puerto HTTP al que conectarse; el valor predeterminado es 8123, a menos que host sea un host de ClickHouse Cloud, en cuyo caso el valor predeterminado es 8443
  • dbname: El nombre de la base de datos a la que conectarse.
  • username: El nombre de usuario con el que conectarse; el valor predeterminado es default
  • password: La contraseña que se usará para autenticarse; de forma predeterminada no hay contraseña
De forma predeterminada, ningún rol tiene acceso EXECUTE a esta función; considere GRANTar acceso solo a los roles que realmente necesiten ejecutar consultas ad hoc de ClickHouse, por ejemplo, un rol de administrador de ClickHouse dedicado: Útil para consultas que no devuelven registros, pero las consultas que sí devuelven valores se devolverán como un único valor de texto:

Funciones con pushdown

pg_clickhouse aplica pushdown a un subconjunto de las funciones integradas de PostgreSQL usadas en expresiones condicionales (cláusulas HAVING y WHERE). Ese subconjunto se corresponde con los equivalentes de ClickHouse de la siguiente manera:

Operadores de pushdown

Funciones personalizadas

Estas funciones personalizadas creadas por pg_clickhouse proporcionan pushdown de consultas externas para determinadas funciones de ClickHouse que no tienen equivalentes en PostgreSQL. Si alguna de estas funciones no se puede ejecutar mediante pushdown, generará una excepción.

Pushdown de extensiones

pg_clickhouse reconoce funciones de algunas extensiones principales y de terceros, y las delega a sus equivalentes en ClickHouse.

re2

Todas las funciones de la extensión re2 se delegan 1:1 en ClickHouse:

intarray

Una función de intarray se delega en ClickHouse:

fuzzystrmatch

Dos funciones de fuzzystrmatch se delegan en ClickHouse:

Conversiones de tipo pushdown

pg_clickhouse hace pushdown de conversiones de tipo como CAST(x AS bigint) para tipos de datos compatibles. En el caso de tipos incompatibles, el pushdown fallará; si x en este ejemplo es un UInt64 de ClickHouse, ClickHouse se negará a convertir el valor. Para hacer pushdown de conversiones de tipo a tipos de datos incompatibles, pg_clickhouse proporciona las siguientes funciones. Generan una excepción en PostgreSQL si no se ejecutan con pushdown.

Agregaciones pushdown

Estas funciones de agregación de PostgreSQL admiten pushdown a ClickHouse.

Agregaciones personalizadas

Estas funciones de agregación personalizadas creadas por pg_clickhouse proporcionan pushdown de consultas externas para algunas funciones de agregación de ClickHouse que no tienen equivalentes en PostgreSQL. Si alguna de estas funciones no puede aplicarse mediante pushdown, generará una excepción.

Agregados de conjunto ordenado con pushdown

Estas [funciones de agregado de conjunto ordenado] se corresponden con las funciones de agregado paramétricas de ClickHouse al pasar su argumento directo como parámetro y sus expresiones ORDER BY como argumentos. Por ejemplo, esta consulta de PostgreSQL:
Se corresponde con esta consulta de ClickHouse:
Ten en cuenta que los sufijos no predeterminados de ORDER BY, DESC y NULLS FIRST, no son compatibles y producirán un error.

Funciones de ventana con pushdown

Estas funciones de ventana de PostgreSQL se delegan en ClickHouse con cláusulas OVER (PARTITION BY ... ORDER BY ...), incluidas las especificaciones de frame cuando corresponde. Las funciones de clasificación (row_number, rank, dense_rank, ntile, cume_dist, percent_rank) omiten su cláusula de frame durante la delegación porque ClickHouse rechaza las especificaciones de frame en estas funciones.

Notas de compatibilidad

Expresiones regulares

Aunque pg_clickhouse hace pushdown de las expresiones regulares a sus equivalentes de ClickHouse cuando pg_clickhouse.pushdown_regex es true (el valor predeterminado), y procura garantizar un nivel básico de compatibilidad, tenga en cuenta las diferencias entre ambos y cómo las gestiona pg_clickhouse.
  • PostgreSQL admite expresiones regulares POSIX, mientras que ClickHouse admite expresiones regulares RE2. Tenga en cuenta las diferencias de comportamiento: use RE2 cuando la expresión regular vaya a evaluarse en ClickHouse (p. ej., en una cláusula WHERE) y POSIX cuando vaya a evaluarse en Postgres (p. ej., en una cláusula SELECT).
  • pg_clickhouse hace pushdown de los [flags de regex] de Postgres anteponiéndolos a la expresión regular de ClickHouse dentro de (?). Por ejemplo:
    Se convierte en
    Tenga en cuenta la inclusión de -s; esto alinea el comportamiento con las expresiones regulares de Postgres al desactivar s, que ClickHouse habilita de forma predeterminada. pg_clickhouse no incluirá -s si los flags de la llamada a la función de Postgres incluyen s. Desafortunadamente, este comportamiento rompe la compatibilidad de algunas expresiones regulares en Postgres 24 y versiones anteriores.
  • Los únicos flags que ambos admiten y que, por lo tanto, pueden usarse cuando se evalúan en ClickHouse son:
    • i: sin distinción entre mayúsculas y minúsculas
    • m: modo multilínea:
    • s: hace que . coincida con \n
    • p: coincidencia parcial sensible a saltos de línea (se trata igual que s)
    • t: sintaxis estricta (la predeterminada, eliminada por pg_clickhouse)
    RE2 solo admite estos flags; no use ningún otro [flag de Postgres]
  • Cualquier otro flag pasado a funciones de expresiones regulares hará que la función no se envíe mediante pushdown.
  • La excepción es regexp_replace(), que también admite el flag g. Cuando g está establecido, pg_clickhouse usa replaceRegexpAll() en lugar de replaceRegexpOne() y elimina el flag antes de anteponer los demás flags.
  • El argumento de reemplazo de regexp_replace() de Postgres admite \& para referirse a la coincidencia completa, mientras que ClickHouse usa \0 para la coincidencia completa. Asegúrese de usar \0 cuando la función se envíe mediante pushdown a ClickHouse.
Para evitar cualquier ambigüedad, considere establecer pg_clickhouse.pushdown_regex para impedir que las expresiones regulares de Postgres se envíen mediante pushdown a ClickHouse, y usar la extensión re2, para la cual pg_clickhouse admite pushdown directo de expresiones regulares RE2 compatibles con ClickHouse.

to_char()

PostgreSQL to_char() para timestamp y timestamp with time zone solo se delega a ClickHouse formatDateTime cuando el argumento de formato es una string constant no NULL en la que cada palabra clave de PostgreSQL tiene un equivalente en ClickHouse idéntico byte por byte. Si el formato es dinámico (no es una Const), o contiene alguna palabra clave o modifier no compatible, la llamada vuelve a evaluarse localmente en PostgreSQL; nunca se intenta delegar con una traducción parcial, por lo que la salida sigue siendo compatible con PG. Las formas de to_char() de dos argumentos sobre numeric, interval y otros tipos que no son de timestamp nunca se delegan; ClickHouse formatDateTime solo da formato a valores de fecha y hora.

Palabras clave traducidas

Texto entre comillas y literales

El texto delimitado por "..." se conserva tal cual, y cualquier % literal se duplica como %% para escapar el prefijo de especificador de ClickHouse. Un \" fuera de las comillas también se conserva como un literal ". Dentro de "...", la barra invertida solo escapa "; las demás secuencias con barra invertida se tratan como texto literal.

Autores

David E. Wheeler Copyright (c) 2025-2026, ClickHouse
Última modificación el 12 de junio de 2026