1
0
Fork 0
mirror of synced 2024-07-15 19:36:08 +12:00

Merge pull request #5271 from appwrite/feat-realtions-jake

Feat relations updates
This commit is contained in:
Jake Barnby 2023-03-24 18:58:25 +13:00 committed by GitHub
commit f6aa4a4ab1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 891 additions and 440 deletions

View file

@ -302,7 +302,6 @@ function updateAttribute(
$dbForProject->updateRelationship( $dbForProject->updateRelationship(
collection: $collectionId, collection: $collectionId,
key: $key, key: $key,
newTwoWayKey: $options['twoWayKey'],
twoWay: $options['twoWay'], twoWay: $options['twoWay'],
onDelete: $options['onDelete'], onDelete: $options['onDelete'],
); );
@ -1529,11 +1528,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP) ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP)
->param('databaseId', '', new UID(), 'Database ID.') ->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('relatedCollectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('relatedCollectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('type', '', new WhiteList([Database::RELATION_ONE_TO_ONE, Database::RELATION_MANY_TO_ONE, Database::RELATION_MANY_TO_MANY, Database::RELATION_ONE_TO_MANY]), 'Relation type') ->param('type', '', new WhiteList([Database::RELATION_ONE_TO_ONE, Database::RELATION_MANY_TO_ONE, Database::RELATION_MANY_TO_MANY, Database::RELATION_ONE_TO_MANY]), 'Relation type')
->param('twoWay', false, new Boolean(), 'Is Two Way?', true) ->param('twoWay', false, new Boolean(), 'Is Two Way?', true)
->param('twoWayKey', null, new Key(), 'Two Way Key', true) ->param('key', null, new Key(), 'Attribute Key.', true)
->param('twoWayKey', null, new Key(), 'Two Way Attribute Key.', true)
->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL]), 'Constraints option', true) ->param('onDelete', Database::RELATION_MUTATE_RESTRICT, new WhiteList([Database::RELATION_MUTATE_CASCADE, Database::RELATION_MUTATE_RESTRICT, Database::RELATION_MUTATE_SET_NULL]), 'Constraints option', true)
->inject('response') ->inject('response')
->inject('dbForProject') ->inject('dbForProject')
@ -1542,10 +1541,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati
->action(function ( ->action(function (
string $databaseId, string $databaseId,
string $collectionId, string $collectionId,
string $key,
string $relatedCollectionId, string $relatedCollectionId,
string $type, string $type,
bool $twoWay, bool $twoWay,
?string $key,
?string $twoWayKey, ?string $twoWayKey,
string $onDelete, string $onDelete,
Response $response, Response $response,
@ -1553,6 +1552,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati
EventDatabase $database, EventDatabase $database,
Event $events Event $events
) { ) {
$key ??= $relatedCollectionId;
$twoWayKey ??= $collectionId; $twoWayKey ??= $collectionId;
$attribute = createAttribute( $attribute = createAttribute(
@ -2750,12 +2750,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
} }
$filterQueries = Query::groupByType($queries)['filters']; $filterQueries = Query::groupByType($queries)['filters'];
// todo: temporary fix until Utopia will be ready !!!!
foreach ($filterQueries as $key => $query) {
if (\str_contains($query->getAttribute(), '.')) {
unset($filterQueries[$key]);
}
}
if ($documentSecurity && !$valid) { if ($documentSecurity && !$valid) {
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT);

View file

@ -95,26 +95,30 @@ class DatabaseV1 extends Worker
$project = $dbForConsole->getDocument('projects', $projectId); $project = $dbForConsole->getDocument('projects', $projectId);
try { try {
if ($type === Database::VAR_RELATIONSHIP) { switch ($type) {
$relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); case Database::VAR_RELATIONSHIP:
if ($relatedCollection->isEmpty()) { $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']);
throw new Exception('Missing collection'); if ($relatedCollection->isEmpty()) {
} throw new Exception('Collection not found');
if ( }
!$dbForProject->createRelationship( if (
collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), !$dbForProject->createRelationship(
relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
type: $options['relationType'], relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(),
twoWay: $options['twoWay'], type: $options['relationType'],
id: $key, twoWay: $options['twoWay'],
twoWayKey: $options['twoWayKey'], id: $key,
onDelete: $options['onDelete'], twoWayKey: $options['twoWayKey'],
) onDelete: $options['onDelete'],
) { )
throw new Exception('Failed to create Attribute'); ) {
} throw new Exception('Failed to create Attribute');
} elseif (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { }
throw new Exception('Failed to create Attribute'); break;
default:
if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) {
throw new Exception('Failed to create Attribute');
}
} }
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available'));
@ -151,6 +155,7 @@ class DatabaseV1 extends Worker
* @param Document $collection * @param Document $collection
* @param Document $attribute * @param Document $attribute
* @param string $projectId * @param string $projectId
* @throws Throwable
*/ */
protected function deleteAttribute(Document $database, Document $collection, Document $attribute, string $projectId): void protected function deleteAttribute(Document $database, Document $collection, Document $attribute, string $projectId): void
{ {
@ -177,12 +182,16 @@ class DatabaseV1 extends Worker
try { try {
if ($status !== 'failed') { if ($status !== 'failed') {
if ($type === Database::VAR_RELATIONSHIP) { switch ($type) {
if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { case Database::VAR_RELATIONSHIP:
throw new Exception('Failed to delete Attribute'); if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
} throw new Exception('Failed to delete Attribute');
} elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { }
throw new Exception('Failed to delete Attribute'); break;
default:
if (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
throw new Exception('Failed to delete Attribute');
}
} }
} }
$dbForProject->deleteDocument('attributes', $attribute->getId()); $dbForProject->deleteDocument('attributes', $attribute->getId());

View file

@ -43,13 +43,13 @@
"ext-sockets": "*", "ext-sockets": "*",
"appwrite/php-clamav": "1.1.*", "appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "0.11.*", "appwrite/php-runtimes": "0.11.*",
"utopia-php/abuse": "0.21.*", "utopia-php/abuse": "0.22.*",
"utopia-php/analytics": "0.2.*", "utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.23.*", "utopia-php/audit": "0.24.*",
"utopia-php/cache": "0.8.*", "utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.13.*", "utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*", "utopia-php/config": "0.2.*",
"utopia-php/database": "dev-feat-relationships as 0.33.0", "utopia-php/database": "dev-feat-relationships as 0.34.0",
"utopia-php/preloader": "0.2.*", "utopia-php/preloader": "0.2.*",
"utopia-php/domains": "1.1.*", "utopia-php/domains": "1.1.*",
"utopia-php/framework": "0.28.*", "utopia-php/framework": "0.28.*",

45
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "65ec111f49af9c148eb69dc16aec7a10", "content-hash": "db3f68f41b0387401b964f65bad3053c",
"packages": [ "packages": [
{ {
"name": "adhocore/jwt", "name": "adhocore/jwt",
@ -1808,23 +1808,23 @@
}, },
{ {
"name": "utopia-php/abuse", "name": "utopia-php/abuse",
"version": "0.21.0", "version": "0.22.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/abuse.git", "url": "https://github.com/utopia-php/abuse.git",
"reference": "7483068b192b27d698da9534c80091f69666d5eb" "reference": "9360a026d18809e35523b254ab57e51055008203"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/7483068b192b27d698da9534c80091f69666d5eb", "url": "https://api.github.com/repos/utopia-php/abuse/zipball/9360a026d18809e35523b254ab57e51055008203",
"reference": "7483068b192b27d698da9534c80091f69666d5eb", "reference": "9360a026d18809e35523b254ab57e51055008203",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
"ext-pdo": "*", "ext-pdo": "*",
"php": ">=8.0", "php": ">=8.0",
"utopia-php/database": "0.33.*" "utopia-php/database": "0.34.*"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "1.2.*", "laravel/pint": "1.2.*",
@ -1851,9 +1851,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/abuse/issues", "issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.21.0" "source": "https://github.com/utopia-php/abuse/tree/0.22.1"
}, },
"time": "2023-03-10T08:49:10+00:00" "time": "2023-03-23T07:30:49+00:00"
}, },
{ {
"name": "utopia-php/analytics", "name": "utopia-php/analytics",
@ -1912,22 +1912,21 @@
}, },
{ {
"name": "utopia-php/audit", "name": "utopia-php/audit",
"version": "0.23.0", "version": "0.24.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/audit.git", "url": "https://github.com/utopia-php/audit.git",
"reference": "f16e893a22b93560d2af02afcb4761b3a940148a" "reference": "237538b618506bbc0efc0e7884d49cdf52c20004"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f16e893a22b93560d2af02afcb4761b3a940148a", "url": "https://api.github.com/repos/utopia-php/audit/zipball/237538b618506bbc0efc0e7884d49cdf52c20004",
"reference": "f16e893a22b93560d2af02afcb4761b3a940148a", "reference": "237538b618506bbc0efc0e7884d49cdf52c20004",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-pdo": "*",
"php": ">=8.0", "php": ">=8.0",
"utopia-php/database": "0.33.*" "utopia-php/database": "0.34.*"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "1.2.*", "laravel/pint": "1.2.*",
@ -1954,9 +1953,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/audit/issues", "issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.23.0" "source": "https://github.com/utopia-php/audit/tree/0.24.1"
}, },
"time": "2023-03-10T08:51:26+00:00" "time": "2023-03-23T07:29:11+00:00"
}, },
{ {
"name": "utopia-php/cache", "name": "utopia-php/cache",
@ -2117,12 +2116,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/database.git", "url": "https://github.com/utopia-php/database.git",
"reference": "3dac815092cf8dc8feff79b7db461c67518db875" "reference": "c1df0b712746b1283737956a1b0b143dca8f8610"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/3dac815092cf8dc8feff79b7db461c67518db875", "url": "https://api.github.com/repos/utopia-php/database/zipball/c1df0b712746b1283737956a1b0b143dca8f8610",
"reference": "3dac815092cf8dc8feff79b7db461c67518db875", "reference": "c1df0b712746b1283737956a1b0b143dca8f8610",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2167,7 +2166,7 @@
"issues": "https://github.com/utopia-php/database/issues", "issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/feat-relationships" "source": "https://github.com/utopia-php/database/tree/feat-relationships"
}, },
"time": "2023-03-22T11:41:15+00:00" "time": "2023-03-23T10:52:28+00:00"
}, },
{ {
"name": "utopia-php/domains", "name": "utopia-php/domains",
@ -5662,8 +5661,8 @@
{ {
"package": "utopia-php/database", "package": "utopia-php/database",
"version": "dev-feat-relationships", "version": "dev-feat-relationships",
"alias": "0.33.0", "alias": "0.34.0",
"alias_normalized": "0.33.0.0" "alias_normalized": "0.34.0.0"
} }
], ],
"minimum-stability": "stable", "minimum-stability": "stable",
@ -5693,5 +5692,5 @@
"platform-overrides": { "platform-overrides": {
"php": "8.0" "php": "8.0"
}, },
"plugin-api-version": "2.2.0" "plugin-api-version": "2.3.0"
} }

View file

@ -83,8 +83,6 @@ services:
- ./docs:/usr/src/code/docs - ./docs:/usr/src/code/docs
- ./public:/usr/src/code/public - ./public:/usr/src/code/public
- ./src:/usr/src/code/src - ./src:/usr/src/code/src
- ./vendor/utopia-php/framework:/usr/src/code/vendor/utopia-php/framework
- ./vendor/utopia-php/database:/usr/src/code/vendor/utopia-php/database
depends_on: depends_on:
- mariadb - mariadb
- redis - redis
@ -345,8 +343,6 @@ services:
volumes: volumes:
- ./app:/usr/src/code/app - ./app:/usr/src/code/app
- ./src:/usr/src/code/src - ./src:/usr/src/code/src
- ./vendor/utopia-php/database:/usr/src/code/vendor/utopia-php/database
- ./vendor/utopia-php/framework:/usr/src/code/vendor/utopia-php/framework
depends_on: depends_on:
- redis - redis
- mariadb - mariadb

View file

@ -62,12 +62,12 @@ class Base extends Queries
]); ]);
$validators = [ $validators = [
new Select(),
new Limit(), new Limit(),
new Offset(), new Offset(),
new Cursor(), new Cursor(),
new Filter($attributes), new Filter($attributes),
new Order($attributes), new Order($attributes),
new Select($attributes),
]; ];
parent::__construct(...$validators); parent::__construct(...$validators);

