Skip to content

feat(duckdb): Add transpilation support for TRY_CAST#7672

Closed
fivetran-amrutabhimsenayachit wants to merge 1 commit into
mainfrom
RD-1069322-try-cast
Closed

feat(duckdb): Add transpilation support for TRY_CAST#7672
fivetran-amrutabhimsenayachit wants to merge 1 commit into
mainfrom
RD-1069322-try-cast

Conversation

@fivetran-amrutabhimsenayachit
Copy link
Copy Markdown
Collaborator

Snowflake's TRY_CAST is semantically richer than DuckDB's: it uses AUTO date/time format detection (accepting ISO-8601, MM/DD/YYYY, and DD-Mon-YYYY), enforces string length constraints on CHAR(n)/VARCHAR(n), accepts ON/OFF as boolean values, and supports interval arithmetic. DuckDB's native TRY_CAST handles only ISO-8601 dates, silently ignores length constraints, rejects ON/OFF, and has no string-to-interval casting. A naive passthrough transpilation produces silently wrong results — not errors — making the gap invisible to users.

This PR fixes it, except for the NANOSECOND time unit for which DuckDb has no support at all.

@github-actions
Copy link
Copy Markdown
Contributor

SQLGlot Integration Test Results

Comparing:

  • this branch (sqlglot:RD-1069322-try-cast, sqlglot version: RD-1069322-try-cast)
  • baseline (main, sqlglot version: 0.0.1.dev1)

By Dialect

dialect main sqlglot:RD-1069322-try-cast transitions links
bigquery -> bigquery 24647/24652 passed (100.0%) 23497/23497 passed (100.0%) No change full result / delta
bigquery -> duckdb 867/1154 passed (75.1%) 0/0 passed (0.0%) Results not found full result / delta
duckdb -> duckdb 5823/5823 passed (100.0%) 5823/5823 passed (100.0%) No change full result / delta
snowflake -> duckdb 1123/1862 passed (60.3%) 1124/1862 passed (60.4%) 1 fail -> pass full result / delta
snowflake -> snowflake 65190/65243 passed (99.9%) 65190/65243 passed (99.9%) No change full result / delta
databricks -> databricks 1370/1370 passed (100.0%) 1370/1370 passed (100.0%) No change full result / delta
postgres -> postgres 6042/6042 passed (100.0%) 6042/6042 passed (100.0%) No change full result / delta
redshift -> redshift 7101/7101 passed (100.0%) 7101/7101 passed (100.0%) No change full result / delta

Overall

main: 113247 total, 112163 passed (pass rate: 99.0%), sqlglot version: 0.0.1.dev1

sqlglot:RD-1069322-try-cast: 110938 total, 110147 passed (pass rate: 99.3%), sqlglot version: RD-1069322-try-cast

Transitions:
1 fail -> pass

Dialect pair changes: 0 previous results not found, 1 current results not found

✅ 65 test(s) passed

Comment on lines +4405 to +4410
return self.sql(
exp.case(exp.func("LOWER", src.copy()))
.when(exp.Literal.string("on"), exp.true())
.when(exp.Literal.string("off"), exp.false())
.else_(exp.TryCast(this=src.copy(), to=to))
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's reuse _to_boolean_sql here.

exp.cast(
exp.func("TRY_STRPTIME", src.copy(), exp.Literal.string(f)), "DATE"
)
for f in self._TRYCAST_DATE_FORMATS
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the only DATE_FORMATS that duckdb supports outside the ISO ?

this=exp.TryCast(this=src.copy(), to=to),
expressions=[
exp.func("TRY_STRPTIME", src.copy(), exp.Literal.string(f))
for f in self._TRYCAST_TIMESTAMP_FORMATS
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src, to, to_type = expression.this, expression.to, expression.to.this

# INTERVAL: TRY_CAST to INT first (preserves NULL for non-numeric input), then call to_*().
if isinstance(to_type, exp.Interval):
Copy link
Copy Markdown
Collaborator

@geooo109 geooo109 May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make something like:

if ...:

elif ...:

and lastly: 

return super().trycast_sql(expression)

@geooo109
Copy link
Copy Markdown
Collaborator

@fivetran-amrutabhimsenayachit let's break this PR into smaller ones, tackling the problem incrementally.

@geooo109 geooo109 closed this May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants