Skip to content

Add JSONB-key range filters#82

Draft
HodaSalim wants to merge 1 commit into
mainfrom
jsonb-range-filters
Draft

Add JSONB-key range filters#82
HodaSalim wants to merge 1 commit into
mainfrom
jsonb-range-filters

Conversation

@HodaSalim
Copy link
Copy Markdown

Summary

Implements #80. Lets a range (a...b) target a key inside a :jsonb column, with the cast type declared per key. Also resolves a latent bug where a ... inside a jsonb value was mis-parsed as a whole-string Range, producing broken SQL.

  • New keys: option on filter_on for :jsonb filters, declaring the cast type per key. Accepts either a Hash ({ price: :decimal }) or a callable (->(key) { ... }) resolved per request (covers dynamic keys like custom-field definition IDs).
  • Range syntax uses the existing JSON object form: ?filters[metadata]={"price":"10...100"}(metadata->>'price')::numeric BETWEEN 10 AND 100 (inclusive; bounds are bind params, key is escaped).
  • Supported range key types: :int, :decimal, :date, :datetime, :time (casts: ::integer, ::numeric, ::date, ::timestamptz, ::time).
  • Validation: a range on an undeclared/unsupported key type, or with bounds that don't cast to the declared type, yields a clear validation error instead of broken SQL.
  • Bug fix: whole-string jsonb values containing ... are no longer treated as a Range.

Existing JSONB behavior (array containment, key equality, null handling) is unchanged.

Key changes

  • filter_on / Filter / Parameter: thread keys:; add Parameter#key_type and #range_key?.
  • ValueParser: per-key range parsing; guard whole-string range detection for jsonb objects.
  • WhereHandler: apply_jsonb_range branch with type-driven cast.
  • TypeValidator + new ValidJsonbValidator: declared-key-type and bounds validation.
  • Docs (docs/filters.md), CHANGELOG.md, version bump 1.0.11.1.0.

Test plan

  • bundle exec rake test — 124 runs, 220 assertions, 0 failures, 0 errors
  • Per-key range parsing produces Range for declared keys; non-range/whole-string jsonb unchanged (value_parser_test)
  • Range branch emits (...)::<cast> BETWEEN ? AND ? with bound params for each key type (where_handler_test)
  • key_type resolves from Hash and callable (parameter_test)
  • Range on undeclared/invalid key → validation error; valid range → no error (filter_validator_test)
  • Controller integration exercises the parse path (SQL stubbed, as in existing jsonb tests) (controller_test)

Note: CI has no PostgreSQL, so generated SQL is asserted as fragments via mocks (same constraint the existing jsonb tests live under) rather than executed against a real DB.

Made with Cursor

Lets a range (a...b) target a key inside a :jsonb column, with the cast
type declared per key via a new keys: option on filter_on (accepting a
Hash or a per-request callable). Resolves the latent bug where a "..."
inside a jsonb value was mis-parsed as a whole-string Range, producing
broken SQL.

Supported range key types: :int, :decimal, :date, :datetime, :time.
A range on an undeclared/unsupported key type now yields a clear
validation error instead of broken SQL. Closes #80.

Co-authored-by: Cursor <cursoragent@cursor.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.

1 participant