From 399947e194c1e316b0fc291f91db078e82d552fc Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:45:38 +0200 Subject: [PATCH] Revert "Merge pull request #4790 from kitsunet/task/split-dimensionspacepoints" This reverts commit c3a81af90881ea89dd8487e60f0d83e6c8629f38, reversing changes made to 117c052e1c86be17943530db6f84f5c4bb1cef6f. --- ...ectionIntegrityViolationDetectionTrait.php | 1 + .../DoctrineDbalContentGraphProjection.php | 14 +-- ...trineDbalContentGraphProjectionFactory.php | 9 +- .../DoctrineDbalContentGraphSchemaBuilder.php | 21 ++-- .../Domain/Projection/HierarchyRelation.php | 27 ++--- .../src/Domain/Projection/NodeRecord.php | 52 ++++----- .../ProjectionIntegrityViolationDetector.php | 22 ++-- .../src/Domain/Repository/ContentGraph.php | 24 ++-- .../DimensionSpacePointsRepository.php | 104 ------------------ .../src/Domain/Repository/NodeFactory.php | 13 ++- .../Repository/ProjectionContentGraph.php | 16 +-- 11 files changed, 74 insertions(+), 229 deletions(-) delete mode 100644 Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/DimensionSpacePointsRepository.php diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php index cb43d749e47..06f352beda3 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php @@ -239,6 +239,7 @@ private function transformDatasetToHierarchyRelationRecord(array $dataset): arra return [ 'contentstreamid' => $dataset['contentStreamId'], + 'dimensionspacepoint' => $dimensionSpacePoint->toJson(), 'dimensionspacepointhash' => $dimensionSpacePoint->hash, 'parentnodeanchor' => $parentHierarchyRelation !== null ? $parentHierarchyRelation['childnodeanchor'] : 9999999, 'childnodeanchor' => $childHierarchyRelation !== null ? $childHierarchyRelation['childnodeanchor'] : 8888888, diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index a3a92150aa8..361394778f1 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -15,7 +15,6 @@ use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRecord; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRelationAnchorPoint; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ContentGraph; -use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; @@ -92,7 +91,6 @@ public function __construct( private readonly NodeTypeManager $nodeTypeManager, private readonly ProjectionContentGraph $projectionContentGraph, private readonly string $tableNamePrefix, - private readonly DimensionSpacePointsRepository $dimensionSpacePointsRepository ) { $this->checkpointStorage = new DbalCheckpointStorage( $this->dbalClient->getConnection(), @@ -177,7 +175,6 @@ private function truncateDatabaseTables(): void $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node'); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation'); $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation'); - $connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints'); } public function canHandle(EventInterface $event): bool @@ -602,6 +599,7 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void childnodeanchor, `name`, position, + dimensionspacepoint, dimensionspacepointhash, subtreetags, contentstreamid @@ -611,6 +609,7 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void h.childnodeanchor, h.name, h.position, + h.dimensionspacepoint, h.dimensionspacepointhash, h.subtreetags, "' . $event->newContentStreamId->value . '" AS contentstreamid @@ -937,8 +936,6 @@ private function copyReferenceRelations( private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void { $this->transactional(function () use ($event) { - $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); - // the ordering is important - we first update the OriginDimensionSpacePoints, as we need the // hierarchy relations for this query. Then, we update the Hierarchy Relations. @@ -977,6 +974,7 @@ function (NodeRecord $nodeRecord) use ($event) { ' UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h SET + h.dimensionspacepoint = :newDimensionSpacePoint, h.dimensionspacepointhash = :newDimensionSpacePointHash WHERE h.dimensionspacepointhash = :originalDimensionSpacePointHash @@ -985,6 +983,7 @@ function (NodeRecord $nodeRecord) use ($event) { [ 'originalDimensionSpacePointHash' => $event->source->hash, 'newDimensionSpacePointHash' => $event->target->hash, + 'newDimensionSpacePoint' => $event->target->toJson(), 'contentStreamId' => $event->contentStreamId->value ] ); @@ -994,8 +993,6 @@ function (NodeRecord $nodeRecord) use ($event) { private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event): void { $this->transactional(function () use ($event) { - $this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target); - // 1) hierarchy relations $this->getDatabaseConnection()->executeStatement( ' @@ -1005,6 +1002,7 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded `name`, position, subtreetags, + dimensionspacepoint, dimensionspacepointhash, contentstreamid ) @@ -1014,6 +1012,7 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded h.name, h.position, h.subtreetags, + :newDimensionSpacePoint AS dimensionspacepoint, :newDimensionSpacePointHash AS dimensionspacepointhash, h.contentstreamid FROM @@ -1024,6 +1023,7 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded 'contentStreamId' => $event->contentStreamId->value, 'sourceDimensionSpacePointHash' => $event->source->hash, 'newDimensionSpacePointHash' => $event->target->hash, + 'newDimensionSpacePoint' => $event->target->toJson(), ] ); }); diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php index 64891e2cc33..546e574d4e2 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjectionFactory.php @@ -4,7 +4,6 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter; -use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph; use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies; @@ -41,16 +40,13 @@ public function build( $projectionFactoryDependencies->contentRepositoryId ); - $dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbalClient->getConnection(), $tableNamePrefix); - return new ContentGraphProjection( new DoctrineDbalContentGraphProjection( $this->dbalClient, new NodeFactory( $projectionFactoryDependencies->contentRepositoryId, $projectionFactoryDependencies->nodeTypeManager, - $projectionFactoryDependencies->propertyConverter, - $dimensionSpacePointsRepository + $projectionFactoryDependencies->propertyConverter ), $projectionFactoryDependencies->contentRepositoryId, $projectionFactoryDependencies->nodeTypeManager, @@ -58,8 +54,7 @@ public function build( $this->dbalClient, $tableNamePrefix ), - $tableNamePrefix, - $dimensionSpacePointsRepository + $tableNamePrefix ) ); } diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php index 06cc35ff431..b260a7ad155 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php @@ -28,7 +28,6 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $this->createNodeTable(), $this->createHierarchyRelationTable(), $this->createReferenceRelationTable(), - $this->createDimensionSpacePointsTable() ]); } @@ -37,6 +36,7 @@ private function createNodeTable(): Table $table = new Table($this->tableNamePrefix . '_node', [ DbalSchemaFactory::columnForNodeAnchorPoint('relationanchorpoint')->setAutoincrement(true), DbalSchemaFactory::columnForNodeAggregateId('nodeaggregateid')->setNotnull(false), + DbalSchemaFactory::columnForDimensionSpacePoint('origindimensionspacepoint')->setNotnull(false), DbalSchemaFactory::columnForDimensionSpacePointHash('origindimensionspacepointhash')->setNotnull(false), DbalSchemaFactory::columnForNodeTypeName('nodetypename'), (new Column('properties', Type::getType(Types::TEXT)))->setNotnull(true)->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION), @@ -56,9 +56,10 @@ private function createNodeTable(): Table private function createHierarchyRelationTable(): Table { $table = new Table($this->tableNamePrefix . '_hierarchyrelation', [ - (new Column('name', Type::getType(Types::STRING)))->setLength(255)->setNotnull(false)->setCustomSchemaOption('charset', 'ascii')->setCustomSchemaOption('collation', 'ascii_general_ci'), + (new Column('name', Type::getType(Types::STRING)))->setLength(255)->setNotnull(false)->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION), (new Column('position', Type::getType(Types::INTEGER)))->setNotnull(true), DbalSchemaFactory::columnForContentStreamId('contentstreamid')->setNotnull(true), + DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotnull(true), DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash')->setNotnull(true), DbalSchemaFactory::columnForNodeAnchorPoint('parentnodeanchor'), DbalSchemaFactory::columnForNodeAnchorPoint('childnodeanchor'), @@ -66,21 +67,13 @@ private function createHierarchyRelationTable(): Table ]); return $table - ->setPrimaryKey(['childnodeanchor', 'contentstreamid', 'dimensionspacepointhash', 'parentnodeanchor']) + ->addIndex(['childnodeanchor']) + ->addIndex(['contentstreamid']) + ->addIndex(['parentnodeanchor']) + ->addIndex(['contentstreamid', 'childnodeanchor', 'dimensionspacepointhash']) ->addIndex(['contentstreamid', 'dimensionspacepointhash']); } - private function createDimensionSpacePointsTable(): Table - { - $table = new Table($this->tableNamePrefix . '_dimensionspacepoints', [ - DbalSchemaFactory::columnForDimensionSpacePointHash('hash')->setNotnull(true), - DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotnull(true) - ]); - - return $table - ->setPrimaryKey(['hash']); - } - private function createReferenceRelationTable(): Table { $table = new Table($this->tableNamePrefix . '_referencerelation', [ diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php index 8bc02f1e7d3..b5e6a3c38eb 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/HierarchyRelation.php @@ -16,7 +16,6 @@ use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; -use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; @@ -45,22 +44,16 @@ public function __construct( */ public function addToDatabase(Connection $databaseConnection, string $tableNamePrefix): void { - $databaseConnection->transactional(function ($databaseConnection) use ( - $tableNamePrefix - ) { - $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); - $dimensionSpacePoints->insertDimensionSpacePoint($this->dimensionSpacePoint); - - $databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [ - 'parentnodeanchor' => $this->parentNodeAnchor->value, - 'childnodeanchor' => $this->childNodeAnchor->value, - 'name' => $this->name?->value, - 'contentstreamid' => $this->contentStreamId->value, - 'dimensionspacepointhash' => $this->dimensionSpacePointHash, - 'position' => $this->position, - 'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT), - ]); - }); + $databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [ + 'parentnodeanchor' => $this->parentNodeAnchor->value, + 'childnodeanchor' => $this->childNodeAnchor->value, + 'name' => $this->name?->value, + 'contentstreamid' => $this->contentStreamId->value, + 'dimensionspacepoint' => $this->dimensionSpacePoint->toJson(), + 'dimensionspacepointhash' => $this->dimensionSpacePointHash, + 'position' => $this->position, + 'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT), + ]); } /** diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php index fbc75314807..d8c3087e7cf 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/NodeRecord.php @@ -15,9 +15,7 @@ namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\DBAL\Types\Types; -use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\Timestamps; @@ -57,6 +55,7 @@ public function updateToDatabase(Connection $databaseConnection, string $tableNa $tableNamePrefix . '_node', [ 'nodeaggregateid' => $this->nodeAggregateId->value, + 'origindimensionspacepoint' => json_encode($this->originDimensionSpacePoint), 'origindimensionspacepointhash' => $this->originDimensionSpacePointHash, 'properties' => json_encode($this->properties), 'nodetypename' => $this->nodeTypeName->value, @@ -139,38 +138,25 @@ public static function createNewInDatabase( ?NodeName $nodeName, Timestamps $timestamps, ): self { - $relationAnchorPoint = $databaseConnection->transactional(function ($databaseConnection) use ( - $tableNamePrefix, - $nodeAggregateId, - $originDimensionSpacePoint, - $originDimensionSpacePointHash, - $properties, - $nodeTypeName, - $classification, - $timestamps - ) { - $dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix); - $dimensionSpacePoints->insertDimensionSpacePointByHashAndCoordinates($originDimensionSpacePointHash, $originDimensionSpacePoint); - - $databaseConnection->insert($tableNamePrefix . '_node', [ - 'nodeaggregateid' => $nodeAggregateId->value, - 'origindimensionspacepointhash' => $originDimensionSpacePointHash, - 'properties' => json_encode($properties), - 'nodetypename' => $nodeTypeName->value, - 'classification' => $classification->value, - 'created' => $timestamps->created, - 'originalcreated' => $timestamps->originalCreated, - 'lastmodified' => $timestamps->lastModified, - 'originallastmodified' => $timestamps->originalLastModified, - ], [ - 'created' => Types::DATETIME_IMMUTABLE, - 'originalcreated' => Types::DATETIME_IMMUTABLE, - 'lastmodified' => Types::DATETIME_IMMUTABLE, - 'originallastmodified' => Types::DATETIME_IMMUTABLE, - ]); + $databaseConnection->insert($tableNamePrefix . '_node', [ + 'nodeaggregateid' => $nodeAggregateId->value, + 'origindimensionspacepoint' => json_encode($originDimensionSpacePoint), + 'origindimensionspacepointhash' => $originDimensionSpacePointHash, + 'properties' => json_encode($properties), + 'nodetypename' => $nodeTypeName->value, + 'classification' => $classification->value, + 'created' => $timestamps->created, + 'originalcreated' => $timestamps->originalCreated, + 'lastmodified' => $timestamps->lastModified, + 'originallastmodified' => $timestamps->originalLastModified, + ], [ + 'created' => Types::DATETIME_IMMUTABLE, + 'originalcreated' => Types::DATETIME_IMMUTABLE, + 'lastmodified' => Types::DATETIME_IMMUTABLE, + 'originallastmodified' => Types::DATETIME_IMMUTABLE, + ]); - return NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId()); - }); + $relationAnchorPoint = NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId()); return new self( $relationAnchorPoint, diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php index adb394fb6cd..46b9d8a5be4 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/ProjectionIntegrityViolationDetector.php @@ -67,8 +67,8 @@ public function hierarchyIntegrityIsProvided(): Result } $invalidlyHashedHierarchyRelationRecords = $this->client->getConnection()->executeQuery( - 'SELECT * FROM ' . $this->tableNamePrefix . '_hierarchyrelation h LEFT JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON dsp.hash = h.dimensionspacepointhash - HAVING dsp.dimensionspacepoint IS NULL' + 'SELECT * FROM ' . $this->tableNamePrefix . '_hierarchyrelation + WHERE dimensionspacepointhash != MD5(dimensionspacepoint)' )->fetchAllAssociative(); foreach ($invalidlyHashedHierarchyRelationRecords as $record) { @@ -118,12 +118,6 @@ public function siblingsAreDistinctlySorted(): Result HAVING COUNT(position) > 1' ); - if ($ambiguouslySortedHierarchyRelationRecords->columnCount() === 0) { - return $result; - } - - $dimensionSpacePoints = $this->findProjectedDimensionSpacePoints(); - foreach ($ambiguouslySortedHierarchyRelationRecords as $hierarchyRelationRecord) { $ambiguouslySortedNodeRecords = $this->client->getConnection()->executeQuery( 'SELECT nodeaggregateid @@ -139,7 +133,7 @@ public function siblingsAreDistinctlySorted(): Result return $record['nodeaggregateid']; }, $ambiguouslySortedNodeRecords)) . ' are ambiguously sorted in content stream ' . $hierarchyRelationRecord['contentstreamid'] - . ' and dimension space point ' . $dimensionSpacePoints[$hierarchyRelationRecord['dimensionspacepointhash']]?->toJson(), + . ' and dimension space point ' . $hierarchyRelationRecord['dimensionspacepoint'], self::ERROR_CODE_SIBLINGS_ARE_AMBIGUOUSLY_SORTED )); } @@ -522,7 +516,7 @@ public function childNodeCoverageIsASubsetOfParentNodeCoverage(): Result $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { $excessivelyCoveringNodeRecords = $this->client->getConnection()->executeQuery( - 'SELECT n.nodeaggregateid, c.dimensionspacepointhash + 'SELECT n.nodeaggregateid, c.dimensionspacepoint FROM ' . $this->tableNamePrefix . '_hierarchyrelation c INNER JOIN ' . $this->tableNamePrefix . '_node n ON c.childnodeanchor = n.relationanchorpoint @@ -541,7 +535,7 @@ public function childNodeCoverageIsASubsetOfParentNodeCoverage(): Result $result->addError(new Error( 'Node aggregate ' . $excessivelyCoveringNodeRecord['nodeaggregateid'] . ' in content stream ' . $contentStreamId->value - . ' covers dimension space point hash ' . $excessivelyCoveringNodeRecord['dimensionspacepointhash'] + . ' covers dimension space point ' . $excessivelyCoveringNodeRecord['dimensionspacepoint'] . ' but its parent does not.', self::ERROR_CODE_CHILD_NODE_COVERAGE_IS_NO_SUBSET_OF_PARENT_NODE_COVERAGE )); @@ -559,7 +553,7 @@ public function allNodesCoverTheirOrigin(): Result $result = new Result(); foreach ($this->findProjectedContentStreamIds() as $contentStreamId) { $nodeRecordsWithMissingOriginCoverage = $this->client->getConnection()->executeQuery( - 'SELECT nodeaggregateid, origindimensionspacepointhash + 'SELECT nodeaggregateid, origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint @@ -585,7 +579,7 @@ public function allNodesCoverTheirOrigin(): Result $result->addError(new Error( 'Node aggregate ' . $nodeRecord['nodeaggregateid'] . ' in content stream ' . $contentStreamId->value - . ' does not cover its origin dimension space point hash ' . $nodeRecord['origindimensionspacepointhash'] + . ' does not cover its origin dimension space point ' . $nodeRecord['origindimensionspacepoint'] . '.', self::ERROR_CODE_NODE_DOES_NOT_COVER_ITS_ORIGIN )); @@ -621,7 +615,7 @@ protected function findProjectedContentStreamIds(): iterable protected function findProjectedDimensionSpacePoints(): DimensionSpacePointSet { $records = $this->client->getConnection()->executeQuery( - 'SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints' + 'SELECT DISTINCT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_hierarchyrelation' )->fetchAllAssociative(); $records = array_map(function (array $record) { diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php index 1df35d06fa3..93381ed2fe5 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentGraph.php @@ -56,9 +56,6 @@ * - cn -> child node * - h -> the hierarchy edge connecting parent and child * - ph -> the hierarchy edge incoming to the parent (sometimes relevant) - * - dsp -> dimension space point, resolves hashes to full dimension coordinates - * - cdsp -> child dimension space point, same as dsp for child queries - * - pdsp -> parent dimension space point, same as dsp for parent queries * * @internal the parent interface {@see ContentGraphInterface} is API */ @@ -140,10 +137,9 @@ public function findRootNodeAggregates( FindRootNodeAggregatesFilter $filter, ): NodeAggregates { $queryBuilder = $this->createQueryBuilder() - ->select('n.*, h.contentstreamid, h.name, h.subtreetags, dsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('n.*, h.contentstreamid, h.name, h.subtreetags, h.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_node', 'n') ->innerJoin('n', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = n.relationanchorpoint') - ->innerJoin('h', $this->tableNamePrefix . '_dimensionspacepoints', 'dsp', 'dsp.hash = h.dimensionspacepointhash') ->where('h.contentstreamid = :contentStreamId') ->andWhere('h.parentnodeanchor = :rootEdgeParentAnchorId') ->setParameters([ @@ -164,10 +160,9 @@ public function findNodeAggregatesByType( NodeTypeName $nodeTypeName ): iterable { $queryBuilder = $this->createQueryBuilder() - ->select('n.*, h.contentstreamid, h.name, h.subtreetags, dsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('n.*, h.contentstreamid, h.name, h.subtreetags, h.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_node', 'n') ->innerJoin('n', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = n.relationanchorpoint') - ->innerJoin('h', $this->tableNamePrefix . '_dimensionspacepoints', 'dsp', 'dsp.hash = h.dimensionspacepointhash') ->where('h.contentstreamid = :contentStreamId') ->andWhere('n.nodetypename = :nodeTypeName') ->setParameters([ @@ -182,10 +177,9 @@ public function findNodeAggregateById( NodeAggregateId $nodeAggregateId ): ?NodeAggregate { $queryBuilder = $this->createQueryBuilder() - ->select('n.*, h.name, h.contentstreamid, h.subtreetags, dsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('n.*, h.name, h.contentstreamid, h.subtreetags, h.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_hierarchyrelation', 'h') ->innerJoin('h', $this->tableNamePrefix . '_node', 'n', 'n.relationanchorpoint = h.childnodeanchor') - ->innerJoin('h', $this->tableNamePrefix . '_dimensionspacepoints', 'dsp', 'dsp.hash = h.dimensionspacepointhash') ->where('n.nodeaggregateid = :nodeAggregateId') ->andWhere('h.contentstreamid = :contentStreamId') ->setParameters([ @@ -208,12 +202,11 @@ public function findParentNodeAggregates( NodeAggregateId $childNodeAggregateId ): iterable { $queryBuilder = $this->createQueryBuilder() - ->select('pn.*, ph.name, ph.contentstreamid, ph.subtreetags, pdsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('pn.*, ph.name, ph.contentstreamid, ph.subtreetags, ph.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_node', 'pn') ->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ph', 'ph.childnodeanchor = pn.relationanchorpoint') ->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ch', 'ch.parentnodeanchor = pn.relationanchorpoint') ->innerJoin('ch', $this->tableNamePrefix . '_node', 'cn', 'cn.relationanchorpoint = ch.childnodeanchor') - ->innerJoin('ph', $this->tableNamePrefix . '_dimensionspacepoints', 'pdsp', 'pdsp.hash = ph.dimensionspacepointhash') ->where('cn.nodeaggregateid = :nodeAggregateId') ->andWhere('ph.contentstreamid = :contentStreamId') ->andWhere('ch.contentstreamid = :contentStreamId') @@ -241,10 +234,9 @@ public function findParentNodeAggregateByChildOriginDimensionSpacePoint( ->andWhere('cn.origindimensionspacepointhash = :childOriginDimensionSpacePointHash'); $queryBuilder = $this->createQueryBuilder() - ->select('n.*, h.name, h.contentstreamid, h.subtreetags, dsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('n.*, h.name, h.contentstreamid, h.subtreetags, h.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_node', 'n') ->innerJoin('n', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = n.relationanchorpoint') - ->innerJoin('h', $this->tableNamePrefix . '_dimensionspacepoints', 'dsp', 'dsp.hash = h.dimensionspacepointhash') ->where('n.nodeaggregateid = (' . $subQueryBuilder->getSQL() . ')') ->andWhere('h.contentstreamid = :contentStreamId') ->setParameters([ @@ -314,10 +306,9 @@ public function getDimensionSpacePointsOccupiedByChildNodeName( DimensionSpacePointSet $dimensionSpacePointsToCheck ): DimensionSpacePointSet { $queryBuilder = $this->createQueryBuilder() - ->select('dsp.dimensionspacepoint, h.dimensionspacepointhash') + ->select('h.dimensionspacepoint, h.dimensionspacepointhash') ->from($this->tableNamePrefix . '_hierarchyrelation', 'h') ->innerJoin('h', $this->tableNamePrefix . '_node', 'n', 'n.relationanchorpoint = h.parentnodeanchor') - ->innerJoin('h', $this->tableNamePrefix . '_dimensionspacepoints', 'dsp', 'dsp.hash = h.dimensionspacepointhash') ->innerJoin('n', $this->tableNamePrefix . '_hierarchyrelation', 'ph', 'ph.childnodeanchor = n.relationanchorpoint') ->where('n.nodeaggregateid = :parentNodeAggregateId') ->andWhere('n.origindimensionspacepointhash = :parentNodeOriginDimensionSpacePointHash') @@ -377,11 +368,10 @@ public function getSubgraphs(): array private function buildChildNodeAggregateQuery(NodeAggregateId $parentNodeAggregateId, ContentStreamId $contentStreamId): QueryBuilder { return $this->createQueryBuilder() - ->select('cn.*, ch.name, ch.contentstreamid, ch.subtreetags, cdsp.dimensionspacepoint AS covereddimensionspacepoint') + ->select('cn.*, ch.name, ch.contentstreamid, ch.subtreetags, ch.dimensionspacepoint AS covereddimensionspacepoint') ->from($this->tableNamePrefix . '_node', 'pn') ->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ph', 'ph.childnodeanchor = pn.relationanchorpoint') ->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ch', 'ch.parentnodeanchor = pn.relationanchorpoint') - ->innerJoin('ch', $this->tableNamePrefix . '_dimensionspacepoints', 'cdsp', 'cdsp.hash = ch.dimensionspacepointhash') ->innerJoin('ch', $this->tableNamePrefix . '_node', 'cn', 'cn.relationanchorpoint = ch.childnodeanchor') ->where('pn.nodeaggregateid = :parentNodeAggregateId') ->andWhere('ph.contentstreamid = :contentStreamId') diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/DimensionSpacePointsRepository.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/DimensionSpacePointsRepository.php deleted file mode 100644 index 1a409b5abc6..00000000000 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/DimensionSpacePointsRepository.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ - private array $dimensionspacePointsRuntimeCache = []; - - public function __construct( - private readonly Connection $databaseConnection, - private readonly string $tableNamePrefix - ) { - } - - public function insertDimensionSpacePoint(AbstractDimensionSpacePoint $dimensionSpacePoint): void - { - if ($this->getCoordinatesByHashFromRuntimeCache($dimensionSpacePoint->hash) !== null) { - return; - } - - $this->dimensionspacePointsRuntimeCache[$dimensionSpacePoint->hash] = $dimensionSpacePoint->toJson(); - $this->writeDimensionSpacePoint($dimensionSpacePoint->hash, $dimensionSpacePoint->toJson()); - } - - /** - * @param string $hash - * @param array $dimensionSpacePointCoordinates - * @return void - * @throws \Doctrine\DBAL\Exception - */ - public function insertDimensionSpacePointByHashAndCoordinates(string $hash, array $dimensionSpacePointCoordinates): void - { - if ($this->getCoordinatesByHashFromRuntimeCache($hash) !== null) { - return; - } - - $dimensionSpacePointCoordinatesJson = json_encode($dimensionSpacePointCoordinates, JSON_THROW_ON_ERROR); - $this->dimensionspacePointsRuntimeCache[$hash] = $dimensionSpacePointCoordinatesJson; - $this->writeDimensionSpacePoint($hash, $dimensionSpacePointCoordinatesJson); - } - - public function getOriginDimensionSpacePointByHash(string $hash): OriginDimensionSpacePoint - { - $coordinates = $this->getCoordinatesByHashFromRuntimeCache($hash); - if ($coordinates === null) { - $this->fillRuntimeCacheFromDatabase(); - $coordinates = $this->getCoordinatesByHashFromRuntimeCache($hash); - } - - if ($coordinates === null) { - throw new \RuntimeException(sprintf('A DimensionSpacePoint record with the given hash "%s" was not found in the projection, cannot determine coordinates.', $hash), 1710335509); - } - - return OriginDimensionSpacePoint::fromJsonString($coordinates); - } - - private function writeDimensionSpacePoint(string $hash, string $dimensionSpacePointCoordinatesJson): void - { - $this->databaseConnection->executeStatement( - 'INSERT IGNORE INTO ' . $this->tableNamePrefix . '_dimensionspacepoints (hash, dimensionspacepoint) VALUES (:dimensionspacepointhash, :dimensionspacepoint)', - [ - 'dimensionspacepointhash' => $hash, - 'dimensionspacepoint' => $dimensionSpacePointCoordinatesJson - ] - ); - } - - private function getCoordinatesByHashFromRuntimeCache(string $hash): ?string - { - return $this->dimensionspacePointsRuntimeCache[$hash] ?? null; - } - - private function fillRuntimeCacheFromDatabase(): void - { - $allDimensionSpacePoints = $this->databaseConnection->fetchAllAssociative('SELECT hash, dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints'); - foreach ($allDimensionSpacePoints as $dimensionSpacePointRow) { - $this->dimensionspacePointsRuntimeCache[(string)$dimensionSpacePointRow['hash']] = (string)$dimensionSpacePointRow['dimensionspacepoint']; - } - } -} diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php index 88887b67d9a..837b7767eda 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php @@ -54,8 +54,7 @@ final class NodeFactory public function __construct( private readonly ContentRepositoryId $contentRepositoryId, private readonly NodeTypeManager $nodeTypeManager, - private readonly PropertyConverter $propertyConverter, - private readonly DimensionSpacePointsRepository $dimensionSpacePointRepository + private readonly PropertyConverter $propertyConverter ) { } @@ -80,7 +79,7 @@ public function mapNodeRowToNode( $visibilityConstraints ), NodeAggregateId::fromString($nodeRow['nodeaggregateid']), - $this->dimensionSpacePointRepository->getOriginDimensionSpacePointByHash($nodeRow['origindimensionspacepointhash']), + OriginDimensionSpacePoint::fromJsonString($nodeRow['origindimensionspacepoint']), NodeAggregateClassification::from($nodeRow['classification']), NodeTypeName::fromString($nodeRow['nodetypename']), $nodeType, @@ -170,7 +169,9 @@ public function mapNodeRowsToNodeAggregate( foreach ($nodeRows as $nodeRow) { // A node can occupy exactly one DSP and cover multiple ones... - $occupiedDimensionSpacePoint = $this->dimensionSpacePointRepository->getOriginDimensionSpacePointByHash($nodeRow['origindimensionspacepointhash']); + $occupiedDimensionSpacePoint = OriginDimensionSpacePoint::fromJsonString( + $nodeRow['origindimensionspacepoint'] + ); if (!isset($nodesByOccupiedDimensionSpacePoints[$occupiedDimensionSpacePoint->hash])) { // ... so we handle occupation exactly once ... $nodesByOccupiedDimensionSpacePoints[$occupiedDimensionSpacePoint->hash] = $this->mapNodeRowToNode( @@ -247,7 +248,9 @@ public function mapNodeRowsToNodeAggregates( foreach ($nodeRows as $nodeRow) { // A node can occupy exactly one DSP and cover multiple ones... $rawNodeAggregateId = $nodeRow['nodeaggregateid']; - $occupiedDimensionSpacePoint = $this->dimensionSpacePointRepository->getOriginDimensionSpacePointByHash($nodeRow['origindimensionspacepointhash']); + $occupiedDimensionSpacePoint = OriginDimensionSpacePoint::fromJsonString( + $nodeRow['origindimensionspacepoint'] + ); if ( !isset($nodesByOccupiedDimensionSpacePointsByNodeAggregate [$rawNodeAggregateId][$occupiedDimensionSpacePoint->hash]) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php index 02e6b63e5b9..ce2552fd2fc 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ProjectionContentGraph.php @@ -71,11 +71,10 @@ public function findParentNode( : $originDimensionSpacePoint->hash ]; $nodeRow = $this->getDatabaseConnection()->executeQuery( - 'SELECT p.*, ph.contentstreamid, ph.name, ph.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node p + 'SELECT p.*, ph.contentstreamid, ph.name, ph.subtreetags FROM ' . $this->tableNamePrefix . '_node p INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation ph ON ph.childnodeanchor = p.relationanchorpoint INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation ch ON ch.parentnodeanchor = p.relationanchorpoint INNER JOIN ' . $this->tableNamePrefix . '_node c ON ch.childnodeanchor = c.relationanchorpoint - INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON p.origindimensionspacepointhash = dsp.hash WHERE c.nodeaggregateid = :childNodeAggregateId AND c.origindimensionspacepointhash = :originDimensionSpacePointHash AND ph.contentstreamid = :contentStreamId @@ -102,9 +101,8 @@ public function findNodeInAggregate( DimensionSpacePoint $coveredDimensionSpacePoint ): ?NodeRecord { $nodeRow = $this->getDatabaseConnection()->executeQuery( - 'SELECT n.*, h.name, h.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n + 'SELECT n.*, h.name, h.subtreetags FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint - INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash WHERE n.nodeaggregateid = :nodeAggregateId AND h.contentstreamid = :contentStreamId AND h.dimensionspacepointhash = :dimensionSpacePointHash', @@ -131,9 +129,8 @@ public function findNodeByIds( OriginDimensionSpacePoint $originDimensionSpacePoint ): ?NodeRecord { $nodeRow = $this->getDatabaseConnection()->executeQuery( - 'SELECT n.*, h.name, h.subtreetags, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n + 'SELECT n.*, h.name, h.subtreetags FROM ' . $this->tableNamePrefix . '_node n INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h ON h.childnodeanchor = n.relationanchorpoint - INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash WHERE n.nodeaggregateid = :nodeAggregateId AND n.origindimensionspacepointhash = :originDimensionSpacePointHash AND h.contentstreamid = :contentStreamId', @@ -219,8 +216,7 @@ public function getAnchorPointsForNodeAggregateInContentStream( public function getNodeByAnchorPoint(NodeRelationAnchorPoint $nodeRelationAnchorPoint): ?NodeRecord { $nodeRow = $this->getDatabaseConnection()->executeQuery( - 'SELECT n.*, dsp.dimensionspacepoint AS origindimensionspacepoint FROM ' . $this->tableNamePrefix . '_node n - INNER JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON n.origindimensionspacepointhash = dsp.hash + 'SELECT n.* FROM ' . $this->tableNamePrefix . '_node n WHERE n.relationanchorpoint = :relationAnchorPoint', [ 'relationAnchorPoint' => $nodeRelationAnchorPoint->value, @@ -652,14 +648,12 @@ public function findDescendantNodeAggregateIds( */ protected function mapRawDataToHierarchyRelation(array $rawData): HierarchyRelation { - $dimensionspacepointRaw = $this->client->getConnection()->fetchOne('SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints WHERE hash = :hash', ['hash' => $rawData['dimensionspacepointhash']]); - return new HierarchyRelation( NodeRelationAnchorPoint::fromInteger((int)$rawData['parentnodeanchor']), NodeRelationAnchorPoint::fromInteger((int)$rawData['childnodeanchor']), $rawData['name'] ? NodeName::fromString($rawData['name']) : null, ContentStreamId::fromString($rawData['contentstreamid']), - DimensionSpacePoint::fromJsonString($dimensionspacepointRaw), + DimensionSpacePoint::fromJsonString($rawData['dimensionspacepoint']), $rawData['dimensionspacepointhash'], (int)$rawData['position'], NodeFactory::extractNodeTagsFromJson($rawData['subtreetags']),