Skip to content

fix(query): refuse a nested path on an attribute that holds no nested values - #1022

Merged
abnegate merged 3 commits into
mainfrom
qfix-unknown-column
Oct 15, 2026
Merged

abnegate merged 3 commits into
mainfrom
qfix-unknown-column

Conversation

@abnegate

@abnegate abnegate commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Problem

Filter and Select treat any dotted attribute as a relationship path and validate only its first segment. On a plain attribute, equal('name.x', [...]) or select(['name.x']) passes validation and reaches the adapter, which names a column that does not exist:

Which shapes reach the engine today, with a string attribute s:

Shape Before After
equal('s.x') (and every filter, count) accepted, engine error refused
select(['s.x']) accepted, engine error refused
orderAsc('s.x') refused unchanged
aggregate / groupBy('s.x') refused (exact schema keys only) unchanged
equal('o.x') on an object, equal('rel.name') on a relationship, alias.column on a join accepted unchanged

Fix

A dotted path passes only when its base is a relationship or object attribute, or a join alias. Otherwise the validator refuses it (Cannot query nested attribute on: s / Cannot select nested attribute on: s), so find/count throw QueryException before the adapter runs. Schemaless adapters (no DefinedAttributes) keep accepting any path. An aggregation select keeps its existing ungrouped-select message.

Tests

  • Unit: FilterTest (plain attribute refused; relationship, object and schemaless accepted), SelectTest (plain refused, object accepted). DocumentQueriesTest::test_valid_queries asserted select(['price.relation']) on a double was valid; it now asserts the refusal. The new refusal cases fail without the fix.
  • E2E: DocumentTests::testNestedPathOnAPlainAttributeIsAnInvalidQuery runs filter, count and select on every adapter with defined attributes (MariaDB, MySQL, Postgres, SQLite, MongoDB, and the shared-table/pool/mirror variants). Without the fix, the SQL adapters throw NotFound and MongoDB returns an empty page.
  • Pint and both PHPStan configs pass locally. Locally the unit suite fails only SwooleAbsentTest (no Redis extension) and BaseAdapterStateTest::testAKeyThePatternEngineCannotFilterIsAnError, both outside this change.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Queries can no longer filter or select nested paths on plain attributes when attribute support is enabled. Nested paths on relationship and object attributes remain supported.
    • Invalid nested queries now return a clear error identifying the attribute that cannot be queried.

abnegate and others added 2 commits October 16, 2026 00:02
… values

The filter and select validators treated any dotted attribute as a
relationship path and checked only its first segment. On a plain attribute,
equal('name.x') or select(['name.x']) passed validation and reached the
engine, which named a column that does not exist: MySQL 1054 and
PostgreSQL 42703 surfaced as NotFound('Attribute not found'), so callers
answered 404 or 500 for a malformed query, and MongoDB silently matched
nothing.

A dotted path now passes only when its base is a relationship or an object
attribute, or a join alias, and is otherwise refused as an invalid query
before it reaches the adapter. Order already refused nested paths, and
aggregate and group-by accept only exact schema keys. Schemaless adapters
keep accepting any path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 48 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: utopia-php/database/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b2187988-277f-42bf-97ff-5c0fcb1c44e6
📥 Commits

Reviewing files that changed from the base of the PR and between f114457 and 384369e.

📒 Files selected for processing: 1
  • tests/e2e/Adapter/Scopes/DocumentTests.php

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: utopia-php/database/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a8512c0c-0119-4a4f-835a-b716f4622819
📥 Commits

Reviewing files that changed from the base of the PR and between 0555ec9 and f114457.

📒 Files selected for processing: 6
  • src/Database/Validator/Query/Filter.php
  • src/Database/Validator/Query/Select.php
  • tests/e2e/Adapter/Scopes/DocumentTests.php
  • tests/unit/Validator/DocumentQueriesTest.php
  • tests/unit/Validator/Query/FilterTest.php
  • tests/unit/Validator/Query/SelectTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Query validation now rejects nested filter and selection paths when the base schema attribute is plain. Relationship and object attributes remain nestable. Filters allow nested paths when defined-attribute support is disabled.

Changes: Nested Path Validation

Layer / File(s) Summary
Filter path validation
src/Database/Validator/Query/Filter.php, tests/unit/Validator/Query/FilterTest.php
Filter validation rejects nested paths under plain attributes when attribute support is enabled. Tests cover plain, relationship, and object attributes, and the disabled-support case.
Selection path validation
src/Database/Validator/Query/Select.php, tests/unit/Validator/Query/SelectTest.php, tests/unit/Validator/DocumentQueriesTest.php, tests/e2e/Adapter/Scopes/DocumentTests.php
Selection validation rejects nested paths under plain attributes and accepts object attributes. Unit and end-to-end tests cover nested selection and query behavior.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Suggested reviewers: fogelito

Merge Risk: ⚪ Minimal · up to f1144

The changed validation rejects invalid nested paths before they reach adapters. No actionable merge-blocking issue remains from the reviewed changes.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: rejecting nested paths on attributes that cannot contain nested values.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abnegate
abnegate merged commit b92964b into main Oct 15, 2026
24 checks passed
@abnegate
abnegate deleted the qfix-unknown-column branch October 15, 2026 11:28
ArnabChatterjee20k pushed a commit to ArnabChatterjee20k/appwrite that referenced this pull request Oct 15, 2026
utopia-php/database#1022 refuses a filter or select on a dotted path under
a plain attribute before the adapter runs, on every adapter. Before it the
SQL engines answered 404 or 500 and MongoDB an empty 200.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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