DuckDB ClickHouse SQL extension

February 18, 2026 · View on GitHub

DuckDB ClickHouse SQL extension

The DuckDB chsql community extension implements popular ClickHouse SQL syntax macros and functions,
making it easier for users to transition between the two database systems ⭐ designed for Quackpipe


Installation

chsql is distributed as a DuckDB Community Extension and can be installed using SQL:

INSTALL chsql FROM community;
LOAD chsql;

If you previously installed the chsql extension, upgrade using the FORCE command

FORCE INSTALL chsql FROM community;
LOAD chsql;

Usage Examples

Once installed, the macro functions provided by the extension can be used just like built-in functions.

Here's a random example out of 100s using the IPv4StringToNum and IPv4NumToString functions:

--- Install and load chsql
D INSTALL chsql FROM community;
D LOAD chsql;

--- Use any of the 100+ ClickHouse Macros
D SELECT IPv4StringToNum('127.0.0.1'), IPv4NumToString(2130706433);
┌──────────────────────────────┬─────────────────────────────┐
│ ipv4stringtonum('127.0.0.1') │ ipv4numtostring(2130706433) │
│            int32             │           varchar
├──────────────────────────────┼─────────────────────────────┤
2130706433127.0.0.1
└──────────────────────────────┴─────────────────────────────┘

Remote Queries

The built-in ch_scan function can be used to query remote ClickHouse servers using the HTTP/s API

--- Set optional X-Header Authentication
D CREATE SECRET extra_http_headers (
      TYPE HTTP,
      EXTRA_HTTP_HEADERS MAP{
          'X-ClickHouse-User': 'user',
          'X-ClickHouse-Key': 'password'
      }
  );
--- Query using the HTTP API
D SELECT * FROM ch_scan("SELECT number * 2 FROM numbers(10)", "https://play.clickhouse.com");
--- Or on your local
SELECT * FROM ch_scan("SELECT number * 2 FROM numbers(10)", "http://localhost:8123", user:='default', format:='parquet');

Supported Functions

👉 The list of supported aliases is available on the dedicated extension page
👉 The combined list of supported functions can be obtained using an SQL Join

System Table

chsql loosely emulates ClickHouse system tables within DuckDB for client compatibility

Table Views

  • system.databases
  • system.tables
  • system.columns
  • system.functions
  • system.uptime
  • system.disks

Scalar

  • uptime()

Motivation

Why is the DuckDB + chsql combo fun and useful

✔ DuckDB SQL is awesome and full of great functions.
✔ ClickHouse SQL is awesome and full of great functions.

✔ The DuckDB library is ~51M and modular. Can LOAD extensions.
❌ The ClickHouse monolith is ~551M and growing. No extensions.

✔ DuckDB is open source and protected by a no-profit foundation.
❌ ClickHouse is open core and controlled by for-profit corporation.

✔ DuckDB embedded is fast, mature and elegantly integrated in many languages.
❌ chdb is still experimental, unstable and currently only supports Python.



Functions

