From ec63dc22d441d628dc0dcc194e3ac9a37af929ba Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 8 Dec 2025 19:09:54 +0530 Subject: [PATCH] updated controllers --- .../Http/Databases/Collections/Create.php | 33 +++-- .../Databases/Collections/Indexes/Create.php | 134 +++++++++--------- .../Http/DocumentsDB/Collections/Create.php | 4 + .../Utopia/Database/Validator/Attributes.php | 7 + .../Databases/Legacy/DatabasesBase.php | 7 +- 5 files changed, 97 insertions(+), 88 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index 8e5f75855f..1866b62653 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -121,12 +121,18 @@ class Create extends Action throw new Exception(Exception::DATABASE_NOT_FOUND); } + /** + * @var Database $dbForDatabases + */ + $dbForDatabases = $getDatabasesDB($database); + $collectionKey = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); $databaseKey = 'database_' . $database->getSequence(); $attributesValidator = new AttributesValidator( APP_LIMIT_ARRAY_PARAMS_SIZE, - $dbForProject->getAdapter()->getSupportForSpatialAttributes() + $dbForDatabases->getAdapter()->getSupportForSpatialAttributes(), + $dbForDatabases->getAdapter()->getSupportForAttributes() ); if (!$attributesValidator->isValid($attributes)) { @@ -155,7 +161,7 @@ class Create extends Action } // Validate indexes - $indexesValidator = new IndexesValidator($dbForProject->getLimitForIndexes()); + $indexesValidator = new IndexesValidator($dbForDatabases->getLimitForIndexes()); if (!$indexesValidator->isValid($indexes)) { $dbForProject->deleteDocument($databaseKey, $collection->getId()); throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $indexesValidator->getDescription()); @@ -178,15 +184,15 @@ class Create extends Action $indexValidator = new IndexValidator( $collectionAttributes, [], - $dbForProject->getAdapter()->getMaxIndexLength(), - $dbForProject->getAdapter()->getInternalIndexesKeys(), - $dbForProject->getAdapter()->getSupportForIndexArray(), - $dbForProject->getAdapter()->getSupportForSpatialIndexNull(), - $dbForProject->getAdapter()->getSupportForSpatialIndexOrder(), - $dbForProject->getAdapter()->getSupportForVectors(), - $dbForProject->getAdapter()->getSupportForAttributes(), - $dbForProject->getAdapter()->getSupportForMultipleFulltextIndexes(), - $dbForProject->getAdapter()->getSupportForIdenticalIndexes() + $dbForDatabases->getAdapter()->getMaxIndexLength(), + $dbForDatabases->getAdapter()->getInternalIndexesKeys(), + $dbForDatabases->getAdapter()->getSupportForIndexArray(), + $dbForDatabases->getAdapter()->getSupportForSpatialIndexNull(), + $dbForDatabases->getAdapter()->getSupportForSpatialIndexOrder(), + $dbForDatabases->getAdapter()->getSupportForVectors(), + $dbForDatabases->getAdapter()->getSupportForAttributes(), + $dbForDatabases->getAdapter()->getSupportForMultipleFulltextIndexes(), + $dbForDatabases->getAdapter()->getSupportForIdenticalIndexes() ); foreach ($collectionIndexes as $indexDoc) { @@ -195,10 +201,7 @@ class Create extends Action throw new Exception($this->getInvalidIndexException(), $indexValidator->getDescription()); } } - /** - * @var Database $dbForDatabases - */ - $dbForDatabases = $getDatabasesDB($database); + try { $dbForDatabases->createCollection( id: $collectionKey, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index e931f37386..24c31c5c29 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -178,73 +178,73 @@ class Create extends Action throw new Exception(Exception::INDEX_INVALID, 'Creating indexes on array attributes is not currently supported.'); } } - - $index = new Document([ - '$id' => ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $key), - 'key' => $key, - 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $db->getSequence(), - 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getSequence(), - 'collectionId' => $collectionId, - 'type' => $type, - 'attributes' => $attributes, - 'lengths' => $lengths, - 'orders' => $orders, - ]); - - $validator = new IndexValidator( - $collection->getAttribute('attributes'), - $collection->getAttribute('indexes'), - $dbForDatabases->getAdapter()->getMaxIndexLength(), - $dbForDatabases->getAdapter()->getInternalIndexesKeys(), - $dbForDatabases->getAdapter()->getSupportForIndexArray(), - $dbForDatabases->getAdapter()->getSupportForSpatialIndexNull(), - $dbForDatabases->getAdapter()->getSupportForSpatialIndexOrder(), - $dbForDatabases->getAdapter()->getSupportForVectors(), - $dbForDatabases->getAdapter()->getSupportForAttributes(), - $dbForDatabases->getAdapter()->getSupportForMultipleFulltextIndexes(), - $dbForDatabases->getAdapter()->getSupportForIdenticalIndexes(), - $dbForDatabases->getAdapter()->getSupportForObject() - ); - - if (!$validator->isValid($index)) { - throw new Exception($this->getInvalidTypeException(), $validator->getDescription()); - } - - try { - $index = $dbForProject->createDocument('indexes', $index); - } catch (DuplicateException) { - throw new Exception($this->getDuplicateException()); - } - - $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); - - $queueForDatabase - ->setType(DATABASE_TYPE_CREATE_INDEX) - ->setDatabase($db); - - if ($this->isCollectionsAPI()) { - $queueForDatabase - ->setCollection($collection) - ->setDocument($index); - } else { - $queueForDatabase - ->setTable($collection) - ->setRow($index); - } - - $queueForEvents - ->setContext('database', $db) - ->setParam('databaseId', $databaseId) - ->setParam('indexId', $index->getId()) - ->setParam('collectionId', $collection->getId()) - ->setParam('tableId', $collection->getId()) - ->setContext($this->getCollectionsEventsContext(), $collection); - - $response - ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) - ->dynamic($index, $this->getResponseModel()); } + + $index = new Document([ + '$id' => ID::custom($db->getSequence() . '_' . $collection->getSequence() . '_' . $key), + 'key' => $key, + 'status' => 'processing', // processing, available, failed, deleting, stuck + 'databaseInternalId' => $db->getSequence(), + 'databaseId' => $databaseId, + 'collectionInternalId' => $collection->getSequence(), + 'collectionId' => $collectionId, + 'type' => $type, + 'attributes' => $attributes, + 'lengths' => $lengths, + 'orders' => $orders, + ]); + + $validator = new IndexValidator( + $collection->getAttribute('attributes'), + $collection->getAttribute('indexes'), + $dbForDatabases->getAdapter()->getMaxIndexLength(), + $dbForDatabases->getAdapter()->getInternalIndexesKeys(), + $dbForDatabases->getAdapter()->getSupportForIndexArray(), + $dbForDatabases->getAdapter()->getSupportForSpatialIndexNull(), + $dbForDatabases->getAdapter()->getSupportForSpatialIndexOrder(), + $dbForDatabases->getAdapter()->getSupportForVectors(), + $dbForDatabases->getAdapter()->getSupportForAttributes(), + $dbForDatabases->getAdapter()->getSupportForMultipleFulltextIndexes(), + $dbForDatabases->getAdapter()->getSupportForIdenticalIndexes(), + $dbForDatabases->getAdapter()->getSupportForObject() + ); + + if (!$validator->isValid($index)) { + throw new Exception($this->getInvalidTypeException(), $validator->getDescription()); + } + + try { + $index = $dbForProject->createDocument('indexes', $index); + } catch (DuplicateException) { + throw new Exception($this->getDuplicateException()); + } + + $dbForProject->purgeCachedDocument('database_' . $db->getSequence(), $collectionId); + + $queueForDatabase + ->setType(DATABASE_TYPE_CREATE_INDEX) + ->setDatabase($db); + + if ($this->isCollectionsAPI()) { + $queueForDatabase + ->setCollection($collection) + ->setDocument($index); + } else { + $queueForDatabase + ->setTable($collection) + ->setRow($index); + } + + $queueForEvents + ->setContext('database', $db) + ->setParam('databaseId', $databaseId) + ->setParam('indexId', $index->getId()) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) + ->setContext($this->getCollectionsEventsContext(), $collection); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED) + ->dynamic($index, $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Create.php index 14f555d3e3..a2d4321bee 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Create.php @@ -12,7 +12,9 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; +use Utopia\Validator\JSON; use Utopia\Validator\Text; class Create extends CollectionCreate @@ -59,6 +61,8 @@ class Create extends CollectionCreate ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('documentSecurity', false, new Boolean(true), 'Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(), 'Is collection enabled? When set to \'disabled\', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.', 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.', true) + ->param('indexes', [], new ArrayList(new JSON(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of attribute keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional).', true) ->inject('response') ->inject('dbForProject') ->inject('getDatabasesDB') diff --git a/src/Appwrite/Utopia/Database/Validator/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Attributes.php index e9bd009217..839d1d2533 100644 --- a/src/Appwrite/Utopia/Database/Validator/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Attributes.php @@ -45,10 +45,12 @@ class Attributes extends Validator /** * @param int $maxAttributes Maximum number of attributes allowed * @param bool $supportForSpatialAttributes Whether DB supports spatial attributes + * @param bool $supportForSpatialAttributes Whether DB supports attributes or not */ public function __construct( int $maxAttributes = APP_LIMIT_ARRAY_PARAMS_SIZE, protected bool $supportForSpatialAttributes = true, + protected bool $supportForAttributes = true ) { $this->maxAttributes = $maxAttributes; } @@ -78,6 +80,11 @@ class Attributes extends Validator return false; } + if (\count($value) && !$this->supportForAttributes) { + $this->message = "Attributes are not supported by the current database"; + return false; + } + if (\count($value) > $this->maxAttributes) { $this->message = 'Maximum of ' . $this->maxAttributes . ' attributes allowed'; return false; diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php index 9972219067..778c587217 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -1391,12 +1391,7 @@ trait DatabasesBase $this->assertEquals(400, $fulltextArray['headers']['status-code']); - // MongoDB only allows one fulltext index per collection, so it returns a different error - if ($this->isMongoDB()) { - $this->assertEquals('There is already a fulltext index in the collection', $fulltextArray['body']['message']); - } else { - $this->assertEquals('Creating indexes on array attributes is not currently supported.', $fulltextArray['body']['message']); - } + $this->assertEquals('Creating indexes on array attributes is not currently supported.', $fulltextArray['body']['message']); $actorsArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json',