Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\ContentStreamDbId;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ContentGraph;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
Expand Down Expand Up @@ -49,11 +50,13 @@ public function getContentGraph(WorkspaceName $workspaceName): ContentGraph
{
$currentContentStreamIdStatement = <<<SQL
SELECT
currentContentStreamId
ws.currentContentStreamId,
cs.dbId AS contentStreamDbId
FROM
{$this->tableNames->workspace()}
{$this->tableNames->workspace()} ws
JOIN {$this->tableNames->contentStream()} cs ON cs.id = ws.currentContentStreamId
WHERE
name = :workspaceName
ws.name = :workspaceName
LIMIT 1
SQL;
try {
Expand All @@ -67,7 +70,8 @@ public function getContentGraph(WorkspaceName $workspaceName): ContentGraph
throw WorkspaceDoesNotExist::butWasSupposedTo($workspaceName);
}
$currentContentStreamId = ContentStreamId::fromString($row['currentContentStreamId']);
return new ContentGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $currentContentStreamId);
$contentStreamDbId = ContentStreamDbId::fromInt((int)$row['contentStreamDbId']);
return new ContentGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $currentContentStreamId, $contentStreamDbId);
}

public function findWorkspaceByName(WorkspaceName $workspaceName): ?Workspace
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Doctrine\DBAL\Connection;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ContentStreamDbIdFinder;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
Expand All @@ -31,6 +32,7 @@ public function build(
);

$dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbal, $tableNames);
$contentStreamDbIdRepository = new ContentStreamDbIdFinder($this->dbal, $tableNames);

