Skip to content

fix(aggregate): refuse min and max of $permissions as of an array attribute - #1027

Merged
abnegate merged 1 commit into
mainfrom
fix/aggregate-permissions
Oct 16, 2026
Merged

abnegate merged 1 commit into
mainfrom
fix/aggregate-permissions

Conversation

@abnegate

Copy link
Copy Markdown
Member

What

8.3.0 staging QA found that min() and max() on $permissions were accepted and returned [], a lexicographic extreme of the stored JSON text. min() and max() on any declared array attribute are refused with a query error.

The aggregate validator built its set of unorderable attributes from the declared attributes only. $permissions is an internal attribute stored as a JSON list, so it slipped through. MySQL, MariaDB and SQLite compared the encoded text, and PostgreSQL failed in the engine on jsonb with a different error.

The internal attributes stored as JSON (those carrying the json filter, which is $permissions) are now unorderable, the same as array attributes. This also applies under a join alias (alias.$permissions).

Other aggregates are kept consistent with array attributes:

  • sum, avg, the deviations and variances, and bitAnd/bitOr/bitXor were already refused for $permissions ("requires a numeric attribute that is not an array"). The tests now pin this.
  • count and countDistinct keep counting $permissions, as they count an array attribute.

Regression tests

Test Adapters origin/main this PR
AggregationTests::testPermissionsAreAggregatedAsAnArrayAttribute: min/max/sum/avg on tags[] and $permissions, joined other.$permissions, count/countDistinct of $permissions MySQL, MariaDB, SQLite fail: the query shape was accepted (min of $permissions) pass
Postgres fail: engine error Query applies a function or operator the attribute type does not support instead of the validator's refusal pass
Mongo, Memory, Redis pass (clean Exception\Query refusal guard, as these adapters do not aggregate) pass
Unit\Validator\QueryValidationTest::testMinAndMaxRefuseValuesWithoutAnOrder: max/min of $permissions, max of joined it.$permissions n/a fail ×3 pass
Unit\Validator\QueryValidationTest::testTheAggregateValidatorRefusesExtremaOfUnorderedTypes: $permissions with arrays; count/countDistinct accepted; sum/avg/bitOr refused n/a fail pass

Run locally against Docker: the full MySQL, MariaDB, Postgres and SQLite adapter suites pass, as do the full unit suite, Pint and PHPStan.

API repro (Appwrite)

GET /v1/tablesdb/{db}/tables/{t}/rows?queries[]= with max("$permissions") (or min) → 400 general_query_invalid, message Invalid query: Aggregate max requires an attribute whose values are ordered, not an array, object, boolean, spatial or vector one: $permissions. Before this PR it returned 200 with []. count("$permissions") → 200 with the row count.

🤖 Generated with Claude Code

…ribute

$permissions is stored as a JSON list, but the aggregate validator built
its map of unorderable attributes from the declared attributes only, so
min() and max() of $permissions were accepted. MariaDB, MySQL and SQLite
then compared the encoded text and answered a lexicographic extreme such
as `[]`, and PostgreSQL failed in the engine on jsonb, while min() and
max() of any declared array attribute are refused with a query error.

The internal attributes stored as JSON (those with the json filter, which
is $permissions) are now unorderable as array attributes are, under a
join alias too. sum(), avg(), the deviations and the bitwise aggregates of
$permissions were already refused as for any array; count() and
countDistinct() keep counting it, as they count an array attribute.

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

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

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 42 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: 6a930a92-8c9e-42e4-bfed-b368d2e8cf26
📥 Commits

Reviewing files that changed from the base of the PR and between 17042a6 and b285062.

📒 Files selected for processing: 3
  • src/Database/Validator/Query/Aggregate.php
  • tests/e2e/Adapter/Scopes/AggregationTests.php
  • tests/unit/Validator/QueryValidationTest.php
  • 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.

@abnegate
abnegate merged commit 165cada into main Oct 16, 2026
24 checks passed
@abnegate
abnegate deleted the fix/aggregate-permissions branch October 16, 2026 03:31
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