Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
";
Expand Down Expand Up @@ -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\");
";
Expand Down Expand Up @@ -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);
";
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();

Expand Down
87 changes: 54 additions & 33 deletions tests/e2e/Adapter/Scopes/DocumentTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}

/**
Expand All @@ -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;
}
Expand Down