$nodeFactory = new NodeFactory(
$projectionFactoryDependencies->contentRepositoryId,
Expand All @@ -54,6 +56,7 @@ public function build(
),
$tableNames,
$dimensionSpacePointsRepository,
$contentStreamDbIdRepository,
$contentGraphReadModel
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private function createHierarchyRelationTable(AbstractPlatform $platform): Table
{
$table = self::createTable($this->tableNames->hierarchyRelation(), [
(new Column('position', self::type(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('contentstreamid', $platform)->setNotnull(true),
(new Column('contentstreamdbid', self::type(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash', $platform)->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('parentnodeanchor', $platform),
DbalSchemaFactory::columnForNodeAnchorPoint('childnodeanchor', $platform),
Expand All @@ -71,11 +71,11 @@ private function createHierarchyRelationTable(AbstractPlatform $platform): Table

return $table
->addIndex(['childnodeanchor'])
->addIndex(['contentstreamid'])
->addIndex(['contentstreamdbid'])
->addIndex(['parentnodeanchor'])
->addIndex(['childnodeanchor', 'contentstreamid', 'dimensionspacepointhash', 'position'])
->addIndex(['parentnodeanchor', 'contentstreamid', 'dimensionspacepointhash', 'position'])
->addIndex(['contentstreamid', 'dimensionspacepointhash']);
->addIndex(['childnodeanchor', 'contentstreamdbid', 'dimensionspacepointhash', 'position'])
->addIndex(['parentnodeanchor', 'contentstreamdbid', 'dimensionspacepointhash', 'position'])
->addIndex(['contentstreamdbid', 'dimensionspacepointhash']);
}

private function createDimensionSpacePointsTable(AbstractPlatform $platform): Table
Expand Down Expand Up @@ -120,6 +120,7 @@ private function createWorkspaceTable(AbstractPlatform $platform): Table
private function createContentStreamTable(AbstractPlatform $platform): Table
{
$contentStreamTable = self::createTable($this->tableNames->contentStream(), [
(new Column('dbId', Type::getType(Types::INTEGER)))->setAutoincrement(true)->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('id', $platform)->setNotnull(true),
(new Column('version', Type::getType(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('sourceContentStreamId', $platform)->setNotnull(false),
Expand All @@ -128,7 +129,9 @@ private function createContentStreamTable(AbstractPlatform $platform): Table
(new Column('hasChanges', Type::getType(Types::BOOLEAN)))->setNotnull(true),
]);

return $contentStreamTable->setPrimaryKey(['id']);
return $contentStreamTable
->addUniqueIndex(['id'])
->setPrimaryKey(['dbId']);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection;

use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;

/**
* @internal adapter specific id for content streams.
* Auto-incrementing int to optimise schema vs unconstrained cr content-stream-ids.
* Each {@see ContentStreamDbId} points to exactly one {@see ContentStreamId}.
*/
final readonly class ContentStreamDbId
{
private function __construct(
public int $value
) {
}

public static function fromInt(int $value): self
{
return new self($value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature;

use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\ContentStreamDbId;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\HierarchyRelation;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRecord;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet;
use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSibling;
use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;

/**
* The NodeMove projection feature trait
Expand All @@ -22,34 +22,34 @@ trait NodeMove
{
use SubtreeTagging;

private function moveNodeAggregate(ContentStreamId $contentStreamId, NodeAggregateId $nodeAggregateId, ?NodeAggregateId $newParentNodeAggregateId, InterdimensionalSiblings $succeedingSiblingsForCoverage): void
private function moveNodeAggregate(ContentStreamDbId $contentStreamDbId, NodeAggregateId $nodeAggregateId, ?NodeAggregateId $newParentNodeAggregateId, InterdimensionalSiblings $succeedingSiblingsForCoverage): void
{
foreach ($succeedingSiblingsForCoverage as $succeedingSiblingForCoverage) {
$nodeToBeMoved = $this->projectionContentGraph->findNodeInAggregate(
$contentStreamId,
$contentStreamDbId,
$nodeAggregateId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);

if (is_null($nodeToBeMoved)) {
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because it does not exist', $nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamId->value), 1716471638);
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because it does not exist', $nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamDbId->value), 1716471638);
}

if ($newParentNodeAggregateId) {
$this->moveNodeBeneathParent(
$contentStreamId,
$contentStreamDbId,
$nodeToBeMoved,
$newParentNodeAggregateId,
$succeedingSiblingForCoverage
);
$this->moveSubtreeTags(
$contentStreamId,
$contentStreamDbId,
$newParentNodeAggregateId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);
} else {
$this->moveNodeBeforeSucceedingSibling(
$contentStreamId,
$contentStreamDbId,
$nodeToBeMoved,
$succeedingSiblingForCoverage,
);
Expand All @@ -66,27 +66,27 @@ private function moveNodeAggregate(ContentStreamId $contentStreamId, NodeAggrega
* The move target is given as $succeedingSiblingNodeMoveTarget. This also specifies the new parent node.
*/
private function moveNodeBeforeSucceedingSibling(
ContentStreamId $contentStreamId,
ContentStreamDbId $contentStreamDbId,
NodeRecord $nodeToBeMoved,
InterdimensionalSibling $succeedingSiblingForCoverage,
): void {
// find the single ingoing hierarchy relation which we want to move
$ingoingHierarchyRelation = $this->findIngoingHierarchyRelationToBeMoved(
$nodeToBeMoved,
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);

$newSucceedingSibling = null;
if ($succeedingSiblingForCoverage->nodeAggregateId) {
// find the new succeeding sibling NodeRecord; We need this record because we'll use its RelationAnchorPoint later.
$newSucceedingSibling = $this->projectionContentGraph->findNodeInAggregate(
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->nodeAggregateId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);
if ($newSucceedingSibling === null) {
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target succeeding sibling node "%s" is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamId->value, $succeedingSiblingForCoverage->nodeAggregateId->value), 1716471881);
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target succeeding sibling node "%s" is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamDbId->value, $succeedingSiblingForCoverage->nodeAggregateId->value), 1716471881);
}
}

Expand All @@ -95,7 +95,7 @@ private function moveNodeBeforeSucceedingSibling(
$ingoingHierarchyRelation->parentNodeAnchor,
null,
$newSucceedingSibling?->relationAnchorPoint,
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);

Expand All @@ -116,38 +116,38 @@ private function moveNodeBeforeSucceedingSibling(
* We always move beneath the parent before the succeeding sibling if given (or to the end)
*/
private function moveNodeBeneathParent(
ContentStreamId $contentStreamId,
ContentStreamDbId $contentStreamDbId,
NodeRecord $nodeToBeMoved,
NodeAggregateId $parentNodeAggregateId,
InterdimensionalSibling $succeedingSiblingForCoverage,
): void {
// find the single ingoing hierarchy relation which we want to move
$ingoingHierarchyRelation = $this->findIngoingHierarchyRelationToBeMoved(
$nodeToBeMoved,
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);

// find the new parent NodeRecord; We need this record because we'll use its RelationAnchorPoints later.
$newParent = $this->projectionContentGraph->findNodeInAggregate(
$contentStreamId,
$contentStreamDbId,
$parentNodeAggregateId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);
if ($newParent === null) {
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target parent node is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamId->value), 1716471955);
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target parent node is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamDbId->value), 1716471955);
}

$newSucceedingSibling = null;
if ($succeedingSiblingForCoverage->nodeAggregateId) {
// find the new succeeding sibling NodeRecord; We need this record because we'll use its RelationAnchorPoint later.
$newSucceedingSibling = $this->projectionContentGraph->findNodeInAggregate(
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->nodeAggregateId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);
if ($newSucceedingSibling === null) {
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target succeeding sibling node is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamId->value), 1716471995);
throw new \RuntimeException(sprintf('Failed to move node "%s" in sub graph %s@%s because target succeeding sibling node is missing', $nodeToBeMoved->nodeAggregateId->value, $succeedingSiblingForCoverage->dimensionSpacePoint->toJson(), $contentStreamDbId->value), 1716471995);
}
}

Expand All @@ -156,7 +156,7 @@ private function moveNodeBeneathParent(
$newParent->relationAnchorPoint,
null,
$newSucceedingSibling?->relationAnchorPoint,
$contentStreamId,
$contentStreamDbId,
$succeedingSiblingForCoverage->dimensionSpacePoint
);

Expand All @@ -171,27 +171,22 @@ private function moveNodeBeneathParent(

/**
* Helper for the move methods.
*
* @param NodeRecord $nodeToBeMoved
* @param ContentStreamId $contentStreamId
* @param DimensionSpacePoint $coveredDimensionSpacePointWhereMoveShouldHappen
* @return HierarchyRelation
*/
private function findIngoingHierarchyRelationToBeMoved(
NodeRecord $nodeToBeMoved,
ContentStreamId $contentStreamId,
ContentStreamDbId $contentStreamDbId,
DimensionSpacePoint $coveredDimensionSpacePointWhereMoveShouldHappen
): HierarchyRelation {
$restrictToSet = DimensionSpacePointSet::fromArray([$coveredDimensionSpacePointWhereMoveShouldHappen]);
$ingoingHierarchyRelations = $this->projectionContentGraph->findIngoingHierarchyRelationsForNode(
$nodeToBeMoved->relationAnchorPoint,
$contentStreamId,
$contentStreamDbId,
$restrictToSet,
);
if (count($ingoingHierarchyRelations) !== 1) {
// there should always be exactly one incoming relation in the given DimensionSpacePoint; everything
// else would be a totally wrong behavior of findIngoingHierarchyRelationsForNode().
throw new \RuntimeException(sprintf('Failed move node "%s" in sub graph %s@%s because ingoing source hierarchy relation is missing', $nodeToBeMoved->nodeAggregateId->value, $restrictToSet->toJson(), $contentStreamId->value), 1716472138);
throw new \RuntimeException(sprintf('Failed move node "%s" in sub graph %s@%s because ingoing source hierarchy relation is missing', $nodeToBeMoved->nodeAggregateId->value, $restrictToSet->toJson(), $contentStreamDbId->value), 1716472138);
}
return reset($ingoingHierarchyRelations);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature;

use Doctrine\DBAL\Exception as DBALException;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\ContentStreamDbId;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\HierarchyRelation;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;

/**
* The NodeRemoval projection feature trait
Expand All @@ -17,12 +17,12 @@
*/
trait NodeRemoval
{
private function removeNodeAggregate(ContentStreamId $contentStreamId, NodeAggregateId $nodeAggregateId, DimensionSpacePointSet $affectedCoveredDimensionSpacePoints): void
private function removeNodeAggregate(ContentStreamDbId $contentStreamDbId, NodeAggregateId $nodeAggregateId, DimensionSpacePointSet $affectedCoveredDimensionSpacePoints): void
{
// the focus here is to be correct; that's why the method is not overly performant (for now at least). We might
// lateron find tricks to improve performance
$ingoingRelations = $this->projectionContentGraph->findIngoingHierarchyRelationsForNodeAggregate(
$contentStreamId,
$contentStreamDbId,
$nodeAggregateId,
$affectedCoveredDimensionSpacePoints
);
Expand All @@ -40,7 +40,7 @@ private function removeRelationRecursivelyFromDatabaseIncludingNonReferencedNode
foreach (
$this->projectionContentGraph->findOutgoingHierarchyRelationsForNode(
$ingoingRelation->childNodeAnchor,
$ingoingRelation->contentStreamId,
$ingoingRelation->contentStreamDbId,
new DimensionSpacePointSet([$ingoingRelation->dimensionSpacePoint])
) as $outgoingRelation
) {
Expand All @@ -59,7 +59,7 @@ private function removeRelationRecursivelyFromDatabaseIncludingNonReferencedNode
WHERE
n.relationanchorpoint = :anchorPointForNode
-- the following line means "left join leads to NO MATCHING hierarchyrelation"
AND h.contentstreamid IS NULL
AND h.contentstreamdbid IS NULL
SQL;
try {
$this->dbal->executeStatement($deleteRelationsStatement, [
Expand Down
Loading
Loading