Skip to content

feat!: support utopia-php/database 8 and PHP 8.5 - #42

Closed
abnegate wants to merge 12 commits into
mainfrom
feat-query-lib
Closed

abnegate wants to merge 12 commits into
mainfrom
feat-query-lib

Conversation

@abnegate

Copy link
Copy Markdown
Member

Summary

  • Carries and supersedes feat: add ordinal event dimension column #40 (feat: add ordinal event dimension column): the ordinal dimension now comes from Metric, through the 8.0 schema API, and feat: add ordinal event dimension column #40 is closed in favour of this PR.
  • usage moves to utopia-php/database 8 and PHP 8.5, to ship as 0.17.0. appwrite and cloud require
    utopia-php/usage: ^0.16.4, and every 0.16.x requires utopia-php/database: ^7.0.0, so database 8.0.0
    (Use query lib database#823) cannot be installed next to usage until a usage release requires it. This PR is that release.
  • The Database adapter builds its collection through the 8.0 schema API. setup() calls
    createCollection(new Collection(id: …, attributes: […], indexes: […])) instead of the removed
    createCollection(string $id, array $attributes, array $indexes). The definitions still come from
    Metric::getEventSchema() and Metric::getEventIndexes(), now converted with Attribute::fromArray() and
    Index::fromArray() (SQL::getAttributeDocuments() / getIndexDocuments() return those models, which are still
    Documents); the adapter's own type and ordinal columns use Attribute::string() and Index::key().
  • contains() compiles through containsString(). utopia-php/query 0.6 deprecates the contains() factory, which
    raises E_USER_DEPRECATED on PHP 8.4+. usage's contains is a substring match and every column in the collection is a
    scalar, so containsString() is the same query; containsAny() keeps its own factory.
  • PHP 8.5. "php": ">=8.5" (database 8's own minimum); the test image builds from php:8.5.8-cli-alpine and
    composer:2.8, the tags the database image uses, and still installs pdo_mysql.
  • Nothing else moves. UsageQuery, the Utopia\Query\Method handling and the ClickHouse adapter are unchanged; main
    already speaks Method throughout.

The collection is unchanged

  • On MariaDB, SHOW CREATE TABLE for the collection this branch creates on database 8 is byte-for-byte the table 0.16.5
    creates on database 7.0.0: 51 columns and 27 indexes, including the path(255), accept(255) and queryKeys(255)
    prefix indexes.
  • The stored metadata matches 0.16.5's on every field 0.16.5 stored, in the same order: $id, type, size,
    required, signed, array, filters and format for all 51 attributes; $id, type, attributes, lengths and
    orders for all 27 indexes; create("any") and documentSecurity: true on the collection. The only differences are
    what the 8.0 models always store (key, default: null, formatOptions: [], ttl: 1) and the ClickHouse-only
    indexType hint, which database 7 kept verbatim in the index metadata and database 8's Index model does not carry.
    The Database adapter never read it; the ClickHouse adapter still reads it from Metric.
  • DatabaseTest::testSetupCreatesTheCollection0165Created pins this. It runs setup() in a fresh namespace and compares
    getCollection() attribute by attribute and index by index against the array definitions 0.16.5 passed to
    createCollection(). Before the port, the whole DatabaseTest class errors against database 8:
    createCollection(): Argument #1 ($collection) must be of type Utopia\Database\Collection, string given.
  • Upgrading keeps an existing collection: on database 8 this branch reuses a collection that 0.16.5 created on database
    7. setup() leaves it alone, and writes, find, sum, gauge getTotal, count, purge and healthCheck all work
    against it.

CHANGELOG (0.17.0, unreleased)

  • Breaking: requires PHP 8.5 and utopia-php/database 8. The Docker test image builds on php:8.5.8-cli-alpine.
  • Changed: the Database adapter creates its collection through the utopia-php/database 8 schema API (Collection,
    Attribute and Index models). The collection is unchanged, and setup() still leaves an existing collection alone,
    so a collection created by 0.16 is reused as it is.
  • Changed: SQL::getAttributeDocuments() and SQL::getIndexDocuments() return Utopia\Database\Attribute and
    Utopia\Database\Index models, which are still Documents. The index models no longer carry the ClickHouse-only
    indexType hint; the ClickHouse adapter reads it from Metric::getEventIndexes() / Metric::getGaugeIndexes() as
    before.
  • Changed: the Database adapter compiles contains() through containsString() instead of the deprecated
    contains() factory. Matching is unchanged: a substring match on the column.

Test plan

  • Full suite in docker compose on the php:8.5.8-cli-alpine image against utopia-php/database
    dev-feat-query-lib (2034b6a0a): OK (379 tests, 1724 assertions)
  • Same suite on the 8.5 image before the port, with database 7.0.0 still locked: OK (378 tests, 1718 assertions)
  • DatabaseTest with the database library swapped for each in-flight Use query lib database#823 fix branch (39
    branches on top of 482e752): 42 of 42 pass on every one, and on every one the MariaDB table and the stored metadata
    match what 0.16.5 creates
  • composer lint (Pint) and composer check (PHPStan, level max): clean

Release

  • "utopia-php/database": "dev-feat-query-lib as 7.0.0" is temporary. A follow-up commit on this branch switches to
    "utopia-php/database": "8.*", adds the 0.17.x-dev branch alias for dev-feat-query-lib and dev-main, and sets
    minimum-stability: dev with prefer-stable: true until database 8.0.0 is tagged. After that tag: restore
    minimum-stability: stable, lock database 8.0.0, merge, tag 0.17.0.

Notes

  • On PHP 8.5 the suite prints about 4,700 deprecation notices from the ClickHouse test helpers
    (ReflectionMethod::setAccessible() / ReflectionProperty::setAccessible(), deprecated in 8.5) and a few from tests
    that call Query::contains(). They come from test code only; nothing under src/ raises one, and PHPUnit 9 does not
    fail on them.
  • origin/codex/query-method-constants (0afa7a8) is superseded and not included: main already compares against the Method enum everywhere and deliberately removed the UsageQuery helpers it patched.

🤖 Generated with Claude Code

abnegate and others added 5 commits September 24, 2026 05:04
utopia-php/database 8 requires PHP 8.5, so usage has to run on 8.5 before
it can take the 8.0 schema API. The image moves to php:8.5.8-cli-alpine and
the vendor stage to composer:2.8, the same tags the database image builds
from; the vendor stage already installs with --ignore-platform-reqs and the
final stage keeps pdo_mysql.

On its own this changes nothing else: the full suite passes on the 8.5
image against the locked utopia-php/database 7.0.0 (378 tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
appwrite and cloud require utopia-php/usage ^0.16.4, and every 0.16.x
requires utopia-php/database ^7.0.0, so database 8.0.0 cannot be installed
next to usage until a usage release requires it. Database 8 removed the
createCollection(string $id, array $attributes, array $indexes) signature
this adapter called, so setup() now builds the collection from Collection,
Attribute and Index models.

The definitions still come from Metric's schema arrays, converted with
Attribute::fromArray() and Index::fromArray(), so the collection is the one
0.16.5 created: the MariaDB table is identical, and the stored metadata
matches on every field 0.16.5 stored. The only difference is the
ClickHouse-only indexType hint, which database 7 kept verbatim in the index
metadata and the 8.0 Index model does not carry; this adapter never read
it. testSetupCreatesTheCollection0165Created pins the equivalence field by
field. Before the port, every DatabaseTest errors against database 8
because setup() cannot create the collection.

contains() compiles through containsString(): utopia-php/query 0.6
deprecates the contains() factory, and every column in this collection is
a scalar, so it is the same substring match.

The database constraint is a temporary root alias of dev-feat-query-lib;
the 8.* constraint and the 0.17.x-dev branch alias follow once database
publishes its own branch alias.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.17.0 is the first usage release that installs next to
utopia-php/database 8: it requires PHP 8.5 and database 8, and the
Database adapter builds the same collection through the 8.0 schema API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lock now points at d82a7ec54, the head the port's test matrix was
run against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gauges already split multi-node resources on ordinal. Counters such as
dedicated-database inbound, outbound and compute need the same column so
a chart can tell members apart. setup() adds it to existing event tables.
The daily MV stays grouped on resource identity only, so billing still
sums every member.

Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit 1dc2314)
@abnegate abnegate mentioned this pull request Sep 24, 2026
3 tasks done
@greptile-apps

greptile-apps Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[High risk] Upgrades core database library and PHP runtime.

The PR appears safe to merge based on the current changes and resolved prior findings.

Summary

The PR prepares usage for database 8 and PHP 8.5, adds event replica ordinals, and updates the ClickHouse tests to exercise observable dimension behavior.

  • The database adapter now creates collections with database 8 schema models and uses containsString().
  • The dependency requirement and branch aliases replace the temporary database 7 alias.
  • The latest changes replace a source-derived dimension test with explicit round-trip fixtures.

Reviews (7) · Last reviewed commit: "test(clickhouse): check event dimensions..."

Comment thread composer.json Outdated
Comment thread tests/Usage/Adapter/DatabaseTest.php
abnegate and others added 3 commits September 24, 2026 21:47
usage 0.16.x requires utopia-php/database ^7.0.0, so database 8.0.0 cannot
be installed next to usage in appwrite or cloud until a usage release asks
for 8. us-01 ported the code behind a temporary "dev-feat-query-lib as
7.0.0" root alias, which also claims a version below database's current
7.3.12 release. Requiring 8.* instead resolves through the branch's own
8.0.x-dev alias today and through the 8.0.0 tag once it exists, with no
root alias to unwind.

The branch alias for dev-feat-query-lib and dev-main lets consumers require
this work before 0.17.0 is tagged. minimum-stability dev with prefer-stable
true is needed only while 8.0.x-dev is untagged; stable is restored with the
tag. The remaining constraint edits are wildcards for the same versions, and
README's requirement line follows "php": ">=8.5".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PR #42 conflicted with main after #43 moved usage to utopia-php/client
0.5's names, so GitHub ran no CI on it and it could not merge.

Conflicts:
- composer.json: both sides edited the require block. Kept this branch's
  file (database 8.*, PHP 8.5, wildcard constraints, dev stability with
  prefer-stable, the 0.17.x-dev branch alias) and took main's
  "utopia-php/client": "^0.5" line as main wrote it.
- composer.lock: both sides changed the content hash. Rebuilt from this
  branch's lock with a partial update of utopia-php/client only, so
  client moves 0.4.3 -> 0.5.1 (the same entry as main's lock) and no
  other package moves; database stays dev-feat-query-lib 8b716e3c1c
  through its 8.0.x-dev alias. With -W, composer/semver would also have
  moved (3.4.4 -> 3.5.0), which client 0.5 does not need.

src/Usage/Adapter/ClickHouse.php merged cleanly and takes main's
Utopia\Client\Client import: client 0.5 moved the class, and the old
Utopia\Client name is only an alias until client's next major (appwrite's
in-repo packages/client, which replaces utopia-php/client there, has no
such alias).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge of main brought "utopia-php/client": "^0.5" and the
Utopia\Client\Client import, so the 0.17.0 entry's claim that client is
written as the 0.4.* wildcard and resolves to the same version no longer
held. The wildcard line now names the three constraints it still covers,
and a separate line records the client 0.5 requirement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tests/Usage/Adapter/ClickHouseColumnTypeTest.php Outdated
abnegate and others added 3 commits September 25, 2026 21:23
The merge of main (da77966) took main's "utopia-php/client": "^0.5"
line as main wrote it, so the branch had a caret constraint again after
24ace64 wrote every constraint as a wildcard. For a 0.x version ^0.5
and 0.5.* are the same range (>=0.5.0 <0.6.0): client stays on 0.5.1
and the lock changes only its content-hash. The 0.17.0 CHANGELOG line
names the constraint, so it follows.

phpunit/phpunit keeps ^9.5, the one range left, because no wildcard
expresses >=9.5 <10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The train wrote the constraints it changed as wildcards under a house
rule that has since been withdrawn: constraints are carets again.
psr/http-client, utopia-php/client, utopia-php/cache and phpstan/phpstan
take main's (and 0.16.6's) form again, ^1.0, ^0.5, ^4.0 and ^2.0. For
client this undoes 6a39ba1, which had rewritten main's ^0.5 as 0.5.*.
utopia-php/database, which the train moved to 8, takes the caret of that
range, ^8.0.

