From 5b52b49ca110885c2eee019ee213373dd82b1ecd Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 28 Sep 2023 20:55:56 +1300 Subject: [PATCH] Allow querying on $internalId --- src/Database/Adapter/MariaDB.php | 9 ++-- src/Database/Adapter/Mongo.php | 48 ++++++++++---------- src/Database/Adapter/Postgres.php | 3 ++ src/Database/Validator/Queries/Documents.php | 8 +++- tests/Database/Base.php | 31 +++++++++++-- 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 24d207b23..d4647f754 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -945,10 +945,10 @@ public function deleteDocument(string $collection, string $id): bool * @param array $orderTypes * @param array $cursor * @param string $cursorDirection - * + * @param int|null $timeout * @return array - * @throws Exception - * @throws PDOException + * @throws DatabaseException + * @throws Timeout */ public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER, ?int $timeout = null): array { @@ -959,6 +959,7 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, $orderAttributes = \array_map(fn ($orderAttribute) => match ($orderAttribute) { '$id' => '_uid', + '$internalId' => '_id', '$createdAt' => '_createdAt', '$updatedAt' => '_updatedAt', default => $orderAttribute @@ -1071,6 +1072,7 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, $attribute = match ($attribute) { '_uid' => '$id', + '_id' => '$internalId', '_createdAt' => '$createdAt', '_updatedAt' => '$updatedAt', default => $attribute @@ -1301,6 +1303,7 @@ protected function getSQLCondition(Query $query): string { $query->setAttribute(match ($query->getAttribute()) { '$id' => '_uid', + '$internalId' => '_id', '$createdAt' => '_createdAt', '$updatedAt' => '_updatedAt', default => $query->getAttribute() diff --git a/src/Database/Adapter/Mongo.php b/src/Database/Adapter/Mongo.php index 14b8a3513..df827a405 100644 --- a/src/Database/Adapter/Mongo.php +++ b/src/Database/Adapter/Mongo.php @@ -857,9 +857,10 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, $orderType = $orderType === Database::ORDER_ASC ? Database::ORDER_DESC : Database::ORDER_ASC; } - $attribute = $attribute == 'id' ? "_uid" : $attribute; - $attribute = $attribute == 'createdAt' ? "_createdAt" : $attribute; - $attribute = $attribute == 'updatedAt' ? "_updatedAt" : $attribute; + $attribute = $attribute == 'id' ? '_uid' : $attribute; + $attribute = $attribute == 'internalId' ? '_id' : $attribute; + $attribute = $attribute == 'createdAt' ? '_createdAt' : $attribute; + $attribute = $attribute == 'updatedAt' ? '_updatedAt' : $attribute; $options['sort'][$attribute] = $this->getOrder($orderType); } @@ -1253,33 +1254,34 @@ protected function buildFilters(array $queries): array if ($query->getAttribute() === '$id') { $query->setAttribute('_uid'); - } - - if ($query->getAttribute() === '$createdAt') { + } elseif ($query->getAttribute() === '$internalId') { + $query->setAttribute('_id'); + $values = $query->getValues(); + foreach ($values as &$value) { + $value = new ObjectId($value); + } + $query->setValues($values); + } elseif ($query->getAttribute() === '$createdAt') { $query->setAttribute('_createdAt'); - } - - if ($query->getAttribute() === '$updatedAt') { + } elseif ($query->getAttribute() === '$updatedAt') { $query->setAttribute('_updatedAt'); } $attribute = $query->getAttribute(); $operator = $this->getQueryOperator($query->getMethod()); - switch ($query->getMethod()) { - case Query::TYPE_IS_NULL: - case Query::TYPE_IS_NOT_NULL: - $value = null; - break; - default: - $value = $this->getQueryValue( - $query->getMethod(), - count($query->getValues()) > 1 - ? $query->getValues() - : $query->getValues()[0] - ); - break; - } + unset($value); + + $value = match ($query->getMethod()) { + Query::TYPE_IS_NULL, + Query::TYPE_IS_NOT_NULL => null, + default => $this->getQueryValue( + $query->getMethod(), + count($query->getValues()) > 1 + ? $query->getValues() + : $query->getValues()[0] + ), + }; if ($operator == '$eq' && \is_array($value)) { $filters[$attribute]['$in'] = $value; diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index f35816aba..8df026bda 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -972,6 +972,7 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, $orderAttributes = \array_map(fn ($orderAttribute) => match ($orderAttribute) { '$id' => '_uid', + '$internalId' => '_id', '$createdAt' => '_createdAt', '$updatedAt' => '_updatedAt', default => $orderAttribute @@ -1077,6 +1078,7 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, $attribute = match ($attribute) { '_uid' => '$id', + '_id' => '$internalId', '_createdAt' => '$createdAt', '_updatedAt' => '$updatedAt', default => $attribute @@ -1313,6 +1315,7 @@ protected function getSQLCondition(Query $query): string { $query->setAttribute(match ($query->getAttribute()) { '$id' => '_uid', + '$internalId' => '_id', '$createdAt' => '_createdAt', '$updatedAt' => '_updatedAt', default => $query->getAttribute() diff --git a/src/Database/Validator/Queries/Documents.php b/src/Database/Validator/Queries/Documents.php index 2dd7c0819..0d1dc2384 100644 --- a/src/Database/Validator/Queries/Documents.php +++ b/src/Database/Validator/Queries/Documents.php @@ -30,14 +30,18 @@ public function __construct(array $attributes, array $indexes) 'type' => Database::VAR_STRING, 'array' => false, ]); - + $attributes[] = new Document([ + '$id' => '$internalId', + 'key' => '$internalId', + 'type' => Database::VAR_STRING, + 'array' => false, + ]); $attributes[] = new Document([ '$id' => '$createdAt', 'key' => '$createdAt', 'type' => Database::VAR_DATETIME, 'array' => false, ]); - $attributes[] = new Document([ '$id' => '$updatedAt', 'key' => '$updatedAt', diff --git a/tests/Database/Base.php b/tests/Database/Base.php index 26726a0ca..34609d113 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -1477,8 +1477,10 @@ public function testDeleteDocument(Document $document): void } - - public function testFind(): void + /** + * @return array + */ + public function testFind(): array { Authorization::setRole(Role::any()->toString()); static::getDatabase()->createCollection('movies', permissions: [ @@ -1495,7 +1497,7 @@ public function testFind(): void $this->assertEquals(true, static::getDatabase()->createAttribute('movies', 'with-dash', Database::VAR_STRING, 128, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('movies', 'nullable', Database::VAR_STRING, 128, false)); - static::getDatabase()->createDocument('movies', new Document([ + $document = static::getDatabase()->createDocument('movies', new Document([ '$id' => ID::custom('frozen'), '$permissions' => [ Permission::read(Role::any()), @@ -1638,6 +1640,10 @@ public function testFind(): void 'with-dash' => 'Works3', 'nullable' => 'Not null' ])); + + return [ + '$internalId' => $document->getInternalId() + ]; } public function testFindBasicChecks(): void @@ -1980,6 +1986,25 @@ public function testFindByID(): void $this->assertEquals('Frozen', $documents[0]['name']); } + + /** + * @depends testFind + * @param array $data + * @return void + * @throws \Utopia\Database\Exception + */ + public function testFindByInternalID(array $data): void + { + /** + * Test that internal ID queries are handled correctly + */ + $documents = static::getDatabase()->find('movies', [ + Query::equal('$internalId', [$data['$internalId']]), + ]); + + $this->assertEquals(1, count($documents)); + } + public function testFindOrderBy(): void { /**