mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 17:08:45 +00:00
Merge branch '1.8.x' into dat-571
This commit is contained in:
commit
e97d10061f
10 changed files with 378 additions and 41 deletions
|
|
@ -22,6 +22,7 @@ use Appwrite\Utopia\Request\Filters\V16 as RequestV16;
|
|||
use Appwrite\Utopia\Request\Filters\V17 as RequestV17;
|
||||
use Appwrite\Utopia\Request\Filters\V18 as RequestV18;
|
||||
use Appwrite\Utopia\Request\Filters\V19 as RequestV19;
|
||||
use Appwrite\Utopia\Request\Filters\V20 as RequestV20;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Filters\V16 as ResponseV16;
|
||||
use Appwrite\Utopia\Response\Filters\V17 as ResponseV17;
|
||||
|
|
@ -851,6 +852,10 @@ App::init()
|
|||
if (version_compare($requestFormat, '1.7.0', '<')) {
|
||||
$request->addFilter(new RequestV19());
|
||||
}
|
||||
if (version_compare($requestFormat, '1.8.0', '<')) {
|
||||
$dbForProject = $getProjectDB($project);
|
||||
$request->addFilter(new RequestV20($dbForProject, $route));
|
||||
}
|
||||
}
|
||||
|
||||
$domain = $request->getHostname();
|
||||
|
|
|
|||
|
|
@ -87,7 +87,15 @@ class Get extends Action
|
|||
}
|
||||
|
||||
try {
|
||||
$document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries);
|
||||
$selects = Query::groupByType($queries)['selections'] ?? [];
|
||||
|
||||
if (! empty($selects)) {
|
||||
// has selects, allow relationship on documents!
|
||||
$document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries);
|
||||
} else {
|
||||
// has no selects, disable relationship looping on documents!
|
||||
$document = $dbForProject->skipRelationships(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries));
|
||||
}
|
||||
} catch (QueryException $e) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,21 @@ class XList extends Action
|
|||
|
||||
$cursor->setValue($cursorDocument);
|
||||
}
|
||||
|
||||
$selectQueries = [];
|
||||
|
||||
try {
|
||||
$documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries);
|
||||
$selectQueries = Query::groupByType($queries)['selections'] ?? [];
|
||||
|
||||
if (! empty($selectQueries)) {
|
||||
// has selects, allow relationship on documents!
|
||||
$documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries);
|
||||
} else {
|
||||
// has no selects, disable relationship looping on documents!
|
||||
/* @type Document[] $documents */
|
||||
$documents = $dbForProject->skipRelationships(fn () => $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries));
|
||||
}
|
||||
|
||||
$total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT);
|
||||
} catch (OrderException $e) {
|
||||
$documents = $this->isCollectionsAPI() ? 'documents' : 'rows';
|
||||
|
|
@ -150,24 +163,40 @@ class XList extends Action
|
|||
}, false);
|
||||
|
||||
// Check if the SELECT query includes $databaseId and $collectionId
|
||||
$hasWildcard = false;
|
||||
$hasDatabaseId = false;
|
||||
$hasCollectionId = false;
|
||||
if ($select) {
|
||||
$hasDatabaseId = \array_reduce($queries, function ($result, $query) {
|
||||
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$databaseId', $query->getValues()));
|
||||
}, false);
|
||||
$hasCollectionId = \array_reduce($queries, function ($result, $query) {
|
||||
return $result || ($query->getMethod() === Query::TYPE_SELECT && \in_array('$collectionId', $query->getValues()));
|
||||
}, false);
|
||||
}
|
||||
$hasSelectQueries = !empty($selectQueries);
|
||||
|
||||
if ($select) {
|
||||
foreach ($documents as $document) {
|
||||
if (!$hasDatabaseId) {
|
||||
$document->removeAttribute('$databaseId');
|
||||
if ($hasSelectQueries) {
|
||||
foreach ($selectQueries as $query) {
|
||||
if ($query->getMethod() !== Query::TYPE_SELECT) {
|
||||
continue;
|
||||
}
|
||||
if (!$hasCollectionId) {
|
||||
$document->removeAttribute('$collectionId');
|
||||
|
||||
$values = $query->getValues();
|
||||
if (\in_array('*', $values, true)) {
|
||||
$hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (\in_array('$databaseId', $values, true)) {
|
||||
$hasDatabaseId = true;
|
||||
}
|
||||
|
||||
if (\in_array('$collectionId', $values, true)) {
|
||||
$hasCollectionId = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasWildcard) {
|
||||
foreach ($documents as $document) {
|
||||
if (!$hasDatabaseId) {
|
||||
$document->removeAttribute('$databaseId');
|
||||
}
|
||||
if (!$hasCollectionId) {
|
||||
$document->removeAttribute('$collectionId');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,20 @@
|
|||
|
||||
namespace Appwrite\Utopia\Request;
|
||||
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Route;
|
||||
|
||||
abstract class Filter
|
||||
{
|
||||
private ?Route $route;
|
||||
private ?Database $dbForProject;
|
||||
|
||||
public function __construct(Database $dbForProject = null, Route $route = null)
|
||||
{
|
||||
$this->route = $route;
|
||||
$this->dbForProject = $dbForProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse params to another format.
|
||||
*
|
||||
|
|
@ -13,4 +25,33 @@ abstract class Filter
|
|||
* @return array
|
||||
*/
|
||||
abstract public function parse(array $content, string $model): array;
|
||||
|
||||
/**
|
||||
* Get the database for the current project.
|
||||
*
|
||||
* @return null|Database
|
||||
*/
|
||||
public function getDbForProject(): ?Database
|
||||
{
|
||||
return $this->dbForProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given route param key, or a default if not found or on error.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParamValue(string $key, mixed $default = ''): mixed
|
||||
{
|
||||
try {
|
||||
$value = $this->route?->getParamValue($key) ?? $default;
|
||||
} catch (\Exception $e) {
|
||||
$value = $default;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class V19 extends Filter
|
|||
return $content;
|
||||
}
|
||||
|
||||
public function convertQueryAttribute(array $content, string $old, string $new)
|
||||
public function convertQueryAttribute(array $content, string $old, string $new): array
|
||||
{
|
||||
if (isset($content['queries']) && is_array($content['queries'])) {
|
||||
foreach ($content['queries'] as $index => $query) {
|
||||
|
|
|
|||
124
src/Appwrite/Utopia/Request/Filters/V20.php
Normal file
124
src/Appwrite/Utopia/Request/Filters/V20.php
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Utopia\Request\Filters;
|
||||
|
||||
use Appwrite\Utopia\Request\Filter;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
|
||||
class V20 extends Filter
|
||||
{
|
||||
// Convert 1.7 params to 1.8
|
||||
public function parse(array $content, string $model): array
|
||||
{
|
||||
switch ($model) {
|
||||
case 'databases.getDocument':
|
||||
case 'databases.listDocuments':
|
||||
$content = $this->manageSelectQueries($content, $model);
|
||||
break;
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* From 1.8.x onward, related documents are no longer returned by default to improve performance.
|
||||
*
|
||||
* Use `Query::select(['related.*'])` for full documents or `Query::select(['related.key'])` for specific fields.
|
||||
*
|
||||
* This filter preserves 1.7.x behavior by including all related documents for backward compatibility with
|
||||
* `listDocuments` and `getDocument` calls.
|
||||
*/
|
||||
protected function manageSelectQueries(array $content, string $model): array
|
||||
{
|
||||
$hasWildcard = false;
|
||||
if (! isset($content['queries'])) {
|
||||
$hasWildcard = true;
|
||||
// only query, make it json encoded!
|
||||
$content['queries'] = [Query::select(['*'])->toString()];
|
||||
}
|
||||
|
||||
try {
|
||||
$parsed = Query::parseQueries($content['queries']);
|
||||
} catch (QueryException) {
|
||||
// don't crash!
|
||||
return $content;
|
||||
}
|
||||
|
||||
$selections = Query::groupByType($parsed)['selections'] ?? [];
|
||||
|
||||
if (! $hasWildcard) {
|
||||
// check if any select includes a wildcard as we added one above
|
||||
foreach ($selections as $select) {
|
||||
if (\in_array('*', $select->getValues(), true)) {
|
||||
$hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasWildcard && $model === 'databases.listDocuments') {
|
||||
$relatedKeys = $this->getRelatedCollectionKeys();
|
||||
|
||||
if (! empty($relatedKeys)) {
|
||||
$selects = \array_values(\array_unique(\array_merge(['*'], $relatedKeys)));
|
||||
|
||||
// remove previous select queries
|
||||
$parsed = \array_filter(
|
||||
$parsed,
|
||||
fn ($query) => $query->getMethod() !== Query::TYPE_SELECT
|
||||
);
|
||||
|
||||
// add wildcard + relationship(s) selects
|
||||
$parsed[] = Query::select($selects);
|
||||
}
|
||||
}
|
||||
|
||||
$resolvedQueries = [];
|
||||
foreach ($parsed as $query) {
|
||||
// make em json encoded!
|
||||
$resolvedQueries[] = $query->toString();
|
||||
}
|
||||
|
||||
$content['queries'] = $resolvedQueries;
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all relationship attribute keys in `key.*` format for use with `Query::select`.
|
||||
*/
|
||||
private function getRelatedCollectionKeys(): array
|
||||
{
|
||||
$dbForProject = $this->getDbForProject();
|
||||
|
||||
if ($dbForProject === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$databaseId = $this->getParamValue('databaseId');
|
||||
$collectionId = $this->getParamValue('collectionId');
|
||||
|
||||
if (empty($databaseId) || empty($collectionId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$collection = $dbForProject->getDocument(
|
||||
'database_' . $database->getSequence(),
|
||||
$collectionId
|
||||
);
|
||||
|
||||
$attributes = $collection->getAttribute('attributes', []);
|
||||
|
||||
return \array_values(\array_map(
|
||||
fn ($attr) => $attr['key'] . '.*',
|
||||
\array_filter(
|
||||
$attributes,
|
||||
fn ($attr) => ($attr['type'] ?? null) === Database::VAR_RELATIONSHIP
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -4563,7 +4563,11 @@ trait DatabasesBase
|
|||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $personCollection . '/documents/' . $person2['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'libraries.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertArrayNotHasKey('$collection', $response['body']);
|
||||
|
|
@ -4573,7 +4577,11 @@ trait DatabasesBase
|
|||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $libraryCollection . '/documents/library11', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['person_one_to_many.$id'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertArrayHasKey('person_one_to_many', $response['body']);
|
||||
|
|
@ -4723,7 +4731,11 @@ trait DatabasesBase
|
|||
$album = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $albums['body']['$id'] . '/documents/album1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'artist.name', 'artist.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $album['headers']['status-code']);
|
||||
$this->assertEquals('album1', $album['body']['$id']);
|
||||
|
|
@ -4735,7 +4747,11 @@ trait DatabasesBase
|
|||
$artist = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $artists['body']['$id'] . '/documents/' . $album['body']['artist']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'albums.$id', 'albums.name', 'albums.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $artist['headers']['status-code']);
|
||||
$this->assertEquals('Artist 1', $artist['body']['name']);
|
||||
|
|
@ -4876,7 +4892,11 @@ trait DatabasesBase
|
|||
$sport = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $sports['body']['$id'] . '/documents/sport1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'players.name', 'players.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $sport['headers']['status-code']);
|
||||
$this->assertEquals('sport1', $sport['body']['$id']);
|
||||
|
|
@ -4890,7 +4910,11 @@ trait DatabasesBase
|
|||
$player = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $players['body']['$id'] . '/documents/' . $sport['body']['players'][0]['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'sports.$id', 'sports.name', 'sports.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $player['headers']['status-code']);
|
||||
$this->assertEquals('Player 1', $player['body']['name']);
|
||||
|
|
@ -4918,6 +4942,7 @@ trait DatabasesBase
|
|||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::isNotNull('$id')->toString(),
|
||||
Query::select(['*', 'libraries.*'])->toString(),
|
||||
Query::startsWith('fullName', 'Stevie')->toString(),
|
||||
Query::endsWith('fullName', 'Wonder')->toString(),
|
||||
Query::between('$createdAt', '1975-12-06', '2050-12-01')->toString(),
|
||||
|
|
|
|||
|
|
@ -3794,7 +3794,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newDocument['body']);
|
||||
$this->assertEquals(1, count($newDocument['body']['new_level_2']));
|
||||
|
|
@ -3904,7 +3908,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newDocument['body']);
|
||||
$this->assertNotEmpty($newDocument['body']['new_level_2']);
|
||||
|
|
@ -4014,7 +4022,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newDocument['body']);
|
||||
$this->assertNotEmpty($newDocument['body']['new_level_2']);
|
||||
|
|
@ -4025,7 +4037,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'level1.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('level1', $level2Document['body']);
|
||||
$this->assertNotEmpty($level2Document['body']['level1']);
|
||||
|
|
@ -4124,7 +4140,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newDocument['body']);
|
||||
$this->assertNotEmpty($newDocument['body']['new_level_2']);
|
||||
|
|
@ -4135,7 +4155,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'level1.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('level1', $level2Document['body']);
|
||||
$this->assertNotEmpty($level2Document['body']['level1']);
|
||||
|
|
@ -4480,6 +4504,14 @@ class DatabasesCustomServerTest extends Scope
|
|||
|
||||
$createBulkDocuments();
|
||||
|
||||
/**
|
||||
* Wait for database to purge cache...
|
||||
*
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
|
||||
// TEST: Update all documents
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -4498,6 +4530,14 @@ class DatabasesCustomServerTest extends Scope
|
|||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(10, $response['body']['documents']);
|
||||
|
||||
/**
|
||||
* Wait for database to purge cache...
|
||||
*
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
|
|
|
|||
|
|
@ -4572,7 +4572,11 @@ trait DatabasesBase
|
|||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $personCollection . '/rows/' . $person2['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'libraries.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertArrayNotHasKey('$table', $response['body']);
|
||||
|
|
@ -4582,7 +4586,11 @@ trait DatabasesBase
|
|||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $libraryCollection . '/rows/library11', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['person_one_to_many.$id'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertArrayHasKey('person_one_to_many', $response['body']);
|
||||
|
|
@ -4732,7 +4740,11 @@ trait DatabasesBase
|
|||
$album = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $albums['body']['$id'] . '/rows/album1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'artist.name', 'artist.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $album['headers']['status-code']);
|
||||
$this->assertEquals('album1', $album['body']['$id']);
|
||||
|
|
@ -4744,7 +4756,11 @@ trait DatabasesBase
|
|||
$artist = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $artists['body']['$id'] . '/rows/' . $album['body']['artist']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'albums.$id', 'albums.name', 'albums.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $artist['headers']['status-code']);
|
||||
$this->assertEquals('Artist 1', $artist['body']['name']);
|
||||
|
|
@ -4885,7 +4901,11 @@ trait DatabasesBase
|
|||
$sport = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $sports['body']['$id'] . '/rows/sport1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'players.name', 'players.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $sport['headers']['status-code']);
|
||||
$this->assertEquals('sport1', $sport['body']['$id']);
|
||||
|
|
@ -4899,7 +4919,11 @@ trait DatabasesBase
|
|||
$player = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/tables/' . $players['body']['$id'] . '/rows/' . $sport['body']['players'][0]['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'sports.$id', 'sports.name', 'sports.$permissions'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $player['headers']['status-code']);
|
||||
$this->assertEquals('Player 1', $player['body']['name']);
|
||||
|
|
@ -4927,6 +4951,7 @@ trait DatabasesBase
|
|||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::isNotNull('$id')->toString(),
|
||||
Query::select(['*', 'libraries.*'])->toString(),
|
||||
Query::startsWith('fullName', 'Stevie')->toString(),
|
||||
Query::endsWith('fullName', 'Wonder')->toString(),
|
||||
Query::between('$createdAt', '1975-12-06', '2050-12-01')->toString(),
|
||||
|
|
|
|||
|
|
@ -3740,7 +3740,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newRow['body']);
|
||||
$this->assertEquals(1, count($newRow['body']['new_level_2']));
|
||||
|
|
@ -3850,7 +3854,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newRow['body']);
|
||||
$this->assertNotEmpty($newRow['body']['new_level_2']);
|
||||
|
|
@ -3960,7 +3968,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newRow['body']);
|
||||
$this->assertNotEmpty($newRow['body']['new_level_2']);
|
||||
|
|
@ -3971,7 +3983,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'level1.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('level1', $level2Row['body']);
|
||||
$this->assertNotEmpty($level2Row['body']['level1']);
|
||||
|
|
@ -4070,7 +4086,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['new_level_2.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('new_level_2', $newRow['body']);
|
||||
$this->assertNotEmpty($newRow['body']['new_level_2']);
|
||||
|
|
@ -4081,7 +4101,11 @@ class DatabasesCustomServerTest extends Scope
|
|||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
]), [
|
||||
'queries' => [
|
||||
Query::select(['*', 'level1.*'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('level1', $level2Row['body']);
|
||||
$this->assertNotEmpty($level2Row['body']['level1']);
|
||||
|
|
@ -4426,6 +4450,14 @@ class DatabasesCustomServerTest extends Scope
|
|||
|
||||
$createBulkRows();
|
||||
|
||||
/**
|
||||
* Wait for database to purge cache...
|
||||
*
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
|
||||
// TEST: Update all rows
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -4444,6 +4476,14 @@ class DatabasesCustomServerTest extends Scope
|
|||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(10, $response['body']['rows']);
|
||||
|
||||
/**
|
||||
* Wait for database to purge cache...
|
||||
*
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
|
||||
$rows = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
|
|
|
|||
Loading…
Reference in a new issue