Record mutate() expression columns in the dataset version schema - #1941
Record mutate() expression columns in the dataset version schema#1941dreadatour wants to merge 4 commits into
Conversation
Deploying datachain with
|
| Latest commit: |
7d31e6d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c7dca5e3.datachain-2g6.pages.dev |
| Branch Preview URL: | https://fix-mutate-column-schema.datachain-2g6.pages.dev |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Ensures mutate() expression columns are persisted in dataset version schemas.
Changes:
- Coerces expression columns to DataChain SQL types.
- Adds schema and cross-operation regression tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/datachain/lib/dc/datachain.py |
Normalizes expression result types during mutation. |
tests/unit/lib/test_datachain.py |
Adds persistence and composition coverage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Test failed 5 times in a row: This is weird, because I've made measurements on localhost. Import time, current branch vs
The diff is inside the noise (stdev ~15–21 ms), and the minimum — which the test asserts on — is identical. The CI failure on 3.14 is environmental: 3.14 imports ~20% slower than 3.10 (214 ms vs 177 ms in clean venvs), putting that runner at ~800–825 ms against the 800 ms cap. |
56b4aff to
afe2b9c
Compare
5552811 to
fda8c4e
Compare
afe2b9c to
1c5160e
Compare
1c5160e to
4801af9
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
tests/unit/lib/test_datachain.py:3934
- The signal→column review matrix requires
to_records, which has its own SQLType-dependent conversion path (src/datachain/lib/dc/records.py:122-125). Since this PR specifically changes these expressions from raw SQLAlchemy types toSQLType, add a record read-back here so that path is covered too.
df = chain.to_pandas()
assert df["minus"].tolist() == [0, 1]
mutate()columns built from plain SQL expressions (e.g.b=C("a") - 1) were missing from the persistedDatasetVersion.schema. The schema dict is built as{c.name: c.type.to_dict() for c in columns if isinstance(c.type, SQLType)}, and expression columns arrived with raw sqlalchemy types (INTEGER), so the filter silently dropped them.feature_schemaand the preview were correct — only the flat schema lost the column, which breaks every consumer that treats it as the column list.Minimal repro:
Before:
After:
ver.schemaincludes'b': Int64.The fix is in the mutate expression branch:
type_coercethe expression to its datachain SQLType (python_to_sql(sql_to_python(...))), the same coercion the nullable path already did. Func/window, group_by, and literal columns already carried SQLTypes, so this was the only save path producing raw types. As a side effect the physical column type is now the canonical one (ClickHouse:Int64instead ofInt32;Nullable(Int64)preserved for nullable expressions).Not every expression type is coercible on main:
python_to_sqlreturns a plain python type for enums, raises forDate/Time, and produces anArraywith an invalid item type forARRAY(Enum(...)). Coercion is therefore guarded — an expression whose type cannot be resolved to a validSQLTypekeeps its raw type and stays out of the flat schema, exactly as on main today. Pinned by tests: an enum-cast column (reads work pre-save, save warns, column absent from.schema, signal dropped on reload), aDatecast, and anARRAY(Enum)cast.🤖 Co-authored by Claude Code and ChatGPT