fix subqueries

This commit is contained in:
fogelito
2026-01-13 13:01:37 +02:00
parent aab780476e
commit df26136dd8
2 changed files with 62 additions and 68 deletions
+56
View File
@@ -69,6 +69,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence()) || empty($document->getAttribute('databaseInternalId'))) {
return [];
}
$attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [
Query::equal('collectionInternalId', [$document->getSequence()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
@@ -104,6 +108,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence()) || empty($document->getAttribute('databaseInternalId'))) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('indexes', [
Query::equal('collectionInternalId', [$document->getSequence()]),
@@ -119,6 +127,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('platforms', [
Query::equal('projectInternalId', [$document->getSequence()]),
@@ -133,6 +145,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('keys', [
Query::equal('resourceType', ['projects']),
@@ -148,6 +164,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('devKeys', [
Query::equal('projectInternalId', [$document->getSequence()]),
@@ -162,6 +182,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('webhooks', [
Query::equal('projectInternalId', [$document->getSequence()]),
@@ -176,6 +200,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database->find('sessions', [
Query::equal('userInternalId', [$document->getSequence()]),
Query::limit(APP_LIMIT_SUBQUERY),
@@ -189,6 +217,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('tokens', [
Query::equal('userInternalId', [$document->getSequence()]),
@@ -203,6 +235,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('challenges', [
Query::equal('userInternalId', [$document->getSequence()]),
@@ -217,6 +253,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('authenticators', [
Query::equal('userInternalId', [$document->getSequence()]),
@@ -231,6 +271,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('memberships', [
Query::equal('userInternalId', [$document->getSequence()]),
@@ -245,6 +289,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
$resourceType = match ($document->getCollection()) {
'functions' => ['function'],
'sites' => ['site'],
@@ -331,6 +379,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
return $database->getAuthorization()->skip(fn () => $database
->find('targets', [
Query::equal('userInternalId', [$document->getSequence()]),
@@ -345,6 +397,10 @@ Database::addFilter(
return;
},
function (mixed $value, Document $document, Database $database) {
if (empty($document->getSequence())) {
return [];
}
$targetIds = $database->getAuthorization()->skip(fn () => \array_map(
fn ($document) => $document->getAttribute('targetInternalId'),
$database->find('subscribers', [
@@ -115,7 +115,12 @@ class XList extends Action
$selectQueries = Query::groupByType($queries)['selections'] ?? [];
$filterQueries = Query::groupByType($queries)['filters'];
$projects = $this->find($dbForPlatform, $queries, $selectQueries);
/**
* Add filters which do not exist in response model?
*/
$filtersToSkip = [];
$projects = $dbForPlatform->skipFilters(fn () => $dbForPlatform->find('projects', $queries), $filtersToSkip);
$total = $includeTotal ? $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT) : 0;
} catch (Order $e) {
throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null.");
@@ -128,71 +133,4 @@ class XList extends Action
'total' => $total,
]), Response::MODEL_PROJECT_LIST);
}
// Build mapping of columns to their subQuery filters
private static function getAttributeToSubQueryFilters(): array
{
if (self::$attributeToSubQueryFilters !== null) {
return self::$attributeToSubQueryFilters;
}
self::$attributeToSubQueryFilters = [];
$collections = Config::getParam('collections', []);
$projectAttributes = $collections['platform']['projects']['attributes'] ?? [];
foreach ($projectAttributes as $attribute) {
$attributeId = $attribute['$id'] ?? null;
$filters = $attribute['filters'] ?? [];
if ($attributeId === null || empty($filters)) {
continue;
}
// extract only subQuery filters
$subQueryFilters = \array_filter($filters, function ($filter) {
return \str_starts_with($filter, 'subQuery');
});
if (!empty($subQueryFilters)) {
self::$attributeToSubQueryFilters[$attributeId] = \array_values($subQueryFilters);
}
}
return self::$attributeToSubQueryFilters;
}
private function find(Database $dbForPlatform, array $queries, array $selectQueries): array
{
if (empty($selectQueries)) {
return $dbForPlatform->find('projects', $queries);
}
$selectedAttributes = [];
foreach ($selectQueries as $query) {
$selectedAttributes[] = $query->getAttribute();
}
if (\in_array('*', $selectedAttributes)) {
return $dbForPlatform->find('projects', $queries);
}
$filtersToSkipMap = [];
$selectedAttributesMap = \array_flip($selectedAttributes);
$attributeToSubQueryFilters = self::getAttributeToSubQueryFilters();
foreach ($attributeToSubQueryFilters as $attributeName => $subQueryFilters) {
if (!isset($selectedAttributesMap[$attributeName])) {
foreach ($subQueryFilters as $filter) {
$filtersToSkipMap[$filter] = true;
}
}
}
$filtersToSkip = \array_keys($filtersToSkipMap);
return empty($filtersToSkip)
? $dbForPlatform->find('projects', $queries)
: $dbForPlatform->skipFilters(fn () => $dbForPlatform->find('projects', $queries), $filtersToSkip);
}
}