functionfun_typedescriptioncommentexample
IPv4NumToStringmacroCast IPv4 address from numeric to string formatSELECT IPv4NumToString(2130706433);
IPv4StringToNummacroCast IPv4 address from string to numeric formatSELECT IPv4StringToNum('127.0.0.1');
arrayExistsmacroCheck if any element of the array satisfies the conditionSELECT arrayExists(x -> x = 1, [1, 2, 3]);
arrayJoinmacroUnroll an array into multiple rowsSELECT arrayJoin([1, 2, 3]);
arrayMapmacroApplies a function to each element of an arraySELECT arrayMap(x -> x + 1, [1, 2, 3]);
bitCountmacroCounts the number of set bits in an integerSELECT bitCount(15);
ch_scantable_macroQuery a remote ClickHouse server using HTTP/s APIReturns the query resultsSELECT * FROM ch_scan('SELECT version()','https://play.clickhouse.com', format := 'parquet');
domainmacroExtracts the domain from a URLSELECT domain('https://clickhouse.com/docs');
emptymacroCheck if a string is emptySELECT empty('');
extractAllGroupsmacroExtracts all matching groups from a string using a regular expressionSELECT extractAllGroups('(\d+)', 'abc123');
formatDateTimemacroFormats a DateTime value into a stringSELECT formatDateTime(now(), '%Y-%m-%d');
generateUUIDv4macroGenerate a UUID v4 valueSELECT generateUUIDv4();
ifNullmacroReturns the first argument if not NULL, otherwise the secondSELECT ifNull(NULL, 'default');
intDivmacroPerforms integer divisionSELECT intDiv(10, 3);
intDivOZeromacroPerforms integer division but returns zero instead of throwing an error for division by zeroSELECT intDivOZero(10, 0);
intDivOrNullmacroPerforms integer division but returns NULL instead of throwing an error for division by zeroSELECT intDivOrNull(10, 0);
leftPadmacroPads a string on the left to a specified lengthSELECT leftPad('abc', 5, '*');
lengthUTF8macroReturns the length of a string in UTF-8 charactersSELECT lengthUTF8('Привет');
matchmacroPerforms a regular expression match on a stringSELECT match('abc123', '\d+');
minusmacroPerforms subtraction of two numbersSELECT minus(5, 3);
modulomacroCalculates the remainder of division (modulus)SELECT modulo(10, 3);
moduloOrZeromacroCalculates modulus but returns zero instead of error on division by zeroSELECT moduloOrZero(10, 0);
notEmptymacroCheck if a string is not emptySELECT notEmpty('abc');
numberstable_macroGenerates a sequence of numbers starting from 0Returns a table with a single column (UInt64)SELECT * FROM numbers(10);
parseURLmacroExtracts parts of a URLSELECT parseURL('https://clickhouse.com', 'host');
pathmacroExtracts the path from a URLSELECT path('https://clickhouse.com/docs');
plusmacroPerforms addition of two numbersSELECT plus(5, 3);
protocolmacroExtracts the protocol from a URLSELECT protocol('https://clickhouse.com');
read_parquet_mergetreefunctionMerge parquet files using a primary sorting key for fast range queriesexperimentalCOPY (SELECT * FROM read_parquet_mergetree(['/folder/*.parquet'], 'sortkey') TO 'sorted.parquet';
rightPadmacroPads a string on the right to a specified lengthSELECT rightPad('abc', 5, '*');
splitByCharmacroSplits a string by a given characterSELECT splitByChar(',', 'a,b,c');
toDayOfMonthmacroExtracts the day of the month from a dateSELECT toDayOfMonth('2023-09-10');
toFixedStringmacroConverts a value to a fixed-length stringSELECT toFixedString('abc', 5);
toFloatmacroConverts a value to a floatSELECT toFloat('123.45');
toFloatOrNullmacroConverts a value to float or returns NULL if the conversion failsSELECT toFloatOrNull('abc');
toFloatOrZeromacroConverts a value to float or returns zero if the conversion failsSELECT toFloatOrZero('abc');
toHourmacroExtracts the hour from a DateTime valueSELECT toHour(now());
toInt128macroConverts a value to a 128-bit integerSELECT toInt128('123456789012345678901234567890');
toInt128OrNullmacroConverts to a 128-bit integer or returns NULL on failureSELECT toInt128OrNull('abc');
toInt128OrZeromacroConverts to a 128-bit integer or returns zero on failureSELECT toInt128OrZero('abc');
toInt16macroConverts a value to a 16-bit integerSELECT toInt16('123');
toInt16OrNullmacroConverts to a 16-bit integer or returns NULL on failureSELECT toInt16OrNull('abc');
toInt16OrZeromacroConverts to a 16-bit integer or returns zero on failureSELECT toInt16OrZero('abc');
toInt256macroConverts a value to a 256-bit integerSELECT toInt256('12345678901234567890123456789012345678901234567890123456789012345678901234567890');
toInt256OrNullmacroConverts to a 256-bit integer or returns NULL on failureSELECT toInt256OrNull('abc');
toInt256OrZeromacroConverts to a 256-bit integer or returns zero on failureSELECT toInt256OrZero('abc');
toInt32macroConverts a value to a 32-bit integerSELECT toInt32('123');
toInt32OrNullmacroConverts to a 32-bit integer or returns NULL on failureSELECT toInt32OrNull('abc');
toInt32OrZeromacroConverts to a 32-bit integer or returns zero on failureSELECT toInt32OrZero('abc');
toInt64macroConverts a value to a 64-bit integerSELECT toInt64('123');
toInt64OrNullmacroConverts to a 64-bit integer or returns NULL on failureSELECT toInt64OrNull('abc');
toInt64OrZeromacroConverts to a 64-bit integer or returns zero on failureSELECT toInt64OrZero('abc');
toInt8macroConverts a value to an 8-bit integerSELECT toInt8('123');
toInt8OrNullmacroConverts to an 8-bit integer or returns NULL on failureSELECT toInt8OrNull('abc');
toInt8OrZeromacroConverts to an 8-bit integer or returns zero on failureSELECT toInt8OrZero('abc');
toMinutemacroExtracts the minute from a DateTime valueSELECT toMinute(now());
toMonthmacroExtracts the month from a Date valueSELECT toMonth('2023-09-10');
toSecondmacroExtracts the second from a DateTime valueSELECT toSecond(now());
toStringmacroConverts a value to a stringSELECT toString(123);
toUInt16macroConverts a value to an unsigned 16-bit integerSELECT toUInt16('123');
toUInt16OrNullmacroConverts to an unsigned 16-bit integer or returns NULL on failureSELECT toUInt16OrNull('abc');
toUInt16OrZeromacroConverts to an unsigned 16-bit integer or returns zero on failureSELECT toUInt16OrZero('abc');
toUInt32macroConverts a value to an unsigned 32-bit integerSELECT toUInt32('123');
toUInt32OrNullmacroConverts to an unsigned 32-bit integer or returns NULL on failureSELECT toUInt32OrNull('abc');
toUInt32OrZeromacroConverts to an unsigned 32-bit integer or returns zero on failureSELECT toUInt32OrZero('abc');
toUInt64macroConverts a value to an unsigned 64-bit integerSELECT toUInt64('123');
toUInt64OrNullmacroConverts to an unsigned 64-bit integer or returns NULL on failureSELECT toUInt64OrNull('abc');
toUInt64OrZeromacroConverts to an unsigned 64-bit integer or returns zero on failureSELECT toUInt64OrZero('abc');
toUInt8macroConverts a value to an unsigned 8-bit integerSELECT toUInt8('123');
toUInt8OrNullmacroConverts to an unsigned 8-bit integer or returns NULL on failureSELECT toUInt8OrNull('abc');
toUInt8OrZeromacroConverts to an unsigned 8-bit integer or returns zero on failureSELECT toUInt8OrZero('abc');
toYYYYMMmacroFormats a Date to 'YYYYMM' string formatSELECT toYYYYMM('2023-09-10');
toYYYYMMDDmacroFormats a Date to 'YYYYMMDD' string formatSELECT toYYYYMMDD('2023-09-10');
toYYYYMMDDhhmmssmacroFormats a DateTime to 'YYYYMMDDhhmmss' string formatSELECT toYYYYMMDDhhmmss(now());
toYearmacroExtracts the year from a Date or DateTime valueSELECT toYear('2023-09-10');
topLevelDomainmacroExtracts the top-level domain (TLD) from a URLSELECT topLevelDomain('https://example.com');
tupleConcatmacroConcatenates two tuples into one tupleSELECT tupleConcat((1, 'a'), (2, 'b'));
tupleDividemacroPerforms element-wise division between two tuplesSELECT tupleDivide((10, 20), (2, 5));
tupleDivideByNumbermacroDivides each element of a tuple by a numberSELECT tupleDivideByNumber((10, 20), 2);
tupleIntDivmacroPerforms element-wise integer division between two tuplesSELECT tupleIntDiv((10, 20), (3, 4));
tupleIntDivByNumbermacroPerforms integer division of each element of a tuple by a numberSELECT tupleIntDivByNumber((10, 20), 3);
tupleMinusmacroPerforms element-wise subtraction between two tuplesSELECT tupleMinus((10, 20), (5, 3));
tupleModulomacroPerforms element-wise modulus between two tuplesSELECT tupleModulo((10, 20), (3, 6));
tupleModuloByNumbermacroCalculates the modulus of each element of a tuple by a numberSELECT tupleModuloByNumber((10, 20), 3);
tupleMultiplymacroPerforms element-wise multiplication between two tuplesSELECT tupleMultiply((10, 20), (2, 5));
tupleMultiplyByNumbermacroMultiplies each element of a tuple by a numberSELECT tupleMultiplyByNumber((10, 20), 3);
tuplePlusmacroPerforms element-wise addition between two tuplesSELECT tuplePlus((1, 2), (3, 4));
urltable_macroPerforms queries against remote URLs using the specified formatSupports JSON, CSV, PARQUET, TEXT, BLOBSELECT * FROM url('https://urleng.com/test','JSON');
JSONExtractmacroExtracts JSON data based on key from a JSON objectSELECT JSONExtract(json_column, 'user.name');
JSONExtractStringmacroExtracts JSON data as a VARCHAR from a JSON objectSELECT JSONExtractString(json_column, 'user.email');
JSONExtractUIntmacroExtracts JSON data as an unsigned integer from a JSON objectSELECT JSONExtractUInt(json_column, 'user.age');
JSONExtractIntmacroExtracts JSON data as a 32-bit integer from a JSON objectSELECT JSONExtractInt(json_column, 'user.balance');
JSONExtractFloatmacroExtracts JSON data as a double from a JSON objectSELECT JSONExtractFloat(json_column, 'user.score');
JSONExtractRawmacroExtracts raw JSON data based on key from a JSON objectSELECT JSONExtractRaw(json_column, 'user.address');
JSONHasmacroChecks if a JSON key exists and is not nullSELECT JSONHas(json_column, 'user.active');
JSONLengthmacroReturns the length of a JSON arraySELECT JSONLength(json_column, 'items');
JSONTypemacroDetermines the type of JSON element at the given pathSELECT JSONType(json_column, 'user.data');
JSONExtractKeysmacroExtracts keys from a JSON objectSELECT JSONExtractKeys(json_column);
JSONExtractValuesmacroExtracts all values as text from a JSON objectSELECT JSONExtractValues(json_column);
equalsmacroChecks if two values are equalSELECT equals(column_a, column_b);
notEqualsmacroChecks if two values are not equalSELECT notEquals(column_a, column_b);
lessmacroChecks if one value is less than anotherSELECT less(column_a, column_b);
greatermacroChecks if one value is greater than anotherSELECT greater(column_a, column_b);
lessOrEqualsmacroChecks if one value is less than or equal to anotherSELECT lessOrEquals(column_a, column_b);
greaterOrEqualsmacroChecks if one value is greater than or equal to anotherSELECT greaterOrEquals(column_a, column_b);
dictGetmacroRetrieves an attribute from a VARIABLE string or MAPSELECT dictGet('dictionary_name', 'attribute');
Disclaimer

DuckDB ® is a trademark of DuckDB Foundation. ClickHouse® is a trademark of ClickHouse Inc. All trademarks, service marks, and logos mentioned or depicted are the property of their respective owners. The use of any third-party trademarks, brand names, product names, and company names is purely informative or intended as parody and does not imply endorsement, affiliation, or association with the respective owners.