Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (12)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the 📝 WalkthroughWalkthroughThis PR adds inline schema validation for collection/table creation and introduces two new validators: Appwrite\Utopia\Database\Validator\Attributes and Appwrite\Utopia\Database\Validator\Indexes. The Collections Create flow now accepts Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–75 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
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. Comment |
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (8)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php (1)
129-137:getParentNotFoundException()duplicatesgetNotFoundException().Both methods return identical values (
COLLECTION_NOT_FOUND/TABLE_NOT_FOUND). Consider reusinggetNotFoundException()or removing one method to avoid confusion and maintenance overhead.- /** - * Get the appropriate parent level not found exception. - */ - protected function getParentNotFoundException(): string - { - return $this->isCollectionsAPI() - ? Exception::COLLECTION_NOT_FOUND - : Exception::TABLE_NOT_FOUND; - } + /** + * Get the appropriate parent level not found exception. + */ + protected function getParentNotFoundException(): string + { + return $this->getNotFoundException(); + }src/Appwrite/Utopia/Database/Validator/Attributes.php (2)
163-169: Consider validating enum elements are unique strings.The enum validation checks for a non-empty
elementsarray but doesn't verify that each element is a string or that elements are unique, which could lead to issues when creating the attribute in the database.// Validate enum elements if format is enum if (isset($attribute['format']) && $attribute['format'] === APP_DATABASE_ATTRIBUTE_ENUM) { if (!isset($attribute['elements']) || !is_array($attribute['elements']) || empty($attribute['elements'])) { $this->message = "Attribute '" . $attribute['key'] . "' with enum format must have 'elements' array"; return false; } + foreach ($attribute['elements'] as $element) { + if (!is_string($element)) { + $this->message = "Attribute '" . $attribute['key'] . "' enum elements must be strings"; + return false; + } + } + if (count($attribute['elements']) !== count(array_unique($attribute['elements']))) { + $this->message = "Attribute '" . $attribute['key'] . "' has duplicate enum elements"; + return false; + } }
151-161: Default value type is not validated against the attribute type.The validator checks for conflicts between
defaultandrequired/array, but does not verify that the default value's type matches the attribute's declared type. For example,{ type: 'boolean', default: 'hello' }would pass validation.Consider adding type validation for default values, or verify that downstream processing handles type mismatches gracefully.
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (3)
6783-6959: Confirm async behavior assumptions for attributes/indexes created via collection createThese assertions assume that attributes and indexes are already in
'available'status immediately after the collection create (nosleep/assertEventuallylike the rest of this file uses for attribute/index creation). If the new multi-create flow still schedules schema work asynchronously, these expectations may be flaky on slower CI or under load.If the implementation really does block until attributes and indexes are fully built, it would be good to confirm that and maybe add a brief comment here. Otherwise, consider wrapping the
/attributesand/indexeschecks inassertEventuallyto poll until all expected keys reach'available'before asserting their metadata.
6960-7111: Nice negative coverage; consider asserting error types and one or two more edge casesThis error suite is useful and focused: invalid type, index referencing unknown attribute, required+default, duplicate keys, and a system-attribute index happy-path. Two optional polish ideas:
- For at least one or two of these cases, also assert the error
type(e.g.AppwriteException::GENERAL_ARGUMENT_INVALID/ATTRIBUTE_DEFAULT_UNSUPPORTED) to lock in the contract beyond just400.- Optionally add one more index-schema check (e.g. mismatched
attributes/orderslength or an invalidtypeconstant) to exercise the newIndexesvalidator a bit more.Not blocking, but would strengthen regression detection around the new validators.
7113-7202: Enum attribute happy-path looks good; optional: add one creation-time failure caseThe enum creation flow and the valid/invalid document checks look correct and align with the new
"type" = string + "format" = enum + "elements"contract. If you want to harden this area further, you could add a single collection-create failure case here (e.g. enum with emptyelements, orformat = 'enum'but missingelements) so creation-time enum validation is exercised as well, not only via the update tests above.Purely optional; current coverage is already solid.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
122-136: Consider clarifying the variable naming for consistency.The variable
$collectionAttributesis later passed tobuildIndexDocumentas$attributeDocuments(line 133 → line 295). While functionally correct, the naming inconsistency can cause confusion during maintenance.Consider renaming for clarity:
- $collectionAttributes = []; - $attributeDocuments = []; + $attributesForCollection = []; + $attributeMetadataDocuments = []; foreach ($attributes as $attributeDef) { $attrDoc = $this->buildAttributeDocument($database, $collection, $attributeDef, $dbForProject); - $collectionAttributes[] = $attrDoc['collection']; - $attributeDocuments[] = $attrDoc['document']; + $attributesForCollection[] = $attrDoc['collection']; + $attributeMetadataDocuments[] = $attrDoc['document']; }Then update the corresponding usages on lines 133, 141, and 157.
154-167: Consider aligning collection creation with the transactional pattern used for document operations.The codebase uses
withTransaction()for multi-step document operations (Upsert, Update, Delete, Create), but collection-level operations (Create, Update, Delete) do not. Since collection creation involves multiple dependent steps—creating the collection document, building the schema, and creating attribute/index metadata documents—consider whether wrapping these operations in a transaction would improve consistency safety, consistent with the pattern established for document operations.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php(1 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(4 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php(2 hunks)src/Appwrite/Utopia/Database/Validator/Attributes.php(1 hunks)src/Appwrite/Utopia/Database/Validator/Indexes.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 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/Http/TablesDB/Tables/Create.phpsrc/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php
🧬 Code graph analysis (3)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
Attributes(9-211)src/Appwrite/Utopia/Database/Validator/Indexes.php (1)
Indexes(9-190)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php (5)
getFormatUnsupportedException(165-170)isCollectionsAPI(57-62)getDefaultUnsupportedException(155-160)getParentNotFoundException(85-90)getStructureException(125-130)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php (3)
isCollectionsAPI(67-72)getParentNotFoundException(103-108)getStructureException(163-168)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
🪛 GitHub Actions: Linter
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
[error] 1-1: PSR-12: no_unused_imports violation detected by Pint. Remove unused imports.
⏰ 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
🔇 Additional comments (10)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php (1)
10-12: LGTM!The new
columnsandindexesparameters are properly defined with appropriate validators and optional defaults. The descriptions correctly use "column" terminology consistent with the Tables API context. Based on learnings, this aligns with the expected table/row terminology for TablesDB endpoints.Also applies to: 65-66
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php (1)
108-127: LGTM!The new exception helper methods follow the established pattern from sibling Action classes and provide consistent context-aware exception mapping between Collections and Tables APIs.
Also applies to: 139-167
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
1-46: LGTM!The validator structure is well-designed with appropriate max limits, clear error messages, and proper implementation of the Validator interface. The
isArray()returningfalsewhilegetType()returnsTYPE_ARRAYis the correct pattern for this framework.Also applies to: 66-77, 197-210
src/Appwrite/Utopia/Database/Validator/Indexes.php (3)
1-38: LGTM!The class setup, imports, and constructor are well-structured. The supported types and orders are correctly defined based on the Database constants.
58-168: Solid validation implementation.The
isValidmethod is thorough and covers all necessary validations:
- Array type check
- Max count enforcement
- Required field presence
- Key validation and duplicate detection
- Type validation against supported types
- Attribute validation including special system attributes
- Optional orders and lengths validation
The error messages are descriptive and include positional context for debugging.
176-189: This is not an inconsistency. TheisArray()andgetType()methods serve different purposes.getType()returns the expected PHP data type (TYPE_ARRAY), whileisArray()indicates framework-level validator behavior. The Operation validator (which returnsisArray() = truewithgetType() = TYPE_OBJECT) confirms these are independent concerns. The Indexes validator correctly implements both methods according to the framework contract.src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (4)
46-88: LGTM!The constructor properly sets up the new
attributesandindexesparameters with appropriate validators and documentation.
184-288: LGTM!The
buildAttributeDocumentmethod is well-structured and handles various attribute types including strings, enums, ranges, and relationships. The validation for required/array defaults and format checks are appropriate.
295-364: LGTM!The
buildIndexDocumentmethod correctly validates that indexed attributes exist, prevents indexing on relationship attributes, and handles array attribute length/order overrides appropriately.
148-149: The Exception constructor signature is verified as correct. The Appwrite\Extend\Exception class has the signature:public function __construct( string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null, ?string $view = null )The code at lines 148-149 correctly passes the error type as the first parameter and the message from the IndexException as the second parameter, which aligns with the constructor's expected signature. The message propagates properly through the constructor to the parent Exception class.
✨ Benchmark results
⚡ Benchmark Comparison
|
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
136-142: Format validation should be restricted to string types.String-specific formats (
enum,ip,url) are validated for all attribute types. This allows invalid combinations like{ type: 'integer', format: 'email' }to pass validation.// Validate format if provided - if (isset($attribute['format']) && $attribute['format'] !== '') { + if ($attribute['type'] === Database::VAR_STRING && isset($attribute['format']) && $attribute['format'] !== '') { if (!in_array($attribute['format'], $this->supportedFormats)) { $this->message = "Invalid format for attribute '" . $attribute['key'] . "': " . $attribute['format']; return false; } }src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (1)
22-22: Remove unused import causing pipeline failure.
StructureExceptionis imported but never used in this file.-use Utopia\Database\Exception\Structure as StructureException;
🧹 Nitpick comments (4)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
6960-7590: Comprehensive negative‑path validation for attributes, enums, and indexes; consider data‑driven consolidationThe new tests around invalid attribute types/defaults, reserved keys, min/max constraints, enum element/default rules, index key/type/attributes/orders/lengths, and cleanup on failure are thorough and align with the behavior exercised by the per‑attribute tests earlier in this class. From a maintainability standpoint, there’s a fair bit of repetition in the “create DB → create collection with 1 attribute/index → assert 400/201” pattern; over time, you might want to move these cases to a data provider or small helper to keep this already‑large test class from growing harder to navigate. Functionally, the expectations look consistent.
src/Appwrite/Utopia/Database/Validator/Indexes.php (1)
183-201: Inconsistency betweenisArray()andgetType()return values.
isArray()returnsfalsewhilegetType()returnsself::TYPE_ARRAY. This is inconsistent—if the validator expects array input (which it does, per line 60),isArray()should returntrue.public function isArray(): bool { - return false; + return true; }src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
355-368: Inconsistency betweenisArray()andgetType()return values.Same issue as in
Indexes.php:isArray()returnsfalsewhilegetType()returnsTYPE_ARRAY. The validator expects array input, soisArray()should returntrue.public function isArray(): bool { - return false; + return true; }src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (1)
331-339: Consider renaming parameter for clarity.The
$attributeDocumentsparameter receives$collectionAttributesfrom the caller (line 149), which are the "collection" documents frombuildAttributeDocument. The naming is confusing since the codebase uses "attributeDocuments" for storage documents and "collectionAttributes" for schema documents.- protected function buildIndexDocument(Document $database, Document $collection, array $indexDef, array $attributeDocuments, Database $dbForProject): array + protected function buildIndexDocument(Document $database, Document $collection, array $indexDef, array $collectionAttributes, Database $dbForProject): array { $key = $indexDef['key']; $type = $indexDef['type']; $indexAttributes = $indexDef['attributes']; $orders = $indexDef['orders'] ?? []; $lengths = $indexDef['lengths'] ?? []; - $attrKeys = array_map(fn ($a) => $a->getAttribute('key'), $attributeDocuments); + $attrKeys = array_map(fn ($a) => $a->getAttribute('key'), $collectionAttributes);And update remaining references to use
$collectionAttributes.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(4 hunks)src/Appwrite/Utopia/Database/Validator/Attributes.php(1 hunks)src/Appwrite/Utopia/Database/Validator/Indexes.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 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/Http/Databases/Collections/Create.php
🧬 Code graph analysis (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
src/Appwrite/Utopia/Database/Validator/Indexes.php (5)
__construct(35-38)getDescription(47-50)isValid(58-181)isArray(188-191)getType(198-201)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (3)
Attributes(13-369)isValid(70-348)getDescription(59-62)src/Appwrite/Utopia/Database/Validator/Indexes.php (3)
Indexes(9-202)isValid(58-181)getDescription(47-50)
🪛 GitHub Actions: Linter
src/Appwrite/Utopia/Database/Validator/Attributes.php
[error] 1-1: Pint: no_unused_imports violation detected.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
[error] 1-1: Pint: no_unused_imports violation detected.
⏰ 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). (17)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (Users)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: Unit Test
- GitHub Check: scan
🔇 Additional comments (8)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
6783-6958: Strong happy‑path coverage for collection multi‑create; verify attribute/index availability semanticsThe
testCreateCollectionWithAttributesAndIndexestest nicely exercises end‑to‑end behavior: declarative attributes + indexes on create, metadata assertions, and document CRUD including defaults. One thing to double‑check: this test assumes that when the create call returns, all attributes and indexes are already inavailablestatus (no sleeps orassertEventually). If the implementation still relies on async workers for physical schema/index creation, consider switching those availability assertions to an eventual check to avoid flakiness in slower environments.
7810-7993: Relationship validation tests look correct; ensure payload shape matches the create API contractThe relationship validation cases (missing
relatedCollection, missing/invalidrelationType, invalidonDelete, non‑booleantwoWay,array= true, and the final valid many‑to‑one two‑way example) give good coverage for the declarative relationship attribute shape. Just make sure the field names (type=Database::VAR_RELATIONSHIP,relatedCollection,relationType,twoWay,twoWayKey,onDelete) are exactly what the collections create endpoint expects, as they differ from the/attributes/relationshippayload used elsewhere; if that contract ever changes, these tests will be the first to break.src/Appwrite/Utopia/Database/Validator/Indexes.php (1)
58-181: Comprehensive validation logic looks correct.The
isValidmethod properly validates required fields, key format, duplicates, type constraints, attributes array, orders, and lengths. Error messages are descriptive and include context (index key/position).src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
70-347: Thorough attribute validation logic.The validation comprehensively covers all attribute types, field constraints, type-specific options (size for strings, min/max for numerics, enum elements, relationship metadata), and default value consistency. Error messages are clear and actionable.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (4)
214-324: Well-structured attribute document builder.The method properly handles type-specific logic (string size defaults, enum elements, numeric ranges, relationship options) and validates constraints (format availability, default value conflicts, spatial support, related collection existence).
420-436: Cleanup logic handles failures gracefully.The method correctly attempts both deletions independently, ignoring errors to ensure best-effort cleanup. This prevents cascading failures during error recovery.
196-197: Cache invalidation placed correctly after successful creation.The cache purge for both the document and collection occurs after all database operations succeed, ensuring stale cache entries are cleared.
140-143: This review comment is incorrect. TheExceptionconstructor properly supports two arguments:Exception($type, $message). Line 142 correctly passes the error type constant fromgetLimitException()as the first argument and a custom message as the second. The constructor signature (lines 387-393 insrc/Appwrite/Extend/Exception.php) explicitly definesstring $message = nullas the second parameter, allowing callers to override the default error description.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (7)
src/Appwrite/Utopia/Database/Validator/Attributes.php (2)
197-271: Defaults for relationship and spatial attributes are neither validated nor explicitly rejected.The default-value switch only covers
string,integer,float,boolean, anddatetimetypes. Forrelationshipand spatial types (point,linestring,polygon), any provideddefault:
- Passes
isValid()without type checking.- Is forwarded into the attribute documents unmodified.
- Relies on the adapter to error out (or silently ignore), which can lead to confusing server-side failures instead of a clear 4xx validation error.
It would be safer to make the behavior explicit for these types:
- Either disallow non-null defaults (and fail fast with a clear message), or
- Add type-specific validation branches (e.g., shape of a spatial object, nullable semantics for relationships).
For example, if defaults should not be supported:
// Validate default value matches attribute type if (isset($attribute['default'])) { switch ($attribute['type']) { @@ case Database::VAR_DATETIME: // existing logic... break; + + case Database::VAR_RELATIONSHIP: + case Database::VAR_POINT: + case Database::VAR_LINESTRING: + case Database::VAR_POLYGON: + $this->message = "Default value is not supported for attribute type '" . $attribute['type'] . "'"; + return false; } }Aligning this with the actual adapter capabilities will prevent hard-to-debug runtime errors.
127-133: Enum elements are not checked against the attributesize, which can yield unsatisfiable enums.You validate:
- String
sizebounds for the attribute (lines 127-133).- Each enum element is a non-empty string and ≤
Database::LENGTH_KEY(lines 281-289).However, you do not ensure that each enum element’s length is ≤ the attribute’s configured
size. This allows definitions where some enum values literally cannot be stored in the column (e.g.size = 4, element"apple").To avoid creating impossible schemas, consider adding a size check inside the enum loop:
- foreach ($attribute['elements'] as $elementIndex => $element) { + $attrSize = $attribute['size'] ?? APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH; + foreach ($attribute['elements'] as $elementIndex => $element) { if (!is_string($element) || empty($element)) { $this->message = "Enum element at index $elementIndex for attribute '" . $attribute['key'] . "' must be a non-empty string"; return false; } if (strlen($element) > Database::LENGTH_KEY) { $this->message = "Enum element at index $elementIndex for attribute '" . $attribute['key'] . "' exceeds maximum length of " . Database::LENGTH_KEY . " characters"; return false; } + if (strlen($element) > $attrSize) { + $this->message = "Enum element at index $elementIndex for attribute '" . $attribute['key'] . "' exceeds attribute size of $attrSize characters"; + return false; + } }This keeps enum definitions consistent with the underlying column size.
Also applies to: 273-299
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
82-83: Attributes param description is slightly out of sync with supported attribute types.
AttributesValidatorsupports additional types like spatial (point,linestring,polygon), but the parameter description only mentionsstring, integer, float, boolean, datetime, relationship.To avoid confusion for SDK users and API consumers, consider updating the description to reflect the full set of supported types (or link to a single source of truth in the docs):
- ->param('attributes', [], new AttributesValidator(), 'Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, integer, float, boolean, datetime, relationship), size (integer, required for string type), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options.', true) + ->param('attributes', [], new AttributesValidator(), 'Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, integer, float, boolean, datetime, relationship, point, linestring, polygon), size (integer, required for string type), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options.', true)This keeps the public API contract aligned with the validator.
122-143: Unify rollback behavior by usingcleanup()instead of scattereddeleteDocument()calls.Failure handling around collection creation is mostly correct, but inconsistent:
- In several places (lines 133-136, 139-142, 152-155, 166-176), you call
$dbForProject->deleteDocument($databaseKey, $collection->getId());directly.- The
cleanup()helper (lines 419-435) encapsulates safe rollback of both the DB collection and the metadata document, swallowing any cleanup errors so they don’t mask the original exception.- Currently, if
deleteDocument()itself throws (e.g. connection issue), that secondary error can override the original validation/adapter failure.To make rollback behavior consistent and less error-prone, consider replacing those direct
deleteDocument()calls withcleanup()wherever you’ve already computed$databaseKeyand$collectionKey:- } catch (\Throwable $e) { - $dbForProject->deleteDocument($databaseKey, $collection->getId()); - throw $e; - } + } catch (\Throwable $e) { + $this->cleanup($dbForProject, $databaseKey, $collectionKey, $collection->getId()); + throw $e; + }Apply the same pattern for:
- Attribute-building failure (lines 133-136).
- Index limit check (lines 139-142).
- Index-building failure (lines 152-155).
createCollection()failures (lines 166-176).
cleanup()already guardsdeleteCollection()/deleteDocument()intry/catch, so calling it before the DB collection exists is safe (the delete will just be ignored), and you avoid leaking cleanup errors to API consumers.Also applies to: 147-155, 166-176, 181-193, 419-435
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (3)
7183-7606: Enum and general attribute edge-case coverage is comprehensive but densely packedThe new tests around enum attributes and general attribute validation edge cases (reserved keys, type/default mismatches, min/max inconsistencies, array+default, invalid
format, etc.) provide very thorough coverage of the validator. The only nit is thattestCreateCollectionAttributeValidationEdgeCasesandtestCreateCollectionEnumValidationEdgeCasesbundle many unrelated assertions into single methods, which can make failures harder to localize when something breaks. If this grows further, consider splitting into smaller tests or using data providers to keep individual scenarios more isolated, while reusing setup.
7608-8011: Index and relationship validation tests are solid; double-check naming consistency for relationship fieldsThe index validation tests hit the important edge cases (duplicate keys, invalid types, empty attributes, orders/lengths mismatch, invalid order values, and a valid compound index) and look correct. Relationship validation also covers missing
relatedCollection, missing/invalidrelationType, invalidonDelete,arraymisuse, badtwoWay, and a valid many-to-one two-way relationship.One design point to verify: in these multi-create payloads, relationship attributes use
relatedCollection+relationTypealongsidetype => Database::VAR_RELATIONSHIP, whereas the dedicated relationship-attribute endpoints elsewhere in the suite userelatedCollectionIdandtypefor the relation kind. If the public API is meant to accept both styles or intentionally diverge here, all good; otherwise, consider aligning field names or documenting the difference clearly to avoid confusion for SDK/CLI users.
8013-8280: Datetime/float/missing-field validation tests match existing rules; consider asserting error types for stronger guaranteesThe new tests for datetime defaults, float min/max + defaults, and missing required fields in attribute/index definitions correctly mirror the validation rules exercised earlier in the file (e.g., date format constraints, numeric range checks, and mandatory keys in definitions). The HTTP status expectations (400 vs 201) look appropriate and should guard against regressions in the new validators.
If you want these tests to catch more subtle changes in error semantics later, you might also assert the error
type(e.g., specific Appwrite exception codes) in a few representative negative cases, similar to other tests in this class. That’s optional but can help ensure the validator fails for the right reasons, not just with a generic 400.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)src/Appwrite/Utopia/Database/Validator/Attributes.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
src/Appwrite/Utopia/Database/Validator/Indexes.php (5)
__construct(35-38)getDescription(47-50)isValid(58-181)isArray(188-191)getType(198-201)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ 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). (18)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Users)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (2)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
6783-6958: Multi-create happy-path test is strong; verify assumptions about synchronous attribute/index availabilityThe coverage for creating a collection plus attributes and indexes in one call looks good and validates defaults and index wiring end-to-end. The test assumes that right after collection creation,
/attributesand/indexeswill expose all entries withstatus === 'available'. If some database adapters keep attributes/indexes in a transientprocessingstate (like the standalone attribute/index APIs), consider wrapping the attribute/index assertions in anassertEventuallyloop to avoid flakiness; if the new multi-create path guarantees synchronous availability by design, this is fine as-is.
6960-7181: Error-path and cleanup tests for multi-create look correctThe negative tests (invalid attribute type, invalid index target, bad required+default combo, duplicate attribute keys, system-attribute indexing) plus
testCreateCollectionCleanupOnFailuretogether exercise the key validation and cleanup behaviors for the new multi-create flow. HTTP status expectations are consistent with the rest of the suite, and the cleanup check (reusingcollectionIdafter a failed create) is a good safeguard. No functional issues spotted here.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
6960-7110: Consider asserting errortypepayloads in addition to 400 statusThe negative tests for invalid attribute/index/relationship definitions currently only assert
status-code === 400. That will catch validation vs. success, but won’t fail if the implementation starts returning a different error classification (e.g., wrongtypecode or a more generic error).Given these tests are encoding the contract of the new validators, you may want to also assert the specific
body['type'](similar to earlier tests in this class that useAppwriteExceptionconstants) for at least a representative subset of these cases (e.g., invalid type, reserved key, min/max violations, enum/relationship/index edge cases). This would tighten regression coverage without much extra noise.Also applies to: 7182-7605, 7607-7825, 8012-8150, 8152-8279
7273-7500: Large “kitchen‑sink” edge‑case tests might benefit from some structuring
testCreateCollectionAttributeValidationEdgeCases,testCreateCollectionEnumValidationEdgeCases, andtestCreateCollectionIndexValidationEdgeCasespack many unrelated invalid‑input scenarios into single methods. Functionally this works, but the methods are long and a bit hard to scan, and a single early failure prevents later cases from running.Consider either:
- Splitting by concern (e.g., reserved keys vs. numeric ranges vs. defaults vs. array/format, and separate enum/index suites), or
- Grouping related payloads into small data‑driven helpers to keep the individual test bodies shorter.
Not urgent, but it would improve readability and future maintenance of this suite.
Also applies to: 7502-7605, 7607-7825
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ 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). (20)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: Unit Test
- GitHub Check: E2E General Test
- GitHub Check: Benchmark
- GitHub Check: scan
🔇 Additional comments (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
6784-6958: Confirm synchronous availability assumptions for multi‑create attributes/indexesThese assertions rely on attributes and indexes being immediately in
status === 'available'right after the collection create call and before anysleep()/assertEventually, unlike the per‑attribute/index endpoints earlier in this file which are explicitly async. IfCollections::createstill offloads DDL work to background workers, this test may be timing‑sensitive.Please confirm the new multi‑create path is guaranteed to return only after attributes/indexes are fully built, or consider wrapping the attribute/index fetches in an
assertEventuallysimilar to other tests here to avoid flakiness.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
184-196: Verify single-bound min/max handling aligns with persistence layer.The validator now correctly accepts single-bound constraints (only
minor onlymax). EnsurebuildAttributeDocumentin Create.php persists whichever bound(s) are provided.
🧹 Nitpick comments (3)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
114-119: Consider defining reserved keys as a class constant.Reserved keys are hardcoded inline. Extracting to a class constant would improve maintainability and reusability.
+ /** + * @var array<string> Reserved attribute keys that cannot be used + */ + protected const RESERVED_KEYS = ['$id', '$createdAt', '$updatedAt', '$permissions', '$collection']; + ... - $reservedKeys = ['$id', '$createdAt', '$updatedAt', '$permissions', '$collection']; - if (in_array($attribute['key'], $reservedKeys)) { + if (in_array($attribute['key'], self::RESERVED_KEYS)) {src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
227-231: Consider documenting the default string size.The default size of 256 for strings is applied silently when not specified. Consider documenting this default in the parameter description or throwing an error since the validator requires
sizefor string types.The validator at lines 128-132 in Attributes.php requires
sizeto be set for string types, so this fallback may be unreachable if validation runs first.
419-435: Consider adding error logging in cleanup.Silently swallowing cleanup errors is appropriate to prevent cascading failures, but logging these errors would aid debugging in production.
protected function cleanup(Database $dbForProject, string $databaseKey, string $collectionKey, string $collectionId): void { try { $dbForProject->deleteCollection($collectionKey); - } catch (\Throwable) { - // Ignore cleanup errors for collection deletion + } catch (\Throwable $e) { + // Log but don't throw cleanup errors + \error_log("Cleanup failed for collection $collectionKey: " . $e->getMessage()); } try { $dbForProject->deleteDocument($databaseKey, $collectionId); - } catch (\Throwable) { - // Ignore cleanup errors for document deletion + } catch (\Throwable $e) { + // Log but don't throw cleanup errors + \error_log("Cleanup failed for document $collectionId: " . $e->getMessage()); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)src/Appwrite/Utopia/Database/Validator/Attributes.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
src/Appwrite/Utopia/Database/Validator/Indexes.php (4)
getDescription(47-50)isValid(58-181)isArray(188-191)getType(198-201)
⏰ 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). (20)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Migrations)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Storage)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: Unit Test
- GitHub Check: scan
🔇 Additional comments (12)
src/Appwrite/Utopia/Database/Validator/Attributes.php (5)
1-49: LGTM on class structure and setup.The imports, class properties, and constructor are well-organized. The supported types and formats are clearly defined.
127-146: LGTM on string and format validation.String size validation is thorough, and format validation is correctly restricted to string types only.
274-300: LGTM on enum validation.Comprehensive validation for enum elements including type, emptiness, and length checks. Default value validation ensures consistency with declared elements.
302-349: LGTM on relationship validation.All relationship constraints are properly validated: array restriction, required fields, relation type, two-way configuration, and onDelete behavior.
355-373: LGTM on utility methods.The
isArray()andgetType()implementations follow the same pattern as the Indexes validator.src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (7)
12-27: LGTM on imports.All imported validators and utilities are used appropriately throughout the file.
122-136: LGTM on attribute document building with cleanup.Proper error handling ensures the collection document is cleaned up if attribute building fails.
179-193: LGTM on document persistence with proper cleanup.Attribute and index documents are created after successful collection creation, with appropriate cleanup on failure.
237-243: Single-bound min/max now persisted with fallback defaults.The implementation uses fallback values (
PHP_INT_MIN/PHP_INT_MAXfor integers,±PHP_FLOAT_MAXfor floats) when only one bound is specified. This ensures the constraint is enforced at runtime.
395-411: LGTM on IndexValidator integration.The IndexValidator is properly instantiated with all necessary adapter capabilities and validates index viability before creation.
340-370: Add$permissionsto system attributes list.The
$permissionsfield is a defined system attribute (see Document.php) but not included in$systemAttrsfor index validation. Add it to prevent "Unknown attribute" errors when indexing on$permissions.$systemAttrs = ['$id', '$createdAt', '$updatedAt', '$permissions'];
138-142: Review comment is incorrect - Exception constructor signature verified.The Appwrite
Exceptionclass constructor signature is__construct(string $message, ?int $code = null, ?\Throwable $previous = null), where the first parameter accepts a string message, not an exception type. The code at line 141 correctly passes a message as the first argument and a custom error message as the second parameter (which becomes the$codeor is handled appropriately). The proposed diff would remove necessary error context and should not be applied.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (5)
81-82: Consider aligning attributes/indexes param docs with validator capabilitiesThe
attributesandindexesparams are correctly wired toAttributesValidator/IndexesValidator, but the descriptions are narrower than what those validators accept (e.g., spatial types, relationship options likerelatedCollection,relationType,twoWay,onDelete, numericmin/max). Consider expanding the docstrings so the HTTP/API surface matches the validator feature set and avoids documentation drift.
124-135: Relationship & spatial attribute handling: verify two‑way behavior and support flagsThe attribute path is generally well-structured: you build collection/attribute documents up front, use
buildAttributeDocument()to centralize type/format/default/options logic, validate relationship parents, and bail out early on errors while rolling back the collection document.Two areas are worth a closer look:
For
type === Database::VAR_RELATIONSHIPwithtwoWayenabled, this code only materializes the parent‑side attribute and immediately marks itstatus => 'available'. If there’s existing logic that backfills the inverse attribute based on new relationship attributes, please confirm it still triggers for attributes created synchronously here (and doesn’t rely on a'processing'status). Otherwise, two‑way relationships defined at collection‑create time might never get their opposite side.Spatial attributes are currently rejected whenever
getAdapter()->getSupportForSpatialIndex()is false. If an adapter can store spatial attribute types but merely lacks spatial index support, this could be overly strict for attribute creation. It’s worth confirming that this flag is intended to gate spatial attribute support, not just spatial index support, or consider separating those concerns.The
isCollectionsAPI()‑based parent-not-found messaging is a nice touch to keep “collection” vs “table” terminology consistent across endpoints. Based on learnings, this aligns well with prior guidance.Also applies to: 212-309
137-155: Index construction & validation are robust; double‑check limit semanticsThe index pipeline looks good overall:
- You enforce a hard cap via
getLimitForIndexes()before doing any heavier work.buildIndexDocument()ensures each index attribute either matches a declared attribute or one of the allowed system fields, rejects relationship attributes, and normalizeslengths/orders(esp. for array attributes viaMAX_ARRAY_INDEX_LENGTH).- You then delegate to
IndexValidatorwith adapter-specific capabilities (getMaxIndexLength(),getInternalIndexesKeys(), spatial/vector support flags, etc.) and surface a contextual invalid-index exception.Two follow-ups to verify:
The limit check is based on
count($indexes)only. IfgetLimitForIndexes()is intended to represent the total number of indexes per collection (user + internal), you may need to subtract the internal index count (fromgetInternalIndexesKeys()) to avoid rejecting valid configurations for adapters with many built‑in indexes.
IndexValidatoris instantiated per index with an empty indexes list ([]), so cross‑index conflicts (duplicate keys, incompatible combinations) depend entirely onIndexesValidatorat the request layer. That’s fine if those two validators stay in lockstep, but if their rules ever diverge you might want to pass the already built$collectionIndexesintoIndexValidatorso it can enforce cross‑index constraints as well.Also applies to: 316-397
132-135: Consider centralizing collection-document rollback logicOn most early error paths (attribute build failure, index count over limit, index build failure,
createCollectionfailures), you manually calldeleteDocument($databaseKey, $collection->getId()), while later failures use the dedicatedcleanup()helper. To reduce duplication and the risk of future inconsistencies, consider routing these paths through a common helper (possiblycleanup()with an option to skipdeleteCollection) so that all rollback logic lives in one place.Also applies to: 139-141, 152-153, 165-175
178-193: Cleanup currently skips attributes/indexes docs; verifycreateDocumentsatomicityIn the post‑creation phase you bulk insert attribute and index documents, and on failure call
cleanup()to drop the underlying DB collection and the parent collection document.cleanup()deliberately ignores errors fromdeleteCollection/deleteDocument, which is reasonable for best‑effort rollback.However, if
createDocuments('attributes' | 'indexes', $docs)can partially succeed before throwing (e.g., per‑document inserts with a mid‑batch duplicate), this sequence will:
- Leave any already‑inserted attribute/index docs in place,
- Remove the parent collection document and drop the physical collection, and
- On retry, likely hit DuplicateExceptions on those orphan docs while the actual collection has been rolled back.
If
createDocumentsis guaranteed to be all‑or‑nothing at the adapter level, this is safe. Otherwise, consider extending the rollback here to also remove any attribute/index docs that were just created, for example by iterating$attributeDocuments/$indexDocumentsand callingdeleteDocument('attributes' | 'indexes', $doc->getId())inside best‑effort try/catch blocks, in addition to the existingcleanup()call.Also applies to: 405-425
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 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/Http/Databases/Collections/Create.php
🧬 Code graph analysis (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (2)
Attributes(12-374)getDescription(58-61)src/Appwrite/Utopia/Database/Validator/Indexes.php (2)
Indexes(9-202)getDescription(47-50)
⏰ 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). (2)
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (3)
12-15: Validator imports and aliases look consistentThe new imports cleanly separate request-level validators (
AttributesValidator,IndexesValidator) from the low-levelIndexValidatorvia aliases; no issues spotted here.Also applies to: 25-25
89-123: Collection metadata creation & exception mapping look solidExtending
action()to takeattributes/indexeswhile keeping the existing flow—database lookup,unique()handling forcollectionId, permission aggregation, thencreateDocument('database_'.$database->getSequence(), …)with Duplicate/Limit/NotFound mapped through the existing helpers—preserves prior behavior and sets up the new schema work cleanly. The derived$collectionKey/$databaseKeyvalues match the established naming conventions for underlying collections.
194-205: Cache purge and event dispatch remain consistent with existing behaviorPurging the cached collection/document using the same
database_{seq}/database_{seq}_collection_{seq}keys you derived earlier, then queuing the event with the collection ID and database context, preserves the previous behavior while extending the flow to cover schema creation. No issues here.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
7294-8300: Extensive attribute/index/relationship validation matrix looks correct but is quite verboseThe new tests for attribute, enum, index, relationship, datetime, float, and “missing required fields” validation cover a wide range of edge cases and failure modes and match the stated goals of the PR. From a behaviour standpoint they look consistent and valuable.
If this area keeps growing, consider extracting small helpers (e.g. “createTestDatabase”, “postCollectionWithPayload”) or data-driven subtests to reduce repetition and make future additions easier to reason about, but this can be deferred.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php(2 hunks)src/Appwrite/Utopia/Database/Validator/Attributes.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 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/Http/TablesDB/Tables/Create.phpsrc/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
🧬 Code graph analysis (3)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-363)
src/Appwrite/Utopia/Database/Validator/Attributes.php (1)
src/Appwrite/Auth/Key.php (1)
Key(14-201)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ 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). (2)
- GitHub Check: Benchmark
- GitHub Check: scan
🔇 Additional comments (2)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
6783-6958: Solid coverage for synchronous multi-create happy pathThis test exercises the intended behaviour well: single-call collection creation with attributes, indexes, and subsequent document CRUD + defaults, and it asserts both attribute/index metadata and data-path usage. Nothing blocking here from a test-design standpoint.
7104-7123: The test at lines 7104-7123 cannot be verified as contradictory because the tests referenced in your comment—specificallytestCreateCollectionRelationshipValidationand exercises usingDatabase::VAR_RELATIONSHIPwith successful relationship attribute creation—do not exist in the codebase.A thorough search reveals:
- No
testCreateCollectionRelationshipValidationtest method exists- No
Database::VAR_RELATIONSHIPconstant is defined anywhere- Only one use of
relationTypeexists in the entire test file: the rejected inline case at lines 7104-7123- No successful inline relationship attribute creation tests are found
The test at lines 7104-7123 correctly demonstrates that the
'type' => 'relationship'attribute is not supported as an inline attribute and is properly rejected with a 400 status and "Invalid type" message. This behavior is consistent with the API design—no contradictory specification exists.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (9)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (7)
82-90: Attributes/indexes params and action signature alignmentThe new
attributes/indexesparams, validators, and the extendedaction()signature line up correctly with the constructor’s param/inject order, so wiring looks sound. One small UX improvement: theattributesdescription listsrelationshipas an allowed type, but inline relationship attributes are rejected later in the method. Consider updating the description to call this out explicitly to avoid surprises.- ->param('attributes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, integer, float, boolean, datetime, relationship), size (integer, required for string type), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options.', true) + ->param('attributes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, integer, float, boolean, datetime, relationship), size (integer, required for string type), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options. Relationship attributes cannot be created inline; use the create relationship endpoint instead.', true)
122-188: Attribute/index validation and document-building flow looks robust; minor duplication in cleanupThe pre-
createCollectionpipeline (computing keys, validating attributes, rejecting relationships, building attribute/index docs, and validating indexes against adapter capabilities) is coherent and ensures we bail out before touching the physical collection when definitions are bad. Repeated calls todeleteDocument($databaseKey, $collection->getId())across several failure branches are correct but a bit duplicated; if this grows further, you might consider a small helper for “delete collection document only” to complementcleanup().
190-210: Consider usingcleanup()for somecreateCollectionfailures to avoid orphaned collectionsPassing
$collectionKey,$collectionAttributes, and$collectionIndexesintocreateCollection()looks correct, and you now consistently drop the collection document on all exception paths. If any adapter can partially create the underlying collection (or indexes) before throwingIndexException,LimitException, or a generic\Throwable, you might end up with an orphaned physical collection sincecleanup()isn’t invoked here.If
Database::createCollection()is guaranteed to be atomic and leave no collection behind on failure, this is fine. Otherwise, consider usingcleanup()for the non-duplicate branches:- } catch (DuplicateException) { - $dbForProject->deleteDocument($databaseKey, $collection->getId()); - throw new Exception($this->getDuplicateException()); - } catch (IndexException $e) { - $dbForProject->deleteDocument($databaseKey, $collection->getId()); - throw new Exception($this->getInvalidIndexException(), $e->getMessage()); - } catch (LimitException) { - $dbForProject->deleteDocument($databaseKey, $collection->getId()); - throw new Exception($this->getLimitException()); - } catch (\Throwable $e) { - $dbForProject->deleteDocument($databaseKey, $collection->getId()); - throw $e; - } + } catch (DuplicateException) { + $dbForProject->deleteDocument($databaseKey, $collection->getId()); + throw new Exception($this->getDuplicateException()); + } catch (IndexException $e) { + $this->cleanup($dbForProject, $databaseKey, $collectionKey, $collection->getId()); + throw new Exception($this->getInvalidIndexException(), $e->getMessage()); + } catch (LimitException) { + $this->cleanup($dbForProject, $databaseKey, $collectionKey, $collection->getId()); + throw new Exception($this->getLimitException()); + } catch (\Throwable $e) { + $this->cleanup($dbForProject, $databaseKey, $collectionKey, $collection->getId()); + throw $e; + }
212-226: Bulk creation of attribute/index documents with centralized cleanup is a good improvement; verifydeleteCollectioncascades as expectedThe two
createDocumentscalls, wrapped in a singletrywithcleanup()on any failure, give you a clear “all-or-nothing” behavior for the schema metadata. This looks solid. One thing to verify: thatDatabase::deleteCollection($collectionKey)reliably removes anyattributes/indexesstate for this collection (or that such state can’t partially survive a failed bulk insert). If it doesn’t, you might still accumulate orphaned attribute/index docs even after cleanup.
228-230: Cache purge is correct; optional reuse of computed keysUsing
purgeCachedDocumentandpurgeCachedCollectionwith the computed database/collection sequences matches how you build$databaseKey/$collectionKeyearlier. For readability, you could reuse those variables here instead of re-concatenating the strings, but that’s purely cosmetic.
321-380:buildIndexDocumentcorrectly normalizes array-attribute indexes; consider minor naming/efficiency polishIndex documents are built with normalized
lengthsandorders, and array attributes are givenDatabase::MAX_ARRAY_INDEX_LENGTHwithnullorder, which lines up with how array indexes are typically treated. Passing the same attributeDocumentinstances that you later feed intoIndexValidatorkeeps things consistent.Two optional nits:
- The parameter name
$attributeDocumentscan be slightly confusing since you’re actually passing$collectionAttributes; renaming either the param or the local variable could improve readability.- If you ever expect many attributes, you could pre-index them by key (assoc array) instead of doing
array_searchinside the loop, though this is likely premature optimization for most collections.
382-402:cleanup()helper is straightforward; parameter naming could be clearerThe cleanup helper safely attempts to drop the underlying DB collection and then the collection document, swallowing any errors. That’s appropriate for a best-effort rollback. The only minor nit is naming:
$databaseIdand$collectionIdhere are internal collection names ($databaseKey/$collectionKey), not the logical database/collection IDs. Renaming them (e.g., to$databaseCollectionId/$dbCollectionName) in a follow-up could make call sites and the docblock slightly clearer.tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
7294-7521: SplittestCreateCollectionAttributeValidationEdgeCasesinto smaller, focused testsThis method bundles many unrelated attribute edge cases (reserved keys, wrong default types, min/max issues, string length, signed on non‑numeric, arrays, invalid
format, and a success case) into one large test. A single failure here will be hard to localize and may short‑circuit checks of later scenarios. Consider splitting into smaller tests (e.g., “ReservedKeys”, “DefaultTypeMismatch”, “RangeValidation”, “ArrayDefaults”, “FormatValidation”) so failures are isolated and easier to debug.
7628-7846: Index edge‑case test is comprehensive but monolithic
testCreateCollectionIndexValidationEdgeCasesvery usefully covers duplicate keys, invalid types, empty attributes, mismatchedorders/lengths, invalid order values, and a valid compound index. For maintainability and clearer failure signals, it would be better to break this into multiple tests (e.g., one per invalid pattern plus one success test) rather than a single long method. This also makes it easier to extend with new edge cases later.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 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/Http/Databases/Collections/Create.php
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
🧬 Code graph analysis (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ 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). (2)
- GitHub Check: Benchmark
- GitHub Check: scan
🔇 Additional comments (6)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
12-30: New validators and helpers are correctly imported and usedThe added imports for
AttributesValidator,IndexValidator,ArrayList, andJSONare all used in the constructor/action and look consistent with the new validation flow.
241-314:buildAttributeDocumentstructure matches expected attribute metadataThe attribute document builder correctly pulls out key/type/size/required/signed/array/default/filters, handles enum
elementsviaformatOptions, and switches to the appropriate int/float range format whenmin/maxare present. The IDs and metadata (database/collection internal IDs vs external IDs) look consistent with how collection and attribute documents are identified elsewhere, so this helper should integrate cleanly with bothcreateCollectionand the bulkcreateDocumentscall.tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (4)
6784-6958: Solid coverage for happy‑path multi‑create collection behaviorThis test exercises inline attributes, defaults, indexes, and subsequent document creation in a single flow, which is exactly what this feature needs. The assumptions about attributes/indexes being immediately
availablelook consistent with the new synchronous schema‑creation semantics.
7848-8031: Nice targeted coverage for inline relationship validationThis test suite around
testCreateCollectionRelationshipValidationexercises missingrelatedCollection, missingrelationType, invalidrelationType, invalidonDelete, invalidtwoWaytype, and a fully valid relationship definition. That’s a good, focused complement to the more generic attribute tests and clearly documents the intended contract for inline relationships.
8033-8171: Datetime/float validation tests align with expected validator behaviorThe datetime and float tests cleanly separate invalid cases (non‑ISO default, min>max, default out of range) from valid ones, and they don’t over‑assert on internal details. These should give good coverage for the new
Attributesvalidator without being brittle.
8173-8300: Missing‑field tests look correct and consistent with the schema modelThe cases for attributes missing
key/typeand indexes missingkey/type/attributesmatch how the public API is documented, and asserting400in each case seems appropriate. No changes needed here.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/Appwrite/Utopia/Database/Validator/Indexes.php (1)
122-133: Consider extracting system attributes to a shared constant.The system attributes (
$id,$createdAt,$updatedAt) are defined inline. If these need to be referenced elsewhere or if new system attributes are added, a shared constant would improve maintainability.+ // Consider defining at class level or using a shared constant + protected array $systemAttributes = ['$id', '$createdAt', '$updatedAt'];Then reference it in the validation:
- $systemAttrs = ['$id', '$createdAt', '$updatedAt']; + $systemAttrs = $this->systemAttributes;src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (1)
165-167: Parameter naming mismatch.
buildIndexDocumentis called with$collectionAttributes, but the method parameter is named$attributeDocuments. Both are arrays ofDocumentobjects, so it works functionally, but the naming is confusing.Consider renaming the parameter for clarity:
- protected function buildIndexDocument(Document $database, Document $collection, array $indexDef, array $attributeDocuments): array + protected function buildIndexDocument(Document $database, Document $collection, array $indexDef, array $collectionAttributes): array { ... - $attrKeys = array_map(fn ($a) => $a->getAttribute('key'), $attributeDocuments); + $attrKeys = array_map(fn ($a) => $a->getAttribute('key'), $collectionAttributes);And update references in lines 343-344.
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
6960-7131: Consider asserting error “type” codes for negative multi-create casesThe error-path scenarios in
testCreateCollectionWithAttributesAndIndexesErrorsare valuable, but they currently only assert HTTP 400 (and, for the relationship case, a substring ofbody['message']). To make these tests more resilient to copy updates and to better document expected failure modes, consider also asserting the structured error code inbody['type']for at least the key cases (invalid attribute type, bad index attributes, relationship payload).
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php(5 hunks)src/Appwrite/Utopia/Database/Validator/Indexes.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php
🧬 Code graph analysis (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (2)
src/Appwrite/Utopia/Database/Validator/Attributes.php (3)
Attributes(15-358)isValid(74-337)getDescription(63-66)src/Appwrite/Utopia/Database/Validator/Indexes.php (3)
Indexes(9-200)isValid(55-179)getDescription(44-47)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ 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). (18)
- GitHub Check: E2E Service Test (Migrations)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: scan
🔇 Additional comments (15)
src/Appwrite/Utopia/Database/Validator/Indexes.php (2)
1-37: LGTM! Well-structured validator setup.The class properly extends Validator, defines supported index types and orders, and has a clean constructor with the configurable
maxIndexeslimit.
186-198: LGTM!The
isArray()andgetType()implementations are consistent with theAttributesvalidator pattern, whereisArray()returnsfalse(the validator handles the array internally) whilegetType()returnsTYPE_ARRAY(the expected input type).src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (8)
12-31: LGTM! Imports are well-organized and all appear to be used.
83-84: LGTM!The new parameters use
ArrayList(new JSON(), ...)which correctly parses each element as JSON, with the deep structure validation delegated toAttributesValidatorandIndexesValidatorlater in the flow.
136-141: Good validation: relationship attributes correctly rejected inline.Clear error message directing users to the appropriate endpoint for relationship creation.
176-196: LGTM! Comprehensive index validation against DB adapter capabilities.Properly validates each index against adapter constraints (max index length, spatial support, fulltext support, etc.) before attempting creation.
220-234: LGTM! Proper transactional semantics with cleanup on failure.The code correctly handles the case where the underlying collection was created but persisting metadata documents failed, ensuring the cleanup method removes both the DB collection and the collection document to maintain consistency.
390-410: LGTM! Appropriate cleanup handling.The silent error handling in the cleanup method is appropriate - if cleanup fails, there's nothing more that can be done at this point, and the original error should be propagated to the caller rather than masking it with a cleanup error.
274-283: No issue found: min/max handling does not conflict with user-provided format.The code correctly overrides format to
APP_DATABASE_ATTRIBUTE_INT_RANGEorAPP_DATABASE_ATTRIBUTE_FLOAT_RANGEwhenminormaxis provided. This poses no conflict becauseAttributesValidatorenforces strict mutual exclusivity:formatis restricted to string types (line 148), whilemin/maxare restricted to integer and float types (line 160). Since these constraints apply to different types, the override is safe and intentional.
350-353: Array attribute indexes intentionally use null order by design.For array attributes, the order is forcibly set to
nullbecause arrays use index-based access (e.g.,arrayInsert(index, value)) rather than sort ordering. This behavior is tested and validated—the test comment explicitly confirms: "set a length for an array attribute, it should get overriden with Database::MAX_ARRAY_INDEX_LENGTH." The validator also explicitly allowsnullas a valid order value for indexes, confirming this is by design across all supported adapters.tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (5)
6784-6958: Inline multi-create happy-path coverage looks solidThe
testCreateCollectionWithAttributesAndIndexesflow exercises attributes, defaults, index definitions (including orders), and document creation end‑to‑end, which is exactly what this feature needs. No issues from my side here.
7133-7201: Cleanup-on-failure test captures the core invariant well
testCreateCollectionCleanupOnFailurenicely proves that a failed multi-create with an invalid index leaves no lingering collection, by reusing the samecollectionIdsuccessfully on the second request. This is an important safety guarantee for callers relying on idempotency.
7203-7521: Enum + attribute validation edge-case tests are thoroughThe new tests for enum attributes and general attribute validation edge cases (reserved keys, wrong default types, range violations, array+default, invalid
format, etc.) give very good coverage of the new validator behavior at collection-create time and mirror the existing per-attribute update tests. No changes requested.
7523-7846: Index validation edge-case suite aligns well with expected invariants
testCreateCollectionIndexValidationEdgeCasesexercises duplicate index keys, invalid types, empty attribute lists, orders/lengths cardinality mismatches, and invalid order values, plus a positive compound-index case. This is a good complement to the attribute tests; I don’t see any functional issues here.
7906-8115: Float and “missing required fields” validation tests look correctThe float range/default tests and the missing‑field cases for attributes/indexes (
key,type,attributes) behave as expected for the new multi-create schema contract. The mix of failing and one successful case at the end is a nice pattern; nothing blocking here.
commit: |
What does this PR do?
Allow passing attributes and indexes when creating a collection, to create the entire schema synchronously
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