Skip to content

ClickHouse

ClickHouse SQL uses unquoted column names, match() for regex, and LIKE for wildcards.

FlyQLGenerated SQL
message='hello'message = 'hello'
message!='hello'message != 'hello'
count>10count > 10
count<=100count <= 100
message~'error.*'match(message, 'error.*')
message!~'test.*'not match(message, 'test.*')
host=prod*host LIKE 'prod%'
FlyQLGenerated SQL
a='1' and b>10(a = '1' and b > 10)
a='1' or b='2'(a = '1' or b = '2')
not a='1'not (a = '1')
FlyQLGenerated SQL
status in [200, 201]status IN (200, 201)
env not in ['dev', 'test']env NOT IN ('dev', 'test')
status in []0
status not in []1

The has operator generates different SQL depending on the column type:

Column TypeFlyQLGenerated SQL
Stringmessage has 'error'position(message, 'error') > 0
String (negated)message not has 'error'(message IS NULL OR position(message, 'error') = 0)
Arraytags has 'web'has(tags, 'web')
Array (negated)tags not has 'web'NOT has(tags, 'web')
Mapmetadata has 'key'mapContains(metadata, 'key')
Map (negated)metadata not has 'key'NOT mapContains(metadata, 'key')
Native JSONdata has 'key'JSON_EXISTS(data, concat('$.', 'key'))
JSON Stringdata has 'key'JSONHas(data, 'key')

ClickHouse supports two JSON column types with different SQL output.

Columns declared as JSON use dot notation with backtick-quoted segments:

FlyQLGenerated SQL
data.name='test'data.`name` = 'test'
data.user.name='john'data.`user`.`name` = 'john'
data.age=25data.`age` = 25

Columns storing JSON as a string (e.g., String type with JSON content) use JSONExtract functions wrapped in multiIf for type checking:

FlyQLGenerated SQL
data.name='test'multiIf(JSONType(data, 'name') = 'String', equals(JSONExtractString(data, 'name'), 'test'), 0)
data.user.name='john'multiIf(JSONType(data, 'user', 'name') = 'String', equals(JSONExtractString(data, 'user', 'name'), 'john'), 0)

Map columns use bracket notation with equals()/notEquals() functions:

FlyQLGenerated SQL
metadata.key1='value1'equals(metadata['key1'], 'value1')
metadata.key1!='value1'notEquals(metadata['key1'], 'value1')
metadata.pattern~'test.*'match(metadata['pattern'], 'test.*')

Array columns use 0-based bracket indexing with equals():

FlyQLGenerated SQL
tags.0='first'equals(tags[0], 'first')
tags.1='second'equals(tags[1], 'second')
tags.0~'tag.*'match(tags[0], 'tag.*')

The jsonString parameter controls which mode is used:

// Go
columns := map[string]*clickhouse.Column{
"message": clickhouse.NewColumn("message", false, "String", nil),
"data": clickhouse.NewColumn("data", false, "JSON", nil), // native JSON
"log": clickhouse.NewColumn("log", true, "String", nil), // JSON string
}
// JavaScript
const columns = {
message: newColumn("message", false, "String", null),
data: newColumn("data", false, "JSON", null), // native JSON
log: newColumn("log", true, "String", null), // JSON string
}