Skip to content

Commit a99ba1f

Browse files
feat(duckDB): Cast inputs (BLOB → VARCHAR) for duckDB STARTS_WITH
1 parent c8b0129 commit a99ba1f

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

sqlglot/dialects/duckdb.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,31 @@ def objectinsert_sql(self, expression: exp.ObjectInsert) -> str:
11801180

11811181
return self.func("STRUCT_INSERT", this, kv_sql)
11821182

1183+
def startswith_sql(self, expression: exp.StartsWith) -> str:
1184+
this = expression.this
1185+
expr = expression.expression
1186+
1187+
if not this.type:
1188+
from sqlglot.optimizer.annotate_types import annotate_types
1189+
1190+
this = annotate_types(this, dialect=self.dialect)
1191+
1192+
if not expr.type:
1193+
from sqlglot.optimizer.annotate_types import annotate_types
1194+
1195+
expr = annotate_types(expr, dialect=self.dialect)
1196+
1197+
# DuckDB's starts_with only accepts VARCHAR, not BLOB
1198+
if this.is_type(exp.DataType.Type.BINARY):
1199+
expression.this.replace(exp.cast(expression.this, exp.DataType.Type.VARCHAR))
1200+
1201+
if expr.is_type(exp.DataType.Type.BINARY):
1202+
expression.expression.replace(
1203+
exp.cast(expression.expression, exp.DataType.Type.VARCHAR)
1204+
)
1205+
1206+
return self.func("STARTS_WITH", expression.this, expression.expression)
1207+
11831208
def unnest_sql(self, expression: exp.Unnest) -> str:
11841209
explode_array = expression.args.get("explode_array")
11851210
if explode_array:

tests/dialects/test_bigquery.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,21 @@ def test_bigquery(self):
11801180
"spark": "CAST(a AS BINARY)",
11811181
},
11821182
)
1183+
# Test STARTS_WITH with BYTES/BLOB handling from BigQuery to DuckDB
1184+
self.validate_all(
1185+
"STARTS_WITH(CAST('foo' AS BYTES), CAST('f' AS BYTES))",
1186+
write={
1187+
"bigquery": "STARTS_WITH(CAST('foo' AS BYTES), CAST('f' AS BYTES))",
1188+
"duckdb": "STARTS_WITH(CAST(CAST('foo' AS BLOB) AS TEXT), CAST(CAST('f' AS BLOB) AS TEXT))",
1189+
},
1190+
)
1191+
self.validate_all(
1192+
"STARTS_WITH(CAST('foo' AS BYTES), b'f')",
1193+
write={
1194+
"bigquery": "STARTS_WITH(CAST('foo' AS BYTES), b'f')",
1195+
"duckdb": "STARTS_WITH(CAST(CAST('foo' AS BLOB) AS TEXT), e'f')",
1196+
},
1197+
)
11831198
self.validate_all(
11841199
"CAST(a AS NUMERIC)",
11851200
write={

0 commit comments

Comments
 (0)