Skip to content

Commit 141338a

Browse files
authored
Merge pull request #739 from utopia-php/postgres-case-insensitive
Postgres case insensitive for UID
2 parents 1ce7ffc + 6b932c1 commit 141338a

File tree

2 files changed

+61
-48
lines changed

2 files changed

+61
-48
lines changed

src/Database/Adapter/Postgres.php

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ public function create(string $name): bool
151151
$this->getPDO()->prepare('CREATE EXTENSION IF NOT EXISTS postgis;')->execute();
152152

153153
$collation = "
154-
CREATE COLLATION IF NOT EXISTS utf8_ci (
154+
CREATE COLLATION IF NOT EXISTS utf8_ci_ai (
155155
provider = icu,
156-
locale = 'und-u-ks-primary',
156+
locale = 'und-u-ks-level1',
157157
deterministic = false
158158
);
159159
";
@@ -244,14 +244,14 @@ public function createCollection(string $name, array $attributes = [], array $in
244244

245245
if ($this->sharedTables) {
246246
$collection .= "
247-
CREATE UNIQUE INDEX \"{$namespace}_{$this->tenant}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\", \"_tenant\");
247+
CREATE UNIQUE INDEX \"{$namespace}_{$this->tenant}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\" COLLATE utf8_ci_ai, \"_tenant\");
248248
CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_created\" ON {$this->getSQLTable($id)} (_tenant, \"_createdAt\");
249249
CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_updated\" ON {$this->getSQLTable($id)} (_tenant, \"_updatedAt\");
250250
CREATE INDEX \"{$namespace}_{$this->tenant}_{$id}_tenant_id\" ON {$this->getSQLTable($id)} (_tenant, _id);
251251
";
252252
} else {
253253
$collection .= "
254-
CREATE UNIQUE INDEX \"{$namespace}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\");
254+
CREATE UNIQUE INDEX \"{$namespace}_{$id}_uid\" ON {$this->getSQLTable($id)} (\"_uid\" COLLATE utf8_ci_ai);
255255
CREATE INDEX \"{$namespace}_{$id}_created\" ON {$this->getSQLTable($id)} (\"_createdAt\");
256256
CREATE INDEX \"{$namespace}_{$id}_updated\" ON {$this->getSQLTable($id)} (\"_updatedAt\");
257257
";
@@ -279,7 +279,7 @@ public function createCollection(string $name, array $attributes = [], array $in
279279
} else {
280280
$permissions .= "
281281
CREATE UNIQUE INDEX \"{$namespace}_{$id}_ukey\"
282-
ON {$this->getSQLTable($id . '_perms')} USING btree (_document,_type,_permission);
282+
ON {$this->getSQLTable($id . '_perms')} USING btree (_document COLLATE utf8_ci_ai,_type,_permission);
283283
CREATE INDEX \"{$namespace}_{$id}_permission\"
284284
ON {$this->getSQLTable($id . '_perms')} USING btree (_permission,_type);
285285
";
@@ -852,15 +852,7 @@ public function createIndex(string $collection, string $id, string $type, array
852852
default => $this->filter($attr),
853853
};
854854

855-
if (Database::INDEX_UNIQUE === $type) {
856-
if (isset($indexAttributeTypes[$attr]) && $indexAttributeTypes[$attr] === Database::VAR_STRING) {
857-
$attributes[$i] = "\"{$attr}\" COLLATE utf8_ci {$order}";
858-
} else {
859-
$attributes[$i] = "\"{$attr}\" {$order}";
860-
}
861-
} else {
862-
$attributes[$i] = "\"{$attr}\" {$order}";
863-
}
855+
$attributes[$i] = "\"{$attr}\" {$order}";
864856
}
865857

866858
$sqlType = match ($type) {
@@ -908,7 +900,7 @@ public function createIndex(string $collection, string $id, string $type, array
908900
*/
909901
public function deleteIndex(string $collection, string $id): bool
910902
{
911-
$name = $this->filter($collection);
903+
$collection = $this->filter($collection);
912904
$id = $this->filter($id);
913905
$schemaName = $this->getDatabase();
914906

tests/e2e/Adapter/Scopes/DocumentTests.php

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4729,36 +4729,40 @@ public function testWritePermissionsUpdateFailure(Document $document): Document
47294729
*/
47304730
public function testUniqueIndexDuplicate(): void
47314731
{
4732-
$this->expectException(DuplicateException::class);
4733-
47344732
/** @var Database $database */
47354733
$database = static::getDatabase();
47364734

47374735
$this->assertEquals(true, $database->createIndex('movies', 'uniqueIndex', Database::INDEX_UNIQUE, ['name'], [128], [Database::ORDER_ASC]));
47384736

4739-
$database->createDocument('movies', new Document([
4740-
'$permissions' => [
4741-
Permission::read(Role::any()),
4742-
Permission::read(Role::user('1')),
4743-
Permission::read(Role::user('2')),
4744-
Permission::create(Role::any()),
4745-
Permission::create(Role::user('1x')),
4746-
Permission::create(Role::user('2x')),
4747-
Permission::update(Role::any()),
4748-
Permission::update(Role::user('1x')),
4749-
Permission::update(Role::user('2x')),
4750-
Permission::delete(Role::any()),
4751-
Permission::delete(Role::user('1x')),
4752-
Permission::delete(Role::user('2x')),
4753-
],
4754-
'name' => 'Frozen',
4755-
'director' => 'Chris Buck & Jennifer Lee',
4756-
'year' => 2013,
4757-
'price' => 39.50,
4758-
'active' => true,
4759-
'genres' => ['animation', 'kids'],
4760-
'with-dash' => 'Works4'
4761-
]));
4737+
try {
4738+
$database->createDocument('movies', new Document([
4739+
'$permissions' => [
4740+
Permission::read(Role::any()),
4741+
Permission::read(Role::user('1')),
4742+
Permission::read(Role::user('2')),
4743+
Permission::create(Role::any()),
4744+
Permission::create(Role::user('1x')),
4745+
Permission::create(Role::user('2x')),
4746+
Permission::update(Role::any()),
4747+
Permission::update(Role::user('1x')),
4748+
Permission::update(Role::user('2x')),
4749+
Permission::delete(Role::any()),
4750+
Permission::delete(Role::user('1x')),
4751+
Permission::delete(Role::user('2x')),
4752+
],
4753+
'name' => 'Frozen',
4754+
'director' => 'Chris Buck & Jennifer Lee',
4755+
'year' => 2013,
4756+
'price' => 39.50,
4757+
'active' => true,
4758+
'genres' => ['animation', 'kids'],
4759+
'with-dash' => 'Works4'
4760+
]));
4761+
4762+
$this->fail('Failed to throw exception');
4763+
} catch (Throwable $e) {
4764+
$this->assertInstanceOf(DuplicateException::class, $e);
4765+
}
47624766
}
47634767
/**
47644768
* @depends testUniqueIndexDuplicate
@@ -4794,9 +4798,13 @@ public function testUniqueIndexDuplicateUpdate(): void
47944798
'with-dash' => 'Works4'
47954799
]));
47964800

4797-
$this->expectException(DuplicateException::class);
4801+
try {
4802+
$database->updateDocument('movies', $document->getId(), $document->setAttribute('name', 'Frozen'));
47984803

4799-
$database->updateDocument('movies', $document->getId(), $document->setAttribute('name', 'Frozen'));
4804+
$this->fail('Failed to throw exception');
4805+
} catch (Throwable $e) {
4806+
$this->assertInstanceOf(DuplicateException::class, $e);
4807+
}
48004808
}
48014809

48024810
public function propagateBulkDocuments(string $collection, int $amount = 10, bool $documentSecurity = false): void
@@ -5298,9 +5306,17 @@ public function testExceptionDuplicate(Document $document): void
52985306
$database = static::getDatabase();
52995307

53005308
$document->setAttribute('$id', 'duplicated');
5309+
$document->removeAttribute('$sequence');
5310+
53015311
$database->createDocument($document->getCollection(), $document);
5302-
$this->expectException(DuplicateException::class);
5303-
$database->createDocument($document->getCollection(), $document);
5312+
$document->removeAttribute('$sequence');
5313+
5314+
try {
5315+
$database->createDocument($document->getCollection(), $document);
5316+
$this->fail('Failed to throw exception');
5317+
} catch (Throwable $e) {
5318+
$this->assertInstanceOf(DuplicateException::class, $e);
5319+
}
53045320
}
53055321

53065322
/**
@@ -5312,13 +5328,18 @@ public function testExceptionCaseInsensitiveDuplicate(Document $document): Docum
53125328
$database = static::getDatabase();
53135329

53145330
$document->setAttribute('$id', 'caseSensitive');
5315-
$document->setAttribute('$sequence', '200');
5316-
$database->createDocument($document->getCollection(), $document);
5331+
$document->removeAttribute('$sequence');
53175332

5333+
$database->createDocument($document->getCollection(), $document);
53185334
$document->setAttribute('$id', 'CaseSensitive');
5335+
$document->removeAttribute('$sequence');
53195336

5320-
$this->expectException(DuplicateException::class);
5321-
$database->createDocument($document->getCollection(), $document);
5337+
try {
5338+
$database->createDocument($document->getCollection(), $document);
5339+
$this->fail('Failed to throw exception');
5340+
} catch (Throwable $e) {
5341+
$this->assertInstanceOf(DuplicateException::class, $e);
5342+
}
53225343

53235344
return $document;
53245345
}

0 commit comments

Comments
 (0)