View file

@ -61,7 +61,7 @@ class Filter extends Base
foreach ($values as $value) { foreach ($values as $value) {
$condition = match ($attributeType) { $condition = match ($attributeType) {
Database::VAR_RELATIONSHIP => true, // Todo: ? Database::VAR_RELATIONSHIP => true,
Database::VAR_DATETIME => gettype($value) === Database::VAR_STRING, Database::VAR_DATETIME => gettype($value) === Database::VAR_STRING,
default => gettype($value) === $attributeType default => gettype($value) === $attributeType
}; };
@ -91,6 +91,7 @@ class Filter extends Base
// Validate method // Validate method
$method = $query->getMethod(); $method = $query->getMethod();
$attribute = $query->getAttribute(); $attribute = $query->getAttribute();
switch ($method) { switch ($method) {
case Query::TYPE_EQUAL: case Query::TYPE_EQUAL:
case Query::TYPE_NOTEQUAL: case Query::TYPE_NOTEQUAL:

View file

@ -41,6 +41,8 @@ class Select extends Base
foreach ($query->getValues() as $attribute) { foreach ($query->getValues() as $attribute) {
if (\str_contains($attribute, '.')) { if (\str_contains($attribute, '.')) {
// For relationships, just validate the top level.
// Utopia will validate each nested level during the recursive calls.
$attribute = \explode('.', $attribute)[0]; $attribute = \explode('.', $attribute)[0];
} }
if (!isset($this->schema[$attribute]) && $attribute !== '*') { if (!isset($this->schema[$attribute]) && $attribute !== '*') {

View file

@ -11,12 +11,6 @@ class AttributeRelationship extends Attribute
parent::__construct(); parent::__construct();
$this $this
->addRule('default', [
'type' => self::TYPE_STRING,
'description' => 'Default value for attribute when not provided. Only null is optional',
'default' => null,
'example' => '',
])
->addRule('relatedCollection', [ ->addRule('relatedCollection', [
'type' => self::TYPE_STRING, 'type' => self::TYPE_STRING,
'description' => 'The Id of the related collection', 'description' => 'The Id of the related collection',
@ -25,26 +19,26 @@ class AttributeRelationship extends Attribute
]) ])
->addRule('relationType', [ ->addRule('relationType', [
'type' => self::TYPE_STRING, 'type' => self::TYPE_STRING,
'description' => 'The type of the relationship ', 'description' => 'The type of the relationship',
'default' => null, 'default' => '',
'example' => 'oneToOne|oneToMany|manyToOne|manyToMany', 'example' => 'oneToOne|oneToMany|manyToOne|manyToMany',
]) ])
->addRule('twoWay', [ ->addRule('twoWay', [
'type' => self::TYPE_BOOLEAN, 'type' => self::TYPE_BOOLEAN,
'description' => 'Is the relationship two-way?', 'description' => 'Is the relationship two-way?',
'default' => null, 'default' => false,
'example' => 'relationship', 'example' => false,
]) ])
->addRule('twoWayKey', [ ->addRule('twoWayKey', [
'type' => self::TYPE_STRING, 'type' => self::TYPE_STRING,
'description' => 'The key of the two-way relationship', 'description' => 'The key of the two-way relationship',
'default' => null, 'default' => '',
'example' => 'string', 'example' => 'string',
]) ])
->addRule('onDelete', [ ->addRule('onDelete', [
'type' => self::TYPE_STRING, 'type' => self::TYPE_STRING,
'description' => 'Action to take on related documents when parent document is deleted', 'description' => 'Action to take on related documents when parent document is deleted',
'default' => null, 'default' => 'restrict',
'example' => 'restrict|cascade|setNull', 'example' => 'restrict|cascade|setNull',
]) ])
; ;

File diff suppressed because it is too large Load diff

View file

@ -1165,7 +1165,7 @@ class DatabasesCustomServerTest extends Scope
$this->assertEquals(202, $attribute['headers']['status-code']); $this->assertEquals(202, $attribute['headers']['status-code']);
} }
sleep(20); sleep(10);
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([ $collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',

View file

@ -26,6 +26,8 @@ trait Base
public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute'; public static string $CREATE_IP_ATTRIBUTE = 'create_ip_attribute';
public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute'; public static string $CREATE_ENUM_ATTRIBUTE = 'create_enum_attribute';
public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute'; public static string $CREATE_DATETIME_ATTRIBUTE = 'create_datetime_attribute';
public static string $CREATE_RELATIONSHIP_ATTRIBUTE = 'create_relationship_attribute';
public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute'; public static string $UPDATE_STRING_ATTRIBUTE = 'update_string_attribute';
public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute'; public static string $UPDATE_INTEGER_ATTRIBUTE = 'update_integer_attribute';
public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute'; public static string $UPDATE_FLOAT_ATTRIBUTE = 'update_float_attribute';
@ -35,6 +37,8 @@ trait Base
public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute'; public static string $UPDATE_IP_ATTRIBUTE = 'update_ip_attribute';
public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute'; public static string $UPDATE_ENUM_ATTRIBUTE = 'update_enum_attribute';
public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute'; public static string $UPDATE_DATETIME_ATTRIBUTE = 'update_datetime_attribute';
public static string $UPDATE_RELATIONSHIP_ATTRIBUTE = 'update_relationship_attribute';
public static string $GET_ATTRIBUTES = 'get_attributes'; public static string $GET_ATTRIBUTES = 'get_attributes';
public static string $GET_ATTRIBUTE = 'get_attribute'; public static string $GET_ATTRIBUTE = 'get_attribute';
public static string $DELETE_ATTRIBUTE = 'delete_attribute'; public static string $DELETE_ATTRIBUTE = 'delete_attribute';
@ -460,6 +464,17 @@ trait Base
array array
} }
}'; }';
case self::$CREATE_RELATIONSHIP_ATTRIBUTE:
return 'mutation createRelationshipAttribute($databaseId: String!, $collectionId: String!, $relatedCollectionId: String!, $type: String!, $twoWay: Boolean, $key: String, $twoWayKey: String, $onDelete: String){
databasesCreateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, relatedCollectionId: $relatedCollectionId, type: $type, twoWay: $twoWay, key: $key, twoWayKey: $twoWayKey, onDelete: $onDelete) {
relatedCollection
relationType
twoWay
key
twoWayKey
onDelete
}
}';
case self::$UPDATE_STRING_ATTRIBUTE: case self::$UPDATE_STRING_ATTRIBUTE:
return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){ return 'mutation updateStringAttribute($databaseId: String!, $collectionId: String!, $key: String!, $required: Boolean!, $default: String){
databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) { databasesUpdateStringAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, required: $required, default: $default) {
@ -528,6 +543,17 @@ trait Base
default default
} }
}'; }';
case self::$UPDATE_RELATIONSHIP_ATTRIBUTE:
return 'mutation updateRelationshipAttribute($databaseId: String!, $collectionId: String!, $key: String!, $twoWay: Boolean, $onDelete: String){
databasesUpdateRelationshipAttribute(databaseId: $databaseId, collectionId: $collectionId, key: $key, twoWay: $twoWay, onDelete: $onDelete) {
relatedCollection
relationType
twoWay
key
twoWayKey
onDelete
}
}';
case self::$CREATE_INDEX: case self::$CREATE_INDEX:
return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){ return 'mutation createIndex($databaseId: String!, $collectionId: String!, $key: String!, $type: String!, $attributes: [String!]!, $orders: [String!]){
databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) { databasesCreateIndex(databaseId: $databaseId, collectionId: $collectionId, key: $key, type: $type, attributes: $attributes, orders: $orders) {

View file

@ -7,6 +7,7 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer; use Tests\E2E\Scopes\SideServer;
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role; use Utopia\Database\Helpers\Role;
@ -75,9 +76,36 @@ class DatabaseServerTest extends Scope
$collection = $collection['body']['data']['databasesCreateCollection']; $collection = $collection['body']['data']['databasesCreateCollection'];
$this->assertEquals('Actors', $collection['name']); $this->assertEquals('Actors', $collection['name']);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
'collectionId' => 'movies',
'name' => 'Movies',
'documentSecurity' => false,
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::users()),
Permission::update(Role::users()),
Permission::delete(Role::users()),
],
]
];
$collection2 = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($collection2['body']['data']);
$this->assertArrayNotHasKey('errors', $collection2['body']);
$collection2 = $collection2['body']['data']['databasesCreateCollection'];
$this->assertEquals('Movies', $collection2['name']);
return [ return [
'database' => $database, 'database' => $database,
'collection' => $collection, 'collection' => $collection,
'collection2' => $collection2,
]; ];
} }
@ -570,6 +598,69 @@ class DatabaseServerTest extends Scope
return $data; return $data;
} }
/**
* @depends testCreateCollection
*/
public function testCreateRelationshipAttribute(array $data): array
{
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$CREATE_RELATIONSHIP_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection2']['_id'], // Movies
'relatedCollectionId' => $data['collection']['_id'], // Actors
'type' => Database::RELATION_ONE_TO_MANY,
'twoWay' => true,
'key' => 'actors',
'twoWayKey' => 'movie'
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $attribute['body']);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesCreateRelationshipAttribute']);
return $data;
}
/**
* @depends testCreateRelationshipAttribute
*/
public function testUpdateRelationshipAttribute(array $data): array
{
sleep(3);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::$UPDATE_RELATIONSHIP_ATTRIBUTE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'collectionId' => $data['collection2']['_id'],
'key' => 'actors',
'twoWay' => false,
]
];
$attribute = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $attribute['body']);
$this->assertIsArray($attribute['body']['data']);
$this->assertIsArray($attribute['body']['data']['databasesUpdateRelationshipAttribute']);
return $data;
}
/** /**
* @depends testCreateCollection * @depends testCreateCollection
* @throws Exception * @throws Exception