Skip to content
Open
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
11 changes: 5 additions & 6 deletions src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ class Database
public const RELATION_SIDE_CHILD = 'child';

public const RELATION_MAX_DEPTH = 3;
public const RELATION_QUERY_CHUNK_SIZE = 5000;

// Orders
public const ORDER_ASC = 'ASC';
Expand Down Expand Up @@ -5325,7 +5324,7 @@ private function populateOneToOneRelationshipsBatch(array $documents, Document $
$relatedDocuments = [];

// Process in chunks to avoid exceeding query value limits
foreach (\array_chunk($uniqueRelatedIds, self::RELATION_QUERY_CHUNK_SIZE) as $chunk) {
foreach (\array_chunk($uniqueRelatedIds, \max(1, $this->maxQueryValues)) as $chunk) {
Comment thread
HarshMN2345 marked this conversation as resolved.
$chunkDocs = $this->find($relatedCollection->getId(), [
Query::equal('$id', $chunk),
Query::limit(PHP_INT_MAX),
Expand Down Expand Up @@ -5417,7 +5416,7 @@ private function populateOneToManyRelationshipsBatch(

$relatedDocuments = [];

foreach (\array_chunk($parentIds, self::RELATION_QUERY_CHUNK_SIZE) as $chunk) {
foreach (\array_chunk($parentIds, \max(1, $this->maxQueryValues)) as $chunk) {
$chunkDocs = $this->find($relatedCollection->getId(), [
Query::equal($twoWayKey, $chunk),
Query::limit(PHP_INT_MAX),
Expand Down Expand Up @@ -5514,7 +5513,7 @@ private function populateManyToOneRelationshipsBatch(

$relatedDocuments = [];

foreach (\array_chunk($childIds, self::RELATION_QUERY_CHUNK_SIZE) as $chunk) {
foreach (\array_chunk($childIds, \max(1, $this->maxQueryValues)) as $chunk) {
$chunkDocs = $this->find($relatedCollection->getId(), [
Query::equal($twoWayKey, $chunk),
Query::limit(PHP_INT_MAX),
Expand Down Expand Up @@ -5593,7 +5592,7 @@ private function populateManyToManyRelationshipsBatch(

$junctions = [];

foreach (\array_chunk($documentIds, self::RELATION_QUERY_CHUNK_SIZE) as $chunk) {
foreach (\array_chunk($documentIds, \max(1, $this->maxQueryValues)) as $chunk) {
$chunkJunctions = $this->skipRelationships(fn () => $this->find($junction, [
Query::equal($twoWayKey, $chunk),
Query::limit(PHP_INT_MAX)
Expand Down Expand Up @@ -5623,7 +5622,7 @@ private function populateManyToManyRelationshipsBatch(
$uniqueRelatedIds = array_unique($relatedIds);
$foundRelated = [];

foreach (\array_chunk($uniqueRelatedIds, self::RELATION_QUERY_CHUNK_SIZE) as $chunk) {
foreach (\array_chunk($uniqueRelatedIds, \max(1, $this->maxQueryValues)) as $chunk) {
$chunkDocs = $this->find($relatedCollection->getId(), [
Query::equal('$id', $chunk),
Query::limit(PHP_INT_MAX),
Expand Down
85 changes: 85 additions & 0 deletions tests/e2e/Adapter/Scopes/RelationshipTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,91 @@ trait RelationshipTests
use ManyToOneTests;
use ManyToManyTests;

/**
* @return array<string, array{string, string, int}>
*/
public static function relationshipQueryValueLimitProvider(): array
{
$cases = [];
foreach ([Database::RELATION_ONE_TO_ONE, Database::RELATION_ONE_TO_MANY, Database::RELATION_MANY_TO_ONE, Database::RELATION_MANY_TO_MANY] as $type) {
foreach (['parents', 'children'] as $collection) {
$cases[$type . ' ' . $collection] = [$type, $collection, 3];
}
}

// One parent can exceed the value limit when fetching its related documents.
$cases['manyToMany related documents'] = [Database::RELATION_MANY_TO_MANY, 'parents', 1];

return $cases;
}

/**
* @dataProvider relationshipQueryValueLimitProvider
*/
public function testRelationshipQueryValueLimit(string $type, string $collection, int $limit): void
{
$database = $this->getDatabase();

if (!$database->getAdapter()->getSupportForRelationships()) {
$this->expectNotToPerformAssertions();
return;
}

$parents = ID::unique();
$children = ID::unique();
$permissions = [
Permission::read(Role::any()),
Permission::create(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
];
$database->createCollection($parents, permissions: $permissions);
$database->createCollection($children, permissions: $permissions);
$database->createRelationship($parents, $children, $type, true, 'children', 'parents');

foreach (['child1', 'child2', 'child3'] as $id) {
$database->createDocument($children, new Document(['$id' => $id]));
}

for ($i = 1; $i <= 3; $i++) {
$related = match ($type) {
Database::RELATION_MANY_TO_MANY => ['child1', 'child2', 'child3'],
Database::RELATION_ONE_TO_MANY => ['child' . $i],
default => 'child' . $i,
};
$database->createDocument($parents, new Document([
'$id' => 'parent' . $i,
'children' => $related,
]));
}

$max = $database->getMaxQueryValues();
$database->setMaxQueryValues(2);

try {
$documents = $database->find($collection === 'parents' ? $parents : $children, [Query::limit($limit)]);

$this->assertCount($limit, $documents);
foreach ($documents as $document) {
$related = $document->getAttribute($collection === 'parents' ? 'children' : 'parents');
$related = $related instanceof Document ? [$related] : $related;
$ids = \array_map(fn (Document $related) => $related->getId(), $related);
$prefix = $collection === 'parents' ? 'child' : 'parent';
$expected = $type === Database::RELATION_MANY_TO_MANY
? [$prefix . '1', $prefix . '2', $prefix . '3']
: [$prefix . \substr($document->getId(), -1)];
$this->assertEqualsCanonicalizing($expected, $ids);
}

$this->expectException(QueryException::class);
$database->find($children, [Query::equal('$id', ['child1', 'child2', 'child3'])]);
} finally {
$database->setMaxQueryValues($max);
$database->deleteCollection($parents);
$database->deleteCollection($children);
}
}

public function testZoo(): void
{
/** @var Database $database */
Expand Down
Loading