Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

!!! TASK: Split dimensionspacepoints into separate table to reduce data duplication #4790

Merged
merged 12 commits into from
Mar 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ private function transformDatasetToHierarchyRelationRecord(array $dataset): arra

return [
'contentstreamid' => $dataset['contentStreamId'],
'dimensionspacepoint' => $dimensionSpacePoint->toJson(),
'dimensionspacepointhash' => $dimensionSpacePoint->hash,
'parentnodeanchor' => $parentNodeAggregateId->isNonExistent()
? 9999999
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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\DimensionSpacePoints;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
Expand Down Expand Up @@ -83,6 +84,8 @@ final class DoctrineDbalContentGraphProjection implements ProjectionInterface, W

private DbalCheckpointStorage $checkpointStorage;

private DimensionSpacePoints $dimensionSpacePoints;

public function __construct(
private readonly DbalClientInterface $dbalClient,
private readonly NodeFactory $nodeFactory,
Expand All @@ -96,6 +99,8 @@ public function __construct(
$this->tableNamePrefix . '_checkpoint',
self::class
);

$this->dimensionSpacePoints = new DimensionSpacePoints($this->dbalClient->getConnection(), $this->tableNamePrefix);
}

protected function getProjectionContentGraph(): ProjectionContentGraph
Expand Down Expand Up @@ -175,6 +180,7 @@ private function truncateDatabaseTables(): void
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_restrictionrelation');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints');
}

public function canHandle(EventInterface $event): bool
Expand Down Expand Up @@ -644,7 +650,6 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void
childnodeanchor,
`name`,
position,
dimensionspacepoint,
dimensionspacepointhash,
contentstreamid
)
Expand All @@ -653,7 +658,6 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void
h.childnodeanchor,
h.name,
h.position,
h.dimensionspacepoint,
h.dimensionspacepointhash,
"' . $event->newContentStreamId->value . '" AS contentstreamid
FROM
Expand Down Expand Up @@ -1111,6 +1115,7 @@ private function copyReferenceRelations(

private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void
{
$this->dimensionSpacePoints->insertDimensionSpacePoint($event->target);
kitsunet marked this conversation as resolved.
Show resolved Hide resolved
$this->transactional(function () use ($event) {
// the ordering is important - we first update the OriginDimensionSpacePoints, as we need the
// hierarchy relations for this query. Then, we update the Hierarchy Relations.
Expand Down Expand Up @@ -1150,7 +1155,6 @@ function (NodeRecord $nodeRecord) use ($event) {
'
UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h
SET
h.dimensionspacepoint = :newDimensionSpacePoint,
h.dimensionspacepointhash = :newDimensionSpacePointHash
WHERE
h.dimensionspacepointhash = :originalDimensionSpacePointHash
Expand All @@ -1159,7 +1163,6 @@ function (NodeRecord $nodeRecord) use ($event) {
[
'originalDimensionSpacePointHash' => $event->source->hash,
'newDimensionSpacePointHash' => $event->target->hash,
'newDimensionSpacePoint' => $event->target->toJson(),
'contentStreamId' => $event->contentStreamId->value
]
);
Expand All @@ -1185,6 +1188,7 @@ function (NodeRecord $nodeRecord) use ($event) {

private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event): void
{
$this->dimensionSpacePoints->insertDimensionSpacePoint($event->target);
$this->transactional(function () use ($event) {
// 1) hierarchy relations
$this->getDatabaseConnection()->executeStatement(
Expand All @@ -1194,7 +1198,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
childnodeanchor,
`name`,
position,
dimensionspacepoint,
dimensionspacepointhash,
contentstreamid
)
Expand All @@ -1203,7 +1206,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
h.childnodeanchor,
h.name,
h.position,
:newDimensionSpacePoint AS dimensionspacepoint,
:newDimensionSpacePointHash AS dimensionspacepointhash,
h.contentstreamid
FROM
Expand All @@ -1214,7 +1216,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
'contentStreamId' => $event->contentStreamId->value,
'sourceDimensionSpacePointHash' => $event->source->hash,
'newDimensionSpacePointHash' => $event->target->hash,
'newDimensionSpacePoint' => $event->target->toJson(),
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePoints;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
Expand Down Expand Up @@ -40,13 +41,16 @@ public function build(
$projectionFactoryDependencies->contentRepositoryId
);



return new ContentGraphProjection(
new DoctrineDbalContentGraphProjection(
$this->dbalClient,
new NodeFactory(
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->nodeTypeManager,
$projectionFactoryDependencies->propertyConverter
$projectionFactoryDependencies->propertyConverter,
new DimensionSpacePoints($this->dbalClient->getConnection(), $tableNamePrefix)
),
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->nodeTypeManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
Expand All @@ -29,7 +28,8 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema
$this->createNodeTable(),
$this->createHierarchyRelationTable(),
$this->createReferenceRelationTable(),
$this->createRestrictionRelationTable()
$this->createRestrictionRelationTable(),
$this->createDimensionSpacePointsTable()
]);
}

Expand All @@ -38,7 +38,6 @@ 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),
Expand All @@ -61,7 +60,6 @@ private function createHierarchyRelationTable(): Table
(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')
Expand All @@ -75,6 +73,17 @@ private function createHierarchyRelationTable(): Table
->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', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection;

use Doctrine\DBAL\Connection;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePoints;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
Expand Down Expand Up @@ -42,12 +43,14 @@ public function __construct(
*/
public function addToDatabase(Connection $databaseConnection, string $tableNamePrefix): void
{
$dimensionSpacePoints = new DimensionSpacePoints($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,
'dimensionspacepoint' => $this->dimensionSpacePoint->toJson(),
'dimensionspacepointhash' => $this->dimensionSpacePointHash,
'position' => $this->position
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
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\DimensionSpacePoints;
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues;
use Neos\ContentRepository\Core\Projection\ContentGraph\Timestamps;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateClassification;
Expand Down Expand Up @@ -55,7 +57,6 @@ 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,
Expand Down Expand Up @@ -138,9 +139,11 @@ public static function createNewInDatabase(
?NodeName $nodeName,
Timestamps $timestamps,
): self {
$dimensionSpacePoints = new DimensionSpacePoints($databaseConnection, $tableNamePrefix);
$dimensionSpacePoints->insertDimensionSpacePointByHashAndCoordinates($originDimensionSpacePointHash, $originDimensionSpacePoint);

$databaseConnection->insert($tableNamePrefix . '_node', [
'nodeaggregateid' => $nodeAggregateId->value,
'origindimensionspacepoint' => json_encode($originDimensionSpacePoint),
'origindimensionspacepointhash' => $originDimensionSpacePointHash,
'properties' => json_encode($properties),
'nodetypename' => $nodeTypeName->value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public function hierarchyIntegrityIsProvided(): Result
}

$invalidlyHashedHierarchyRelationRecords = $this->client->getConnection()->executeQuery(
'SELECT * FROM ' . $this->tableNamePrefix . '_hierarchyrelation
WHERE dimensionspacepointhash != MD5(dimensionspacepoint)'
'SELECT * FROM ' . $this->tableNamePrefix . '_hierarchyrelation h LEFT JOIN ' . $this->tableNamePrefix . '_dimensionspacepoints dsp ON dsp.hash = h.dimensionspacepointhash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what the purpose for this check is. But after it's not fully the same as before. So we just check if the entry for a given hash is present in _dimensionspacepoints. But before we also checked if the md5-hashed value is equal to the hash.

Copy link
Member Author

@kitsunet kitsunet Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm, we can't know if the hash is the right one though, either it exists in the DSP table or it's invalid, if it exists in there IMHO we can assume it matches the dimension coordinates. We could add a separate check that reads all DSP entries and compares hash and getting the hash from the coordinates in the same row if we really want to.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with keeping it as it is. Just wanted to point out this difference.

HAVING dsp.dimensionspacepoint IS NULL'
)->fetchAllAssociative();

foreach ($invalidlyHashedHierarchyRelationRecords as $record) {
Expand Down Expand Up @@ -118,6 +118,12 @@ 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
Expand All @@ -133,7 +139,7 @@ public function siblingsAreDistinctlySorted(): Result
return $record['nodeaggregateid'];
}, $ambiguouslySortedNodeRecords))
. ' are ambiguously sorted in content stream ' . $hierarchyRelationRecord['contentstreamid']
. ' and dimension space point ' . $hierarchyRelationRecord['dimensionspacepoint'],
. ' and dimension space point ' . $dimensionSpacePoints[$hierarchyRelationRecord['dimensionspacepointhash']]?->toJson(),
self::ERROR_CODE_SIBLINGS_ARE_AMBIGUOUSLY_SORTED
));
}
Expand Down Expand Up @@ -179,7 +185,7 @@ public function restrictionsArePropagatedRecursively(): Result
{
$result = new Result();
$nodeRecordsWithMissingRestrictions = $this->client->getConnection()->executeQuery(
'SELECT c.nodeaggregateid, h.contentstreamid, h.dimensionspacepoint
'SELECT c.nodeaggregateid, h.contentstreamid, h.dimensionspacepointhash
FROM ' . $this->tableNamePrefix . '_hierarchyrelation h
INNER JOIN ' . $this->tableNamePrefix . '_node p
ON p.relationanchorpoint = h.parentnodeanchor
Expand All @@ -200,7 +206,7 @@ public function restrictionsArePropagatedRecursively(): Result
$result->addError(new Error(
'Node aggregate ' . $nodeRecord['nodeaggregateid']
. ' misses a restriction relation in content stream ' . $nodeRecord['contentstreamid']
. ' and dimension space point ' . $nodeRecord['dimensionspacepoint'],
. ' and dimension space point hash ' . $nodeRecord['dimensionspacepointhash'],
self::ERROR_CODE_NODE_HAS_MISSING_RESTRICTION
));
}
Expand Down Expand Up @@ -557,7 +563,7 @@ public function childNodeCoverageIsASubsetOfParentNodeCoverage(): Result
$result = new Result();
foreach ($this->findProjectedContentStreamIds() as $contentStreamId) {
$excessivelyCoveringNodeRecords = $this->client->getConnection()->executeQuery(
'SELECT n.nodeaggregateid, c.dimensionspacepoint
'SELECT n.nodeaggregateid, c.dimensionspacepointhash
FROM ' . $this->tableNamePrefix . '_hierarchyrelation c
INNER JOIN ' . $this->tableNamePrefix . '_node n
ON c.childnodeanchor = n.relationanchorpoint
Expand All @@ -576,7 +582,7 @@ public function childNodeCoverageIsASubsetOfParentNodeCoverage(): Result
$result->addError(new Error(
'Node aggregate ' . $excessivelyCoveringNodeRecord['nodeaggregateid']
. ' in content stream ' . $contentStreamId->value
. ' covers dimension space point ' . $excessivelyCoveringNodeRecord['dimensionspacepoint']
. ' covers dimension space point hash ' . $excessivelyCoveringNodeRecord['dimensionspacepointhash']
. ' but its parent does not.',
self::ERROR_CODE_CHILD_NODE_COVERAGE_IS_NO_SUBSET_OF_PARENT_NODE_COVERAGE
));
Expand All @@ -594,7 +600,7 @@ public function allNodesCoverTheirOrigin(): Result
$result = new Result();
foreach ($this->findProjectedContentStreamIds() as $contentStreamId) {
$nodeRecordsWithMissingOriginCoverage = $this->client->getConnection()->executeQuery(
'SELECT nodeaggregateid, origindimensionspacepoint
'SELECT nodeaggregateid, origindimensionspacepointhash
FROM ' . $this->tableNamePrefix . '_node n
INNER JOIN ' . $this->tableNamePrefix . '_hierarchyrelation h
ON h.childnodeanchor = n.relationanchorpoint
Expand All @@ -620,7 +626,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 ' . $nodeRecord['origindimensionspacepoint']
. ' does not cover its origin dimension space point hash ' . $nodeRecord['origindimensionspacepointhash']
. '.',
self::ERROR_CODE_NODE_DOES_NOT_COVER_ITS_ORIGIN
));
Expand Down Expand Up @@ -656,7 +662,7 @@ protected function findProjectedContentStreamIds(): iterable
protected function findProjectedDimensionSpacePoints(): DimensionSpacePointSet
{
$records = $this->client->getConnection()->executeQuery(
'SELECT DISTINCT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_hierarchyrelation'
'SELECT dimensionspacepoint FROM ' . $this->tableNamePrefix . '_dimensionspacepoints'
)->fetchAllAssociative();
dlubitz marked this conversation as resolved.
Show resolved Hide resolved

$records = array_map(function (array $record) {
Expand Down
Loading
Loading