ReservedWordsCommand.php 4.78 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Tools\Console\Command;

5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Platforms\Keywords\DB2Keywords;
7
use Doctrine\DBAL\Platforms\Keywords\MariaDb102Keywords;
8 9 10 11
use Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords;
use Doctrine\DBAL\Platforms\Keywords\MySQL80Keywords;
use Doctrine\DBAL\Platforms\Keywords\MySQLKeywords;
use Doctrine\DBAL\Platforms\Keywords\OracleKeywords;
12
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL100Keywords;
13
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL94Keywords;
14
use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator;
15 16
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords;
use Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords;
17
use Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords;
18
use InvalidArgumentException;
Benjamin Morel's avatar
Benjamin Morel committed
19 20
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
Benjamin Morel's avatar
Benjamin Morel committed
22
use Symfony\Component\Console\Output\OutputInterface;
23 24 25
use function array_keys;
use function count;
use function implode;
26 27 28

class ReservedWordsCommand extends Command
{
29
    /** @var string[] */
30
    private $keywordListClasses = [
31
        'db2'           => DB2Keywords::class,
32 33 34
        'mysql'         => MySQLKeywords::class,
        'mysql57'       => MySQL57Keywords::class,
        'mysql80'       => MySQL80Keywords::class,
35
        'mariadb102'    => MariaDb102Keywords::class,
36
        'oracle'        => OracleKeywords::class,
37
        'pgsql'         => PostgreSQL94Keywords::class,
38
        'pgsql100'      => PostgreSQL100Keywords::class,
39
        'sqlanywhere'   => SQLAnywhereKeywords::class,
40
        'sqlite'        => SQLiteKeywords::class,
41
        'sqlserver'     => SQLServer2012Keywords::class,
42
    ];
43

44
    /**
Benjamin Morel's avatar
Benjamin Morel committed
45
     * If you want to add or replace a keywords list use this command.
46
     *
47
     * @param string $name
48
     * @param string $class
Benjamin Morel's avatar
Benjamin Morel committed
49 50
     *
     * @return void
51 52 53 54 55
     */
    public function setKeywordListClass($name, $class)
    {
        $this->keywordListClasses[$name] = $class;
    }
56

57
    /** @return void */
58 59 60 61 62
    protected function configure()
    {
        $this
        ->setName('dbal:reserved-words')
        ->setDescription('Checks if the current database contains identifiers that are reserved.')
63 64 65 66 67 68
        ->setDefinition([new InputOption(
            'list',
            'l',
            InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
            'Keyword-List name.'
        ),
69
        ])
70 71 72 73
        ->setHelp(<<<EOT
Checks if the current database contains tables and columns
with names that are identifiers in this dialect or in other SQL dialects.

74 75
By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server, Oracle
and SQL Anywhere keywords are checked:
76

77
    <info>%command.full_name%</info>
78

79 80 81
If you want to check against specific dialects you can
pass them to the command:

82
    <info>%command.full_name% -l mysql -l pgsql</info>
83

84 85 86
The following keyword lists are currently shipped with Doctrine:

    * mysql
87
    * mysql57
88
    * mysql80
89
    * mariadb102
90
    * pgsql
91
    * pgsql100
92 93
    * sqlite
    * oracle
94
    * sqlserver
95
    * sqlserver2012
96
    * sqlanywhere
97 98 99 100
    * db2 (Not checked by default)
EOT
        );
    }
101

102
    /**
Benjamin Morel's avatar
Benjamin Morel committed
103
     * {@inheritdoc}
104 105 106
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
107
        /** @var Connection $conn */
108
        $conn = $this->getHelper('db')->getConnection();
109

110
        $keywordLists = (array) $input->getOption('list');
111
        if (count($keywordLists) === 0) {
112
            $keywordLists = array_keys($this->keywordListClasses);
113
        }
114

115
        $keywords = [];
116
        foreach ($keywordLists as $keywordList) {
117 118 119 120
            if (! isset($this->keywordListClasses[$keywordList])) {
                throw new InvalidArgumentException(
                    "There exists no keyword list with name '" . $keywordList . "'. " .
                    'Known lists: ' . implode(', ', array_keys($this->keywordListClasses))
121 122
                );
            }
123 124
            $class      = $this->keywordListClasses[$keywordList];
            $keywords[] = new $class();
125
        }
126

127
        $output->write('Checking keyword violations for <comment>' . implode(', ', $keywordLists) . '</comment>...', true);
128

129
        $schema  = $conn->getSchemaManager()->createSchema();
130 131
        $visitor = new ReservedKeywordsValidator($keywords);
        $schema->visit($visitor);
132

133
        $violations = $visitor->getViolations();
134
        if (count($violations) !== 0) {
135
            $output->write('There are <error>' . count($violations) . '</error> reserved keyword violations in your database schema:', true);
136
            foreach ($violations as $violation) {
137 138
                $output->write('  - ' . $violation, true);
            }
139 140

            return 1;
141
        }
142

143 144
        $output->write('No reserved keywords violations have been found!', true);

145
        return 0;
146 147
    }
}