Each caret is the same range as the wildcard it replaces, and every
locked version satisfies it (database through its 8.0.x-dev branch
alias), so composer update --lock modifies nothing and the lock changes
only its content-hash.

The 0.17.0 CHANGELOG spells database and client as carets and drops the
bullet that called the other three constraints wildcards: they equal
0.16.6's again. utopia-php/query keeps main's own 0.6.*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ClickHouseColumnTypeTest reflected into the adapter's private
getColumnType() and compared the type string of 22 dimension columns,
the ordinal on events and gauges among them. It never touched a table:
a column that stopped storing, filtering or returning values passed,
while a storage-only change such as dropping LowCardinality failed.

What callers can see of those types is that a missing value is NULL
and every value is kept as the string written. ClickHouseTest now
checks that through the public API:

- For events and gauges, ordinals '0', '1' and 10 read back as '0',
  '1' and '10', and a row without one reads back null. equal('10')
  and isNull() each match only their row, and grouping by ordinal
  lists each member in order, with the rows without one apart.
- The daily rollup still totals every member. The event ordinal test
  said so but only summed the raw table.
- Every event dimension, taken from Metric::EVENT_COLUMNS, filters and
  reads back as written and is null when omitted. The previous list
  held 24 of the 47 columns and read none of them back.

A non-nullable or FixedString(1) ordinal fails the new tests; a plain
Nullable(String) passes them, where the removed test failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tests/Usage/Adapter/ClickHouseTest.php Outdated
testEveryEventDimensionRoundTrips built its tags from Metric::EVENT_COLUMNS
and asserted over the same list, so a dimension dropped from that list
dropped out of the test too: with weatherCode left out of EVENT_COLUMNS it
still passed, checking 46 columns. Its '<column>-value' strings, 34 bytes
at most, also let a cap on stored values go unnoticed.

