Repository navigation
user-relation-expression-projection-and-purge-exclusion - #837
Merged
Merged
Conversation
Fixes #798: a SELECT over a user space table or materialized view bound every expression projection (CASE, function call, concatenation) to the catalogued column it referenced, so the expression collapsed to the bare column. The shared catalogue column was also mutated in place by alias and qualifier decoration, which made sibling columns disappear. Only bare column references now bind to the catalogue, and a copy is decorated. Fixes #799: PURGE, PURGE CONSERVATIVE and PURGE EPHEMERAL emptied or dropped the physical tables behind user space tables and materialized views. Garbage collection and purge now exclude relations registered in "__iql__.tables" and "__iql__.materialized_views" on both sqlite and postgres backends. Adds a robot scenario covering both behaviours. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8Boy4k8xPfMwnCUV8D39K
general-kroll-4-life
approved these changes
Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two fixes for user space tables and materialized views.
#798, expressions in a SELECT over a user space table or materialized view were not evaluated. The projection rewrite in
internal/stackql/astvisit/query_rewriting.golooked up the column referenced by each select expression in the relation's catalogue and used that catalogued column as the projection. For a bare column reference that is right. For aCASE, function call or concatenation it collapsed the expression to the referenced column, soCASE WHEN enabled = 'true' ...rendered as"enabled" AS "status". The catalogued column object is also shared across the statement, and alias / qualifier decoration mutated it in place, which is why a sibling plain column could vanish ("repo" AS "evidence", "repo" AS "evidence"). Now only a bare column reference binds to the catalogue, the catalogue entry is copied before decoration, and expressions fall through to the existing decorated-expression path.physical_table_indirect.goalso no longer matches an empty alias against an empty lookup name (the materialized view indirect already had this guard); both files carry a file-levelduplsuppression since they are now structurally identical, mirroring the existingphysical_table_dto.goprecedent.#799, PURGE emptied or dropped materialized views and user space tables. The garbage collection and purge queries in
sql_system/sqlite.goandsql_system/postgres.goselected every non-control table. They now exclude relations registered in__iql__.tablesand__iql__.materialized_views, soPURGE,PURGE CONSERVATIVEandPURGE EPHEMERALonly touch provider cache tables. Postgres matches both the bare table name andschema.tablefor the export-namespace case.PURGE CACHEwas already scoped to the analytics namespace and is unchanged.Design notes: no new types or exported surface; the one helper added is unexported and local to the rewrite visitor. Six files touched, one of which is the lint suppression only.
Type of change
Issues referenced.
Evidence
Reproduction from the issues against a file backend, after the fix:
New robot scenario
Select Expressions Over User Space Table and Materialized View Survive Purgeinstackql_mocked_from_cmd_line.robotcovers CASE, function and concatenation projections over a user space table and a materialized view, thenpurge conservativeand globalpurge, asserting row counts survive. It is written with portable SQL so it also runs on the postgres backend in CI.Local results (native, sqlite embedded):
go test -timeout 1200s ./...: pass.golangci-lint run: 0 issues.--test "*View*" --test "*Table*" --test "*Materialized*" --test "*Purge*" --test "*Userspace*"onstackql_mocked_from_cmd_line.robot: 149 of 151 pass. The two failures arePreview Rows Are Emitted Throughout The Runand its OTel variant, failing in the Python harness withAttributeError: 'float' object has no attribute 'total_seconds'under the locally available robotframework 7.5 rather than the pinned 7.0.1; unrelated to this change.Checklist:
Variations
Platforms: only linux/amd64 with the embedded sqlite backend was exercised locally. The postgres GC and purge SQL changes compile and follow the existing query shape but were not run against a live postgres here; the docker postgres_tcp robot jobs in CI exercise the new scenario on that backend.
Tech Debt
None added.
materialized_view_indirect.goandphysical_table_indirect.gowere already near-duplicates; this PR makes the lookup logic identical and records that with a file-levelduplsuppression rather than consolidating the two, which is out of scope for a bug fix.🤖 Generated with Claude Code
https://claude.ai/code/session_01L8Boy4k8xPfMwnCUV8D39K
Generated by Claude Code