Skip to content

Commit

Permalink
Fill in dummy types to deal with DC2:... column comments (#102)
Browse files Browse the repository at this point in the history
We're using the `SchemaManager` to simplify listing tables, views and so
on. But, the information provided by it also includes the DBAL types
used for columns, and that information may be parsed from column
comments in the database.

The problem is that a table definition like so:

```sql
CREATE TABLE `test` (
  `some_col` int NOT NULL COMMENT '(DC2Type:some_type)'
)
```

... `slimdump` fail fail with an exception because it does not know
about the `some_type`. This type may be available and defined in your
application, but we cannot put it into the `slimdump` command.

Now, in fact, we don't care about the type and its conversion
capabilities at all. So, this PR adds a runtime "just in type"
registration of a `DummyType` that serves as a placeholder to avoid
issues when loading the schema.

Fixes #96.
  • Loading branch information
mpdude authored Jan 18, 2024
1 parent 0abfaaa commit 02315a3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 13 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
],
"require": {
"php": "^7.2|8.0.*|8.1.*",
"ext-SimpleXML": "*",
"ext-libxml": "*",
"ext-pdo": "*",
"ext-SimpleXML": "*",
"doctrine/dbal": "^2.5.2",
"doctrine/event-manager": "^1.0",
"fakerphp/faker": "^1.6",
"symfony/console": "^4.0|^5.0|^6.0",
"symfony/service-contracts": "^2.1.2"
Expand Down
23 changes: 12 additions & 11 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions src/Webfactory/Slimdump/Doctrine/DummyType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Webfactory\Slimdump\Doctrine;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use LogicException;

class DummyType extends Type
{
public const NAME = 'dummy_type';

public function convertToPHPValue($value, AbstractPlatform $platform)
{
throw new LogicException('this should not be called in the first place');
}

public function getSQLDeclaration(array $column, AbstractPlatform $platform)
{
throw new LogicException('this should not be called in the first place');
}

public function getName()
{
return self::NAME;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Webfactory\Slimdump\Doctrine;

use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Types\Type;

class DummyTypeRegistrationEventSubscriber implements EventSubscriber
{
/**
* @var AbstractSchemaManager
*/
private $schemaManager;

public function __construct(AbstractSchemaManager $schemaManager)
{
$this->schemaManager = $schemaManager;
}

public function getSubscribedEvents(): array
{
return [Events::onSchemaColumnDefinition];
}

public function onSchemaColumnDefinition(SchemaColumnDefinitionEventArgs $event): void
{
$tableColumn = array_change_key_case($event->getTableColumn(), \CASE_LOWER);
$dbType = strtolower($tableColumn['type']);
$dbType = strtok($dbType, '(), ');

if (isset($tableColumn['comment'])) {
$type = $this->schemaManager->extractDoctrineTypeFromComment($tableColumn['comment'], '');

if ($type && !Type::hasType($type)) {
Type::addType($type, DummyType::class);
}
}

$databasePlatform = $this->schemaManager->getDatabasePlatform();
if (!$databasePlatform->hasDoctrineTypeMappingFor($dbType)) {
if (!Type::hasType(DummyType::NAME)) {
Type::addType(DummyType::NAME, DummyType::class);
}
$databasePlatform->registerDoctrineTypeMapping($dbType, DummyType::NAME);
}
}
}
3 changes: 2 additions & 1 deletion src/Webfactory/Slimdump/SlimdumpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Webfactory\Slimdump\Database\CsvOutputFormatDriver;
use Webfactory\Slimdump\Database\MysqlOutputFormatDriver;
use Webfactory\Slimdump\Database\OutputFormatDriverInterface;
use Webfactory\Slimdump\Doctrine\DummyTypeRegistrationEventSubscriber;

final class SlimdumpCommand extends Command
{
Expand Down Expand Up @@ -74,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$progressOutput = $this->createProgressOutput($input, $output);

$connection = $this->createConnection($input);
$connection->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
$connection->getEventManager()->addEventSubscriber(new DummyTypeRegistrationEventSubscriber($connection->getSchemaManager()));
$this->setMaxExecutionTimeUnlimited($connection, $progressOutput);

$config = ConfigBuilder::createConfigurationFromConsecutiveFiles($input->getArgument('config'));
Expand Down

0 comments on commit 02315a3

Please sign in to comment.