-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Spatial type attributes #10356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 1.8.x
Are you sure you want to change the base?
Spatial type attributes #10356
Conversation
📝 WalkthroughWalkthroughAdds geospatial data type support (point, line/linestring, polygon) across the platform. Introduces new constants and format registrations, updates database filters, GraphQL column mapping, and response models (attribute/column) for these types. Adds API endpoints to create/update point/line/polygon attributes (Collections) and to create corresponding columns (TablesDB). Registers new actions in service registries. Extends validation models for collections, tables, and lists. Includes comprehensive end-to-end tests for CRUD and bulk operations with spatial data, and new GraphQL test constants. Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 PHPStan (2.1.17)Note: Using configuration file /phpstan.neon. If the excluded path can sometimes exist, append (?) parameters: Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
✨ Benchmark results
⚡ Benchmark Comparison
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
tests/e2e/Services/GraphQL/Base.php (2)
346-418
: Extend FRAGMENT_ATTRIBUTES to cover spatial types so attribute selections don’t return empty objects.Without inline fragments for AttributePoint/AttributeLine/AttributePolygon, queries that list attributes and rely solely on this fragment will return empty selections for spatial attributes.
... on AttributeDatetime { key required array status default } + ... on AttributePoint { + key + required + array + status + } + ... on AttributeLine { + key + required + array + status + } + ... on AttributePolygon { + key + required + array + status + }
421-494
: Extend FRAGMENT_COLUMNS to cover spatial types for parity with new column models.Same rationale as attributes; without these inline fragments, list/get column queries won’t project spatial column fields.
... on ColumnDatetime { key required array status default } + ... on ColumnPoint { + key + required + array + status + } + ... on ColumnLine { + key + required + array + status + } + ... on ColumnPolygon { + key + required + array + status + }src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (1)
473-479
: Fix brokengetAttribute
conditionals and use correct'format'
keyThe two conditional checks in
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
(lines 473–479) are mis-parenthesized—causinggetAttribute
to receive a boolean—and the second guard uses the wrong key ('filter'
instead of'format'
). Applying the following patch will correct both issues:• Locations requiring fixes:
- File:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
• Line 473: misplaced parentheses around'type'
• Line 477: misplaced parentheses around'filter'
and wrong attribute key• Diff to apply:
--- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -473,7 +473,7 @@ // Ensure the attribute’s type matches expected - if ($attribute->getAttribute(('type') !== $type)) { + if ($attribute->getAttribute('type') !== $type) { throw new Exception($this->getTypeInvalidException()); } @@ -477,7 +477,7 @@ // For string types, ensure the format matches the provided filter - if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) { + if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('format') !== $filter) { throw new Exception($this->getTypeInvalidException()); }No other instances of nested parentheses in
getAttribute
calls were found in this file, so these two changes address the full scope of this bug.
♻️ Duplicate comments (1)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php (1)
43-51
: Docs path parity with other spatial endpointsSame note as Point: please ensure the docs page exists or update the reference.
🧹 Nitpick comments (26)
tests/e2e/Services/GraphQL/Base.php (1)
1-3388
: Optional: add GraphQL smoke tests for new constants.Once the cases and fragments are added, consider adding minimal e2e calls using these constants to avoid regression.
Happy to draft a couple of CRUD tests mirroring existing attribute/column tests for one spatial type (e.g., point) as a template for the others.
app/init/database/filters.php (1)
96-99
: Explicit no-op for spatial attributes is fine; add intent comment for maintainersThese cases make it explicit that no extra mutations are needed for spatial attributes in this filter. Add a short comment to avoid future “missing logic?” confusion.
Apply this minimal diff:
case Database::VAR_STRING: $filters = $attribute->getAttribute('filters', []); $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); break; + // Spatial attributes: no extra processing required in subQueryAttributes. case Database::VAR_POINT: case Database::VAR_LINESTRING: case Database::VAR_POLYGON: break;
src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php (1)
141-152
: Spatial attribute actions registered; minor docs consistency follow-upThe action registrations are correct and mirror other attribute types. Note: the corresponding Action classes’ parameter docs for collectionId sometimes mention “create a new table” even under Collections (see Create/Update for Point/Line/Polygon). Consider updating those descriptions to say “collection” for consistency.
I can prepare a small PR patch to normalize those descriptions across the three action classes if helpful.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (1)
373-379
: Avoid undefined index when checking two-way relationshipsAccessing $options['twoWay'] and $primaryDocumentOptions['twoWay'] without guarding can raise notices if not set. Use !empty(...) to be safe.
- if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + if ($type === Database::VAR_RELATIONSHIP && !empty($options['twoWay'])) { - if ($primaryDocumentOptions['twoWay']) { + if (!empty($primaryDocumentOptions['twoWay'])) {Also applies to: 574-589
src/Appwrite/Utopia/Response/Model/AttributePoint.php (1)
26-33
: Consistency check: default value shapeDefault is declared as TYPE_JSON here (good for an array like [x, y]). Ensure downstream serializers/SDKs expect JSON for attribute defaults of spatial types. See ColumnPoint/ColumnLine using TYPE_STRING for defaults; consider aligning types across attributes vs columns for consistency, or document the intentional difference.
src/Appwrite/Utopia/Response/Model/ColumnPoint.php (1)
26-33
: Consider using TYPE_JSON for 'default' to match the array shapeThe example '[0, 0]' represents JSON array coordinates, but the rule uses TYPE_STRING. If clients should receive a JSON array, prefer TYPE_JSON for stronger typing and parity with AttributePoint/Line/Polygon defaults.
- ->addRule('default', [ - 'type' => self::TYPE_STRING, + ->addRule('default', [ + 'type' => self::TYPE_JSON, 'description' => 'Default value for column when not provided. Cannot be set when column is required.', 'default' => null, 'required' => false, 'example' => '[0, 0]' ])src/Appwrite/Utopia/Response/Model/ColumnLine.php (1)
26-33
: Prefer TYPE_JSON for line default for consistency and typingLike ColumnPoint, the default represents a JSON array. Switching to TYPE_JSON would better reflect the payload shape and align with attribute models.
- ->addRule('default', [ - 'type' => self::TYPE_STRING, + ->addRule('default', [ + 'type' => self::TYPE_JSON, 'description' => 'Default value for column when not provided. Cannot be set when column is required.', 'default' => null, 'required' => false, 'example' => '[[0, 0], [1, 1]]' ])src/Appwrite/Utopia/Response/Model/ColumnPolygon.php (2)
13-33
: Polygon default example should be a fully closed ring (5 coordinates) for clarityUse a canonical rectangle or square with the first/last positions equal to avoid confusion about ring closure. Current example forms a triangle.
Apply this minimal change:
- 'example' => '[[[0, 0], [0, 10], [10, 10], [0, 0]]]' + 'example' => '[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]'
26-33
: Confirm spatial column default rule type consistency
Verified that ColumnPoint, ColumnLine, and ColumnPolygon all declare theirdefault
rule with'type' => self::TYPE_STRING
and no use ofTYPE_JSON
.
- src/Appwrite/Utopia/Response/Model/ColumnPoint.php:
->addRule('default', ['type' => self::TYPE_STRING, …])
- src/Appwrite/Utopia/Response/Model/ColumnLine.php:
->addRule('default', ['type' => self::TYPE_STRING, …])
- src/Appwrite/Utopia/Response/Model/ColumnPolygon.php:
->addRule('default', ['type' => self::TYPE_STRING, …])
If your API contracts return spatial defaults as native JSON arrays rather than encoded strings, you may optionally refactor these to use
self::TYPE_JSON
for all three models to reflect the actual data type. Otherwise, keeping them asTYPE_STRING
is consistent and acceptable.src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php (1)
105-160
: Confirm absence of Update endpoints for spatial columns
- Verified that there are no
UpdateLine
,UpdatePoint
, orUpdatePolygon
class definitions undersrc/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line
,…/Point
, or…/Polygon
, nor are any such updates registered inregisterColumnActions()
(lines 105–160).- If spatial-column updates are intentionally unsupported, please file a backlog ticket or update the API reference/docs to explicitly document that behavior.
src/Appwrite/Utopia/Response/Model/AttributePolygon.php (1)
13-33
: Nit: make 'type' a string rule for semantic consistencyBase Attribute defines 'type' as a string; Point/Line currently use JSON for 'type'. To align semantics (and Swagger/SDK typing), consider using TYPE_STRING here (and optionally across geometry models) while keeping 'default' as JSON.
Apply within this hunk:
- ->addRule('type', [ - 'type' => self::TYPE_JSON, + ->addRule('type', [ + 'type' => self::TYPE_STRING, 'description' => 'Attribute type.', 'default' => '', 'example' => 'polygon', ])src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (1)
61-66
: Confirm stance ondefault
for spatial attributes.Parameter type is
Text(0, 0)
and action signature uses?string $default
. If defaults for POINT are intentionally unsupported (which is reasonable), consider:
- Explicitly documenting that defaults are not accepted for spatial attributes.
- Or removing the
default
parameter entirely (like other types did historically) to prevent misuse.If defaults should be supported later, the input type will likely need to be JSON (
array|null
) rather than string to better matchAttributePoint
’s JSON rules.tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (4)
6248-6251
: Reduce flakiness: poll instead of fixed sleeps for attribute readiness.Replace
sleep(2)
with anassertEventually(...)
that waits until attributes are available, similar to prior tests in this file. This will stabilize CI on slower machines.Apply this diff:
- // Wait for attributes to be created - sleep(2); + // Wait for attributes to be created + $this->assertEventually(function () use ($databaseId, $collectionId) { + $attributes = $this->client->call( + Client::METHOD_GET, + "/databases/{$databaseId}/collections/{$collectionId}/attributes", + array_merge(['content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id']], $this->getHeaders()) + ); + return ($attributes['headers']['status-code'] ?? 0) === 200 + && ($attributes['body']['total'] ?? 0) >= 2; // expecting at least name + location (+ polygon) + }, 60000, 500);
6286-6295
: Avoid brittle geometry assertions; normalize once, then assert.Current checks branch on whether
area[0]
is an array. Prefer a tiny normalizer (e.g., wrap a ring if not nested) to keep assertions simple and future-proof.Apply this diff:
- // Check polygon structure - it might be stored as an array of arrays - if (is_array($document['area'][0])) { - $this->assertGreaterThan(1, count($document['area'][0])); // POLYGON has multiple points - } else { - $this->assertGreaterThan(1, count($document['area'])); // POLYGON has multiple points - } + // Normalize polygon to rings and assert minimum points + $rings = is_array($document['area'][0]) && is_array(($document['area'][0])[0]) + ? $document['area'] // already rings + : [$document['area']]; // single ring + $this->assertGreaterThan(1, count($rings[0]), 'POLYGON must contain multiple points');
6545-6568
: Avoid hitting batch size limits implicitly.Use the configured
APP_LIMIT_DATABASE_BATCH
instead of hardcoding 100 to keep the test portable across deployments.Apply this diff:
- for ($i = 0; $i < 100; $i++) { + $batch = defined('APP_LIMIT_DATABASE_BATCH') ? min(APP_LIMIT_DATABASE_BATCH, 100) : 100; + for ($i = 0; $i < $batch; $i++) {
6569-6581
: Cleanup path is correct; consider asserting cascade effects.You may assert 204s and optionally verify the database is gone to catch cleanup races.
Apply this diff:
- $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([ + $deletedDb = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); + $this->assertEquals(204, $deletedDb['headers']['status-code']);src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php (2)
61-66
: Default parameter description vs. validator mismatch.The description suggests clients can send a default value, but the validator
new Text(0, 0)
effectively disallows any non-empty payload for default (only null/empty). If defaults for spatial types are intentionally unsupported, adjust the description to say “Defaults are not supported for polygon attributes” (and consider omitting the parameter from the public contract in a future major). If defaults should be supported, switch to an appropriate validator (e.g., JSON) and document the expected shape.Proposed doc-only tweak:
- ->param('default', null, new Text(0, 0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('default', null, new Text(0, 0), 'Defaults are not supported for polygon attributes and will be ignored.', true)
85-87
: Status code override is fine; consider a short note in code.createAttribute() sets 201 internally, then you override to 202 here for async processing semantics. That’s okay and matches other attribute endpoints, but it’s easy to miss. Consider a short inline comment to explain why we force 202.
$response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + // Return 202 to indicate async attribute provisioning (aligns with legacy attributes API) + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) ->dynamic($attribute, $this->getResponseModel());src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (2)
61-66
: Default parameter text should match behavior.Like Polygon/Point, the
Text(0, 0)
validator prevents non-empty defaults, while the description implies defaults are usable. Either (a) clarify that defaults aren’t supported for line attributes or (b) adopt a validator that accepts a JSON array shape if defaults should be allowed.- ->param('default', null, new Text(0, 0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) + ->param('default', null, new Text(0, 0), 'Defaults are not supported for line attributes and will be ignored.', true)
85-87
: Optional: add a note on forcing 202.Same 201→202 override as other attribute endpoints; a brief comment improves maintainability.
$response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + // Force 202 to indicate async provisioning and maintain API parity with other attributes + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) ->dynamic($attribute, $this->getResponseModel());tests/e2e/Services/Databases/Legacy/DatabasesCustomClientTest.php (6)
1082-1093
: Comment contradicts expected status.The comment says “handle both 201/200,” but the assertion expects 202. Update the comment to reduce confusion.
- // Create point attribute - handle both 201 (created) and 200 (already exists) + // Create point attribute - endpoint returns 202 Accepted after enqueueing attribute creation
1135-1147
: Upsert requests: path documentId vs body documentId mismatch.PUT requests include a documentId in the path and also pass a (different) documentId in the body. Depending on server-side validation, this can be rejected or introduce ambiguity. Prefer either:
- Rely on the path-only (omit documentId from body), or
- Ensure the body documentId matches the path id.
Suggest removing the body documentId for clarity.
Proposed changes (Point upsert as example):
- $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([ + $upsertId = ID::unique(); + $response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $upsertId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => ID::unique(), 'data' => [ 'name' => 'Upserted Location', 'location' => [34.0522, -118.2437] // Los Angeles coordinates ] ]);Apply the same pattern to the line and polygon upsert calls in the other tests.
Also applies to: 1270-1283, 1407-1420
1177-1312
: Line tests are comprehensive; consider adding an invalid-shape test.Great coverage for CRUD and delete/404 verification. Consider an extra negative test: reject a line with fewer than two points, or with non-numeric coordinates, to exercise validator paths.
1314-1447
: Polygon tests look good; add ring-closure and winding validation cases if applicable.You already test a closed ring. If the backend enforces ring closure or winding order, add:
- A polygon without a closing point → expect 400.
- A polygon with an empty ring or non-array members → expect 400.
1490-1518
: Mixed collection coverage is valuable; consider array-typed spatial attributes.Endpoints accept the “array” flag; adding one attribute with array=true (e.g., multiple polygons) would strengthen coverage for serialization and validation of arrays of geometries.
1164-1168
: Reduce flakiness: replace fixed sleeps with a polling helper.Fixed sleeps can be brittle under load. Consider a small polling helper that repeatedly GETs the collection until the attribute status is “available” (with timeout), then proceeds. This will make the tests more deterministic.
Example helper sketch (outside this file):
private function waitForAttributesReady(string $databaseId, string $collectionId, int $timeoutSec = 20): void { $deadline = time() + $timeoutSec; do { $res = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}", [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]); $ready = 200 === $res['headers']['status-code'] && array_reduce($res['body']['attributes'] ?? [], fn($ok, $a) => $ok && ($a['status'] ?? '') === 'available', true); if ($ready) return; usleep(250_000); } while (time() < $deadline); $this->fail('Attributes not ready before timeout'); }Then call this instead of sleep().
Also applies to: 1299-1312, 1435-1447, 1590-1601
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (4)
composer.lock
is excluded by!**/*.lock
docs/references/databases/create-line-attribute.md
is excluded by!docs/references/**
docs/references/databases/create-point-attribute.md
is excluded by!docs/references/**
docs/references/databases/create-polygon-attribute.md
is excluded by!docs/references/**
📒 Files selected for processing (30)
app/init/constants.php
(1 hunks)app/init/database/filters.php
(1 hunks)app/init/database/formats.php
(1 hunks)src/Appwrite/GraphQL/Types/Mapper.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php
(1 hunks)src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php
(2 hunks)src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php
(2 hunks)src/Appwrite/Utopia/Response.php
(6 hunks)src/Appwrite/Utopia/Response/Model/AttributeLine.php
(1 hunks)src/Appwrite/Utopia/Response/Model/AttributeList.php
(1 hunks)src/Appwrite/Utopia/Response/Model/AttributePoint.php
(1 hunks)src/Appwrite/Utopia/Response/Model/AttributePolygon.php
(1 hunks)src/Appwrite/Utopia/Response/Model/Collection.php
(1 hunks)src/Appwrite/Utopia/Response/Model/ColumnLine.php
(1 hunks)src/Appwrite/Utopia/Response/Model/ColumnList.php
(1 hunks)src/Appwrite/Utopia/Response/Model/ColumnPoint.php
(1 hunks)src/Appwrite/Utopia/Response/Model/ColumnPolygon.php
(1 hunks)src/Appwrite/Utopia/Response/Model/Table.php
(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomClientTest.php
(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php
(1 hunks)tests/e2e/Services/GraphQL/Base.php
(4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
PR: appwrite/appwrite#9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php:57-59
Timestamp: 2025-06-19T09:20:03.312Z
Learning: In table-related endpoints (such as `src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php`), parameter descriptions should use "table" and "row" terminology instead of "collection" and "document" for clarity and consistency.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php
🧬 Code graph analysis (24)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (5)
src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php (1)
Collections
(68-173)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)createAttribute
(287-447)src/Appwrite/Utopia/Response.php (3)
Response
(157-981)__construct
(419-618)dynamic
(689-722)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Utopia/Response/Model/AttributeLine.php (2)
getName
(45-48)__construct
(9-34)
src/Appwrite/Utopia/Response/Model/Collection.php (1)
src/Appwrite/Utopia/Response.php (1)
Response
(157-981)
src/Appwrite/Utopia/Response/Model/AttributeList.php (1)
src/Appwrite/Utopia/Response.php (1)
Response
(157-981)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (4)
getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (4)
getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)
src/Appwrite/Utopia/Response/Model/Table.php (1)
src/Appwrite/Utopia/Response.php (1)
Response
(157-981)
src/Appwrite/Utopia/Response/Model/ColumnList.php (1)
src/Appwrite/Utopia/Response.php (1)
Response
(157-981)
src/Appwrite/Utopia/Response/Model/ColumnPolygon.php (4)
src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Column.php (1)
Column
(8-85)src/Appwrite/Utopia/Response/Model/ColumnLine.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php (5)
src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php (1)
Collections
(68-173)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)createAttribute
(287-447)src/Appwrite/Utopia/Response.php (3)
Response
(157-981)__construct
(419-618)dynamic
(689-722)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Utopia/Response/Model/AttributePolygon.php (2)
getName
(45-48)__construct
(9-34)
src/Appwrite/Utopia/Response/Model/ColumnPoint.php (5)
src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Column.php (1)
Column
(8-85)src/Appwrite/Utopia/Response/Model/AttributePoint.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)src/Appwrite/Utopia/Response/Model/ColumnLine.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)
src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php (7)
src/Appwrite/Platform/Modules/Databases/Services/Http.php (1)
Http
(11-27)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (2)
Create
(20-89)getName
(22-25)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (2)
Create
(20-89)getName
(22-25)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php (2)
Create
(20-89)getName
(22-25)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php (2)
Update
(20-92)getName
(22-25)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php (2)
Update
(19-91)getName
(21-24)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php (2)
Update
(20-92)getName
(22-25)
src/Appwrite/Utopia/Response/Model/ColumnLine.php (4)
src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Column.php (1)
Column
(8-85)src/Appwrite/Utopia/Response/Model/ColumnList.php (3)
__construct
(10-40)getName
(47-50)getType
(57-60)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php (5)
src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php (1)
Tables
(72-185)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php (4)
Create
(15-64)getName
(17-20)getResponseModel
(22-25)__construct
(27-63)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (4)
getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)
src/Appwrite/Utopia/Response.php (8)
src/Appwrite/Utopia/Response/Model/AttributeLine.php (1)
AttributeLine
(7-59)src/Appwrite/Utopia/Response/Model/AttributeList.php (1)
AttributeList
(8-61)src/Appwrite/Utopia/Response/Model/AttributePoint.php (1)
AttributePoint
(7-59)src/Appwrite/Utopia/Response/Model/AttributePolygon.php (1)
AttributePolygon
(7-59)src/Appwrite/Utopia/Response/Model/ColumnLine.php (1)
ColumnLine
(7-59)src/Appwrite/Utopia/Response/Model/ColumnList.php (1)
ColumnList
(8-61)src/Appwrite/Utopia/Response/Model/ColumnPoint.php (1)
ColumnPoint
(7-59)src/Appwrite/Utopia/Response/Model/ColumnPolygon.php (1)
ColumnPolygon
(7-59)
src/Appwrite/Utopia/Response/Model/AttributePoint.php (6)
src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Attribute.php (1)
Attribute
(8-85)src/Appwrite/Utopia/Response/Model/AttributeLine.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)src/Appwrite/Utopia/Response/Model/AttributeList.php (3)
__construct
(10-40)getName
(47-50)getType
(57-60)src/Appwrite/Utopia/Response/Model/AttributePolygon.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)
src/Appwrite/Utopia/Response/Model/AttributePolygon.php (6)
src/Appwrite/Utopia/Response.php (1)
Response
(157-981)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Attribute.php (1)
Attribute
(8-85)src/Appwrite/Utopia/Response/Model/AttributeLine.php (2)
getName
(45-48)getType
(55-58)src/Appwrite/Utopia/Response/Model/AttributeList.php (2)
getName
(47-50)getType
(57-60)src/Appwrite/Utopia/Response/Model/AttributePoint.php (2)
getName
(45-48)getType
(55-58)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php (6)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)updateAttribute
(449-656)src/Appwrite/Utopia/Response.php (3)
Response
(157-981)__construct
(419-618)dynamic
(689-722)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php (5)
Update
(20-92)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-91)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php (5)
Update
(20-92)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-91)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (4)
getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Utopia/Response/Model/AttributePoint.php (2)
getName
(45-48)__construct
(9-34)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)updateAttribute
(449-656)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php (5)
Update
(19-91)getName
(21-24)getResponseModel
(26-29)__construct
(31-71)action
(73-90)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php (5)
Update
(20-92)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-91)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (4)
getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Utopia/Response/Model/AttributeLine.php (2)
getName
(45-48)__construct
(9-34)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)updateAttribute
(449-656)src/Appwrite/Utopia/Response.php (3)
Response
(157-981)__construct
(419-618)dynamic
(689-722)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php (5)
Update
(19-91)getName
(21-24)getResponseModel
(26-29)__construct
(31-71)action
(73-90)src/Appwrite/Utopia/Response/Model/AttributePolygon.php (2)
getName
(45-48)__construct
(9-34)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client
(8-328)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (6)
Action
(26-657)getResponseModel
(36-36)setHttpPath
(38-44)getSdkNamespace
(77-80)getSdkGroup
(69-72)createAttribute
(287-447)src/Appwrite/Utopia/Response.php (3)
Response
(157-981)__construct
(419-618)dynamic
(689-722)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php (5)
Create
(20-89)getName
(22-25)getResponseModel
(27-30)__construct
(32-72)action
(74-88)src/Appwrite/Utopia/Response/Model/AttributePoint.php (2)
getName
(45-48)__construct
(9-34)
tests/e2e/Services/Databases/Legacy/DatabasesCustomClientTest.php (1)
tests/e2e/Client.php (1)
Client
(8-328)
src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php (3)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php (1)
Create
(15-64)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php (1)
Create
(15-64)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php (1)
Create
(15-64)
src/Appwrite/Utopia/Response/Model/AttributeLine.php (6)
src/Appwrite/Utopia/Response.php (2)
Response
(157-981)__construct
(419-618)src/Appwrite/Utopia/Response/Model.php (2)
Model
(7-189)addRule
(87-99)src/Appwrite/Utopia/Response/Model/Attribute.php (1)
Attribute
(8-85)src/Appwrite/Utopia/Response/Model/AttributeList.php (3)
__construct
(10-40)getName
(47-50)getType
(57-60)src/Appwrite/Utopia/Response/Model/AttributePoint.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)src/Appwrite/Utopia/Response/Model/AttributePolygon.php (3)
__construct
(9-34)getName
(45-48)getType
(55-58)
⏰ 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). (3)
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
), | ||
)) | ||
->param('databaseId', '', new UID(), 'Database ID.') | ||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc nit: “table” vs “collection”.
Same wording issue as in the Polygon endpoint; recommend switching to “collection”.
- ->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
+ ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Databases service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
📝 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.
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') | |
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Databases service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') |
🤖 Prompt for AI Agents
In
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php
around line 62, the param description erroneously uses the word "table"; update
the string to use "collection" instead (e.g., "Collection ID. You can create a
new collection using the Database service [server
integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).")
so the wording is consistent with the rest of the API docs.
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void | ||
{ | ||
$attribute = $this->updateAttribute( | ||
databaseId: $databaseId, | ||
collectionId: $collectionId, | ||
key: $key, | ||
dbForProject: $dbForProject, | ||
queueForEvents: $queueForEvents, | ||
type: Database::VAR_LINESTRING, | ||
default: $default, | ||
required: $required, | ||
newKey: $newKey | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Same upstream bug in Action::updateAttribute() impacts line attributes
This call path is also affected by the misplaced-parentheses bug in updateAttribute() described in the Point update review. Apply the same fix in Action.php to ensure correct type/filter validation.
Reuse the verification script shared in the Point update comment.
🏁 Script executed:
#!/bin/bash
# Locate the updateAttribute method in attribute Action classes and display surrounding context
rg -nP --type=php --context=5 "function updateAttribute" -g "src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/**/Action.php"
Length of output: 1875
🏁 Script executed:
#!/bin/bash
# Locate the Attributes Action class definition file
FILE=$(fd -g "Action.php" src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes)
echo "Inspecting file: $FILE"
# Show the signature of updateAttribute
grep -nP "protected function updateAttribute" -C2 "$FILE"
# Show code around type validation (misplaced parentheses bug)
grep -nP -C5 "switch\s*\(\$type\)" "$FILE"
grep -nP -C5 "if\s*\(\$filter" "$FILE"
Length of output: 1324
🏁 Script executed:
#!/bin/bash
# Extract updateAttribute implementation to inspect type and filter validation
sed -n '430,580p' src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
Length of output: 6749
Fix misplaced parentheses in updateAttribute type and filter checks
The updateAttribute()
implementation in src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
contains two logical errors where the parentheses around the key strings are misplaced. This causes PHP to evaluate the comparison first and then pass a boolean into getAttribute()
, rather than comparing the attribute value to the provided parameter. Please correct both occurrences:
• File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
– Around line 459: type validation
– Around line 462: filter validation for string attributes
Proposed diff:
- if ($attribute->getAttribute(('type') !== $type)) {
+ if ($attribute->getAttribute('type') !== $type) {
throw new Exception($this->getTypeInvalidException());
}
- if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) {
+ if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('filter') !== $filter) {
throw new Exception($this->getTypeInvalidException());
}
These changes ensure that we retrieve the stored 'type'
and 'filter'
attributes before comparing them to $type
and $filter
, matching the fix applied for the Point attribute update path.
🤖 Prompt for AI Agents
In
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
around lines 459 and 462, the comparisons are written so PHP evaluates ($type
=== '...') first and passes a boolean into getAttribute(); change each to
retrieve the stored attribute first then compare it to the incoming parameter
(e.g. $attribute->getAttribute('type') === $type and
$attribute->getAttribute('filter') === $filter), matching the Point attribute
update path so the updated code fetches the attribute values before performing
the equality checks.
public function action(string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, ?string $newKey, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents): void | ||
{ | ||
$attribute = $this->updateAttribute( | ||
databaseId: $databaseId, | ||
collectionId: $collectionId, | ||
key: $key, | ||
dbForProject: $dbForProject, | ||
queueForEvents: $queueForEvents, | ||
type: Database::VAR_POINT, | ||
default: $default, | ||
required: $required, | ||
newKey: $newKey | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Bug upstream in updateAttribute(): broken 'type' and 'filter' checks due to misplaced parentheses
This action delegates to Action::updateAttribute(), which currently has two logic errors:
- Uses $attribute->getAttribute(('type') !== $type) instead of comparing getAttribute('type') to $type.
- Same issue for the 'filter' comparison.
These will cause incorrect validation/exception behavior when updating attributes (including points). Fix in Action.php:
Proposed fix (outside this file):
// src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
// inside updateAttribute():
// before:
if ($attribute->getAttribute(('type') !== $type)) {
throw new Exception($this->getTypeInvalidException());
}
if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) {
throw new Exception($this->getTypeInvalidException());
}
// after:
if ($attribute->getAttribute('type') !== $type) {
throw new Exception($this->getTypeInvalidException());
}
if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('filter') !== $filter) {
throw new Exception($this->getTypeInvalidException());
}
🏁 Script executed:
#!/bin/bash
# Show the offending lines to confirm the fix location
rg -n "getAttribute\(\('type'\)" src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
rg -n "getAttribute\(\('filter'\)" src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
Length of output: 454
Fix misplaced parentheses in updateAttribute type and filter checks
The comparisons for both type
and filter
attributes are currently passing a boolean into getAttribute()
rather than comparing its return value. This will cause incorrect validation and exceptions. Please update the logic in src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
at the following locations:
• Line 473
• Line 477
Proposed diff:
--- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
+++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
@@ -470,7 +470,7 @@ public function updateAttribute(…): Attribute
- if ($attribute->getAttribute(('type') !== $type)) {
+ if ($attribute->getAttribute('type') !== $type) {
throw new Exception($this->getTypeInvalidException());
}
@@ -474,7 +474,7 @@ public function updateAttribute(…): Attribute
- if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute(('filter') !== $filter)) {
+ if ($attribute->getAttribute('type') === Database::VAR_STRING && $attribute->getAttribute('filter') !== $filter) {
throw new Exception($this->getTypeInvalidException());
}
These changes ensure getAttribute('type')
and getAttribute('filter')
are properly compared against $type
and $filter
.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php
around lines 473 to 477, the code mistakenly calls getAttribute() with a boolean
by placing the comparison inside the parentheses; change expressions like
getAttribute('type' == $type) to getAttribute('type') == $type and
getAttribute('filter' == $filter) to getAttribute('filter') == $filter so you
compare the returned attribute value to $type/$filter rather than passing a
boolean into getAttribute(), preserving the existing conditional logic and
exception behavior.
), | ||
)) | ||
->param('databaseId', '', new UID(), 'Database ID.') | ||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User-facing doc nit: “table” vs “collection”.
This is the Collections API; the help text says “create a new table…”. Suggest aligning terminology to “collection” to avoid confusion.
- ->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
+ ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Databases service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
📝 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.
->param('collectionId', '', new UID(), 'Collection ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') | |
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Databases service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') |
🤖 Prompt for AI Agents
In
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php
around line 62, the param help text refers to creating a "table" which is
inconsistent with the Collections API; update the string to say "collection"
(e.g., "Collection ID. You can create a new collection using the Database
service [server
integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).")
so terminology matches the rest of the API docs.
public function __construct() | ||
{ | ||
$this | ||
->setHttpMethod(self::HTTP_REQUEST_METHOD_POST) | ||
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/columns/line') | ||
->desc('Create line column') | ||
->groups(['api', 'database', 'schema']) | ||
->label('event', 'databases.[databaseId].tables.[tableId].columns.[columnId].create') | ||
->label('scope', 'tables.write') | ||
->label('resourceType', RESOURCE_TYPE_DATABASES) | ||
->label('audits.event', 'column.create') | ||
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') | ||
->label('sdk', new Method( | ||
namespace: $this->getSdkNamespace(), | ||
group: $this->getSdkGroup(), | ||
name: self::getName(), | ||
description: '/docs/references/tablesdb/create-line-column.md', | ||
auth: [AuthType::KEY], | ||
responses: [ | ||
new SDKResponse( | ||
code: SwooleResponse::STATUS_CODE_ACCEPTED, | ||
model: $this->getResponseModel(), | ||
) | ||
] | ||
)) | ||
->param('databaseId', '', new UID(), 'Database ID.') | ||
->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreate).') | ||
->param('key', '', new Key(), 'Column Key.') | ||
->param('required', null, new \Utopia\Validator\Boolean(), 'Is column required?') | ||
->param('default', null, new Text(0, 0), 'Default value for column when not provided. Cannot be set when column is required.', true) | ||
->param('array', false, new \Utopia\Validator\Boolean(), 'Is column an array?', true) | ||
->inject('response') | ||
->inject('dbForProject') | ||
->inject('queueForDatabase') | ||
->inject('queueForEvents') | ||
->callback($this->action(...)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Parity with other spatial column endpoints; minor follow-ups
Constructor mirrors Point/Polygon column endpoints (path, labels, SDK metadata, params, injections). Looks good. As a minor check, please verify docs and model registration exist:
- The docs page referenced in the SDK method: /docs/references/tablesdb/create-line-column.md
- Response::MODEL_COLUMN_LINE is registered with a ColumnLine model in Response’s constructor.
Run:
🏁 Script executed:
#!/bin/bash
# Verify model constant and model registration
rg -n "MODEL_COLUMN_LINE"
rg -nP "(?s)class\\s+ColumnLine\\b|new\\s+ColumnLine\\("
# Optionally search for the docs page if docs are in-repo
fd create-line-column.md docs || true
Length of output: 942
Missing SDK documentation for Line column endpoint
- Confirmed that
Response::MODEL_COLUMN_LINE
is declared insrc/Appwrite/Utopia/Response.php
(line 230) and that theColumnLine
model is registered via->setModel(new ColumnLine())
in the same file. - The referenced docs page
/docs/references/tablesdb/create-line-column.md
could not be found in thedocs/
directory. - Please add the markdown file at
docs/references/tablesdb/create-line-column.md
, mirroring the structure and content style of the existing spatial column docs, to ensure complete documentation parity.
🤖 Prompt for AI Agents
In
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php
around lines 27-63, the SDK label references a docs page
'/docs/references/tablesdb/create-line-column.md' that does not exist; create
that markdown file under docs/references/tablesdb/create-line-column.md
following the same structure and conventions as the existing spatial column docs
(title, description, HTTP method/path, parameters with types and descriptions,
example request/response, and SDK response model referencing
Response::MODEL_COLUMN_LINE), ensure links and front-matter match repository
style, and commit the new file so the SDK documentation link resolves.
->addRule('type', [ | ||
'type' => self::TYPE_JSON, | ||
'description' => 'Attribute type.', | ||
'default' => '', | ||
'example' => 'point', | ||
]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'type' rule must be a string, not JSON
The attribute's type field is a literal string value ('point'), but the rule declares TYPE_JSON. This breaks response validation and generated SDK metadata.
- ->addRule('type', [
- 'type' => self::TYPE_JSON,
+ ->addRule('type', [
+ 'type' => self::TYPE_STRING,
'description' => 'Attribute type.',
'default' => '',
'example' => 'point',
])
📝 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.
->addRule('type', [ | |
'type' => self::TYPE_JSON, | |
'description' => 'Attribute type.', | |
'default' => '', | |
'example' => 'point', | |
]) | |
->addRule('type', [ | |
'type' => self::TYPE_STRING, | |
'description' => 'Attribute type.', | |
'default' => '', | |
'example' => 'point', | |
]) |
🤖 Prompt for AI Agents
In src/Appwrite/Utopia/Response/Model/AttributePoint.php around lines 20 to 25,
the rule for 'type' incorrectly uses self::TYPE_JSON while the field is a
literal string ('point'); change the rule to use self::TYPE_STRING and ensure
the default (and/or enum/example) reflects the literal 'point' value so response
validation and SDK metadata treat it as a string.
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ | ||
'content-type' => 'application/json', | ||
'x-appwrite-project' => $this->getProject()['$id'], | ||
], $this->getHeaders()), [ | ||
'documents' => [ | ||
[ | ||
'$id' => ID::unique(), | ||
'name' => 'Invalid Polygon', | ||
'location' => [10.0, 20.0], | ||
'area' => [ | ||
[10.0, 20.0], | ||
[11.0, 20.0] | ||
] | ||
] | ||
], | ||
]); | ||
|
||
$this->assertEquals(201, $response['headers']['status-code']); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Polygon with two points should fail validation.
A polygon requires a ring (closed, minimum 4 distinct points plus closure). Expect 400, not 201.
Apply this diff:
- $this->assertEquals(201, $response['headers']['status-code']);
+ $this->assertEquals(400, $response['headers']['status-code']);
🤖 Prompt for AI Agents
In tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php around
lines 6424 to 6442, the test is creating a document with an invalid Polygon
(only two points) but asserts a 201 Created; update the test to expect a 400 Bad
Request instead. Change the assertion to check for status-code 400 (and
optionally assert the response body contains a validation error for the polygon
field) so the test verifies the server properly rejects polygons that are not
closed and have fewer than the required points.
public const string UPDATE_POINT_ATTRIBUTE = 'update_point_attribute'; | ||
public const string UPDATE_LINE_ATTRIBUTE = 'update_line_attribute'; | ||
public const string UPDATE_POLYGON_ATTRIBUTE = 'update_polygon_attribute'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing update mutations for spatial attributes in getQuery().
UPDATE_POINT/LINE/POLYGON_ATTRIBUTE constants exist, but the switch lacks cases. Add them so tests can exercise updates.
case self::UPDATE_DATETIME_ATTRIBUTE:
return 'mutation updateDatetimeAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateDatetimeAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
required
default
}
}';
+case self::UPDATE_POINT_ATTRIBUTE:
+ return 'mutation updatePointAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!){
+ databasesUpdatePointAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required) {
+ required
+ }
+ }';
+case self::UPDATE_LINE_ATTRIBUTE:
+ return 'mutation updateLineAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!){
+ databasesUpdateLineAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required) {
+ required
+ }
+ }';
+case self::UPDATE_POLYGON_ATTRIBUTE:
+ return 'mutation updatePolygonAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!){
+ databasesUpdatePolygonAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required) {
+ required
+ }
+ }';
🤖 Prompt for AI Agents
In tests/e2e/Services/GraphQL/Base.php around lines 62 to 64, the constants
UPDATE_POINT_ATTRIBUTE, UPDATE_LINE_ATTRIBUTE and UPDATE_POLYGON_ATTRIBUTE are
defined but getQuery() has no switch cases for them; add three switch cases that
return the correct GraphQL update mutation names (match the existing naming
convention used for other attributes, e.g. the mutation string for
UPDATE_POINT_ATTRIBUTE should be the same pattern as other update_* constants),
ensure the cases use the constant names exactly and return the corresponding
mutation query string so the tests can exercise point/line/polygon attribute
updates.
public const string CREATE_POINT_COLUMN = 'create_point_column'; | ||
public const string CREATE_LINE_COLUMN = 'create_line_column'; | ||
public const string CREATE_POLYGON_COLUMN = 'create_polygon_column'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Missing create mutations for spatial columns in TablesDB.
CREATE_POINT/LINE/POLYGON_COLUMN constants are present, but the switch offers no cases. Add them analogous to existing column creators.
case self::CREATE_DATETIME_COLUMN:
return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){
tablesDBCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) {
key
required
default
array
}
}';
+case self::CREATE_POINT_COLUMN:
+ return 'mutation createPointColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreatePointColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
+case self::CREATE_LINE_COLUMN:
+ return 'mutation createLineColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreateLineColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
+case self::CREATE_POLYGON_COLUMN:
+ return 'mutation createPolygonColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreatePolygonColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
🏁 Script executed:
#!/bin/bash
rg -nP "tablesDBCreate(Point|Line|Polygon)Column\s*\(" -C2 src
Length of output: 64
🏁 Script executed:
#!/bin/bash
# Verify existing mapping for datetime and check for spatial column cases in GraphQL Base
rg -nP "case self::CREATE_DATETIME_COLUMN" -C3 tests/e2e/Services/GraphQL/Base.php
rg -nP "case self::CREATE_POINT_COLUMN" -C3 tests/e2e/Services/GraphQL/Base.php
rg -nP "case self::CREATE_LINE_COLUMN" -C3 tests/e2e/Services/GraphQL/Base.php
rg -nP "case self::CREATE_POLYGON_COLUMN" -C3 tests/e2e/Services/GraphQL/Base.php
rg -nP "switch\s*\(.*CREATE_.*_COLUMN.*\)" -C5 tests/e2e/Services/GraphQL/Base.php
Length of output: 919
Add missing spatial column mutation cases in GraphQL Base switch
The CREATE_POINT_COLUMN
, CREATE_LINE_COLUMN
, and CREATE_POLYGON_COLUMN
constants are defined in tests/e2e/Services/GraphQL/Base.php
(lines 81–83), but the switch
on column-creation type only handles existing cases such as CREATE_DATETIME_COLUMN
(around line 936) and never returns the corresponding GraphQL mutation strings for spatial columns. As a result, attempts to create point, line, or polygon columns will fall through without generating the proper mutation.
Please add the following cases (modeled on the existing datetime case) to the switch
in tests/e2e/Services/GraphQL/Base.php
:
case self::CREATE_DATETIME_COLUMN:
return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){
tablesDBCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) {
key
required
default
array
}
}';
+case self::CREATE_POINT_COLUMN:
+ return 'mutation createPointColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreatePointColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
+case self::CREATE_LINE_COLUMN:
+ return 'mutation createLineColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreateLineColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
+case self::CREATE_POLYGON_COLUMN:
+ return 'mutation createPolygonColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){
+ tablesDBCreatePolygonColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) {
+ key
+ required
+ array
+ status
+ }
+ }';
Locations to update:
- tests/e2e/Services/GraphQL/Base.php around line 936 (after the
CREATE_DATETIME_COLUMN
case).
These additions ensure that spatial column mutations are correctly generated for TablesDB.
📝 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.
public const string CREATE_POINT_COLUMN = 'create_point_column'; | |
public const string CREATE_LINE_COLUMN = 'create_line_column'; | |
public const string CREATE_POLYGON_COLUMN = 'create_polygon_column'; | |
case self::CREATE_DATETIME_COLUMN: | |
return 'mutation createDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String, $array: Boolean){ | |
tablesDBCreateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default, array: $array) { | |
key | |
required | |
default | |
array | |
} | |
}'; | |
case self::CREATE_POINT_COLUMN: | |
return 'mutation createPointColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){ | |
tablesDBCreatePointColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) { | |
key | |
required | |
array | |
status | |
} | |
}'; | |
case self::CREATE_LINE_COLUMN: | |
return 'mutation createLineColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){ | |
tablesDBCreateLineColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) { | |
key | |
required | |
array | |
status | |
} | |
}'; | |
case self::CREATE_POLYGON_COLUMN: | |
return 'mutation createPolygonColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $array: Boolean){ | |
tablesDBCreatePolygonColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, array: $array) { | |
key | |
required | |
array | |
status | |
} | |
}'; |
🤖 Prompt for AI Agents
In tests/e2e/Services/GraphQL/Base.php around line 936, the switch that
generates column-creation GraphQL mutations is missing cases for
CREATE_POINT_COLUMN, CREATE_LINE_COLUMN, and CREATE_POLYGON_COLUMN; add three
new case blocks (after the CREATE_DATETIME_COLUMN case) that mirror the existing
CREATE_DATETIME_COLUMN pattern but return the appropriate GraphQL mutation
strings for creating a point, line, and polygon column respectively (use the
same field names and structure as the datetime case, substituting the spatial
column type names and any required args), and ensure each case returns the
mutation string and breaks.
public const string UPDATE_POINT_COLUMN = 'update_point_column'; | ||
public const string UPDATE_LINE_COLUMN = 'update_line_column'; | ||
public const string UPDATE_POLYGON_COLUMN = 'update_polygon_column'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing update mutations for spatial columns in TablesDB.
UPDATE_POINT/LINE/POLYGON_COLUMN constants lack getQuery() cases. Add them to keep parity with other column types.
case self::UPDATE_DATETIME_COLUMN:
return 'mutation updateDatetimeColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!, $default: String){
tablesDBUpdateDatetimeColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required, default: $default) {
required
default
}
}';
+case self::UPDATE_POINT_COLUMN:
+ return 'mutation updatePointColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!){
+ tablesDBUpdatePointColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required) {
+ required
+ }
+ }';
+case self::UPDATE_LINE_COLUMN:
+ return 'mutation updateLineColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!){
+ tablesDBUpdateLineColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required) {
+ required
+ }
+ }';
+case self::UPDATE_POLYGON_COLUMN:
+ return 'mutation updatePolygonColumn($databaseId: String!, $tableId: String!, $key: String!, $required: Boolean!){
+ tablesDBUpdatePolygonColumn(databaseId: $databaseId, tableId: $tableId, key: $key, required: $required) {
+ required
+ }
+ }';
🤖 Prompt for AI Agents
In tests/e2e/Services/GraphQL/Base.php around lines 95 to 97, the new constants
UPDATE_POINT_COLUMN, UPDATE_LINE_COLUMN and UPDATE_POLYGON_COLUMN were added but
not handled in the TablesDB getQuery() switch/case; add corresponding getQuery()
cases for each constant mirroring the existing update-column handling (construct
the proper UPDATE mutation string for spatial point/line/polygon columns exactly
like other column types), ensuring they return the correct GraphQL update
mutation query and fall through to the same logic/structure used for other
UPDATE_*_COLUMN cases.
What does this PR do?
(Provide a description of what this PR does and why it's needed.)
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
Related PRs and Issues
Checklist