Skip to content

fix(tables): filtering on built-in columns (createdAt/updatedAt/id) returns no rows - #6114

Open
serhiizghama wants to merge 2 commits into
simstudioai:mainfrom
serhiizghama:fix/filter-builtin-columns
Open

fix(tables): filtering on built-in columns (createdAt/updatedAt/id) returns no rows#6114
serhiizghama wants to merge 2 commits into
simstudioai:mainfrom
serhiizghama:fix/filter-builtin-columns

Conversation

@serhiizghama

Copy link
Copy Markdown

Closes #5920. Filtering on the built-in columns always came back empty. They live as real top-level columns on user_table_rows, but the filter builder pulled them out of the data JSONB — data->>'createdAt' is always NULL, so a numeric-coerced timestamp matched nothing and a plain date string hit the "requires a number" error (the unknown column type fell back to a numeric cast).

Routed built-in columns through a small BUILTIN_COLUMNS map that resolves the wire name to the physical column and type, so a filter references user_table_rows.created_at directly. Equality compiles to =/IN instead of JSONB containment (which can't touch a real column), and date columns cast the value to timestamptz like the existing data-column path. A user column with a colliding key still shadows the built-in.

The sort builder had the mirror image of the same bug: its createdAt/updatedAt case emitted user_table_rows.createdAt, which Postgres folds to createdat (no such column), and id fell through to data->>'id'. Both now go through the same map and reference created_at/updated_at/id.

Added tests for the built-in filter/sort SQL and the user-column shadow case. bun run type-check is clean and the table lib suite (491 tests) passes.

…row columns

id, createdAt and updatedAt are stored as top-level columns on user_table_rows, not inside the data JSONB, but the filter builder extracted them via data->>'field' (always NULL, so filters matched nothing) and the sort builder referenced user_table_rows.createdAt, which folds to a non-existent createdat. Route both through a shared BUILTIN_COLUMNS map that resolves the wire name to the real column (created_at/updated_at) and type; equality on a built-in compiles to =/IN since JSONB containment can't touch a real column. A user column with the same key still wins.
Range/equality/membership on id, createdAt, updatedAt now reference the physical column; a user column with a colliding key still falls back to the JSONB path.
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 31, 2026 1:50am

Request Review

@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes core table query SQL generation for all reads/filters on built-in columns; behavior fix is localized to sql.ts with strong test coverage, but incorrect mapping would affect row queries broadly.

Overview
Fixes empty or broken results when filtering or sorting on id, createdAt, or updatedAt. Those fields are real columns on user_table_rows, but the SQL builder treated them like JSONB keys (data->>'createdAt', etc.), so date filters never matched and sort referenced wrong names (createdAt vs created_at).

Introduces a BUILTIN_COLUMNS map (wire name → physical column + type) and a buildBuiltinFieldCondition path that generates =, IN, range comparisons with ::timestamptz for dates, and pattern operators against the top-level column—not JSONB @> containment. Sort uses the same map so created_at, updated_at, and id order correctly.

If a user-defined column shares the same id (e.g. a custom id column), it still shadows the built-in and keeps the JSONB behavior. Tests cover built-in filter/sort SQL and the shadow case.

Reviewed by Cursor Bugbot for commit 1c88779. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Corrects filtering and sorting for built-in table-row fields.

  • Maps id, createdAt, and updatedAt to their physical top-level database columns while preserving user-column shadowing.
  • Adds direct-column filter handling with appropriate timestamp casts and SQL operators.
  • Adds coverage for built-in filtering, sorting, and colliding user-column keys.

Confidence Score: 5/5

The PR appears safe to merge, with built-in filtering and sorting now targeting the correct physical columns.

The fixed identifier map selects the schema-backed columns, filter values remain parameterized, date comparisons receive the expected timestamp cast, and user-defined colliding columns retain the documented precedence.

Important Files Changed

Filename Overview
apps/sim/lib/table/sql.ts Routes built-in filters and sorts through a fixed physical-column map with bound values and type-aware timestamp casts; no actionable defect identified.
apps/sim/lib/table/tests/sql.test.ts Adds focused SQL-generation tests for built-in date/id filters, sorting, and user-column shadowing.

Reviews (1): Last reviewed commit: "test(tables): cover built-in column filt..." | Re-trigger Greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator

@TheodoreSpeaks

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.

[BUG] Filtering on built-in columns (createdAt, updatedAt) silently returns zero rows

2 participants