Skip to content

Conversation

@ArnabChatterjee20k
Copy link
Contributor

@ArnabChatterjee20k ArnabChatterjee20k commented Oct 17, 2025

Summary by CodeRabbit

  • New Features

    • First-class support for object (JSON/JSONB) attributes, JSONB query operators, and optional GIN-style indexes where supported; adapters now expose object-support flags.
  • Behavior / Validation

    • Validation, casting, defaults, queries (equal/contains/notContains) and error messages updated to recognize object types; index creation enforces GIN rules and adapter support.
  • Tests

    • Added comprehensive end-to-end and unit tests covering object attributes, GIN index scenarios, defaults, and invalid cases.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 17, 2025

Walkthrough

Adds first-class object (JSON/JSONB) attribute support: new Database type and INDEX_GIN, adapter capability flags and Pool delegation, Postgres JSONB SQL/query handling and GIN index DDL, validation updates (attributes, queries, indexes), width accounting, and new e2e/unit tests.

Changes

Cohort / File(s) Summary
Adapter API & delegator
src/Database/Adapter.php, src/Database/Adapter/Pool.php, src/Database/Adapter/MariaDB.php, src/Database/Adapter/SQLite.php
Added getSupportForObject(): bool to Adapter; Pool delegates; MariaDB and SQLite return false.
Postgres JSONB handling & index DDL
src/Database/Adapter/Postgres.php
Implements getSupportForObject(), maps Database::TYPE_OBJECTJSONB, adds handleObjectQueries() integrated into getSQLCondition(), and emits USING GIN for JSONB GIN indexes.
Core DB model & SQL sizing
src/Database/Database.php, src/Database/Query.php, src/Database/Adapter/SQL.php
Adds TYPE_OBJECT and INDEX_GIN; object-aware validation, casting/decoding, create/update flows; Query::isObjectAttribute() added; accounts for object attribute width (+20 bytes).
Validators — query, structure & index
src/Database/Validator/Query/Filter.php, src/Database/Validator/Structure.php, src/Database/Validator/Index.php
Adds object-type validation (object values must be arrays), allows object in contains/notContains; Index validator gains objectIndexSupport ctor flag and checkGinIndex() enforcing GIN rules (single object attribute, no orders, adapter support).
Tests — e2e & unit
tests/e2e/Adapter/Base.php, tests/e2e/Adapter/Scopes/ObjectAttributeTests.php, tests/e2e/Adapter/Scopes/AttributeTests.php, tests/e2e/Adapter/Scopes/DocumentTests.php, tests/unit/Validator/IndexTest.php
Adds comprehensive e2e tests for object attributes (queries, defaults, invalid cases, GIN index behavior); updates contains/notContains error expectations; adds unit test for GIN index validation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Q as Query
  participant DB as Database
  participant V as Validator
  participant A as Adapter(Postgres)

  Note over Q,DB: Query targets attribute typed TYPE_OBJECT
  Q->>DB: isObjectAttribute()
  DB->>V: validate attribute/index (object & GIN checks)
  V-->>DB: validation result
  DB->>A: getSQLCondition(...) for object attribute
  alt object condition path
    A->>A: handleObjectQueries() → JSONB operators (=, !=, @>, <@)
    A-->>DB: SQL fragment (may include USING GIN in DDL)
  end
  DB->>DB: execute SQL / return results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • abnegate
  • fogelito

Poem

🐇 I nibbled through JSON leaves, tidy and stout,
Nested keys and GIN paths I proudly rout.
Queries hop, indexes hum a bright song,
Tests keep watch as I dance along.
🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Object(json) attribute support for postgres" accurately refers to a real and significant aspect of the changeset. The changes do indeed add object attribute support with Postgres being the adapter that receives full implementation (handleObjectQueries, JSONB type mapping, GIN index support), while MariaDB and SQLite explicitly return false for object support. While the PR also includes system-wide framework changes to the base Database class and validators to enable this feature across the codebase, the title correctly identifies postgres as the primary beneficiary and implementation target. A teammate scanning the commit history would understand that this PR adds object/JSON attribute support specifically for Postgres.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch var_object

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 979619f and 6ba8558.

📒 Files selected for processing (1)
  • src/Database/Database.php (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Database/Database.php (5)
src/Database/Adapter/Pool.php (1)
  • getSupportForObject (577-580)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2097-2100)
src/Database/Adapter.php (1)
  • getSupportForObject (1071-1071)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Adapter Tests (Mirror)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (MariaDB)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (Postgres)
  • GitHub Check: Adapter Tests (MySQL)

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Database/Validator/Query/Filter.php (1)

209-219: notContains allowed here, but Postgres doesn’t implement it for objects

This path allows CONTAINS/NOT_CONTAINS on non-array attributes when type is string/object/spatial. Postgres::handleObjectQueries supports CONTAINS but not NOT_CONTAINS (nor NOT_EQUAL), so NOT_CONTAINS on an object will throw at runtime.

Either: (a) implement NOT_CONTAINS (and NOT_EQUAL) in Postgres, or (b) reject NOT_CONTAINS for objects here.

