Skip to content

feat: implicit VARCHAR-to-numeric cast for aggregate functions#326

Merged
tekumara merged 2 commits intotekumara:mainfrom
pliable-inc:fix/implicit-varchar-aggregate-cast
Apr 11, 2026
Merged

feat: implicit VARCHAR-to-numeric cast for aggregate functions#326
tekumara merged 2 commits intotekumara:mainfrom
pliable-inc:fix/implicit-varchar-aggregate-cast

Conversation

@mattotodd
Copy link
Copy Markdown
Contributor

Problem

Snowflake implicitly casts VARCHAR columns to numeric when used in aggregate functions like SUM(), AVG(), MEDIAN(), etc. DuckDB is strict and rejects these:

Binder Error: No function matches the given name and argument types 'sum(VARCHAR)'.

This is a common pattern when data is loaded via CSV (everything comes in as VARCHAR) and then aggregated without explicit casts.

Solution

Add a numeric_agg_implicit_cast transform that wraps arguments to numeric-only aggregate functions with TRY_CAST(... AS DOUBLE), matching Snowflake's implicit coercion behavior.

  • Only applies to numeric-only aggregates: SUM, AVG, MEDIAN, VARIANCE, STDDEV, etc.
  • Does NOT affect COUNT, MIN, MAX, ARRAY_AGG, etc. which work on any type
  • Skips arguments that are already Cast/TryCast expressions (no double-wrapping)

Example

-- Input (Snowflake SQL)
SELECT SUM(amount) FROM t

-- After transform (DuckDB-compatible)
SELECT SUM(TRY_CAST(amount AS DOUBLE)) FROM t

Tests

  • Unit tests in test_transforms.py covering SUM, AVG, COUNT (unchanged), MAX (unchanged), already-cast args, and mixed queries
  • Integration test in test_fakes.py verifying end-to-end SUM/AVG on a VARCHAR column

Snowflake implicitly casts VARCHAR columns to numeric when used in
aggregate functions like SUM(), AVG(), MEDIAN(), etc. DuckDB is strict
and rejects these with a BinderError.

Add a numeric_agg_implicit_cast transform that wraps arguments to
numeric-only aggregate functions with TRY_CAST(... AS DOUBLE), matching
Snowflake's behavior. Only applies to SUM, AVG, MEDIAN, VARIANCE,
STDDEV, etc. — not COUNT, MIN, MAX, ARRAY_AGG which work on any type.
Copy link
Copy Markdown
Owner

@tekumara tekumara left a comment

Choose a reason for hiding this comment

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

thanks for the contribution!

@tekumara tekumara merged commit 3f47c30 into tekumara:main Apr 11, 2026
1 check passed
tekumara pushed a commit that referenced this pull request Apr 11, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.11.5](v0.11.4...v0.11.5)
(2026-04-11)


### Features

* implicit VARCHAR-to-numeric cast for aggregate functions
([#326](#326))
([3f47c30](3f47c30))


### Bug Fixes

* implicit VARCHAR-to-number cast matches snowflake column names
([5733c70](5733c70))


### Chores

* **deps-dev:** update snowflake-sqlalchemy requirement from ~=1.8.2 to
~=1.9.0 in the pip group across 1 directory
([#321](#321))
([b8f4ede](b8f4ede))
* **deps:** update duckdb requirement from ~=1.4.1 to ~=1.5.1
([#323](#323))
([e8f49a0](e8f49a0))
* **deps:** update sqlglot requirement from ~=29.0.1 to ~=30.2.0
([#322](#322))
([3b434fa](3b434fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: potatobot-prime[bot] <132267321+potatobot-prime[bot]@users.noreply.github.com>
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