The dimensions are now written out in the test, grouped by what callers
send (request, resource, network, location, client), with values shaped
like real input: a 135-byte Accept header, a route with placeholders, an
IPv6 address, a non-ASCII city, a postal code with a space, a negative
coordinate, uppercase codes and numeric-looking identifiers. For each one,
equal() returns only the event that carries it, with the value as written,
and isNull() returns only the event without it. Removing or renaming a
dimension now fails the test; storage-only changes such as dropping
LowCardinality still pass.

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

Copy link
Copy Markdown
Member

Usage now lives in packages/usage in appwrite/appwrite (appwrite/appwrite#13956), and this repository is a read-only mirror. @abnegate, please re-open this against packages/usage there if you still want it.

abnegate added a commit to appwrite/appwrite that referenced this pull request Sep 29, 2026
utopia-php/usage#42 moved usage onto utopia-php/database 8: typed
Attribute and Index models for the schema, the event ordinal dimension,
PHP 8.5. Main absorbed usage into packages/usage (#13956) and the
mirror closed #42 in favour of a change here, so this applies #42's
final head (bf9ab997fa) to the package: every line it changed, in the
package layout, with its tests. The package requires database ^8.0
with dev stability until 8.0.0 is tagged, because bin/monorepo check
and test resolve it from Packagist, where it exists only as
8.0.x-dev; the mirror's branch alias does not apply to a split
package.

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.

2 participants