Here’s option (a) preferred for parity:

  • Postgres: add NOT_CONTAINS using NOT (col @> :val::jsonb); add NOT_EQUAL using NOT (col = :val::jsonb); keep multi‑value separator consistent with NOT queries (AND).

If you prefer option (b), I can provide a compact guard here to block NOT_CONTAINS for object attributes.

🧹 Nitpick comments (2)
src/Database/Adapter/SQLite.php (1)

976-979: Capability flag implemented correctly

SQLite advertises no object/JSON support, consistent with current storage-as-text behavior in create/update. No concerns.

If/when JSON1 usage is introduced, consider feature-detecting it and flipping this to true behind a config/feature flag.

src/Database/Adapter/Postgres.php (1)

2019-2027: Capability flag advertises JSONB support

Looks good. As a follow-up, consider first-class JSONB indexing for performance on @> queries (GIN).

I can draft a proposal to leverage $indexAttributeTypes inside createIndex() to emit USING GIN ("col") for object attributes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 141338a and 4483496.

📒 Files selected for processing (11)
  • src/Database/Adapter.php (1 hunks)
  • src/Database/Adapter/MariaDB.php (1 hunks)
  • src/Database/Adapter/Postgres.php (5 hunks)
  • src/Database/Adapter/SQL.php (1 hunks)
  • src/Database/Adapter/SQLite.php (1 hunks)
  • src/Database/Database.php (7 hunks)
  • src/Database/Query.php (1 hunks)
  • src/Database/Validator/Query/Filter.php (2 hunks)
  • src/Database/Validator/Structure.php (1 hunks)
  • tests/e2e/Adapter/Scopes/AttributeTests.php (1 hunks)
  • tests/e2e/Adapter/Scopes/DocumentTests.php (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-03T02:04:17.803Z
Learnt from: abnegate
PR: utopia-php/database#721
File: tests/e2e/Adapter/Scopes/DocumentTests.php:6418-6439
Timestamp: 2025-10-03T02:04:17.803Z
Learning: In tests/e2e/Adapter/Scopes/DocumentTests::testSchemalessDocumentInvalidInteralAttributeValidation (PHP), when the adapter reports getSupportForAttributes() === false (schemaless), the test should not expect exceptions from createDocuments for “invalid” internal attributes; remove try/catch and ensure the test passes without exceptions, keeping at least one assertion.

Applied to files:

  • tests/e2e/Adapter/Scopes/AttributeTests.php
  • tests/e2e/Adapter/Scopes/DocumentTests.php
🧬 Code graph analysis (10)
src/Database/Query.php (1)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Adapter/SQLite.php (3)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2024-2027)
src/Database/Adapter.php (3)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2024-2027)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Adapter/MariaDB.php (3)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2024-2027)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Validator/Query/Filter.php (2)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Query.php (1)
  • Query (8-1124)
src/Database/Adapter/SQL.php (1)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Adapter/Postgres.php (5)
src/Database/Query.php (2)
  • Query (8-1124)
  • isObjectAttribute (966-969)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Validator/Structure.php (1)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Database.php (4)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2024-2027)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
tests/e2e/Adapter/Scopes/DocumentTests.php (5)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Database.php (1)
  • Database (37-8180)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2024-2027)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
🪛 GitHub Actions: CodeQL
src/Database/Database.php

[error] 2057-2057: phpstan: Unreachable statement - code above always terminates. (Command: ./vendor/bin/phpstan analyse --level 7 src tests --memory-limit 2G)


[error] 2065-2065: phpstan: Unreachable statement - code above always terminates. (Command: ./vendor/bin/phpstan analyse --level 7 src tests --memory-limit 2G)

tests/e2e/Adapter/Scopes/DocumentTests.php

[error] 6571-6571: phpstan: Unreachable statement - code above always terminates. (in context of class Tests\E2E\Adapter\Base) (Command: ./vendor/bin/phpstan analyse --level 7 src tests --memory-limit 2G)


[error] 7064-7064: phpstan: Unreachable statement - code above always terminates. (in context of class Tests\E2E\Adapter\Base) (Command: ./vendor/bin/phpstan analyse --level 7 src tests --memory-limit 2G)

🪛 PHPMD (2.15.0)
tests/e2e/Adapter/Scopes/DocumentTests.php

6628-6628: Avoid unused local variables such as '$doc2'. (undefined)

(UnusedLocalVariable)


6839-6839: Avoid unused local variables such as '$doc7'. (undefined)

(UnusedLocalVariable)


6853-6853: Avoid unused local variables such as '$doc8'. (undefined)

(UnusedLocalVariable)


6944-6944: Avoid unused local variables such as '$doc11'. (undefined)

