@@ -27,9 +27,7 @@ namespace duckdb {
2727// If you do not have parameters, simplify to {nullptr}
2828// Add the text of your SQL macro as a raw string with the format R"( select 42 )"
2929
30-
3130static DefaultMacro chsql_macros[] = {
32- {DEFAULT_SCHEMA, " times_two" , {" x" , nullptr }, R"( x*2)" },
3331 // -- Type conversion macros
3432 {DEFAULT_SCHEMA, " toString" , {" x" , nullptr }, R"( CAST(x AS VARCHAR))" },
3533 {DEFAULT_SCHEMA, " toInt8" , {" x" , nullptr }, R"( CAST(x AS INT8))" },
@@ -69,11 +67,63 @@ static DefaultMacro chsql_macros[] = {
6967 {DEFAULT_SCHEMA, " toFloatOrZero" , {" x" , nullptr }, R"( CASE WHEN TRY_CAST(x AS DOUBLE) IS NOT NULL THEN CAST(x AS DOUBLE) ELSE 0 END)" },
7068 // -- Arithmetic macros
7169 {DEFAULT_SCHEMA, " intDiv" , {" a" , " b" }, R"( (CAST(a AS BIGINT) // CAST(b AS BIGINT)))" },
70+ {DEFAULT_SCHEMA, " intDivOrNull" , {" a" , " b" }, R"( TRY_CAST((TRY_CAST(a AS BIGINT) // TRY_CAST(b AS BIGINT)) AS BIGINT))" },
71+ {DEFAULT_SCHEMA, " intDivOZero" , {" x" , nullptr }, R"( COALESCE((TRY_CAST((TRY_CAST(a AS BIGINT) // TRY_CAST(b AS BIGINT)) AS BIGINT)),0))" },
72+ {DEFAULT_SCHEMA, " plus" , {" a" , " b" }, R"( add(a, b))" },
73+ {DEFAULT_SCHEMA, " minus" , {" a" , " b" }, R"( subtract(a, b))" },
74+ {DEFAULT_SCHEMA, " modulo" , {" a" , " b" }, R"( CAST(a AS BIGINT) % CAST(b AS BIGINT))" },
75+ {DEFAULT_SCHEMA, " moduloOrZero" , {" a" , " b" }, R"( COALESCE(((TRY_CAST(a AS BIGINT) % TRY_CAST(b AS BIGINT))),0))" },
76+ // -- Tuple macros
77+ {DEFAULT_SCHEMA, " tupleIntDiv" , {" a" , " b" }, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] // CAST(x AS BIGINT)))" },
78+ {DEFAULT_SCHEMA, " tupleIntDivByNumber" , {" a" , " b" }, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) // CAST(x AS BIGINT)))" },
79+ {DEFAULT_SCHEMA, " tupleDivide" , {" a" , " b" }, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] / CAST(x AS BIGINT)))" },
80+ {DEFAULT_SCHEMA, " tupleMultiply" , {" a" , " b" }, R"( apply(a, (x,i) -> CAST(apply(b, x -> CAST(x AS BIGINT))[i] as BIGINT) * CAST(x AS BIGINT)))" },
81+ {DEFAULT_SCHEMA, " tupleMinus" , {" a" , " b" }, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] - CAST(x AS BIGINT)))" },
82+ {DEFAULT_SCHEMA, " tuplePlus" , {" a" , " b" }, R"( apply(a, (x,i) -> apply(b, x -> CAST(x AS BIGINT))[i] + CAST(x AS BIGINT)))" },
83+ {DEFAULT_SCHEMA, " tupleMultiplyByNumber" , {" a" , " b" }, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) * CAST(x AS BIGINT)))" },
84+ {DEFAULT_SCHEMA, " tupleDivideByNumber" , {" a" , " b" }, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) / CAST(x AS BIGINT)))" },
85+ {DEFAULT_SCHEMA, " tupleModulo" , {" a" , " b" }, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
86+ {DEFAULT_SCHEMA, " tupleModuloByNumber" , {" a" , " b" }, R"( apply(a, (x) -> CAST(apply(b, x -> CAST(x AS BIGINT))[1] as BIGINT) % CAST(x AS BIGINT)))" },
87+ {DEFAULT_SCHEMA, " tupleConcat" , {" a" , " b" }, R"( list_concat(a, b))" },
7288 // -- String matching macros
7389 {DEFAULT_SCHEMA, " match" , {" string" , " token" }, R"( string LIKE token)" },
7490 // -- Array macros
7591 {DEFAULT_SCHEMA, " arrayExists" , {" needle" , " haystack" }, R"( haystack @> ARRAY[needle])" },
7692 {DEFAULT_SCHEMA, " arrayMap" , {" e" , " arr" }, R"( array_transform(arr, e -> (e * e)))" },
93+ // Date and Time Functions
94+ {DEFAULT_SCHEMA, " toYear" , {" date_expression" , nullptr }, R"( EXTRACT(YEAR FROM date_expression))" },
95+ {DEFAULT_SCHEMA, " toMonth" , {" date_expression" , nullptr }, R"( EXTRACT(MONTH FROM date_expression))" },
96+ {DEFAULT_SCHEMA, " toDayOfMonth" , {" date_expression" , nullptr }, R"( EXTRACT(DAY FROM date_expression))" },
97+ {DEFAULT_SCHEMA, " toHour" , {" date_expression" , nullptr }, R"( EXTRACT(HOUR FROM date_expression))" },
98+ {DEFAULT_SCHEMA, " toMinute" , {" date_expression" , nullptr }, R"( EXTRACT(MINUTE FROM date_expression))" },
99+ {DEFAULT_SCHEMA, " toSecond" , {" date_expression" , nullptr }, R"( EXTRACT(SECOND FROM date_expression))" },
100+ {DEFAULT_SCHEMA, " toYYYYMM" , {" date_expression" , nullptr }, R"( DATE_FORMAT(date_expression, '%Y%m'))" },
101+ {DEFAULT_SCHEMA, " toYYYYMMDD" , {" date_expression" , nullptr }, R"( DATE_FORMAT(date_expression, '%Y%m%d'))" },
102+ {DEFAULT_SCHEMA, " toYYYYMMDDhhmmss" , {" date_expression" , nullptr }, R"( DATE_FORMAT(date_expression, '%Y%m%d%H%M%S'))" },
103+ {DEFAULT_SCHEMA, " formatDateTime" , {" time" , " format" , " timezone" , nullptr }, R"( CASE WHEN timezone IS NULL THEN strftime(time, format) ELSE strftime(time AT TIME ZONE timezone, format) END)" },
104+ // String Functions
105+ {DEFAULT_SCHEMA, " empty" , {" str" , nullptr }, R"( LENGTH(str) = 0)" },
106+ {DEFAULT_SCHEMA, " notEmpty" , {" str" , nullptr }, R"( LENGTH(str) > 0)" },
107+ {DEFAULT_SCHEMA, " lengthUTF8" , {" str" , nullptr }, R"( LENGTH(str))" },
108+ {DEFAULT_SCHEMA, " leftPad" , {" str" , " length" , " pad_str" , nullptr }, R"( LPAD(str, length, pad_str))" },
109+ {DEFAULT_SCHEMA, " rightPad" , {" str" , " length" , " pad_str" , nullptr }, R"( RPAD(str, length, pad_str))" },
110+ {DEFAULT_SCHEMA, " extractAllGroups" , {" text" , " pattern" , nullptr }, R"( regexp_extract_all(text, pattern))" },
111+ {DEFAULT_SCHEMA, " toFixedString" , {" str" , " length" , nullptr }, R"( RPAD(LEFT(str, length), length, '\0'))" },
112+ {DEFAULT_SCHEMA, " ifNull" , {" x" , " y" , nullptr }, R"( COALESCE(x, y))" },
113+ {DEFAULT_SCHEMA, " arrayJoin" , {" arr" , nullptr }, R"( UNNEST(arr))" },
114+ {DEFAULT_SCHEMA, " splitByChar" , {" separator" , " str" , nullptr }, R"( string_split(str, separator))" },
115+ // URL Functions
116+ {DEFAULT_SCHEMA, " protocol" , {" url" , nullptr }, R"( REGEXP_EXTRACT(url, '^(\w+)://', 1))" },
117+ {DEFAULT_SCHEMA, " domain" , {" url" , nullptr }, R"( REGEXP_EXTRACT(url, '://([^/]+)', 1))" },
118+ {DEFAULT_SCHEMA, " topLevelDomain" , {" url" , nullptr }, R"( REGEXP_EXTRACT(url, '\.([^./:]+)([:/]|$)', 1))" },
119+ {DEFAULT_SCHEMA, " path" , {" url" , nullptr }, R"( REGEXP_EXTRACT(url, '://[^/]+(/.*)', 1))" },
120+ // IP Address Functions
121+ {DEFAULT_SCHEMA, " IPv4NumToString" , {" num" , 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)))" },
122+ {DEFAULT_SCHEMA, " IPv4StringToNum" , {" ip" , 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))" },
123+ // -- Misc macros
124+ {DEFAULT_SCHEMA, " generateUUIDv4" , {nullptr }, R"( toString(uuid()))" },
125+ {DEFAULT_SCHEMA, " parseURL" , {" url" , " part" , 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)" },
126+ {DEFAULT_SCHEMA, " bitCount" , {" num" , nullptr }, R"( BIT_COUNT(num))" },
77127 {nullptr , nullptr , {nullptr }, nullptr }};
78128
79129// To add a new table SQL macro, add a new macro to this array!
@@ -92,7 +142,8 @@ static DefaultMacro chsql_macros[] = {
92142
93143// clang-format off
94144static const DefaultTableMacro chsql_table_macros[] = {
95- {DEFAULT_SCHEMA, " times_two_table" , {" x" , nullptr }, {{" two" , " 2" }, {nullptr , nullptr }}, R"( SELECT x * two as output_column;)" },
145+ {DEFAULT_SCHEMA, " tableMultiply" , {" x" , nullptr }, {{" two" , " 2" }, {nullptr , nullptr }}, R"( SELECT x * two as output_column;)" },
146+ {DEFAULT_SCHEMA, " numbers" , {" x" , nullptr }, {{" z" , " 0" }, {nullptr , nullptr }}, R"( SELECT * as number FROM generate_series(z,x-1);)" },
96147 {nullptr , nullptr , {nullptr }, {{nullptr , nullptr }}, nullptr }
97148 };
98149// clang-format on
0 commit comments