From e615162960f99867e2f30861a56af5d7411d0e40 Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Thu, 22 Oct 2026 12:08:26 +0530 Subject: [PATCH 1/2] fix(sql): filter dotted attribute keys in batch create and upsert createAttribute stores a key like demo.column as the column democolumn, but the batch insert and upsert rows kept the raw key, which the builder quoted as "demo"."column" and the database rejected as an unknown column. --- src/Database/Adapter/SQL.php | 14 ++++++++++---- tests/e2e/Adapter/Scopes/AttributeTests.php | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index 7112adf53..58fbf4d63 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -924,7 +924,7 @@ private function buildDocumentsInsert(string $name, array $documents, array $spa $spatialMap = \array_fill_keys($spatialAttributes, true); foreach ($spatialAttributes as $spatialColumn) { - $builder->insertColumnExpression($spatialColumn, $this->getSpatialGeometryFromText('?')); + $builder->insertColumnExpression($this->filter($spatialColumn), $this->getSpatialGeometryFromText('?')); } $intBools = $this->supports(Capability::IntegerBooleans); @@ -3912,6 +3912,9 @@ protected function executeUpsertBatch( ): void { $builder = $this->dialectBuilder()->into($this->getTableRaw($name)); + $spatialAttributes = \array_map($this->filter(...), $spatialAttributes); + $operators = \array_combine(\array_map($this->filter(...), \array_keys($operators)), $operators); + foreach ($spatialAttributes as $spatialColumn) { $builder->insertColumnExpression($spatialColumn, $this->getSpatialGeometryFromText('?')); } @@ -3956,11 +3959,14 @@ protected function executeUpsertBatch( $currentRegularAttributes = $this->decorateRow($currentRegularAttributes, $document); - foreach (\array_keys($currentRegularAttributes) as $column) { + $row = []; + foreach ($currentRegularAttributes as $column => $value) { + $column = $this->filter($column); + $row[$column] = $value; $allColumnNames[$column] = true; } - $documentsData[] = $currentRegularAttributes; + $documentsData[] = $row; } foreach (\array_keys($operators) as $column) { @@ -6550,7 +6556,7 @@ protected function buildDocumentRow(Document $document, array $attributeKeys, ar if ($intBools && ! isset($spatialMap[$key])) { $value = (\is_bool($value)) ? (int) $value : $value; } - $row[$key] = $value; + $row[$this->filter($key)] = $value; } return $row; diff --git a/tests/e2e/Adapter/Scopes/AttributeTests.php b/tests/e2e/Adapter/Scopes/AttributeTests.php index 772ec8797..67601168c 100644 --- a/tests/e2e/Adapter/Scopes/AttributeTests.php +++ b/tests/e2e/Adapter/Scopes/AttributeTests.php @@ -519,6 +519,26 @@ public function testDottedAttributeKeysInGroups(): void $database->deleteCollection($collection); } + public function testDottedAttributeKeysInBatchWrites(): void + { + $database = $this->getDatabase(); + $collection = $this->createDottedKeyCollection($database); + + $database->createDocuments($collection, [ + new Document(['$id' => 'e', 'dots.name' => 'x', 'dots.score' => 7]), + new Document(['$id' => 'f', 'dots.name' => 'x', 'dots.score' => 11]), + ]); + $database->getAuthorization()->skip(fn (): int => $database->upsertDocuments($collection, [ + new Document(['$id' => 'e', 'dots.name' => 'y', 'dots.score' => 7]), + new Document(['$id' => 'g', 'dots.name' => 'y', 'dots.score' => 13]), + ])); + + $this->assertSame(['e', 'g'], $this->sortedIds($database->find($collection, [Query::equal('dots.name', ['y'])]))); + $this->assertSame(['f'], $this->sortedIds($database->find($collection, [Query::equal('dots.name', ['x'])]))); + + $database->deleteCollection($collection); + } + /** * @param array $group */ From 916669bc53db39bb4783bd07f89a90e068366aa6 Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Thu, 22 Oct 2026 12:20:00 +0530 Subject: [PATCH 2/2] test: skip dotted batch write test on adapters without upserts --- tests/e2e/Adapter/Scopes/AttributeTests.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/e2e/Adapter/Scopes/AttributeTests.php b/tests/e2e/Adapter/Scopes/AttributeTests.php index 67601168c..6381b9028 100644 --- a/tests/e2e/Adapter/Scopes/AttributeTests.php +++ b/tests/e2e/Adapter/Scopes/AttributeTests.php @@ -522,6 +522,12 @@ public function testDottedAttributeKeysInGroups(): void public function testDottedAttributeKeysInBatchWrites(): void { $database = $this->getDatabase(); + if (! $database->getAdapter()->hasFeature(Feature\Upserts::class)) { + $this->expectNotToPerformAssertions(); + + return; + } + $collection = $this->createDottedKeyCollection($database); $database->createDocuments($collection, [