(UnusedLocalVariable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Setup & Build Docker Image
🔇 Additional comments (10)
src/Database/Database.php (7)

47-47: Add object type constant — looks good.
Public constant for object attributes is clear and scoped correctly.


1954-1964: Attribute validation for object type — good constraints.
Adapter gating + empty size + non-array are correct.


1980-1980: Error message update includes object type — OK.
Keeps guidance complete for unknown types.


2067-2067: Unknown-type message includes object — OK.
Matches earlier list.


2314-2325: Update-attribute rules for object type — good.
Same constraints as create path and adapter gating. Consistent.


7321-7325: Casting support for object — good fallback.
Decoding JSON string to array when the adapter doesn’t cast types is appropriate.


2052-2065: Fix unreachable code and incorrect array recursion for object/spatial types.

The current code has an early return at line 2036 when $defaultType === 'array', making the case self::TYPE_OBJECT and spatial type cases (lines 2049–2062) unreachable. Additionally, for object and spatial types with array defaults, the code incorrectly recurses into each element, causing validation errors. The proposed diff moves the return inside a conditional that excludes TYPE_OBJECT and spatial types, allowing them to skip element-wise recursion and be validated directly in the switch statement.

Apply the provided diff to resolve both the unreachable code and the incorrect validation logic.

Note: phpstan cannot be run in this environment, but the code inspection confirms the logic issue and the correctness of the proposed fix.

src/Database/Adapter/Postgres.php (3)

1646-1648: Early dispatch for object attributes

Routing object queries here is good. With the above patch, NOT_* will also be handled cleanly; otherwise NOT_* will still throw. Please align both layers (validator and adapter) before merging.


1797-1800: Type mapping: object → JSONB

Correct choice for Postgres. No issues.


1811-1811: Error message updated to include object

Good catch adding TYPE_OBJECT to the exception text.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Database/Database.php (1)

2055-2070: Restore proper control flow in validateDefaultTypes.

case self::TYPE_OBJECT currently hits a var_dump and falls through to default, so every object (and spatial) attribute default now throws Unknown attribute type. Besides killing valid defaults, the var_dump dumps to stdout in production. Drop the debug call and add explicit breaks so known types don’t cascade into the default case.

Apply this diff:

-            case self::TYPE_OBJECT:
-                // Object types expect arrays as default values
-                var_dump($defaultType);
-                if ($defaultType !== 'array') {
-                    throw new DatabaseException('Default value for object type must be an array');
-                }
-                // no break
+            case self::TYPE_OBJECT:
+                // Object types expect arrays as default values
+                if ($defaultType !== 'array') {
+                    throw new DatabaseException('Default value for object type must be an array');
+                }
+                break;
             case self::VAR_POINT:
             case self::VAR_LINESTRING:
             case self::VAR_POLYGON:
                 // Spatial types expect arrays as default values
                 if ($defaultType !== 'array') {
                     throw new DatabaseException('Default value for spatial type ' . $type . ' must be an array');
                 }
-                // no break
+                break;
             default:
                 throw new DatabaseException('Unknown attribute type: ' . $type . '. Must be one of ' . self::VAR_STRING . ', ' . self::VAR_INTEGER . ', ' . self::VAR_FLOAT . ', ' . self::VAR_BOOLEAN . ', ' . self::VAR_DATETIME . ', ' . self::VAR_RELATIONSHIP . ', ' . self::TYPE_OBJECT . ', ' . self::VAR_POINT . ', ' . self::VAR_LINESTRING . ', ' . self::VAR_POLYGON);
♻️ Duplicate comments (1)
src/Database/Adapter/Postgres.php (1)

1571-1624: JSONB query semantics: make EQUAL strict, drop auto-wrap, and guard types

  • EQUAL uses @> for arrays/objects (containment), not equality.
  • CONTAINS auto-wraps values; surprising and leaky.
  • count($value) on non-arrays can warn at runtime.

Apply this refactor for predictable behavior and full parity (adds strict equality, NOT_* support, and input guarding):

-    protected function handleObjectQueries(Query $query, array &$binds, string $attribute, string $alias, string $placeholder): string
-    {
-        switch ($query->getMethod()) {
-            case Query::TYPE_EQUAL:
-            case Query::TYPE_NOT_EQUAL: {
-                $isNot = $query->getMethod() === Query::TYPE_NOT_EQUAL;
-                $conditions = [];
-                foreach ($query->getValues() as $key => $value) {
-                    $binds[":{$placeholder}_{$key}"] = json_encode($value);
-                    if (is_array($value)) {
-                        $fragment = "{$alias}.{$attribute} @> :{$placeholder}_{$key}::jsonb";
-                        $conditions[] = $isNot ? "NOT (" . $fragment . ")" : $fragment;
-                    } else {
-                        $fragment = "{$alias}.{$attribute} = :{$placeholder}_{$key}::jsonb";
-                        $conditions[] = $isNot ? "{$alias}.{$attribute} <> :{$placeholder}_{$key}::jsonb" : $fragment;
-                    }
-                }
-                $separator = $isNot ? ' AND ' : ' OR ';
-                return empty($conditions) ? '' : '(' . implode($separator, $conditions) . ')';
-            }
-
-            case Query::TYPE_CONTAINS:
-            case Query::TYPE_NOT_CONTAINS: {
-                $isNot = $query->getMethod() === Query::TYPE_NOT_CONTAINS;
-                $conditions = [];
-                foreach ($query->getValues() as $key => $value) {
-                    if (count($value) === 1) {
-                        $jsonKey = array_key_first($value);
-                        $jsonValue = $value[$jsonKey];
-                        // wrap to represent array; eg: key -> [value]
-                        $value[$jsonKey] = [$jsonValue];
-                    }
-                    $binds[":{$placeholder}_{$key}"] = json_encode($value);
-                    $fragment = "{$alias}.{$attribute} @> :{$placeholder}_{$key}::jsonb";
-                    $conditions[] = $isNot ? "NOT (" . $fragment . ")" : $fragment;
-                }
-                $separator = $isNot ? ' AND ' : ' OR ';
-                return empty($conditions) ? '' : '(' . implode($separator, $conditions) . ')';
-            }
-
-            default:
-                throw new DatabaseException('Query method ' . $query->getMethod() . ' not supported for object attributes');
-        }
-    }
+    protected function handleObjectQueries(Query $query, array &$binds, string $attribute, string $alias, string $placeholder): string
+    {
+        $conditions = [];
+        $method = $query->getMethod();
+        $isNot = \in_array($method, [Query::TYPE_NOT_EQUAL, Query::TYPE_NOT_CONTAINS], true);
+
+        foreach ($query->getValues() as $key => $value) {
+            // Expect JSON arrays/objects for object queries
+            if (!\is_array($value)) {
+                throw new DatabaseException('Object queries expect JSON objects/arrays');
+            }
+            $binds[":{$placeholder}_{$key}"] = \json_encode($value);
+            $rhs = ":{$placeholder}_{$key}::jsonb";
+
+            $cond = match ($method) {
+                // Strict JSONB equality/inequality
+                Query::TYPE_EQUAL        => "{$alias}.{$attribute} = {$rhs}",
+                Query::TYPE_NOT_EQUAL    => "NOT ({$alias}.{$attribute} = {$rhs})",
+                // JSONB containment
+                Query::TYPE_CONTAINS     => "{$alias}.{$attribute} @> {$rhs}",
+                Query::TYPE_NOT_CONTAINS => "NOT ({$alias}.{$attribute} @> {$rhs})",
+                default => throw new DatabaseException('Query method ' . $method . ' not supported for object attributes'),
+            };
+            $conditions[] = $cond;
+        }
+
+        $separator = $isNot ? ' AND ' : ' OR ';
+        return empty($conditions) ? '' : '(' . \implode($separator, $conditions) . ')';
+    }
🧹 Nitpick comments (6)
src/Database/Adapter/Postgres.php (1)

870-887: Shared-tables + GIN/GIST: use per-tenant partial indexes

Since _tenant can’t be a GIN/GIST column, add a WHERE clause to scope the index per tenant for planner usability.

         $sql = "CREATE {$sqlType} {$key} ON {$this->getSQLTable($collection)}";
@@
-        $sql .= " ({$attributes});";
+        $whereTenant = '';
+        if ($this->sharedTables && ($type === Database::INDEX_SPATIAL || $type === Database::INDEX_GIN)) {
+            $whereTenant = ' WHERE _tenant = ' . (int)$this->tenant;
+        }
+        $sql .= " ({$attributes}){$whereTenant};";
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (5)

30-30: Prefer assertTrue over assertEquals(true, …)

Use assertTrue for boolean assertions.

-        $this->assertEquals(true, $database->createAttribute($collectionId, 'meta', Database::TYPE_OBJECT, 0, false));
+        $this->assertTrue($database->createAttribute($collectionId, 'meta', Database::TYPE_OBJECT, 0, false));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'data', Database::TYPE_OBJECT, 0, false));
+        $this->assertTrue($database->createAttribute($collectionId, 'data', Database::TYPE_OBJECT, 0, false));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'metaDefaultEmpty', Database::TYPE_OBJECT, 0, false, []));
+        $this->assertTrue($database->createAttribute($collectionId, 'metaDefaultEmpty', Database::TYPE_OBJECT, 0, false, []));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'settings', Database::TYPE_OBJECT, 0, false, $defaultSettings));
+        $this->assertTrue($database->createAttribute($collectionId, 'settings', Database::TYPE_OBJECT, 0, false, $defaultSettings));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'profile', Database::TYPE_OBJECT, 0, true, null));
+        $this->assertTrue($database->createAttribute($collectionId, 'profile', Database::TYPE_OBJECT, 0, true, null));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'profile2', Database::TYPE_OBJECT, 0, false, ['name' => 'anon']));
+        $this->assertTrue($database->createAttribute($collectionId, 'profile2', Database::TYPE_OBJECT, 0, false, ['name' => 'anon']));
-        $this->assertEquals(true, $database->createAttribute($collectionId, 'misc', Database::TYPE_OBJECT, 0, false, null));
+        $this->assertTrue($database->createAttribute($collectionId, 'misc', Database::TYPE_OBJECT, 0, false, null));

