@@ -65,30 +65,30 @@ static DefaultMacro chsql_macros[] = {
6565 {DEFAULT_SCHEMA , " toFloatOrNull" , {" x" , nullptr }, {{nullptr , nullptr }}, R"( TRY_CAST(x AS DOUBLE))" },
6666 {DEFAULT_SCHEMA , " toFloatOrZero" , {" x" , nullptr }, {{nullptr , nullptr }}, R"( CASE WHEN TRY_CAST(x AS DOUBLE) IS NOT NULL THEN CAST(x AS DOUBLE) ELSE 0 END)" },
6767 // -- Arithmetic macros
68- {DEFAULT_SCHEMA , " intDiv" , {" a" , " b" }, {{nullptr , nullptr }}, R"( (CAST(a AS BIGINT) // CAST(b AS BIGINT)))" },
69- {DEFAULT_SCHEMA , " intDivOrNull" , {" a" , " b" }, {{nullptr , nullptr }}, R"( TRY_CAST((TRY_CAST(a AS BIGINT) // TRY_CAST(b AS BIGINT)) AS BIGINT))" },
68+ {DEFAULT_SCHEMA , " intDiv" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (CAST(a AS BIGINT) // CAST(b AS BIGINT)))" },
69+ {DEFAULT_SCHEMA , " intDivOrNull" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( TRY_CAST((TRY_CAST(a AS BIGINT) // TRY_CAST(b AS BIGINT)) AS BIGINT))" },
7070 {DEFAULT_SCHEMA , " intDivOZero" , {" x" , nullptr }, {{nullptr , nullptr }}, R"( COALESCE((TRY_CAST((TRY_CAST(a AS BIGINT) // TRY_CAST(b AS BIGINT)) AS BIGINT)),0))" },
71- {DEFAULT_SCHEMA , " plus" , {" a" , " b" }, {{nullptr , nullptr }}, R"( add(a, b))" },
72- {DEFAULT_SCHEMA , " minus" , {" a" , " b" }, {{nullptr , nullptr }}, R"( subtract(a, b))" },
73- {DEFAULT_SCHEMA , " modulo" , {" a" , " b" }, {{nullptr , nullptr }}, R"( CAST(a AS BIGINT) % CAST(b AS BIGINT))" },
74- {DEFAULT_SCHEMA , " moduloOrZero" , {" a" , " b" }, {{nullptr , nullptr }}, R"( COALESCE(((TRY_CAST(a AS BIGINT) % TRY_CAST(b AS BIGINT))),0))" },
71+ {DEFAULT_SCHEMA , " plus" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( add(a, b))" },
72+ {DEFAULT_SCHEMA , " minus" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( subtract(a, b))" },
73+ {DEFAULT_SCHEMA , " modulo" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( CAST(a AS BIGINT) % CAST(b AS BIGINT))" },
74+ {DEFAULT_SCHEMA , " moduloOrZero" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( COALESCE(((TRY_CAST(a AS BIGINT) % TRY_CAST(b AS BIGINT))),0))" },
7575 // -- Tuple macros
76- {DEFAULT_SCHEMA , " tupleIntDiv" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] // CAST(x AS BIGINT)))" },
77- {DEFAULT_SCHEMA , " tupleIntDivByNumber" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) // CAST(x AS BIGINT)))" },
78- {DEFAULT_SCHEMA , " tupleDivide" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] / CAST(x AS BIGINT)))" },
79- {DEFAULT_SCHEMA , " tupleMultiply" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> CAST(apply(b, x -> CAST(x AS BIGINT))[i] as BIGINT) * CAST(x AS BIGINT)))" },
80- {DEFAULT_SCHEMA , " tupleMinus" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] - CAST(x AS BIGINT)))" },
81- {DEFAULT_SCHEMA , " tuplePlus" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] + CAST(x AS BIGINT)))" },
82- {DEFAULT_SCHEMA , " tupleMultiplyByNumber" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) * CAST(x AS BIGINT)))" },
83- {DEFAULT_SCHEMA , " tupleDivideByNumber" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) / CAST(x AS BIGINT)))" },
84- {DEFAULT_SCHEMA , " tupleModulo" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
85- {DEFAULT_SCHEMA , " tupleModuloByNumber" , {" a" , " b" }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
86- {DEFAULT_SCHEMA , " tupleConcat" , {" a" , " b" }, {{nullptr , nullptr }}, R"( list_concat(a, b))" },
76+ {DEFAULT_SCHEMA , " tupleIntDiv" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] // CAST(x AS BIGINT)))" },
77+ {DEFAULT_SCHEMA , " tupleIntDivByNumber" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) // CAST(x AS BIGINT)))" },
78+ {DEFAULT_SCHEMA , " tupleDivide" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] / CAST(x AS BIGINT)))" },
79+ {DEFAULT_SCHEMA , " tupleMultiply" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> CAST(apply(b, x -> CAST(x AS BIGINT))[i] as BIGINT) * CAST(x AS BIGINT)))" },
80+ {DEFAULT_SCHEMA , " tupleMinus" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] - CAST(x AS BIGINT)))" },
81+ {DEFAULT_SCHEMA , " tuplePlus" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] + CAST(x AS BIGINT)))" },
82+ {DEFAULT_SCHEMA , " tupleMultiplyByNumber" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) * CAST(x AS BIGINT)))" },
83+ {DEFAULT_SCHEMA , " tupleDivideByNumber" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) / CAST(x AS BIGINT)))" },
84+ {DEFAULT_SCHEMA , " tupleModulo" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
85+ {DEFAULT_SCHEMA , " tupleModuloByNumber" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
86+ {DEFAULT_SCHEMA , " tupleConcat" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( list_concat(a, b))" },
8787 // -- String matching macros
8888 {DEFAULT_SCHEMA , " match" , {" string" , " token" }, {{nullptr , nullptr }}, R"( string LIKE token)" },
8989 // -- Array macros
90- {DEFAULT_SCHEMA , " arrayExists" , {" needle" , " haystack" }, {{nullptr , nullptr }}, R"( haystack @> ARRAY[needle])" },
91- {DEFAULT_SCHEMA , " arrayMap" , {" e" , " arr" }, {{nullptr , nullptr }}, R"( array_transform(arr, e -> (e * e)))" },
90+ {DEFAULT_SCHEMA , " arrayExists" , {" needle" , " haystack" , nullptr }, {{nullptr , nullptr }}, R"( haystack @> ARRAY[needle])" },
91+ {DEFAULT_SCHEMA , " arrayMap" , {" e" , " arr" , nullptr }, {{nullptr , nullptr }}, R"( array_transform(arr, e -> (e * e)))" },
9292 // Date and Time Functions
9393 {DEFAULT_SCHEMA , " toYear" , {" date_expression" , nullptr }, {{nullptr , nullptr }}, R"( EXTRACT(YEAR FROM date_expression))" },
9494 {DEFAULT_SCHEMA , " toMonth" , {" date_expression" , nullptr }, {{nullptr , nullptr }}, R"( EXTRACT(MONTH FROM date_expression))" },
@@ -119,10 +119,32 @@ static DefaultMacro chsql_macros[] = {
119119 // IP Address Functions
120120 {DEFAULT_SCHEMA , " IPv4NumToString" , {" num" , nullptr }, {{nullptr , nullptr }}, R"( CONCAT(CAST((num >> 24) & 255 AS VARCHAR), '.', CAST((num >> 16) & 255 AS VARCHAR), '.', CAST((num >> 8) & 255 AS VARCHAR), '.', CAST(num & 255 AS VARCHAR)))" },
121121 {DEFAULT_SCHEMA , " IPv4StringToNum" , {" ip" , nullptr }, {{nullptr , nullptr }}, R"( CAST(SPLIT_PART(ip, '.', 1) AS INTEGER) * 256 * 256 * 256 + CAST(SPLIT_PART(ip, '.', 2) AS INTEGER) * 256 * 256 + CAST(SPLIT_PART(ip, '.', 3) AS INTEGER) * 256 + CAST(SPLIT_PART(ip, '.', 4) AS INTEGER))" },
122+ // -- JSON Macros
123+ {DEFAULT_SCHEMA , " JSONExtract" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( json_extract(json, key))" },
124+ {DEFAULT_SCHEMA , " JSONExtractString" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( CAST(json_extract(json, key) AS VARCHAR))" },
125+ {DEFAULT_SCHEMA , " JSONExtractUInt" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( CAST(json_extract(json, key) AS UINTEGER))" },
126+ {DEFAULT_SCHEMA , " JSONExtractInt" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( CAST(json_extract(json, key) AS INT32))" },
127+ {DEFAULT_SCHEMA , " JSONExtractFloat" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( CAST(json_extract(json, key) AS DOUBLE))" },
128+ {DEFAULT_SCHEMA , " JSONExtractRaw" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( json_extract(json, key))" },
129+ {DEFAULT_SCHEMA , " JSONHas" , {" json" , " key" , nullptr }, {{nullptr , nullptr }}, R"( json_extract(json, key) IS NOT NULL)" },
130+ {DEFAULT_SCHEMA , " JSONLength" , {" json" , nullptr }, {{nullptr , nullptr }}, R"( json_array_length(json))" },
131+ {DEFAULT_SCHEMA , " JSONType" , {" json" , " path" , nullptr }, {{nullptr , nullptr }}, R"( CASE WHEN path IS NULL THEN json_each(json) ELSE json_each(json,path) END)" },
132+ {DEFAULT_SCHEMA , " JSONExtractKeys" , {" json" , nullptr }, {{nullptr , nullptr }}, R"( json_object_keys(json))" },
133+ {DEFAULT_SCHEMA , " JSONExtractValues" , {" json" , nullptr }, {{nullptr , nullptr }}, R"( json_each_text(json))" },
134+ // -- Compare Macros
135+ {DEFAULT_SCHEMA , " equals" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a = b))" },
136+ {DEFAULT_SCHEMA , " notEquals" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a <> b))" },
137+ {DEFAULT_SCHEMA , " less" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a < b))" },
138+ {DEFAULT_SCHEMA , " greater" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a > b))" },
139+ {DEFAULT_SCHEMA , " lessOrEquals" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a <= b))" },
140+ {DEFAULT_SCHEMA , " greaterOrEquals" , {" a" , " b" , nullptr }, {{nullptr , nullptr }}, R"( (a >= b))" },
122141 // -- Misc macros
123142 {DEFAULT_SCHEMA , " generateUUIDv4" , {nullptr }, {{nullptr , nullptr }}, R"( toString(uuid()))" },
124143 {DEFAULT_SCHEMA , " parseURL" , {" url" , " part" , nullptr }, {{nullptr , nullptr }}, R"( CASE part WHEN 'protocol' THEN REGEXP_EXTRACT(url, '^(\w+)://') WHEN 'domain' THEN REGEXP_EXTRACT(url, '://([^/:]+)') WHEN 'port' THEN REGEXP_EXTRACT(url, ':(\d+)') WHEN 'path' THEN REGEXP_EXTRACT(url, '://[^/]+(/.+?)(\?|#|$)') WHEN 'query' THEN REGEXP_EXTRACT(url, '\?([^#]+)') WHEN 'fragment' THEN REGEXP_EXTRACT(url, '#(.+)$') END)" },
125144 {DEFAULT_SCHEMA , " bitCount" , {" num" , nullptr }, {{nullptr , nullptr }}, R"( BIT_COUNT(num))" },
145+ // Dictionary Emulation using MAP VARIABLES
146+ {DEFAULT_SCHEMA , " dictGet" , {" dict" ," attr" , nullptr }, {{nullptr , nullptr }}, R"( getvariable(dict)[attr][1])" },
147+ // -- End Macro
126148 {nullptr , nullptr , {nullptr }, {{nullptr , nullptr }}, nullptr }};
127149
128150// To add a new table SQL macro, add a new macro to this array!
@@ -142,8 +164,23 @@ static DefaultMacro chsql_macros[] = {
142164// clang-format off
143165static const DefaultTableMacro chsql_table_macros[] = {
144166 {DEFAULT_SCHEMA , " numbers" , {" x" , nullptr }, {{" z" , " 0" }, {nullptr , nullptr }}, R"( SELECT * as number FROM generate_series(z,x-1);)" },
145- {DEFAULT_SCHEMA , " ch_scan" , {" query" , " server" }, {{" format" , " JSONEachRow" }, {" user" , " play" }, {nullptr , nullptr }}, R"( SELECT * FROM read_json_auto(concat(server, '/?default_format=', format, '&user=', user, '&query=', query)))" },
146- {DEFAULT_SCHEMA , " url" , {" url" , " format" }, {{nullptr , nullptr }}, R"( WITH "JSON" as (SELECT * FROM read_json_auto(url)), "PARQUET" as (SELECT * FROM read_parquet(url)), "CSV" as (SELECT * FROM read_csv_auto(url)), "BLOB" as (SELECT * FROM read_blob(url)), "TEXT" as (SELECT * FROM read_text(url)) FROM query_table(format))" },
167+ {DEFAULT_SCHEMA , " url" , {" url" , " format" , nullptr }, {{nullptr , nullptr }}, R"( WITH "JSON" as (SELECT * FROM read_json_auto(url)), "PARQUET" as (SELECT * FROM read_parquet(url)), "CSV" as (SELECT * FROM read_csv_auto(url)), "BLOB" as (SELECT * FROM read_blob(url)), "TEXT" as (SELECT * FROM read_text(url)) FROM query_table(format))" },
168+ {DEFAULT_SCHEMA , " ch_scan" , {" query" , " server" , nullptr }, {{" format" , " JSONEachRow" }, {" user" , " play" }, {nullptr , nullptr }}, R"(
169+ WITH
170+ "json" AS (SELECT * FROM read_json_auto(concat(server, '/?default_format=jsoneachrow&user=', user, '&query=', query))),
171+ "parquet" AS (SELECT * FROM read_parquet(concat(server, '/?default_format=parquet&user=', user, '&query=', query))),
172+ "csv" AS (SELECT * FROM read_csv_auto(concat(server, '/?default_format=csv&user=', user, '&query=', query))),
173+ "blob" AS (SELECT * FROM read_blob(concat(server, '/?default_format=blob&user=', user, '&query=', query))),
174+ "text" AS (SELECT * FROM read_text(concat(server, '/?default_format=text&user=', user, '&query=', query)))
175+ FROM query_table(CASE
176+ WHEN LOWER(format) LIKE 'json%' THEN 'json'
177+ WHEN LOWER(format) LIKE 'csv%' THEN 'csv'
178+ WHEN LOWER(format) = 'parquet' THEN 'parquet'
179+ WHEN LOWER(format) = 'blob' THEN 'blob'
180+ WHEN LOWER(format) = 'text' THEN 'text'
181+ ELSE 'json'
182+ END)
183+ )" },
147184 {nullptr , nullptr , {nullptr }, {{nullptr , nullptr }}, nullptr }
148185 };
149186// clang-format on
0 commit comments