Skip to content

Commit

Permalink
Redo column generation methods for schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsunet committed Nov 18, 2023
1 parent 6fa97ce commit 8134d95
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 257 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter;

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;
use Doctrine\DBAL\Types\Types;
use Neos\ContentRepository\Core\Infrastructure\DbalSchemaFactory;

Expand All @@ -21,105 +25,84 @@ public function __construct(

public function buildSchema(AbstractSchemaManager $schemaManager): Schema
{
$schema = DbalSchemaFactory::createEmptySchema($schemaManager);

$this->createNodeTable($schema);
$this->createHierarchyRelationTable($schema);
$this->createReferenceRelationTable($schema);
$this->createRestrictionRelationTable($schema);

return $schema;
return DbalSchemaFactory::createSchemaWithTables($schemaManager, [
$this->createNodeTable(),
$this->createHierarchyRelationTable(),
$this->createReferenceRelationTable(),
$this->createRestrictionRelationTable()
]);
}

private function createNodeTable(Schema $schema): void
private function createNodeTable(): Table
{
$table = $schema->createTable($this->tableNamePrefix . '_node');
$table = DbalSchemaFactory::addColumnForNodeAnchorPoint($table, 'relationanchorpoint');
$table = DbalSchemaFactory::addColumnForNodeAggregateId($table, 'nodeaggregateid', false);
$table = DbalSchemaFactory::addColumnForDimensionSpacePoint($table, 'origindimensionspacepoint', false);
$table = DbalSchemaFactory::addColumnForDimensionSpacePointHash($table, 'origindimensionspacepointhash', false);
$table = DbalSchemaFactory::addColumnForNodeTypeName($table, 'nodetypename');
$table->addColumn('properties', Types::TEXT)
->setNotnull(true)
->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION);
$table->addColumn('classification', Types::STRING)
->setLength(20)
->setNotnull(true)
->setCustomSchemaOption('charset', 'binary');
$table->addColumn('created', Types::DATETIME_IMMUTABLE)
->setDefault('CURRENT_TIMESTAMP')
->setNotnull(true);
$table->addColumn('originalcreated', Types::DATETIME_IMMUTABLE)
->setDefault('CURRENT_TIMESTAMP')
->setNotnull(true);
$table->addColumn('lastmodified', Types::DATETIME_IMMUTABLE)
->setNotnull(false)
->setDefault(null);
$table->addColumn('originallastmodified', Types::DATETIME_IMMUTABLE)
->setNotnull(false)
->setDefault(null);
$table
$table = new Table($this->tableNamePrefix . '_node', [
DbalSchemaFactory::columnForNodeAnchorPoint('relationanchorpoint'),
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),
(new Column('classification', Type::getType(Types::STRING)))->setLength(20)->setNotnull(true)->setCustomSchemaOption('charset', 'binary'),
(new Column('created', Type::getType(Types::DATETIME_IMMUTABLE)))->setDefault('CURRENT_TIMESTAMP')->setNotnull(true),
(new Column('originalcreated', Type::getType(Types::DATETIME_IMMUTABLE)))->setDefault('CURRENT_TIMESTAMP')->setNotnull(true),
(new Column('lastmodified', Type::getType(Types::DATETIME_IMMUTABLE)))->setNotnull(false)->setDefault(null),
(new Column('originallastmodified', Type::getType(Types::DATETIME_IMMUTABLE)))->setNotnull(false)->setDefault(null)
]);

return $table
->setPrimaryKey(['relationanchorpoint'])
->addIndex(['nodeaggregateid'])
->addIndex(['nodetypename']);
}

