Descrição
pg_clickhouse é uma extensão do PostgreSQL que permite executar consultas remotamente em bancos de dados do ClickHouse, incluindo um foreign data wrapper. É compatível com o PostgreSQL 14 ou superior e o ClickHouse 23.3 ou superior.Primeiros passos
A forma mais simples de testar o pg_clickhouse é usar a [imagem Docker], que contém a imagem Docker padrão do PostgreSQL com as extensões pg_clickhouse e [re2][extensão re2]:Uso
Política de versionamento
pg_clickhouse segue o [Versionamento Semântico] em suas versões públicas.- A versão principal é incrementada para mudanças na API
- A versão secundária é incrementada para mudanças de SQL compatíveis com versões anteriores
- A versão de correção é incrementada para mudanças apenas no binário
- A versão da biblioteca (definida por
PG_MODULE_MAGICno PostgreSQL 18 e superiores) inclui a versão semântica completa, visível na saída da funçãopgch_version()ou da funçãopg_get_loaded_modules()do Postgres. - A versão da extensão (definida no arquivo de controle) inclui apenas as versões principal
e secundária, visíveis na tabela
pg_catalog.pg_extension, na saída da funçãopg_available_extension_versions()e em\dx pg_clickhouse.
v0.1.0 para v0.1.1, beneficia todos os bancos de dados que carregaram v0.1 e
não precisam executar ALTER EXTENSION para aproveitar a atualização.
Já uma versão que incrementa a versão secundária ou principal
virá acompanhada de scripts de atualização SQL, e todos os bancos de dados existentes que contêm
a extensão deverão executar ALTER EXTENSION pg_clickhouse UPDATE para aproveitar
a atualização.
Referência de SQL DDL
As expressões SQL DDL a seguir usam o pg_clickhouse.CREATE EXTENSION
Use CREATE EXTENSION para adicionar a extensão pg_clickhouse a um banco de dados:WITH SCHEMA para instalá-la em um esquema específico (recomendado):
ALTER EXTENSION
Use ALTER EXTENSION para modificar a extensão pg_clickhouse. Exemplos:-
Depois de instalar uma nova versão do pg_clickhouse, use a cláusula
UPDATE: -
Use
SET SCHEMApara mover a extensão para um novo esquema:
DROP EXTENSION
Use DROP EXTENSION para remover pg_clickhouse de um banco de dados:CASCADE para removê-los também:
CREATE SERVER
Use CREATE SERVER para criar um servidor externo que se conecta a um servidor ClickHouse. Exemplo:driver: O driver de conexão do ClickHouse a ser usado: “binary” ou “http”. Obrigatório.compression: Compressão do protocolo nativo para o driver “binary”, uma entre “none”, “lz4” ou “zstd”. O padrão é “lz4”. Ignorada pelo driver “http”.dbname: O banco de dados do ClickHouse a ser usado na conexão. O padrão é “default”.host: O nome do host do servidor ClickHouse. O padrão é “localhost”;port: A porta à qual se conectar no servidor ClickHouse. Os padrões são os seguintes:- 9440 se
driverfor “binary” ehostfor um host do ClickHouse Cloud - 9004 se
driverfor “binary” ehostnão for um host do ClickHouse Cloud - 8443 se
driverfor “http” ehostfor um host do ClickHouse Cloud - 8123 se
driverfor “http” ehostnão for um host do ClickHouse Cloud
- 9440 se
min_tls_version: Versão mínima do protocolo TLS a ser negociada em conexões que usam TLS. Uma entreTLSv1,TLSv1.1,TLSv1.2ouTLSv1.3. O padrão é o mínimo da própria biblioteca TLS. Aplica-se a ambos os drivers.secure: Controla o uso de TLS na conexão. Uma entre:auto(padrão): usa TLS quandohosté um host do ClickHouse Cloud ouporté uma porta segura; caso contrário, plaintext.on(outrue/yes/1): sempre usa TLS. O padrão deporté 8443 (“http”) ou 9440 (“binary”).off(oufalse/no/0): nunca usa TLS. O padrão deporté 8123 (“http”) ou 9000 (“binary”).
encoding_check: Define como tratar caracteres inválidos segundo a [codificação do banco de dados] ao converter valores String e JSON do ClickHouse. Uma entre:fail(padrão): gera um erroremoveremove os bytes inválidosreplace: na codificação UTF-8, substitui os bytes inválidos pelo caractere de substituição Unicode (�); equivale aremovenas demais codificaçõestruncatetrunca o texto no primeiro byte inválido
ALTER SERVER
Use ALTER SERVER para modificar um servidor externo. Exemplo:DROP SERVER
Use o DROP SERVER para remover um servidor externo:CASCADE para
também remover essas dependências:
CREATE USER MAPPING
Use CREATE USER MAPPING para mapear um usuário do PostgreSQL a um usuário do ClickHouse. Por exemplo, para mapear o usuário atual do PostgreSQL ao usuário remoto do ClickHouse ao se conectar ao servidor externotaxi_srv:
user: O nome do usuário do ClickHouse. O valor padrão é “default”.password: A senha do usuário do ClickHouse.
ALTER USER MAPPING
Use ALTER USER MAPPING para alterar a definição de um mapeamento de usuário:DROP USER MAPPING
Use o comando DROP USER MAPPING para remover um mapeamento de usuário:IMPORT FOREIGN SCHEMA
Use IMPORT FOREIGN SCHEMA para importar todas as tabelas definidas em um banco de dados do ClickHouse como tabelas externas em um esquema do PostgreSQL:LIMIT TO para restringir a importação a tabelas específicas:
EXCEPT para excluir tabelas:
-
As colunas importadas mantêm o modificador de tipo do tipo do ClickHouse, inclusive
os que estão dentro de
Arrays. Ou seja,Array(Decimal(12,6))é importado comonumeric(12,6)[]. -
Colunas
Nullablesão importadas semNOT NULL; jáNullabledentro de umArraynão tem esse efeito, pois arrays do PostgreSQL sempre permitem elementos NULL. -
Colunas
AggregateFunctioneSimpleAggregateFunctionsão importadas semNOT NULL, independentemente da declaração no ClickHouse; consulte Colunas de estado eNOT NULL. -
Colunas
Tuplesão importadas comotext[]. ColunasMape colunasNestedcriadas comflatten_nested=0são importadas comotext[][]. Cada conversão emite umNOTICE. O pseudotiporecorddo PostgreSQL não pode definir uma coluna de tabela; por isso, cada tupla se torna um array de valores, cada map se torna um array bidimensional de pares chave-valor e cada valor Nested se torna um array bidimensional de linhas. Para ler campos como registros, altere a coluna para um array de um tipo composto correspondente; consulte Mapeamentos manuais de tipos para ver um exemplo. -
Colunas
DateTime64eTime64com precisão maior que 6 (microssegundos) também geram umNOTICE, já que o PostgreSQL limita a precisão atimestamp(6)etime(6). -
Tipos de coluna sem equivalente no PostgreSQL, incluindo o tipo legado
Object('json'), anterior aoJSONdo ClickHouse, geram um erro.
CREATE FOREIGN TABLE
Use CREATE FOREIGN TABLE para criar uma tabela externa capaz de consultar dados de um banco de dados do ClickHouse:database: O nome do banco de dados remoto. O padrão é o banco de dados definido para o servidor externo.table_name: O nome da tabela remota. O padrão é o nome especificado para a tabela externa.engine: O [engine da tabela] usado pela tabela ClickHouse. ParaCollapsingMergeTree()eAggregatingMergeTree(), o pg_clickhouse aplica automaticamente os parâmetros às expressões de função executadas na tabela.
-
column_name: O nome da coluna no lado do ClickHouse, usado em vez do nome do atributo do PostgreSQL ao reconstruir consultas e inserções. Útil para mapear nomes de colunas do PostgreSQL em minúsculas e sem aspas para colunas do ClickHouse sensíveis a maiúsculas e minúsculas, por exemplo: -
AggregateFunction: O nome da função de agregação aplicada a uma coluna do [tipo AggregateFunction]. Mapeie o tipo de dado para o tipo do ClickHouse passado à função e especifique o nome da função de agregação por meio da opção de coluna apropriada; o pg_clickhouse acrescentará automaticamenteMergeà função de agregação usada para avaliar a coluna. Declare a coluna como anulável para evitar os problemas descritos em Colunas de estado eNOT NULL. -
SimpleAggregateFunction: O nome da função de agregação aplicada a uma coluna do [tipo SimpleAggregateFunction]. Mapeie o tipo de dado para o tipo do ClickHouse passado à função e especifique o nome da função de agregação por meio da opção de coluna apropriada.
Colunas de estado e NOT NULL
Mantenha as colunas AggregateFunction e SimpleAggregateFunction como anuláveis.
O PostgreSQL 19 converte count(column) em count(*) para colunas de estado NOT NULL,
o que faz com que sejam contadas linhas em vez de mesclados os estados.
Considere uma tabela do ClickHouse que armazena um estado count por usuário, sendo cada estado gerado
a partir de 1.000 eventos:
NOT NULL, o PostgreSQL conta os estados, o que resulta em uma contagem inválida:
NOT NULL, o pg_clickhouse usa countMerge() para mesclar os estados, obtendo
a contagem correta de 1000:
ALTER FOREIGN TABLE para remover a restrição de uma tabela externa existente:
NOT NULL afeta apenas o PostgreSQL. Por isso, o IMPORT FOREIGN
SCHEMA importa as colunas de estado como anuláveis.
ALTER FOREIGN TABLE
Use ALTER FOREIGN TABLE para alterar a definição de uma tabela externa:DROP FOREIGN TABLE
Use DROP FOREIGN TABLE para remover uma tabela externa:CASCADE para removê-los também:
Referência de SQL DML
As expressões DML em SQL abaixo podem usar pg_clickhouse. Os exemplos dependem destas tabelas do ClickHouse:EXPLAIN
O comando EXPLAIN funciona como esperado, mas a opçãoVERBOSE aciona a emissão da consulta “Remote SQL” do ClickHouse:
SELECT
Use a instrução SELECT para executar consultas em tabelas pg_clickhouse, assim como em qualquer outra tabela:nodes e fazemos join com ela em vez de usar a tabela remota:
node_id em vez da coluna local e, depois, fazer join
com a tabela de lookup:
node_id, reduzindo
o número de linhas que precisam ser trazidas de volta para o Postgres de 1000 (todas
elas) para apenas 8, uma para cada nó.
Tabelas particionadas
Uma [tabela particionada] do PostgreSQL pode combinar partições locais com partições estrangeiras armazenadas no ClickHouse. Uma configuração comum transfere dados mais antigos para o ClickHouse, enquanto os dados mais recentes permanecem no PostgreSQL:enable_partitionwise_aggregate ativado, o PostgreSQL calcula uma agregação
parcial abaixo de Append, e um agregado de finalização acima combina esses
parciais no resultado. O pg_clickhouse envia o parcial da partição estrangeira
ao ClickHouse:
Quando agregações parciais são enviadas ao destino
O PostgreSQL representa uma agregação parcial como um estado de transição que a etapa de finalização combina entre as partições. O pg_clickhouse pode enviar a agregação parcial de uma partição ao destino somente quando puder expressá-la como um valor do ClickHouse:- Agregações decomponíveis cujo estado de transição já é o valor final
são enviadas diretamente ao destino:
count,sum,min,max,bool_and/every,bool_or,bit_and,bit_orebit_xor. avgsobre inteiros envia seu estado{count, sum}como um array.avg,var_pop,var_samp,stddev_popestddev_sampsobre ponto flutuante enviam seu estado{N, sum, sum of squared deviations}como um array.
FILTER (WHERE …) é enviado ao destino com essas funções de agregação.
Quando usam uma alternativa
Agregações cujo estado de transição é o tipo opacointernal do PostgreSQL não têm
representação portátil; por isso, a partição estrangeira busca suas linhas
e as agrega localmente. Isso abrange tudo o que usa numeric, além de
avg(bigint) e avg(interval). Agregações DISTINCT, de conjunto ordenado e variádicas
também usam uma alternativa.
PREPARE, EXECUTE, DEALLOCATE
A partir da v0.1.2, o pg_clickhouse oferece suporte a consultas parametrizadas, criadas principalmente com o comando PREPARE:{param:type} do ClickHouse:
INSERT
Use o comando INSERT para inserir valores em uma tabela remota do ClickHouse:COPY
Use o comando COPY para inserir um lote de linhas em uma tabela remota do ClickHouse:⚠️ Limitações da API de Batch pg_clickhouse ainda não implementou suporte à API de inserção em lote do FDW do PostgreSQL. Portanto, COPY atualmente usa instruções INSERT para inserir registros. Isso será aprimorado em uma versão futura.
LOAD
Use LOAD para carregar a biblioteca compartilhada pg_clickhouse:SET
Use SET para definir os parâmetros personalizados de configuração do pg_clickhouse.pg_clickhouse.session_settings
O parâmetro pg_clickhouse.session_settings configura as [configurações
do ClickHouse] a serem aplicadas às consultas subsequentes. Exemplo:
join_use_nulls para junções externas e transform_null_in para a família IN
(consulte IN e semântica de NULL).
date_time_output_format: o driver HTTP exige que seja “iso”format_tsv_null_representation: o driver HTTP exige o valor padrãooutput_format_tsv_crlf_end_of_lineo driver HTTP exige o valor padrão
pg_clickhouse.session_settings; use [pré-carregamento de biblioteca compartilhada] ou
simplesmente use um dos objetos da extensão para garantir que ele seja carregado.
pg_clickhouse.pushdown_regex
O parâmetro pg_clickhouse.pushdown_regex controla se o pg_clickhouse
faz pushdown de funções e operadores de expressão regular. Isso ocorre por padrão;
defina esse parâmetro como false para impedir esse pushdown:
ALTER ROLE
Use o comandoSET de ALTER ROLE’s para pré-carregar o pg_clickhouse
e/ou SET seus parâmetros para roles específicos:
RESET de ALTER ROLE para redefinir o pré-carregamento do pg_clickhouse
e/ou os parâmetros:
Pré-carregamento
Se toda ou quase toda conexão com o Postgres precisar usar o pg_clickhouse, considere usar o [pré-carregamento de biblioteca compartilhada] para carregá-lo automaticamente:session_preload_libraries
Carrega a biblioteca compartilhada a cada nova conexão com o PostgreSQL:
shared_preload_libraries
Carrega a biblioteca compartilhada no processo principal do PostgreSQL durante a inicialização:
Tipos de dados
Esta tabela apresenta o mapeamento preferencial dos tipos de dados do ClickHouse para os do PostgreSQL. IMPORT FOREIGN SCHEMA usa esses mapeamentos e deriva os modificadores de tipo e as dimensões de array apropriados. Use CREATE FOREIGN TABLE para declarar tipos alternativos do PostgreSQL. Os destinos de leitura adicionais listam as conversões compatíveis com o driverbinary além dos
casts explícitos do PostgreSQL. Células vazias continuam permitindo esses casts. Os valores precisam
caber nos tipos de destino. Esses destinos se referem a leituras; as gravações seguem regras de
conversão próprias.
Qualquer coluna também pode ser lida como
text, varchar ou outro tipo string. O valor
assume o tipo PostgreSQL indicado acima e, em seguida, é renderizado pela função de saída
desse tipo. Uma string do ClickHouse lida como tipo texto é validada em relação à
codificação do banco de dados; assim, bytes que o PostgreSQL não consegue ler geram um erro. Declare uma
coluna String, FixedString, Enum ou JSON como BYTEA para ler seus bytes exatamente como o
ClickHouse os gravou.
Tipos compatíveis com entrada podem ler strings usando a respectiva função de entrada do PostgreSQL.
Tipos compostos devem ter os mesmos campos, na mesma ordem. Para ler uma tupla
como array, cada campo deve poder ser convertido para o tipo de elemento do array, e nenhum campo
pode ser, ele próprio, um array.
Quando lidos como arrays, Map usa uma linha por par chave-valor e Nested usa
uma linha por registro aninhado. Para ler uma tupla como box, forneça dois pontos; para
circle, forneça um ponto e um raio; para line, forneça três coeficientes.
Confira a seguir observações e detalhes adicionais.
Coerção de tipos
Com o driverbinary, tipos escalares alternativos usam as conversões explícitas
do PostgreSQL quando disponíveis, e os elementos de array são convertidos para o
tipo de elemento declarado. Conversões sem suporte e valores fora do intervalo geram erros.
Com qualquer um dos drivers, mapeie os tipos Interval do ClickHouse para smallint, integer
ou bigint para ler e gravar a quantidade de suas unidades. Por exemplo, um valor
IntervalDay igual a 3 é mapeado para o inteiro 3. Mapear
IntervalNanosecond para bigint preserva os nanossegundos, enquanto o mapeamento para
interval trunca o valor para microssegundos.
BYTEA
O ClickHouse não oferece um equivalente ao tipo BYTEA do PostgreSQL, mas permite que quaisquer bytes sejam armazenados no tipo [String]. Em geral, strings do ClickHouse devem ser mapeadas para o tipo [TEXT] do PostgreSQL, mas ao trabalhar com dados binários, mapeie-as para BYTEA. Exemplo:SELECT final produzirá:
FixedString(N) preenche valores curtos com bytes nulos. Uma coluna de texto
descarta esse preenchimento final, enquanto uma coluna BYTEA preserva todos os bytes.
Tipos compostos
Array
Os [Array]s do ClickHouse são mapeados diretamente para arrays do PostgreSQL, com semântica equivalente. A principal diferença é que, no Postgres, arrays multidimensionais precisam ter expressões de array com dimensões correspondentes. Tentar ler um array do ClickHouse com dimensões diferentes, como[[1], [2,3]],
gera um erro.
O acesso por índice de array faz pushdown quando apropriado, inclusive o acesso
por índice multidimensional. Exemplos:
Map
O PostgreSQL não oferece nenhum tipo correspondente ao tipo [Map] do ClickHouse. Por isso, o pg_clickhouse mapeia colunas [Map] paratext[][], em que cada par
chave-valor é representado como um array próprio. O IMPORT FOREIGN SCHEMA utiliza
esse mapeamento. Também é possível fazer INSERT de maps como arrays. Por exemplo:
Inserir um
Map requer o driver binary, que obtém os tipos de coluna
do servidor ClickHouse. O driver http não faz isso e, por isso, não dispõe das
informações necessárias para formatar e inserir o valor adequado.Tuple
Da mesma forma, colunas [Tuple] do ClickHouse são mapeadas paratext[] e aceitam INSERTs
por meio do driver binário. IMPORT FOREIGN SCHEMA emite um NOTICE sempre que
realiza esse tipo de mapeamento.
Nested
Por padrão, o ClickHouse divide uma colunaNested em uma coluna Array por
campo (flatten_nested=1). O IMPORT FOREIGN SCHEMA lê essas colunas do
catálogo system.columns do ClickHouse e cria colunas de array separadas no PostgreSQL,
preservando nomes com ponto, como items.a e items.b. Por exemplo,
considere esta tabela estrangeira:
WHERE usando os recursos comuns de arrays,
incluindo a sintaxe de subscrito de array:
flatten_nested=0 é mapeada para um array com um
item para cada linha aninhada. Cada item do array contém os valores dessa linha:
c2 Nested(id Int64, name String) neste exemplo, ficaria assim:
text[][] para tipos Nested falha:
Mapeamentos manuais de tipos
IMPORT FOREIGN SCHEMA usa tipos genéricos do PostgreSQL. Por exemplo,
considere uma tabela do ClickHouse com colunas [Enum], [Tuple], Map e
[Nested] não achatadas (flatten_nested = 0), como:
key e value, neste
caso). Nested e Map passam a ser arrays de compostos, enquanto Tuple
se torna um único valor composto:
SELECT:
WHERE --- desde que os nomes dos campos sejam
idênticos:
INSERT usando esses tipos compostos.
Referência de funções e operadores
Funções
Essas funções fornecem a interface para executar consultas em um banco de dados ClickHouse.clickhouse_server_version
major.minor.patch, para o
servidor estrangeiro especificado, conectando-se, se necessário, usando as opções do servidor e o
user mapping do usuário atual:
SELECT version(), e a armazena em cache durante toda a
vida da conexão.
clickhouse_query
driver do servidor,
as credenciais, o banco de dados e o cache de conexão.
O primeiro argumento é o nome de um servidor criado com CREATE SERVER. Uma
lista de definição de colunas (AS name(col type, ...)) é obrigatória: o PostgreSQL precisa
conhecer a estrutura do resultado antes de buscar as linhas, e ela deve corresponder às colunas retornadas pela
consulta. Os valores são convertidos do ClickHouse para os tipos declarados da mesma forma
que seriam em uma coluna de tabela estrangeira. Instruções que não retornam resultados, como DDL,
não têm nada a declarar; execute-as com
clickhouse_perform.
Nenhuma role tem acesso EXECUTE por padrão; conceda GRANT a uma role para permitir o uso
da função.
clickhouse_perform
clickhouse_query não tem formato de resultado a declarar. Ela
resolve o servidor da mesma forma que clickhouse_query, reutilizando o
driver, as credenciais, o banco de dados e o cache de conexão.
Por ser um procedimento, deve ser invocada com CALL, e não com SELECT, e não retorna
linhas. Nenhuma role tem acesso a EXECUTE por padrão; conceda GRANT a uma role para permitir o
uso do procedimento.
Funções com pushdown
pg_clickhouse faz pushdown de um subconjunto das funções nativas do PostgreSQL usadas em condicionais (cláusulasHAVING e WHERE). Esse subconjunto corresponde aos equivalentes
no ClickHouse, da seguinte forma:
abs: absfactorial: factorialmod(int2/int4/int8/numeric): módulopow&power(float8, não numeric): powround: roundsin,cos,tan,atan,atan2,sinh,cosh,tanh,asinh,degrees,radians,pi: funções matemáticas do ClickHouse com o mesmo nome.asin,acos,atanh,acoshnão são delegadas: o PG gera erro quando a entrada está fora do intervalo, enquanto o CH retornaNaN.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): os mesmos mapeamentos dedate_partdate(timestamp)&date(timestamptz): toDate (reapresentado como alias do CHdate)array_position: indexOf com nullIf para converter0emNULLe arraySlice quando houver um terceiro argumento para o índice inicial da busca; observe quenanatualmente não encontra correspondênciaarray_cat: arrayConcatarray_append: arrayPushBackarray_prepend: arrayPushFrontarray_remove: arrayRemovecardinality: arrayFlattenedLength no ClickHouse 26.9+; caso contrário, length, que conta apenas o array externoarray_length(array, 1):nullIf(length(array), 0)array_length&cardinality: comprimentoarray_to_string: arrayStringConcatstring_to_array: splitByStringsplit_part: splitByString + acesso por índice em arraytrim_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 se a expressão regular contiver subexpressões entre parênteses; caso contrário, extractAll fatiado com arraySlice.regexp_replace: replaceRegexpOne ou replaceRegexpOne quando a flaggestiver presenteregexp_split_to_array: splitByRegexpmd5: MD5sha224,sha256,sha384esha512: as funções SHA correspondentes do ClickHouseencode(bytea, fmt)quandofmté uma string constant (sem distinção entre maiúsculas e minúsculas):encode(bytea, 'hex'): hex envolvido por lower, pois o PostgreSQL gera valores hexadecimais em minúsculas.encode(bytea, 'base64'): base64Encode envolvido por replaceRegexpAll para reproduzir a quebra de linha MIME (RFC 2045) do PostgreSQL a cada 76 caracteres.encode(bytea, 'base64url')(PostgreSQL 19+): base64URLEncode, que corresponde ao alfabeto de URL da RFC 4648 do PostgreSQL, sem padding.
json_extract_path_text: sintaxe de subcolunajson_extract_path: toJSONString + sintaxe de subcolunasjsonb_extract_path_text: sintaxe de subcolunajsonb_extract_path: toJSONString + sintaxe de subcolunasbit_count(bytea): bitCountto_timestamp(float8): toDateTime64to_char(timestamp[tz], fmt): formatDateTime quandofmté uma string constant cujas palavras-chave têm todas um equivalente fiel no ClickHouse. Consulte to_char(), em Notas de compatibilidade, para ver as palavras-chave compatíveis. Caso contrário, a função é executada localmente no PostgreSQL.statement_timestamp,transaction_timestamp, &clock_timestamp: nowInBlock64 (nowInBlock64(9, $session_timezone))CURRENT_DATE: now e 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: Passado como valor de uma função do PostgreSQL.CURRENT_SCHEMA: Passado como valor de uma função do PostgreSQL.CURRENT_CATALOG: Passado como valor retornado pela função do PostgreSQL.CURRENT_USER: Passado como valor da função do PostgreSQL.USER: Passado como valor por uma função do PostgreSQL.CURRENT_ROLE: Passado como valor de uma função do PostgreSQL.SESSION_USER: Passado como valor de uma função do PostgreSQL.
Operadores de pushdown
- Fatiamento de Array (
arr[L:U]): arraySlice @>(array contém): hasAll<@(array contido em): hasAll&&(sobreposição de arrays): hasAny~(correspondência com regexp): match!~(sem correspondência com regexp): match~*(regexp sem distinção entre maiúsculas e minúsculas, sem correspondência): match!~*(regexp sem distinção entre maiúsculas e minúsculas, sem correspondência): match->>(extrai elemento de JSON/JSONB como texto): sintaxe de subcoluna->(extrai JSON/JSONB): toJSONString + sintaxe de subcoluna
Semântica de IN e NULL
O ClickHouse avaliaIN com lógica de dois valores: quando a busca não encontra
correspondência, retorna 0, mesmo que haja um NULL envolvido, enquanto o PostgreSQL retorna
NULL. Para preservar a semântica do PostgreSQL, o pg_clickhouse faz pushdown incondicionalmente da família
IN sobre uma lista ou array constante (IN, NOT IN, = ANY, = ALL, <> ANY, <> ALL): usa a forma nativa ou mais econômica quando consegue provar
que nem o valor pesquisado nem um elemento do array podem ser NULL, ou, caso contrário, uma forma CASE com proteções,
que verifica valores NULL em tempo de execução e calcula
a resposta exata de três valores do PostgreSQL (TRUE, FALSE, NULL) em todos os contextos,
inclusive em posições de valor, como em uma lista SELECT ou em GROUP BY.
Um filtro NOT IN (SELECT ...) sobre colunas Nullable também recebe pushdown,
sendo reconvertido com proteções compensatórias que preservam o comportamento do PostgreSQL: um conjunto
que contém um NULL desqualifica todas as linhas, e um valor pesquisado NULL passa apenas contra
um conjunto vazio. Cada proteção é omitida quando uma declaração NOT NULL prova que ela é
desnecessária. Ao contrário das formas de array acima, essa proteção se aplica somente em uma condição de
filtro simples (ou sob NOT); ainda não fazemos pushdown de IN (SELECT ...)
(em uma posição de valor), nem de corpos de subconsulta agrupados ou agregados. Declarar
colunas como NOT NULL maximiza o pushdown, pois permite enviar a forma mais econômica
sem proteções; IMPORT FOREIGN SCHEMA faz isso automaticamente para colunas do ClickHouse que não são Nullable.
A prova considera constantes não NULL, colunas NOT NULL
e aritmética básica (+, -, *, - unário) sobre elas.
Essas regras pressupõem o valor padrão do ClickHouse transform_null_in = 0, que
o pg_clickhouse define em cada consulta por meio do valor padrão do
parâmetro pg_clickhouse.session_settings,
impedindo que um perfil de servidor do ClickHouse o altere silenciosamente. Definir
transform_null_in = 1 quebra a semântica de todos os IN com pushdown.
Funções personalizadas
Estas funções personalizadas criadas por pg_clickhouse permitem o pushdown de consultas externas para determinadas funções do ClickHouse que não têm equivalentes no PostgreSQL. Se alguma dessas funções não puder ser processada via pushdown, será gerada uma exceção.Pushdown de extensões
O pg_clickhouse reconhece funções de algumas extensões principais e de terceiros, fazendo o pushdown delas para seus equivalentes no ClickHouse.re2
Todos os operadores e funções da [extensão re2] são convertidos 1:1 para o ClickHouse:@~→ matchre2match→ matchre2extract→ extractre2extractall→ extractAllre2regexpextract→ regexpExtractre2extractgroups→ extractGroupsre2replaceregexpone→ replaceRegexpOnere2replaceregexpall→ replaceRegexpAllre2countmatches→ countMatchesre2countmatchescaseinsensitive→ countMatchesCaseInsensitivere2multimatchany→ multiMatchAnyre2multimatchanyindex→ multiMatchAnyIndexre2multimatchallindices→ multiMatchAllIndices
intarray
Uma função [intarray] pode fazer pushdown para o ClickHouse:idx→ indexOf
fuzzystrmatch
Duas funções [fuzzystrmatch] podem ser executadas no ClickHouse:soundex: soundexlevenshtein(2 argumentos): editDistanceUTF8
pgcyrpto
digest(text, text)edigest(bytea, text): função de hash correspondente do ClickHouse quando o algoritmo é uma constantemd5,sha1,sha224,sha256,sha384ousha512(sem diferenciar maiúsculas de minúsculas).
Casts com pushdown
O pg_clickhouse faz pushdown de casts comoCAST(x AS bigint) para
tipos de dados compatíveis. Para tipos incompatíveis, o pushdown falha; se x, neste
exemplo, for um UInt64 do ClickHouse, o ClickHouse se recusará a converter o valor.
Para fazer pushdown de casts para tipos de dados incompatíveis, o pg_clickhouse fornece
as funções a seguir. Elas geram uma exceção no PostgreSQL se não forem
executadas com pushdown.
Funções de agregação com pushdown
Estas funções de agregação do PostgreSQL oferecem suporte a pushdown para o ClickHouse.- 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
Agregações personalizadas
Estas funções de agregação personalizadas criadas por pg_clickhouse fornecem pushdown de consultas externas para algumas funções de agregação do ClickHouse sem equivalentes no PostgreSQL. Se alguma dessas funções não puder ter pushdown, será gerada uma exceção.Agregações ordered-set com pushdown
Estas funções de agregação de conjunto ordenado são mapeadas para funções de agregação paramétricas do ClickHouse, passando o argumento direto como parâmetro e as expressões deORDER BY como argumentos. Por exemplo, esta consulta PostgreSQL:
DESC e NULLS FIRST de ORDER BY
não têm suporte e gerarão um erro.
percentile_cont(double): quantilepercentile_cont(double[]): quantilespercentile_disc(double): quantileExactLowpercentile_disc(double[]): quantilesExactLow
Agregações ordered-set personalizadas
Estas funções de agregação de conjunto ordenado personalizadas, criadas pelo pg_clickhouse, oferecem pushdown de consultas externas para determinadas funções de agregação paramétricas do ClickHouse. Se não for possível aplicar pushdown a alguma dessas funções, será gerada uma exceção.quantile(double): quantilequantileExact(double): quantileExact
Agregados personalizados de conjunto ordenado
Estas funções de agregação de conjunto ordenado personalizadas, criadas pelo pg_clickhouse, permitem o pushdown de consultas externas para funções de [agregação paramétricas] selecionadas do ClickHouse. Se não for possível aplicar pushdown a alguma dessas funções, será gerada uma exceção.Funções de janela com pushdown
Estas [funções de janela] do PostgreSQL fazem pushdown para o ClickHouse com cláusulasOVER (PARTITION BY ... ORDER BY ...), incluindo especificações de frame
quando aplicável.
- row_number
- rank
- dense_rank
- ntile
- cume_dist
- percent_rank
- lead
- lag
- first_value
- last_value
- nth_value
min/max(com a cláusulaOVER)
row_number, rank, dense_rank, ntile, cume_dist,
percent_rank) omitem a cláusula de frame durante o pushdown porque o ClickHouse
rejeita especificações de frame nessas funções.
Notas de compatibilidade
Expressões regulares
Embora o pg_clickhouse faça pushdown de expressões regulares para equivalentes no ClickHouse quando pg_clickhouse.pushdown_regex é true (o padrão), e se esforce para garantir um nível básico de compatibilidade, esteja ciente das diferenças entre os dois e de como o pg_clickhouse as trata.-
O PostgreSQL oferece suporte a [Expressões Regulares POSIX], enquanto o ClickHouse oferece suporte a
[Expressões Regulares RE2][RE2]. Fique atento às diferenças de comportamento: use RE2
quando a expressão regular for avaliada pelo ClickHouse (por exemplo, em uma
cláusula
WHERE) e POSIX quando ela for avaliada pelo Postgres (por exemplo, em uma cláusulaSELECT). -
pg_clickhouse aplica as [flags do Postgres] prefixando-as à
expressão regular do ClickHouse dentro de
(?). Por exemplo:Passa a ser -
As únicas flags compatíveis com ambos e, portanto, que podem ser usadas quando interpretadas pelo
ClickHouse são:
O RE2 oferece suporte apenas a estas flags; não use nenhuma outra [flags do Postgres].
-
Esta tabela resume os efeitos das várias flags (e da ausência de flag, que
é o mesmo que
s) na correspondência de quebras de linha e terminações de linha. Observe que, no Postgres,mepimpedem que classes de caracteres negadas ([^xyz]) correspondam a uma quebra de linha, enquanto os equivalentes no ClickHouse não. Fora isso, os comportamentos são os mesmos no ClickHouse e no Postgres: - Quaisquer outras flags passadas para funções de expressão regular impedem o pushdown da função.
-
A exceção é
regexp_replace(), que também aceita a flagg. Quandogestá definida, pg_clickhouse usareplaceRegexpAll()em vez dereplaceRegexpOne()e remove a flag antes de adicionar outras flags no início. -
O argumento de substituição de
regexp_replace()no Postgres aceita\¶ se referir à correspondência inteira, enquanto no ClickHouse\0representa a correspondência inteira. Certifique-se de usar\0quando a função fizer pushdown para o ClickHouse. -
Postgres
regexp_matchretornaNULLquando não há correspondências, enquanto as expressões delegadas retornam um array vazio. UseCOALESCE()para retornar um array vazio em vez deNULLe comparar os valores de retorno de forma compatível. Por exemplo:
to_char()
O [to_char()] do PostgreSQL para timestamp e timestamp with time zone só
faz pushdown para o ClickHouse [formatDateTime] quando o argumento de formato é uma
constante de string não NULL em que cada palavra-chave do PostgreSQL tem um
equivalente idêntico byte a byte no ClickHouse. Se o formato for dinâmico ou contiver qualquer
palavra-chave ou modificador sem suporte, a chamada recorre à avaliação local no
PostgreSQL. O pg_clickhouse nunca faz pushdown de uma tradução parcial, para que a saída
permaneça compatível.
As variantes de to_char() com dois argumentos aplicadas a numeric, interval e outros
tipos que não sejam timestamp nunca usam pushdown; o [formatDateTime] do ClickHouse apenas formata
valores de data e hora.
Palavras-chave traduzidas
Texto entre aspas e literais
O texto entre"..." é passado literalmente, com qualquer % literal duplicado
como %% para escapar o prefixo de especificador do ClickHouse. Um \" fora das aspas também
é passado como um literal ". Dentro de "...", a barra invertida escapa apenas ";
outras sequências com barra invertida são tratadas como texto literal.
Autores
David E. WheelerDireitos autorais
Copyright (c) 2025-2026, ClickHouse [Array] https://clickhouse.com/docs/reference/data-types/array “Documentação do ClickHouse: Array(T)” [Map]: https://clickhouse.com/docs/sql-reference/data-types/map “Documentação do ClickHouse: Map” [Tuple]: https://clickhouse.com/docs/reference/data-types/tuple “Documentação do ClickHouse: Tuple(T1, T2, …)” [Nested]: https://clickhouse.com/docs/sql-reference/data-types/nested-data-structures/nested “Documentação do ClickHouse: Nested” [Enum]: https://clickhouse.com/docs/reference/data-types/enum “Documentação do ClickHouse: Enum” [String]: /reference/data-types/string “Documentação do ClickHouse: String” [TEXT]: https://www.postgresql.org/docs/current/datatype-character.html “Documentação do PostgreSQL: Tipos de caracteres” [window functions]: https://www.postgresql.org/docs/current/functions-window.html “Documentação do PostgreSQL: Funções de janela” [POSIX Regular Expressions]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP “Documentação do PostgreSQL: Expressões regulares POSIX” [Postgres flags]: https://www.postgresql.org/docs/current/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE “Documentação do PostgreSQL: Letras de opções embutidas do ARE” [RE2]: https://github.com/google/re2/wiki/Syntax “Sintaxe do RE2” [re2 extension]: https://github.com/ClickHouse/pg_re2 “pg_re2: funções de regex compatíveis com ClickHouse usando RE2” [intarray]: https://www.postgresql.org/docs/current/intarray.html “Documentação do PostgreSQL: intarray” [fuzzystrmatch]: https://www.postgresql.org/docs/current/fuzzystrmatch.html “Documentação do PostgreSQL: fuzzystrmatch” [to_char()]: https://www.postgresql.org/docs/current/functions-formatting.html “Documentação do PostgreSQL: Funções de formatação de tipos de dados”
[formatDateTime]: /reference/functions/regular-functions/date-time-functions#formatDateTime “Documentação do ClickHouse: formatDateTime”