Skip to content

Commit a096447

Browse files
authored
Merge pull request #649 from utopia-php/feat-mongo-shared-tables-v2
Fix mongo shared tables for v2
2 parents c49619b + d84583f commit a096447

5 files changed

Lines changed: 846 additions & 824 deletions

File tree

composer.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Database/Adapter.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,15 +1208,6 @@ abstract public function getInternalIndexesKeys(): array;
12081208
*/
12091209
abstract public function getSchemaAttributes(string $collection): array;
12101210

1211-
/**
1212-
* Get the query to check for tenant when in shared tables mode
1213-
*
1214-
* @param string $collection The collection being queried
1215-
* @param string $alias The alias of the parent collection if in a subquery
1216-
* @return string
1217-
*/
1218-
abstract public function getTenantQuery(string $collection, string $alias = ''): string;
1219-
12201211
/**
12211212
* @param mixed $stmt
12221213
* @return bool

src/Database/Adapter/Mongo.php

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,11 @@ public function createCollection(string $name, array $attributes = [], array $in
288288
$key[$attribute] = $order;
289289
}
290290

291-
$newIndexes[$i] = ['key' => $key, 'name' => $this->filter($index->getId()), 'unique' => $unique];
291+
$newIndexes[$i] = [
292+
'key' => $key,
293+
'name' => $this->filter($index->getId()),
294+
'unique' => $unique
295+
];
292296
}
293297

294298
if (!$this->getClient()->createIndexes($id, $newIndexes)) {
@@ -337,7 +341,7 @@ public function getSizeOfCollection(string $collection): int
337341
{
338342
$namespace = $this->getNamespace();
339343
$collection = $this->filter($collection);
340-
$collection = $namespace. '_' . $collection;
344+
$collection = $namespace . '_' . $collection;
341345

342346
$command = [
343347
'collStats' => $collection,
@@ -745,7 +749,7 @@ public function getDocument(string $collection, string $id, array $queries = [],
745749
$filters = ['_uid' => $id];
746750

747751
if ($this->sharedTables) {
748-
$filters['_tenant'] = $this->getTenant();
752+
$filters['_tenant'] = $this->getTenantFilters($collection);
749753
}
750754

751755
$options = [];
@@ -803,17 +807,14 @@ public function createDocument(string $collection, Document $document): Document
803807
return new Document($result);
804808
}
805809

806-
807810
/**
808811
* Returns the document after casting from
809-
*@param Document $collection
812+
* @param Document $collection
810813
* @param Document $document
811-
812814
* @return Document
813815
*/
814-
public function castingAfter($collection, $document): Document
816+
public function castingAfter(Document $collection, Document $document): Document
815817
{
816-
817818
if (!$this->getSupportForInternalCasting()) {
818819
return $document;
819820
}
@@ -850,7 +851,7 @@ public function castingAfter($collection, $document): Document
850851
break;
851852
case Database::VAR_DATETIME :
852853
if ($node instanceof UTCDateTime) {
853-
$node = DateTime::format($node->toDateTime());
854+
$node = DateTime::format($node->toDateTime());
854855
}
855856
break;
856857
default:
@@ -866,14 +867,13 @@ public function castingAfter($collection, $document): Document
866867

867868
/**
868869
* Returns the document after casting to
869-
*@param Document $collection
870+
* @param Document $collection
870871
* @param Document $document
871-
872872
* @return Document
873+
* @throws Exception
873874
*/
874-
public function castingBefore($collection, $document): Document
875+
public function castingBefore(Document $collection, Document $document): Document
875876
{
876-
877877
if (!$this->getSupportForInternalCasting()) {
878878
return $document;
879879
}
@@ -939,7 +939,7 @@ public function createDocuments(string $collection, array $documents): array
939939

940940
$records = [];
941941
$hasSequence = null;
942-
$documents = array_map(fn ($doc) => clone $doc, $documents);
942+
$documents = \array_map(fn ($doc) => clone $doc, $documents);
943943

944944
foreach ($documents as $document) {
945945
$sequence = $document->getSequence();
@@ -950,12 +950,6 @@ public function createDocuments(string $collection, array $documents): array
950950
throw new DatabaseException('All documents must have an sequence if one is set');
951951
}
952952

953-
$document->removeAttribute('$sequence');
954-
955-
if ($this->sharedTables) {
956-
$document->setAttribute('$tenant', $this->getTenant());
957-
}
958-
959953
$record = $this->replaceChars('$', '_', (array)$document);
960954

961955
if (!empty($sequence)) {
@@ -985,15 +979,14 @@ public function createDocuments(string $collection, array $documents): array
985979
*/
986980
private function insertDocument(string $name, array $document): array
987981
{
988-
989982
try {
990983
$this->client->insert($name, $document);
991984

992985
$filters = [];
993986
$filters['_uid'] = $document['_uid'];
994987

995988
if ($this->sharedTables) {
996-
$filters['_tenant'] = $this->getTenant();
989+
$filters['_tenant'] = $this->getTenantFilters($name);
997990
}
998991

999992
$result = $this->client->find(
@@ -1008,17 +1001,16 @@ private function insertDocument(string $name, array $document): array
10081001
}
10091002
}
10101003

1011-
1012-
10131004
/**
10141005
* Update Document
10151006
*
10161007
* @param string $collection
10171008
* @param string $id
10181009
* @param Document $document
1019-
*
1010+
* @param bool $skipPermissions
10201011
* @return Document
1021-
* @throws Exception
1012+
* @throws DatabaseException
1013+
* @throws Duplicate
10221014
*/
10231015
public function updateDocument(string $collection, string $id, Document $document, bool $skipPermissions): Document
10241016
{
@@ -1027,12 +1019,13 @@ public function updateDocument(string $collection, string $id, Document $documen
10271019
$record = $document->getArrayCopy();
10281020
$record = $this->replaceChars('$', '_', $record);
10291021

1030-
10311022
$filters = [];
10321023
$filters['_uid'] = $id;
1024+
10331025
if ($this->sharedTables) {
1034-
$filters['_tenant'] = $this->getTenant();
1026+
$filters['_tenant'] = $this->getTenantFilters($collection);
10351027
}
1028+
10361029
try {
10371030
unset($record['_id']); // Don't update _id
10381031

@@ -1069,7 +1062,7 @@ public function updateDocuments(string $collection, Document $updates, array $do
10691062
$filters = $this->buildFilters($queries);
10701063

10711064
if ($this->sharedTables) {
1072-
$filters['_tenant'] = $this->getTenant();
1065+
$filters['_tenant'] = $this->getTenantFilters($collection);
10731066
}
10741067

10751068
$record = $updates->getArrayCopy();
@@ -1125,10 +1118,10 @@ public function createOrUpdateDocuments(string $collection, string $attribute, a
11251118
$record = $this->removeNullKeys($record);
11261119

11271120
// Build filter for upsert
1128-
$filter = ['_uid' => $document->getId()];
1121+
$filters = ['_uid' => $document->getId()];
11291122

11301123
if ($this->sharedTables) {
1131-
$filter['_tenant'] = $document->getTenant();
1124+
$filters['_tenant'] = $this->getTenantFilters($collection);
11321125
}
11331126

11341127
unset($record['_id']); // Don't update _id
@@ -1154,7 +1147,7 @@ public function createOrUpdateDocuments(string $collection, string $attribute, a
11541147
}
11551148

11561149
$operations[] = [
1157-
'filter' => $filter,
1150+
'filter' => $filters,
11581151
'update' => $update,
11591152
];
11601153
}
@@ -1178,6 +1171,8 @@ public function createOrUpdateDocuments(string $collection, string $attribute, a
11781171
* @param string $collection
11791172
* @param array<Document> $documents
11801173
* @return array<Document>
1174+
* @throws DatabaseException
1175+
* @throws MongoException
11811176
*/
11821177
public function getSequences(string $collection, array $documents): array
11831178
{
@@ -1203,7 +1198,7 @@ public function getSequences(string $collection, array $documents): array
12031198
$filters = ['_uid' => ['$in' => $documentIds]];
12041199

12051200
if ($this->sharedTables) {
1206-
$filters['_tenant'] = ['$in' => $documentTenants];
1201+
$filters['_tenant'] = $this->getTenantFilters($collection, $documentTenants);
12071202
}
12081203

12091204
$results = $this->client->find($name, $filters, ['projection' => ['_uid' => 1, '_id' => 1]]);
@@ -1242,7 +1237,7 @@ public function increaseDocumentAttribute(string $collection, string $id, string
12421237
$filters = ['_uid' => $id];
12431238

12441239
if ($this->sharedTables) {
1245-
$filters['_tenant'] = $this->getTenant();
1240+
$filters['_tenant'] = $this->getTenantFilters($collection);
12461241
}
12471242

12481243
if ($max) {
@@ -1280,8 +1275,9 @@ public function deleteDocument(string $collection, string $id): bool
12801275

12811276
$filters = [];
12821277
$filters['_uid'] = $id;
1278+
12831279
if ($this->sharedTables) {
1284-
$filters['_tenant'] = $this->getTenant();
1280+
$filters['_tenant'] = $this->getTenantFilters($collection);
12851281
}
12861282

12871283
$result = $this->client->delete($name, $filters);
@@ -1308,7 +1304,7 @@ public function deleteDocuments(string $collection, array $sequences, array $per
13081304
$filters = $this->buildFilters([new Query(Query::TYPE_EQUAL, '_id', $sequences)]);
13091305

13101306
if ($this->sharedTables) {
1311-
$filters['_tenant'] = $this->getTenant();
1307+
$filters['_tenant'] = $this->getTenantFilters($collection);
13121308
}
13131309

13141310
$filters = $this->replaceInternalIdsKeys($filters, '$', '_', $this->operators);
@@ -1346,7 +1342,6 @@ public function updateAttribute(string $collection, string $id, string $type, in
13461342
if (!empty($newKey) && $newKey !== $id) {
13471343
return $this->renameAttribute($collection, $id, $newKey);
13481344
}
1349-
13501345
return true;
13511346
}
13521347

@@ -1391,14 +1386,13 @@ protected function getInternalKeyForAttribute(string $attribute): string
13911386
*/
13921387
public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER, string $forPermission = Database::PERMISSION_READ): array
13931388
{
1394-
13951389
$name = $this->getNamespace() . '_' . $this->filter($collection);
13961390
$queries = array_map(fn ($query) => clone $query, $queries);
13971391

13981392
$filters = $this->buildFilters($queries);
13991393

14001394
if ($this->sharedTables) {
1401-
$filters['_tenant'] = $this->getTenant();
1395+
$filters['_tenant'] = $this->getTenantFilters($collection);
14021396
}
14031397

14041398
// permissions
@@ -1525,7 +1519,6 @@ public function find(string $collection, array $queries = [], ?int $limit = 25,
15251519
}
15261520

15271521

1528-
15291522
/**
15301523
* Converts timestamp to Mongo\BSON datetime format.
15311524
*
@@ -1597,6 +1590,10 @@ public function count(string $collection, array $queries = [], ?int $max = null)
15971590
// queries
15981591
$filters = $this->buildFilters($queries);
15991592

1593+
if ($this->sharedTables) {
1594+
$filters['_tenant'] = $this->getTenantFilters($collection);
1595+
}
1596+
16001597
// permissions
16011598
if (Authorization::$status) { // skip if authorization is disabled
16021599
$roles = \implode('|', Authorization::getRoles());
@@ -1625,6 +1622,10 @@ public function sum(string $collection, string $attribute, array $queries = [],
16251622
$queries = array_map(fn ($query) => clone $query, $queries);
16261623
$filters = $this->buildFilters($queries);
16271624

1625+
if ($this->sharedTables) {
1626+
$filters['_tenant'] = $this->getTenantFilters($collection);
1627+
}
1628+
16281629
// permissions
16291630
if (Authorization::$status) { // skip if authorization is disabled
16301631
$roles = \implode('|', Authorization::getRoles());
@@ -1843,10 +1844,10 @@ protected function getQueryValue(string $method, mixed $value): mixed
18431844
switch ($method) {
18441845
case Query::TYPE_STARTS_WITH:
18451846
$value = $this->escapeWildcards($value);
1846-
return $value.'.*';
1847+
return $value . '.*';
18471848
case Query::TYPE_ENDS_WITH:
18481849
$value = $this->escapeWildcards($value);
1849-
return '.*'.$value;
1850+
return '.*' . $value;
18501851
default:
18511852
return $value;
18521853
}
@@ -1865,7 +1866,7 @@ protected function getOrder(string $order): int
18651866
return match ($order) {
18661867
Database::ORDER_ASC => 1,
18671868
Database::ORDER_DESC => -1,
1868-
default => throw new DatabaseException('Unknown sort order:' . $order . '. Must be one of ' . Database::ORDER_ASC . ', ' . Database::ORDER_DESC),
1869+
default => throw new DatabaseException('Unknown sort order:' . $order . '. Must be one of ' . Database::ORDER_ASC . ', ' . Database::ORDER_DESC),
18691870
};
18701871
}
18711872

@@ -2294,8 +2295,8 @@ protected function execute(mixed $stmt): bool
22942295
}
22952296

22962297
/**
2297-
* @return string
2298-
*/
2298+
* @return string
2299+
*/
22992300
public function getIdAttributeType(): string
23002301
{
23012302
return Database::VAR_OBJECT_ID;
@@ -2324,10 +2325,36 @@ public function getSchemaAttributes(string $collection): array
23242325
return [];
23252326
}
23262327

2327-
public function getTenantQuery(string $collection, string $parentAlias = ''): string
2328-
{
2329-
// ** tenant in mongodb is an int but we need to return a string in order to be compatible with the rest of the code
2330-
return (string)$this->getTenant();
2331-
}
2328+
/**
2329+
* @param string $collection
2330+
* @param array<int> $tenants
2331+
* @return int|array<string, array<int>>
2332+
*/
2333+
public function getTenantFilters(
2334+
string $collection,
2335+
array $tenants = [],
2336+
): int|array {
2337+
$values = [];
2338+
if (!$this->sharedTables) {
2339+
return $values;
2340+
}
23322341

2342+
if (\count($tenants) === 0) {
2343+
$values[] = $this->getTenant();
2344+
} else {
2345+
for ($index = 0; $index < \count($tenants); $index++) {
2346+
$values[] = $tenants[$index];
2347+
}
2348+
}
2349+
2350+
if ($collection === Database::METADATA) {
2351+
$values[] = null;
2352+
}
2353+
2354+
if (\count($values) === 1) {
2355+
return $values[0];
2356+
}
2357+
2358+
return ['$in' => $values];
2359+
}
23332360
}

0 commit comments

Comments
 (0)