SqliteSchemaManagerTest.php 8.57 KB
Newer Older
1 2
<?php

3
namespace Doctrine\DBAL\Tests\Functional\Schema;
4

5
use Doctrine\DBAL\DBALException;
Sergei Morozov's avatar
Sergei Morozov committed
6
use Doctrine\DBAL\Driver\Connection;
7
use Doctrine\DBAL\Schema;
Sergei Morozov's avatar
Sergei Morozov committed
8
use Doctrine\DBAL\Schema\Table;
Sergei Morozov's avatar
Sergei Morozov committed
9
use Doctrine\DBAL\Types\BlobType;
10
use Doctrine\DBAL\Types\Type;
11
use Doctrine\DBAL\Types\Types;
12

13
use function dirname;
14

romanb's avatar
romanb committed
15
class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
16
{
romanb's avatar
romanb committed
17
    /**
18
     * SQLITE does not support databases.
romanb's avatar
romanb committed
19
     */
20
    public function testListDatabases(): void
21
    {
22 23
        $this->expectException(DBALException::class);

Sergei Morozov's avatar
Sergei Morozov committed
24
        $this->schemaManager->listDatabases();
25 26
    }

27
    public function testCreateAndDropDatabase(): void
28
    {
Sergei Morozov's avatar
Sergei Morozov committed
29
        $path = dirname(__FILE__) . '/test_create_and_drop_sqlite_database.sqlite';
30

Sergei Morozov's avatar
Sergei Morozov committed
31
        $this->schemaManager->createDatabase($path);
Gabriel Caruso's avatar
Gabriel Caruso committed
32
        self::assertFileExists($path);
Sergei Morozov's avatar
Sergei Morozov committed
33
        $this->schemaManager->dropDatabase($path);
34
        self::assertFileDoesNotExist($path);
jwage's avatar
jwage committed
35
    }
36

37 38 39
    /**
     * @group DBAL-1220
     */
40
    public function testDropsDatabaseWithActiveConnections(): void
41
    {
Sergei Morozov's avatar
Sergei Morozov committed
42
        $this->schemaManager->dropAndCreateDatabase('test_drop_database');
43

44
        self::assertFileExists('test_drop_database');
45

Sergei Morozov's avatar
Sergei Morozov committed
46
        $params           = $this->connection->getParams();
47 48
        $params['dbname'] = 'test_drop_database';

49
        $connection = $this->connection->getDriver()->connect($params);
50

Sergei Morozov's avatar
Sergei Morozov committed
51
        self::assertInstanceOf(Connection::class, $connection);
52

Sergei Morozov's avatar
Sergei Morozov committed
53
        $this->schemaManager->dropDatabase('test_drop_database');
54

55
        self::assertFileDoesNotExist('test_drop_database');
56 57 58 59

        unset($connection);
    }

60
    public function testRenameTable(): void
61
    {
62
        $this->createTestTable('oldname');
Sergei Morozov's avatar
Sergei Morozov committed
63
        $this->schemaManager->renameTable('oldname', 'newname');
64

Sergei Morozov's avatar
Sergei Morozov committed
65
        $tables = $this->schemaManager->listTableNames();
66 67
        self::assertContains('newname', $tables);
        self::assertNotContains('oldname', $tables);
68
    }
69

70
    public function createListTableColumns(): Table
71
    {
72 73 74 75
        $table = parent::createListTableColumns();
        $table->getColumn('id')->setAutoincrement(true);

        return $table;
76
    }
77

78
    public function testListForeignKeysFromExistingDatabase(): void
79
    {
Sergei Morozov's avatar
Sergei Morozov committed
80
        $this->connection->exec(<<<EOS
81 82 83 84 85 86 87 88 89 90
CREATE TABLE user (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    page INTEGER CONSTRAINT FK_1 REFERENCES page (key) DEFERRABLE INITIALLY DEFERRED,
    parent INTEGER REFERENCES user(id) ON DELETE CASCADE,
    log INTEGER,
    CONSTRAINT FK_3 FOREIGN KEY (log) REFERENCES log ON UPDATE SET NULL NOT DEFERRABLE
)
EOS
        );

Sergei Morozov's avatar
Sergei Morozov committed
91 92 93 94
        $expected = [
            new Schema\ForeignKeyConstraint(
                ['log'],
                'log',
Grégoire Paris's avatar
Grégoire Paris committed
95
                [''],
Sergei Morozov's avatar
Sergei Morozov committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
                'FK_3',
                ['onUpdate' => 'SET NULL', 'onDelete' => 'NO ACTION', 'deferrable' => false, 'deferred' => false]
            ),
            new Schema\ForeignKeyConstraint(
                ['parent'],
                'user',
                ['id'],
                '1',
                ['onUpdate' => 'NO ACTION', 'onDelete' => 'CASCADE', 'deferrable' => false, 'deferred' => false]
            ),
            new Schema\ForeignKeyConstraint(
                ['page'],
                'page',
                ['key'],
                'FK_1',
                ['onUpdate' => 'NO ACTION', 'onDelete' => 'NO ACTION', 'deferrable' => true, 'deferred' => true]
            ),
        ];
114

Sergei Morozov's avatar
Sergei Morozov committed
115
        self::assertEquals($expected, $this->schemaManager->listTableForeignKeys('user'));
116
    }
Steve Müller's avatar
Steve Müller committed
117

118
    public function testColumnCollation(): void
119 120 121 122 123 124
    {
        $table = new Schema\Table('test_collation');
        $table->addColumn('id', 'integer');
        $table->addColumn('text', 'text');
        $table->addColumn('foo', 'text')->setPlatformOption('collation', 'BINARY');
        $table->addColumn('bar', 'text')->setPlatformOption('collation', 'NOCASE');
Sergei Morozov's avatar
Sergei Morozov committed
125
        $this->schemaManager->dropAndCreateTable($table);
126

Sergei Morozov's avatar
Sergei Morozov committed
127
        $columns = $this->schemaManager->listTableColumns('test_collation');
128

129 130 131 132
        self::assertArrayNotHasKey('collation', $columns['id']->getPlatformOptions());
        self::assertEquals('BINARY', $columns['text']->getPlatformOption('collation'));
        self::assertEquals('BINARY', $columns['foo']->getPlatformOption('collation'));
        self::assertEquals('NOCASE', $columns['bar']->getPlatformOption('collation'));
133 134
    }

135
    public function testListTableWithBinary(): void
Steve Müller's avatar
Steve Müller committed
136 137 138
    {
        $tableName = 'test_binary_table';

Sergei Morozov's avatar
Sergei Morozov committed
139
        $table = new Table($tableName);
Steve Müller's avatar
Steve Müller committed
140
        $table->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
141 142 143
        $table->addColumn('column_varbinary', 'binary', []);
        $table->addColumn('column_binary', 'binary', ['fixed' => true]);
        $table->setPrimaryKey(['id']);
Steve Müller's avatar
Steve Müller committed
144

Sergei Morozov's avatar
Sergei Morozov committed
145
        $this->schemaManager->createTable($table);
Steve Müller's avatar
Steve Müller committed
146

Sergei Morozov's avatar
Sergei Morozov committed
147
        $table = $this->schemaManager->listTableDetails($tableName);
Steve Müller's avatar
Steve Müller committed
148

Sergei Morozov's avatar
Sergei Morozov committed
149
        self::assertInstanceOf(BlobType::class, $table->getColumn('column_varbinary')->getType());
150
        self::assertFalse($table->getColumn('column_varbinary')->getFixed());
Steve Müller's avatar
Steve Müller committed
151

Sergei Morozov's avatar
Sergei Morozov committed
152
        self::assertInstanceOf(BlobType::class, $table->getColumn('column_binary')->getType());
153
        self::assertFalse($table->getColumn('column_binary')->getFixed());
Steve Müller's avatar
Steve Müller committed
154
    }
155

156 157 158
    /**
     * @group DBAL-1779
     */
159
    public function testListTableColumnsWithWhitespacesInTypeDeclarations(): void
160 161 162 163 164 165 166 167
    {
        $sql = <<<SQL
CREATE TABLE dbal_1779 (
    foo VARCHAR (64) ,
    bar TEXT (100)
)
SQL;

Sergei Morozov's avatar
Sergei Morozov committed
168
        $this->connection->exec($sql);
169

Sergei Morozov's avatar
Sergei Morozov committed
170
        $columns = $this->schemaManager->listTableColumns('dbal_1779');
171

172
        self::assertCount(2, $columns);
173

174 175
        self::assertArrayHasKey('foo', $columns);
        self::assertArrayHasKey('bar', $columns);
176

177 178
        self::assertSame(Type::getType(Types::STRING), $columns['foo']->getType());
        self::assertSame(Type::getType(Types::TEXT), $columns['bar']->getType());
179

180 181
        self::assertSame(64, $columns['foo']->getLength());
        self::assertSame(100, $columns['bar']->getLength());
182 183
    }

184 185 186 187
    /**
     * @dataProvider getDiffListIntegerAutoincrementTableColumnsData
     * @group DBAL-924
     */
188
    public function testDiffListIntegerAutoincrementTableColumns(string $integerType, bool $unsigned, bool $expectedComparatorDiff): void
189 190 191
    {
        $tableName = 'test_int_autoincrement_table';

Sergei Morozov's avatar
Sergei Morozov committed
192 193 194
        $offlineTable = new Table($tableName);
        $offlineTable->addColumn('id', $integerType, ['autoincrement' => true, 'unsigned' => $unsigned]);
        $offlineTable->setPrimaryKey(['id']);
195

Sergei Morozov's avatar
Sergei Morozov committed
196
        $this->schemaManager->dropAndCreateTable($offlineTable);
197

Sergei Morozov's avatar
Sergei Morozov committed
198
        $onlineTable = $this->schemaManager->listTableDetails($tableName);
Sergei Morozov's avatar
Sergei Morozov committed
199 200
        $comparator  = new Schema\Comparator();
        $diff        = $comparator->diffTable($offlineTable, $onlineTable);
201 202

        if ($expectedComparatorDiff) {
Sergei Morozov's avatar
Sergei Morozov committed
203
            self::assertEmpty($this->schemaManager->getDatabasePlatform()->getAlterTableSQL($diff));
204
        } else {
205
            self::assertFalse($diff);
206 207 208 209
        }
    }

    /**
Sergei Morozov's avatar
Sergei Morozov committed
210
     * @return mixed[][]
211
     */
212
    public static function getDiffListIntegerAutoincrementTableColumnsData(): iterable
213
    {
Sergei Morozov's avatar
Sergei Morozov committed
214 215 216 217 218 219 220 221
        return [
            ['smallint', false, true],
            ['smallint', true, true],
            ['integer', false, false],
            ['integer', true, true],
            ['bigint', false, true],
            ['bigint', true, true],
        ];
222
    }
223 224 225 226

    /**
     * @group DBAL-2921
     */
227
    public function testPrimaryKeyNoAutoIncrement(): void
228 229 230 231 232
    {
        $table = new Schema\Table('test_pk_auto_increment');
        $table->addColumn('id', 'integer');
        $table->addColumn('text', 'text');
        $table->setPrimaryKey(['id']);
Sergei Morozov's avatar
Sergei Morozov committed
233
        $this->schemaManager->dropAndCreateTable($table);
234

Sergei Morozov's avatar
Sergei Morozov committed
235
        $this->connection->insert('test_pk_auto_increment', ['text' => '1']);
236

Sergei Morozov's avatar
Sergei Morozov committed
237
        $this->connection->query('DELETE FROM test_pk_auto_increment');
238

Sergei Morozov's avatar
Sergei Morozov committed
239
        $this->connection->insert('test_pk_auto_increment', ['text' => '2']);
240

241 242 243
        $result = $this->connection->query('SELECT id FROM test_pk_auto_increment WHERE text = "2"');

        $lastUsedIdAfterDelete = (int) $result->fetchOne();
244 245

        // with an empty table, non autoincrement rowid is always 1
246
        self::assertEquals(1, $lastUsedIdAfterDelete);
247
    }
248

249
    public function testOnlyOwnCommentIsParsed(): void
250 251 252 253 254 255 256 257 258
    {
        $table = new Table('own_column_comment');
        $table->addColumn('col1', 'string', ['length' => 16]);
        $table->addColumn('col2', 'string', ['length' => 16, 'comment' => 'Column #2']);
        $table->addColumn('col3', 'string', ['length' => 16]);

        $sm = $this->connection->getSchemaManager();
        $sm->createTable($table);

259
        self::assertNull($sm->listTableDetails('own_column_comment')
260 261 262
            ->getColumn('col1')
            ->getComment());
    }
263
}