diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index fe8214e9c..d8cd83f4e 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -151,9 +151,9 @@ public function create(string $name): bool $this->getPDO()->prepare('CREATE EXTENSION IF NOT EXISTS postgis;')->execute(); $collation = " - CREATE COLLATION IF NOT EXISTS utf8_ci ( + CREATE COLLATION IF NOT EXISTS utf8_ci_ai ( provider = icu, - locale = 'und-u-ks-primary', + locale = 'und-u-ks-level1', deterministic = false ); "; @@ -244,14 +244,14 @@ public function createCollection(string $name, array $attributes = [], array $in if ($this->sharedTables) { $collection .= " - CREATE UNIQUE INDEX \"{$namespace}_{$this->tenant}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\", \"_tenant\"); + CREATE UNIQUE INDEX \"{$namespace}_{$this->tenant}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\" COLLATE utf8_ci_ai, \"_tenant\"); CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_created\" ON {$this->getSQLTable($id)} (_tenant, \"_createdAt\"); CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_updated\" ON {$this->getSQLTable($id)} (_tenant, \"_updatedAt\"); CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_tenant_id\" ON {$this->getSQLTable($id)} (_tenant, _id); "; } else { $collection .= " - CREATE UNIQUE INDEX \"{$namespace}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\"); + CREATE UNIQUE INDEX \"{$namespace}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\" COLLATE utf8_ci_ai); CREATE INDEX \"{$namespace}_{$id}_created\" ON {$this->getSQLTable($id)} (\"_createdAt\"); CREATE INDEX \"{$namespace}_{$id}_updated\" ON {$this->getSQLTable($id)} (\"_updatedAt\"); "; @@ -279,7 +279,7 @@ public function createCollection(string $name, array $attributes = [], array $in } else { $permissions .= " CREATE UNIQUE INDEX \"{$namespace}_{$id}_ukey\" - ON {$this->getSQLTable($id . '_perms')} USING btree (_document,_type,_permission); + ON {$this->getSQLTable($id . '_perms')} USING btree (_document COLLATE utf8_ci_ai,_type,_permission); CREATE INDEX \"{$namespace}_{$id}_permission\" ON {$this->getSQLTable($id . '_perms')} USING btree (_permission,_type); "; @@ -852,15 +852,7 @@ public function createIndex(string $collection, string $id, string $type, array default => $this->filter($attr), }; - if (Database::INDEX_UNIQUE === $type) { - if (isset($indexAttributeTypes[$attr]) && $indexAttributeTypes[$attr] === Database::VAR_STRING) { - $attributes[$i] = "\"{$attr}\" COLLATE utf8_ci {$order}"; - } else { - $attributes[$i] = "\"{$attr}\" {$order}"; - } - } else { - $attributes[$i] = "\"{$attr}\" {$order}"; - } + $attributes[$i] = "\"{$attr}\" {$order}"; } $sqlType = match ($type) { @@ -908,7 +900,7 @@ public function createIndex(string $collection, string $id, string $type, array */ public function deleteIndex(string $collection, string $id): bool { - $name = $this->filter($collection); + $collection = $this->filter($collection); $id = $this->filter($id); $schemaName = $this->getDatabase(); diff --git a/tests/e2e/Adapter/Scopes/DocumentTests.php b/tests/e2e/Adapter/Scopes/DocumentTests.php index 81f3eee5b..76c9231fc 100644 --- a/tests/e2e/Adapter/Scopes/DocumentTests.php +++ b/tests/e2e/Adapter/Scopes/DocumentTests.php @@ -4729,36 +4729,40 @@ public function testWritePermissionsUpdateFailure(Document $document): Document */ public function testUniqueIndexDuplicate(): void { - $this->expectException(DuplicateException::class); - /** @var Database $database */ $database = static::getDatabase(); $this->assertEquals(true, $database->createIndex('movies', 'uniqueIndex', Database::INDEX_UNIQUE, ['name'], [128], [Database::ORDER_ASC])); - $database->createDocument('movies', new Document([ - '$permissions' => [ - Permission::read(Role::any()), - Permission::read(Role::user('1')), - Permission::read(Role::user('2')), - Permission::create(Role::any()), - Permission::create(Role::user('1x')), - Permission::create(Role::user('2x')), - Permission::update(Role::any()), - Permission::update(Role::user('1x')), - Permission::update(Role::user('2x')), - Permission::delete(Role::any()), - Permission::delete(Role::user('1x')), - Permission::delete(Role::user('2x')), - ], - 'name' => 'Frozen', - 'director' => 'Chris Buck & Jennifer Lee', - 'year' => 2013, - 'price' => 39.50, - 'active' => true, - 'genres' => ['animation', 'kids'], - 'with-dash' => 'Works4' - ])); + try { + $database->createDocument('movies', new Document([ + '$permissions' => [ + Permission::read(Role::any()), + Permission::read(Role::user('1')), + Permission::read(Role::user('2')), + Permission::create(Role::any()), + Permission::create(Role::user('1x')), + Permission::create(Role::user('2x')), + Permission::update(Role::any()), + Permission::update(Role::user('1x')), + Permission::update(Role::user('2x')), + Permission::delete(Role::any()), + Permission::delete(Role::user('1x')), + Permission::delete(Role::user('2x')), + ], + 'name' => 'Frozen', + 'director' => 'Chris Buck & Jennifer Lee', + 'year' => 2013, + 'price' => 39.50, + 'active' => true, + 'genres' => ['animation', 'kids'], + 'with-dash' => 'Works4' + ])); + + $this->fail('Failed to throw exception'); + } catch (Throwable $e) { + $this->assertInstanceOf(DuplicateException::class, $e); + } } /** * @depends testUniqueIndexDuplicate @@ -4794,9 +4798,13 @@ public function testUniqueIndexDuplicateUpdate(): void 'with-dash' => 'Works4' ])); - $this->expectException(DuplicateException::class); + try { + $database->updateDocument('movies', $document->getId(), $document->setAttribute('name', 'Frozen')); - $database->updateDocument('movies', $document->getId(), $document->setAttribute('name', 'Frozen')); + $this->fail('Failed to throw exception'); + } catch (Throwable $e) { + $this->assertInstanceOf(DuplicateException::class, $e); + } } public function propagateBulkDocuments(string $collection, int $amount = 10, bool $documentSecurity = false): void @@ -5298,9 +5306,17 @@ public function testExceptionDuplicate(Document $document): void $database = static::getDatabase(); $document->setAttribute('$id', 'duplicated'); + $document->removeAttribute('$sequence'); + $database->createDocument($document->getCollection(), $document); - $this->expectException(DuplicateException::class); - $database->createDocument($document->getCollection(), $document); + $document->removeAttribute('$sequence'); + + try { + $database->createDocument($document->getCollection(), $document); + $this->fail('Failed to throw exception'); + } catch (Throwable $e) { + $this->assertInstanceOf(DuplicateException::class, $e); + } } /** @@ -5312,13 +5328,18 @@ public function testExceptionCaseInsensitiveDuplicate(Document $document): Docum $database = static::getDatabase(); $document->setAttribute('$id', 'caseSensitive'); - $document->setAttribute('$sequence', '200'); - $database->createDocument($document->getCollection(), $document); + $document->removeAttribute('$sequence'); + $database->createDocument($document->getCollection(), $document); $document->setAttribute('$id', 'CaseSensitive'); + $document->removeAttribute('$sequence'); - $this->expectException(DuplicateException::class); - $database->createDocument($document->getCollection(), $document); + try { + $database->createDocument($document->getCollection(), $document); + $this->fail('Failed to throw exception'); + } catch (Throwable $e) { + $this->assertInstanceOf(DuplicateException::class, $e); + } return $document; }