diff --git a/packages/mosaic/sql/src/ast/node.ts b/packages/mosaic/sql/src/ast/node.ts index 74fc0904c..201820c1c 100644 --- a/packages/mosaic/sql/src/ast/node.ts +++ b/packages/mosaic/sql/src/ast/node.ts @@ -9,13 +9,17 @@ export function isNode(value: unknown): value is SQLNode { export class SQLNode { /** The SQL AST node type. */ readonly type: string; + /** The SQL dialect. */ + readonly dialect: string; /** * Instantiate a SQL AST node. * @param type The SQL AST node type. + * @param dialect The SQL dialect (defaults to "duckdb"). */ - constructor(type: string) { + constructor(type: string, dialect: string = "duckdb") { this.type = type; + this.dialect = dialect; } /** diff --git a/packages/mosaic/sql/src/functions/list.ts b/packages/mosaic/sql/src/functions/list.ts index 330a4e647..473e0269a 100644 --- a/packages/mosaic/sql/src/functions/list.ts +++ b/packages/mosaic/sql/src/functions/list.ts @@ -33,7 +33,16 @@ export function listContains( list1: ExprValue | ExprValue[], element: ExprValue, ) { - return fn("list_contains", asList(list1), asLiteral(element)); + switch (this.dialect) { + case "clickhouse": + return fn("has", asList(list1), asLiteral(element)); + case "starrocks": + return fn("array_contains", asList(list1), asLiteral(element)); + case "bigquery": + return "element IN UNNEST(list1)"; + default: + return fn("list_contains", asList(list1), asLiteral(element)); + } } /** @@ -46,7 +55,16 @@ export function listHasAll( list1: ExprValue | ExprValue[], list2: ExprValue | ExprValue[], ) { - return fn("list_has_all", asList(list1), asList(list2)); + switch (this.dialect) { + case "clickhouse": + return fn("hasAll", asList(list1), asList(list2)); + case "starrocks": + return fn("array_contains_all", asList(list1), asList(list2)); + case "bigquery": + return "(SELECT COUNT(l2) = ARRAY_LENGTH(list2) FROM UNNEST(list1) AS l1 JOIN UNNEST(list1) AS l2 ON l1 = l2)"; + default: + return fn("list_has_all", asList(list1), asList(list2)); + } } /** @@ -59,5 +77,14 @@ export function listHasAny( list1: ExprValue | ExprValue[], list2: ExprValue | ExprValue[], ) { - return fn("list_has_any", asList(list1), asList(list2)); + switch (this.dialect) { + case "clickhouse": + return fn("hasAny", asList(list1), asList(list2)); + case "starrocks": + return fn("arrays_overlap", asList(list1), asList(list2)); + case "bigquery": + return "EXISTS(SELECT * FROM UNNEST(list1) AS l1 WHERE l1 IN UNNEST(list2))"; + default: + return fn("list_has_any", asList(list1), asList(list2)); + } }