Also applies to: 556-556, 848-848, 852-852, 855-855, 858-858, 861-861


80-80: Remove unused local variables flagged by PHPMD

These variables aren’t read; drop the assignments to quiet static analysis without changing behavior.

-        $doc2 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([
-        $doc7 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([
-        $doc8 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([
-        $doc11 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([
-        $doc1 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([
-        $doc2 = $database->createDocument($collectionId, new Document([
+        $database->createDocument($collectionId, new Document([

Also applies to: 313-313, 327-327, 430-430, 563-563, 576-576


446-446: Misleading comment

This isn’t a negative test; it expects a match. Tweak comment for clarity.

-        // Test 29: Negative test - partial object match should still work (containment)
+        // Test 29: Partial object match (containment) should succeed

255-270: Duplicate of Test 15; consider making it a true partial-path check

This block repeats the same nested object used in Test 15. If the goal is partial-path containment, reduce the structure or switch to contains() to exercise subset matching.


589-595: Test intent vs. query target

You query data with ['env' => 'production'] but ‘env’ lives under 'config'. The 0-result assertion is fine, but consider clarifying the comment or querying ['config' => ['env' => 'production']] to demonstrate positive equality semantics separately.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4483496 and 10cf2bd.

📒 Files selected for processing (8)
  • src/Database/Adapter/Pool.php (1 hunks)
  • src/Database/Adapter/Postgres.php (7 hunks)
  • src/Database/Database.php (14 hunks)
  • src/Database/Validator/Index.php (4 hunks)
  • tests/e2e/Adapter/Base.php (2 hunks)
  • tests/e2e/Adapter/Scopes/DocumentTests.php (2 hunks)
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (1 hunks)
  • tests/unit/Validator/IndexTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/Adapter/Scopes/DocumentTests.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-03T02:04:17.803Z
Learnt from: abnegate
PR: utopia-php/database#721
File: tests/e2e/Adapter/Scopes/DocumentTests.php:6418-6439
Timestamp: 2025-10-03T02:04:17.803Z
Learning: In tests/e2e/Adapter/Scopes/DocumentTests::testSchemalessDocumentInvalidInteralAttributeValidation (PHP), when the adapter reports getSupportForAttributes() === false (schemaless), the test should not expect exceptions from createDocuments for “invalid” internal attributes; remove try/catch and ensure the test passes without exceptions, keeping at least one assertion.

Applied to files:

  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
  • tests/e2e/Adapter/Base.php
🧬 Code graph analysis (7)
src/Database/Validator/Index.php (1)
src/Database/Database.php (1)
  • Database (37-8211)
tests/unit/Validator/IndexTest.php (3)
src/Database/Document.php (2)
  • Document (12-470)
  • getAttribute (224-231)
src/Database/Database.php (1)
  • Database (37-8211)
src/Database/Validator/Index.php (3)
  • Index (10-433)
  • isValid (278-317)
  • getDescription (70-73)
src/Database/Database.php (5)
src/Database/Adapter/Pool.php (1)
  • getSupportForObject (572-575)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2027-2030)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Adapter/Postgres.php (7)
src/Database/Database.php (2)
  • Database (37-8211)
  • count (6989-7038)
src/Database/Adapter.php (2)
  • count (825-825)
  • getSupportForObject (1064-1064)
src/Database/Query.php (2)
  • Query (8-1124)
  • isObjectAttribute (966-969)
src/Database/Adapter/Pool.php (2)
  • count (273-276)
  • getSupportForObject (572-575)
src/Database/Adapter/SQL.php (1)
  • count (2534-2596)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (6)
src/Database/Adapter.php (1)
  • Adapter (16-1325)
src/Database/Database.php (4)
  • Database (37-8211)
  • createAttribute (1695-1750)
  • count (6989-7038)
  • createIndex (3271-3454)
src/Database/Validator/Index.php (1)
  • Index (10-433)
src/Database/Query.php (5)
  • Query (8-1124)
  • equal (435-438)
  • contains (507-510)
  • notEqual (447-450)
  • select (580-583)
src/Database/Adapter/Pool.php (4)
  • getSupportForObject (572-575)
  • createAttribute (168-171)
  • count (273-276)
  • createIndex (213-216)
src/Database/Adapter/Postgres.php (3)
  • getSupportForObject (2027-2030)
  • createAttribute (444-463)
  • createIndex (839-897)
src/Database/Adapter/Pool.php (5)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2027-2030)
src/Database/Adapter.php (1)
  • getSupportForObject (1064-1064)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Mirror.php (1)
  • delegate (88-103)
tests/e2e/Adapter/Base.php (1)
src/Database/Adapter.php (1)
  • Adapter (16-1325)
🪛 GitHub Actions: CodeQL
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

[error] 841-841: PHPStan: Unreachable statement - code above always terminates. (tests/e2e/Adapter/Scopes/ObjectAttributeTests.php:841)

🪛 PHPMD (2.15.0)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

80-80: Avoid unused local variables such as '$doc2'. (undefined)

(UnusedLocalVariable)


313-313: Avoid unused local variables such as '$doc7'. (undefined)

(UnusedLocalVariable)


327-327: Avoid unused local variables such as '$doc8'. (undefined)

(UnusedLocalVariable)


430-430: Avoid unused local variables such as '$doc11'. (undefined)

(UnusedLocalVariable)


563-563: Avoid unused local variables such as '$doc1'. (undefined)

(UnusedLocalVariable)


576-576: Avoid unused local variables such as '$doc2'. (undefined)

(UnusedLocalVariable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (MariaDB)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (MySQL)
  • GitHub Check: Adapter Tests (Postgres)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (Mirror)
🔇 Additional comments (11)
src/Database/Adapter/Pool.php (1)

571-575: LGTM: delegator added for getSupportForObject()

Matches existing delegation pattern. No issues.

src/Database/Adapter/Postgres.php (3)

1649-1651: LGTM: object-attribute query path integrated

Delegates to handleObjectQueries when attribute type is object.


1800-1815: LGTM: TYPE_OBJECT mapped to JSONB

Consistent with Postgres JSON storage.


2022-2031: LGTM: capability flag returns true

Matches adapter capabilities; Pool and interface aligned.

tests/unit/Validator/IndexTest.php (1)

241-326: LGTM: comprehensive GIN index validator coverage

Covers support gating, single-attr constraint, type check, and order restriction.

src/Database/Validator/Index.php (3)

33-55: LGTM: plumbed objectIndexSupport through constructor

Docblock updated; field assigned.


312-315: LGTM: GIN check included in validation chain

Order is appropriate; returns early on failure.


392-431: LGTM: dedicated GIN rules

Rules match Database::createIndex() errors and new tests.

tests/e2e/Adapter/Base.php (1)

11-11: Verified: Trait gating properly implemented

Confirmed that ObjectAttributeTests trait includes getSupportForObject() checks at multiple test entry points (lines 22, 548, 656, 839), each followed by markTestSkipped() calls. Tests will correctly skip on unsupporting adapters. Code changes approved.

tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (2)

21-24: Good skip gating for unsupported adapters

Adapter capability checks are correct and prevent false negatives on non-JSON backends.

Also applies to: 547-551, 655-659


346-356: Query::notContains is available and properly wired for object attributes.

Verification confirms that Query::notContains exists at src/Database/Query.php:519 and is fully implemented for object attributes:

  • Postgres adapter handles JSONB queries with explicit negation logic (wraps conditions with NOT())
  • SQL adapter supports the method via getLikeOperator()
  • Test 21 validates that contains works on the same object structure; Test 23b correctly expects notContains to exclude matching documents

No replacement or alternative is needed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (3)

153-156: Fix notEqual payload: remove extra array nesting.

Query::notEqual expects a single value (object or scalar). The extra wrapping [[...]] produces incorrect semantics.

Apply:

-            Query::notEqual('meta', [['age' => 26]])
+            Query::notEqual('meta', ['age' => 26])

162-169: Fix notEqual payload: remove extra array nesting.

Same issue—remove the outer array wrapper.

Apply:

-            Query::notEqual('meta', [[
-                'user' => [
-                    'info' => [
-                        'country' => 'CA'
-                    ]
-                ]
-            ]])
+            Query::notEqual('meta', [
+                'user' => [
+                    'info' => [
+                        'country' => 'CA'
+                    ]
+                ]
+            ])

478-482: Fix contains check for nested array element.

To assert that meta.matrix contains [4,5,6] as an array element (not individual scalars), wrap it as an array-of-array:

-            Query::contains('meta', [['matrix' => [4, 5, 6]]])
+            Query::contains('meta', [['matrix' => [[4, 5, 6]]]])
🧹 Nitpick comments (1)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (1)

589-593: Clarify comment: query doesn't match document structure.

The comment "GIN index doesn't make equal queries work differently" is misleading. The query returns 0 results because it searches for {'env': 'production'} at the top level of data, but the actual structure is nested under data.config.env. Consider clarifying:

-        $this->assertCount(0, $results); // Note: GIN index doesn't make equal queries work differently
+        $this->assertCount(0, $results); // Query structure doesn't match document nesting (env is under config)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10cf2bd and 8cd5921.

📒 Files selected for processing (1)
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-03T02:04:17.803Z
Learnt from: abnegate
PR: utopia-php/database#721
File: tests/e2e/Adapter/Scopes/DocumentTests.php:6418-6439
Timestamp: 2025-10-03T02:04:17.803Z
Learning: In tests/e2e/Adapter/Scopes/DocumentTests::testSchemalessDocumentInvalidInteralAttributeValidation (PHP), when the adapter reports getSupportForAttributes() === false (schemaless), the test should not expect exceptions from createDocuments for “invalid” internal attributes; remove try/catch and ensure the test passes without exceptions, keeping at least one assertion.

Applied to files:

  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
🧬 Code graph analysis (1)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (5)
src/Database/Adapter.php (1)
  • Adapter (16-1325)
src/Database/Database.php (5)
  • Database (37-8211)
  • createAttribute (1695-1750)
  • createDocument (4237-4331)
  • updateDocument (4783-4984)
  • createIndex (3271-3454)
src/Database/Validator/Index.php (1)
  • Index (10-433)
src/Database/Query.php (6)
  • Query (8-1124)
  • equal (435-438)
  • contains (507-510)
  • notEqual (447-450)
  • select (580-583)
  • notContains (519-522)
src/Database/Adapter/Postgres.php (5)
  • getSupportForObject (2027-2030)
  • createAttribute (444-463)
  • createDocument (956-1056)
  • updateDocument (1070-1270)
  • createIndex (839-897)
🪛 PHPMD (2.15.0)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

80-80: Avoid unused local variables such as '$doc2'. (undefined)

(UnusedLocalVariable)


313-313: Avoid unused local variables such as '$doc7'. (undefined)

(UnusedLocalVariable)


327-327: Avoid unused local variables such as '$doc8'. (undefined)

(UnusedLocalVariable)


430-430: Avoid unused local variables such as '$doc11'. (undefined)

(UnusedLocalVariable)


563-563: Avoid unused local variables such as '$doc1'. (undefined)

(UnusedLocalVariable)


576-576: Avoid unused local variables such as '$doc2'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (10)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (10)

22-24: LGTM: Clean adapter capability check.

The skip logic correctly gates the test without the unreachable return that was flagged in other methods.


16-540: Excellent comprehensive test coverage.

This test method thoroughly exercises object attribute functionality including CRUD operations, nested structures, special characters, mixed types, null/empty values, and edge cases. The test progression is logical and well-commented.


548-550: LGTM: Correct skip logic.

The adapter support check is properly implemented without unreachable code.


609-644: Excellent error case coverage for GIN indexes.

The negative tests properly validate all three GIN index constraints: object-type-only, single-attribute, and no explicit orders. Exception handling is thorough with appropriate assertions on exception type and message content.


656-658: LGTM: Clean skip logic.

Adapter support check is properly implemented.


666-706: Correct type validation tests.

The three tests properly validate that non-array values (string, integer, boolean) are rejected for object attributes with StructureException. The skip guard at line 656 ensures these only run on adapters with object support.


764-795: Good edge case: large structure test.

Testing a 50-element nested structure validates that the implementation handles realistic large JSONB documents. The query verification on line 783 ensures retrieval works correctly within large structures.


839-841: LGTM: Unreachable return fixed.

The previous issue with an unreachable return after markTestSkipped has been corrected. The skip logic is now clean.


862-874: Correct validation of required attribute.

The test properly validates that omitting a required object attribute (profile) throws StructureException. The exception handling and assertions are appropriate.


876-908: Thorough default value validation.

The test correctly validates all default scenarios: empty array, nested object, explicit null, and required vs non-required behavior. The query test at lines 903-907 confirms defaults are properly stored and queryable.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Database/Database.php (1)

2599-2607: Pass the new “object support” flag to IndexValidator.

IndexValidator now expects the adapter’s object-support flag. This call site still uses the old signature, so updateAttribute() will trigger an ArgumentCountError as soon as it tries to validate indexes. Add the missing $this->adapter->getSupportForObject() argument here to keep attribute updates working.

                     $validator = new IndexValidator(
                         $attributes,
                         $this->adapter->getMaxIndexLength(),
                         $this->adapter->getInternalIndexesKeys(),
                         $this->adapter->getSupportForIndexArray(),
                         $this->adapter->getSupportForSpatialIndexNull(),
                         $this->adapter->getSupportForSpatialIndexOrder(),
-                        $this->adapter->getSupportForVectors(),
+                        $this->adapter->getSupportForVectors(),
+                        $this->adapter->getSupportForObject(),
                     );
♻️ Duplicate comments (1)
src/Database/Adapter/Postgres.php (1)

1607-1618: Address the unresolved issues from previous review.

The past review comment on lines 1594-1648 identified critical semantic issues that remain unaddressed:

  1. EQUAL (line 1613): Uses @> (containment) instead of = (strict equality). This means Query::equal('meta', ['status' => 'active']) will match documents where meta is {"status": "active", "other": "field"} instead of requiring an exact match. This is a semantic mismatch with the query name "equal".

  2. CONTAINS auto-wrapping (lines 1633-1635): Still wraps scalar values in arrays automatically. The previous review recommended removing this auto-wrapping so callers explicitly pass the JSON shape they want to contain.

These issues affect query semantics and should be resolved before merge.

Also applies to: 1620-1643

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 117af69 and a92fd41.

📒 Files selected for processing (12)
  • src/Database/Adapter.php (1 hunks)
  • src/Database/Adapter/MariaDB.php (1 hunks)
  • src/Database/Adapter/Pool.php (1 hunks)
  • src/Database/Adapter/Postgres.php (7 hunks)
  • src/Database/Adapter/SQL.php (1 hunks)
  • src/Database/Database.php (12 hunks)
  • src/Database/Query.php (1 hunks)
  • src/Database/Validator/Index.php (4 hunks)
  • src/Database/Validator/Query/Filter.php (2 hunks)
  • src/Database/Validator/Structure.php (1 hunks)
  • tests/e2e/Adapter/Base.php (2 hunks)
  • tests/e2e/Adapter/Scopes/DocumentTests.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/Database/Adapter/Pool.php
  • src/Database/Adapter.php
  • src/Database/Adapter/SQL.php
  • src/Database/Validator/Structure.php
  • src/Database/Query.php
  • src/Database/Adapter/MariaDB.php
  • tests/e2e/Adapter/Scopes/DocumentTests.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-03T02:04:17.803Z
Learnt from: abnegate
PR: utopia-php/database#721
File: tests/e2e/Adapter/Scopes/DocumentTests.php:6418-6439
Timestamp: 2025-10-03T02:04:17.803Z
Learning: In tests/e2e/Adapter/Scopes/DocumentTests::testSchemalessDocumentInvalidInteralAttributeValidation (PHP), when the adapter reports getSupportForAttributes() === false (schemaless), the test should not expect exceptions from createDocuments for “invalid” internal attributes; remove try/catch and ensure the test passes without exceptions, keeping at least one assertion.

Applied to files:

  • tests/e2e/Adapter/Base.php
🧬 Code graph analysis (4)
src/Database/Validator/Query/Filter.php (2)
src/Database/Database.php (1)
  • Database (37-8344)
src/Database/Query.php (1)
  • Query (8-1177)
src/Database/Adapter/Postgres.php (6)
src/Database/Database.php (2)
  • Database (37-8344)
  • count (7123-7172)
src/Database/Adapter.php (2)
  • count (825-825)
  • getSupportForObject (1071-1071)
src/Database/Query.php (2)
  • Query (8-1177)
  • isObjectAttribute (983-986)
src/Database/Adapter/Pool.php (2)
  • count (273-276)
  • getSupportForObject (577-580)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Database.php (5)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObject (2097-2100)
src/Database/Adapter/Pool.php (1)
  • getSupportForObject (577-580)
src/Database/Adapter.php (1)
  • getSupportForObject (1071-1071)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObject (1852-1855)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObject (976-979)
src/Database/Validator/Index.php (2)
src/Database/Document.php (2)
  • Document (12-470)
  • getAttribute (224-231)
src/Database/Database.php (1)
  • Database (37-8344)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (Postgres)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (MariaDB)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (Mirror)
  • GitHub Check: Adapter Tests (MySQL)
  • GitHub Check: Unit Test
🔇 Additional comments (10)
tests/e2e/Adapter/Base.php (1)

11-11: LGTM! Clean addition of object attribute test coverage.

The import and trait usage are correctly integrated into the Base test class. The import follows alphabetical ordering, and the trait usage is appropriately positioned.

Also applies to: 30-30

src/Database/Validator/Query/Filter.php (2)

150-158: LGTM! Clean validation for object type queries.

The array-only requirement is now enforced consistently across validator and adapter layers.


232-236: LGTM! Error message accurately reflects object type support.

The condition and message correctly allow contains/notContains on object attributes alongside strings and spatial types.

src/Database/Adapter/Postgres.php (4)

889-890: LGTM! GIN index support properly integrated.

The index creation handles GIN consistently with other special index types (spatial, HNSW), includes appropriate tenant column handling for shared tables, and uses the correct USING GIN clause for JSONB indexes.

Also applies to: 896-896, 909-909


1673-1675: LGTM! Routing logic is correct.

The placement and pattern match the spatial query handling above. Once the issues in handleObjectQueries are resolved, this integration point will work correctly.


1858-1860: LGTM! SQL type mapping is correct.

JSONB is the appropriate PostgreSQL type for object attributes, and the error message accurately reflects the expanded type support.

Also applies to: 1874-1874


2092-2100: LGTM! Capability method correctly implemented.

Returns true to indicate Postgres supports object (JSONB) attributes, following the established pattern for adapter capability flags.

src/Database/Validator/Index.php (3)

27-38: LGTM! Constructor parameter follows established pattern.

The objectIndexSupport flag is wired consistently with other adapter capability parameters and defaults safely to false.


411-413: LGTM! Validation flow correctly extended.

The checkGinIndex call is properly integrated into the validation chain.


442-482: LGTM! GIN index validation is thorough and consistent.

The implementation correctly mirrors the patterns from checkSpatialIndex and checkVectorIndex:

  • Single attribute requirement
  • Type checking (must be TYPE_OBJECT)
  • Order restrictions
  • Adapter support flag validation

All error messages are clear and actionable.

Comment on lines 2153 to 2158
// Object types expect arrays as default values
var_dump($defaultType);
if ($defaultType !== 'array') {
throw new DatabaseException('Default value for object type must be an array');
}
// no break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove debug output and stop falling through to the vector case.

var_dump($defaultType) will leak debug output in production, and the missing break; means any valid object default falls into the vector branch and immediately throws (“Vector components must be numeric”). As written, every non-array default for type: object is unusable. Please delete the debug call and add a break; after the array check so object defaults validate correctly.

             case self::TYPE_OBJECT:
                 // Object types expect arrays as default values
-                var_dump($defaultType);
                 if ($defaultType !== 'array') {
                     throw new DatabaseException('Default value for object type must be an array');
                 }
-                // no break
+                break;
             case self::VAR_VECTOR:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Object types expect arrays as default values
var_dump($defaultType);
if ($defaultType !== 'array') {
throw new DatabaseException('Default value for object type must be an array');
}
// no break
// Object types expect arrays as default values
if ($defaultType !== 'array') {
throw new DatabaseException('Default value for object type must be an array');
}
break;
🤖 Prompt for AI Agents
In src/Database/Database.php around lines 2153 to 2158, remove the stray debug
var_dump($defaultType) and add a break after the array-type check so object-type
default handling does not fall through to the vector branch; specifically delete
the var_dump call and insert a break; immediately after confirming $defaultType
=== 'array' so valid object defaults are accepted and do not trigger the vector
error.

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