private function createHierarchyRelationTable(Schema $schema): void
private function createHierarchyRelationTable(): Table
{
$table = $schema->createTable($this->tableNamePrefix . '_hierarchyrelation');
$table->addColumn('name', Types::STRING)
->setLength(255)
->setNotnull(false)
->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION);
$table->addColumn('position', Types::INTEGER)
->setNotnull(true);
$table = DbalSchemaFactory::addColumnForContentStreamId($table, 'contentstreamid', true);
$table = DbalSchemaFactory::addColumnForDimensionSpacePoint($table, 'dimensionspacepoint', true);
$table = DbalSchemaFactory::addColumnForDimensionSpacePointHash($table, 'dimensionspacepointhash', true);
$table = DbalSchemaFactory::addColumnForNodeAnchorPoint($table, 'parentnodeanchor');
$table = DbalSchemaFactory::addColumnForNodeAnchorPoint($table, 'childnodeanchor');
$table
$table = new Table($this->tableNamePrefix . '_hierarchyrelation', [
(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')
]);

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

private function createReferenceRelationTable(Schema $schema): void
private function createReferenceRelationTable(): Table
{
$table = $schema->createTable($this->tableNamePrefix . '_referencerelation');
$table->addColumn('name', Types::STRING)
->setLength(255)
->setNotnull(true)
->setCustomSchemaOption('charset', 'ascii')
->setCustomSchemaOption('collation', 'ascii_general_ci');
$table->addColumn('position', Types::INTEGER)
->setNotnull(true);
$table = DbalSchemaFactory::addColumnForNodeAnchorPoint($table, 'nodeanchorpoint');
$table->addColumn('properties', Types::TEXT)
->setNotnull(false)
->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION);
$table = DbalSchemaFactory::addColumnForNodeAggregateId($table, 'destinationnodeaggregateid', true);
$table = new Table($this->tableNamePrefix . '_referencerelation', [
(new Column('name', Type::getType(Types::STRING)))->setLength(255)->setNotnull(true)->setCustomSchemaOption('charset', 'ascii')->setCustomSchemaOption('collation', 'ascii_general_ci'),
(new Column('position', Type::getType(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('nodeanchorpoint'),
(new Column('properties', Type::getType(Types::TEXT)))->setNotnull(false)->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION),
DbalSchemaFactory::columnForNodeAggregateId('destinationnodeaggregateid')->setNotnull(true)
]);

$table
return $table
->setPrimaryKey(['name', 'position', 'nodeanchorpoint']);
}

private function createRestrictionRelationTable(Schema $schema): void
private function createRestrictionRelationTable(): Table
{
$table = $schema->createTable($this->tableNamePrefix . '_restrictionrelation');
$table = DbalSchemaFactory::addColumnForContentStreamId($table, 'contentstreamid', true);
$table = DbalSchemaFactory::addColumnForDimensionSpacePointHash($table, 'dimensionspacepointhash', true);
$table = DbalSchemaFactory::addColumnForNodeAggregateId($table, 'originnodeaggregateid', true);
$table = DbalSchemaFactory::addColumnForNodeAggregateId($table, 'affectednodeaggregateid', true);
$table = new Table($this->tableNamePrefix . '_restrictionrelation', [
DbalSchemaFactory::columnForContentStreamId('contentstreamid')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash')->setNotnull(true),
DbalSchemaFactory::columnForNodeAggregateId('originnodeaggregateid')->setNotnull(false),
DbalSchemaFactory::columnForNodeAggregateId('affectednodeaggregateid')->setNotnull(false),
]);

$table
->setPrimaryKey([
'contentstreamid',
'dimensionspacepointhash',
'originnodeaggregateid',
'affectednodeaggregateid'
]);
return $table->setPrimaryKey([
'contentstreamid',
'dimensionspacepointhash',
'originnodeaggregateid',
'affectednodeaggregateid'
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
namespace Neos\ContentRepository\Core\Infrastructure;

use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
Expand All @@ -26,15 +28,12 @@ final class DbalSchemaFactory
*
* @see NodeAggregateId
*/
public static function addColumnForNodeAggregateId(Table $table, string $columnName, bool $notNull): Table
public static function columnForNodeAggregateId(string $columnName): Column
{
$table->addColumn($columnName, Types::STRING)
->setLength(64)
->setNotnull($notNull)
->setCustomSchemaOption('charset', 'ascii')
->setCustomSchemaOption('collation', 'ascii_general_ci');

return $table;
return (new Column($columnName, Type::getType(Types::STRING)))
->setLength(64)
->setCustomSchemaOption('charset', 'ascii')
->setCustomSchemaOption('collation', 'ascii_general_ci');
}

/**
Expand All @@ -47,14 +46,11 @@ public static function addColumnForNodeAggregateId(Table $table, string $columnN
*
* @see ContentStreamId
*/
public static function addColumnForContentStreamId(Table $table, string $columnName, bool $notNull): Table
public static function columnForContentStreamId(string $columnName): Column
{
$table->addColumn($columnName, Types::STRING)
return (new Column($columnName, Type::getType(Types::STRING)))
->setLength(36)
->setNotnull($notNull)
->setCustomSchemaOption('charset', 'binary');

return $table;
}

/**
Expand All @@ -65,13 +61,11 @@ public static function addColumnForContentStreamId(Table $table, string $columnN
* A simpler and faster format would be preferable though, int or a shorter binary format if possible. Fortunately
* this is a pure projection information and therefore could change by replay.
*/
public static function addColumnForNodeAnchorPoint(Table $table, string $columnName): Table
public static function columnForNodeAnchorPoint(string $columnName): Column
{
$table->addColumn($columnName, Types::BINARY)
return (new Column($columnName, Type::getType(Types::BINARY)))
->setLength(36)
->setNotnull(true);

return $table;
}

/**
Expand All @@ -82,14 +76,11 @@ public static function addColumnForNodeAnchorPoint(Table $table, string $columnN
*
* @see DimensionSpacePoint
*/
public static function addColumnForDimensionSpacePoint(Table $table, string $columnName, bool $notNull): Table
public static function columnForDimensionSpacePoint(string $columnName): Column
{
$table->addColumn($columnName, Types::TEXT)
->setNotnull($notNull)
return (new Column($columnName, Type::getType(Types::TEXT)))
->setDefault('{}')
->setCustomSchemaOption('collation', 'utf8mb4_unicode_520_ci');

return $table;
}

/**
Expand All @@ -100,39 +91,39 @@ public static function addColumnForDimensionSpacePoint(Table $table, string $col
*
* @see DimensionSpacePoint
*/
public static function addColumnForDimensionSpacePointHash(Table $table, string $columnName, bool $notNull): Table
public static function columnForDimensionSpacePointHash(string $columnName): Column
{
$table->addColumn($columnName, Types::BINARY)
return (new Column($columnName, Type::getType(Types::BINARY)))
->setLength(32)
->setDefault('')
->setNotnull($notNull);

return $table;
->setDefault('');
}

/**
* The NodeTypeName is an ascii string, we should be able to sort it properly, but we don't need unicode here.
*
* @see NodeTypeName
*/
public static function addColumnForNodeTypeName(Table $table, string $columnName): Table
public static function columnForNodeTypeName(string $columnName): Column
{
$table->addColumn($columnName, Types::STRING)
return (new Column($columnName, Type::getType(Types::STRING)))
->setLength(255)
->setNotnull(true)
->setCustomSchemaOption('charset', 'ascii')
->setCustomSchemaOption('collation', 'ascii_general_ci');

return $table;
}

public static function createEmptySchema(AbstractSchemaManager $schemaManager): Schema
/**
* @param AbstractSchemaManager $schemaManager
* @param Table[] $tables
* @return Schema
*/
public static function createSchemaWithTables(AbstractSchemaManager $schemaManager, array $tables): Schema
{
$schemaConfig = $schemaManager->createSchemaConfig();
$schemaConfig->setDefaultTableOptions([
'charset' => 'utf8mb4'
]);

return new Schema([], [], $schemaConfig);
return new Schema($tables, [], $schemaConfig);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaConfig;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Neos\ContentRepository\Core\EventStore\EventInterface;
use Neos\ContentRepository\Core\Feature\Common\EmbedsContentStreamAndNodeAggregateId;
Expand Down Expand Up @@ -91,19 +94,17 @@ private function setupTables(): void
$connection->executeStatement(sprintf("UPDATE %s SET state='FORKED' WHERE state='REBASING'; ", $this->tableName));
}

$schema = DbalSchemaFactory::createEmptySchema($schemaManager);
$contentStreamTable = $schema->createTable($this->tableName);
$contentStreamTable = DbalSchemaFactory::addColumnForContentStreamId($contentStreamTable, 'contentStreamId', true);
$contentStreamTable->addColumn('version', Types::INTEGER)
->setNotnull(true);
$contentStreamTable = DbalSchemaFactory::addColumnForContentStreamId($contentStreamTable, 'sourceContentStreamId', false);
// Should become a DB ENUM or int (latter needs adaption to code)
$contentStreamTable->addColumn('state', Types::BINARY)
->setLength(20)
->setNotnull(true);
$contentStreamTable->addColumn('removed', Types::BOOLEAN)
->setDefault(false)
->setNotnull(false);
$schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [
(new Table($this->tableName, [
DbalSchemaFactory::columnForContentStreamId('contentStreamId')->setNotnull(true),
(new Column('version', Type::getType(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('sourceContentStreamId')->setNotnull(false),
// Should become a DB ENUM (unclear how to configure with DBAL) or int (latter needs adaption to code)
(new Column('state', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(true),
(new Column('removed', Type::getType(Types::BOOLEAN)))->setDefault(false)->setNotnull(false)
]))
]);

$schemaDiff = (new Comparator())->compare($schemaManager->createSchema(), $schema);
foreach ($schemaDiff->toSaveSql($connection->getDatabasePlatform()) as $statement) {
$connection->executeStatement($statement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Neos\ContentRepository\Core\EventStore\EventInterface;
use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked;
Expand Down Expand Up @@ -65,20 +68,20 @@ private function setupTables(): void
if (!$schemaManager instanceof AbstractSchemaManager) {
throw new \RuntimeException('Failed to retrieve Schema Manager', 1625653914);
}
$schema = DbalSchemaFactory::createEmptySchema($schemaManager);
$contentStreamTable = $schema->createTable($this->tableName);
$contentStreamTable = DbalSchemaFactory::addColumnForContentStreamId($contentStreamTable, 'contentstreamid', true);
$contentStreamTable = DbalSchemaFactory::addColumnForNodeAggregateId($contentStreamTable, 'nodeaggregateid', false);
$contentStreamTable = DbalSchemaFactory::addColumnForDimensionSpacePointHash($contentStreamTable, 'dimensionspacepointhash', false);
$contentStreamTable = DbalSchemaFactory::addColumnForDimensionSpacePoint($contentStreamTable, 'dimensionspacepoint', false);
$contentStreamTable->addColumn('hidden', Types::BOOLEAN)
->setDefault(false)
->setNotnull(false);

$contentStreamTable->setPrimaryKey(

$nodeHiddenStateTable = new Table($this->tableName, [
DbalSchemaFactory::columnForContentStreamId('contentstreamid')->setNotNull(true),
DbalSchemaFactory::columnForNodeAggregateId('nodeaggregateid')->setNotNull(false),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash')->setNotNull(false),
DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotNull(false),
(new Column('hidden', Type::getType(Types::BOOLEAN)))->setDefault(false)->setNotnull(false)
]);
$nodeHiddenStateTable->setPrimaryKey(
['contentstreamid', 'nodeaggregateid', 'dimensionspacepointhash']
);

$schema = DbalSchemaFactory::createSchemaWithTables($schemaManager, [$nodeHiddenStateTable]);

$schemaDiff = (new Comparator())->compare($schemaManager->createSchema(), $schema);
foreach ($schemaDiff->toSaveSql($connection->getDatabasePlatform()) as $statement) {
$connection->executeStatement($statement);
Expand Down
Loading

0 comments on commit 8134d95

Please sign in to comment.