Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework SQLite auto-increment introspection #6862

Merged
merged 1 commit into from
Mar 19, 2025
Merged
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
6 changes: 6 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -8,6 +8,12 @@ awareness about deprecated code.

# Upgrade to 5.0

## BC BREAK: `INTEGER PRIMARY KEY` columns are no longer introspected as auto-incremented on SQLite

Even though `INTEGER PRIMARY KEY` columns are effectively auto-incremented on SQLite, DBAL no longer introspects them as
such. Only if the column is declared as `INTEGER PRIMARY KEY AUTOINCREMENT`, it will be introspected as
auto-incremented.

## BC BREAK: removed support for invalid auto-increment column definitions on SQLite

The following auto-increment column definitions are no longer supported on SQLite:
28 changes: 12 additions & 16 deletions src/Schema/SQLiteSchemaManager.php
Original file line number Diff line number Diff line change
@@ -237,6 +237,14 @@
return parent::_getPortableTableForeignKeysList($list);
}

/** @link https://www.sqlite.org/autoinc.html#the_autoincrement_keyword */
private function parseColumnAutoIncrementFromSQL(string $column, string $sql): bool

Check warning on line 241 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L241

Added line #L241 was not covered by tests
{
$pattern = '/' . $this->buildIdentifierPattern($column) . 'INTEGER\s+PRIMARY\s+KEY\s+AUTOINCREMENT/i';

Check warning on line 243 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L243

Added line #L243 was not covered by tests

return preg_match($pattern, $sql) === 1;

Check warning on line 245 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L245

Added line #L245 was not covered by tests
}

private function parseColumnCollationFromSQL(string $column, string $sql): ?string
{
$pattern = '{' . $this->buildIdentifierPattern($column)
@@ -497,28 +505,16 @@

$rows = parent::fetchTableColumns($databaseName, $tableName);

$sqlByTable = $pkColumnNamesByTable = $result = [];

foreach ($rows as $row) {
$unqualifiedTableName = $row[self::TABLE_NAME_COLUMN];

$sqlByTable[$unqualifiedTableName] ??= $this->getCreateTableSQL($unqualifiedTableName);

if ($row['pk'] === 0 || $row['pk'] === '0' || $row['type'] !== 'INTEGER') {
continue;
}

$pkColumnNamesByTable[$unqualifiedTableName][] = $row['name'];
}
$sqlByTable = $result = [];

Check warning on line 508 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L508

Added line #L508 was not covered by tests

foreach ($rows as $row) {
$unqualifiedTableName = $row[self::TABLE_NAME_COLUMN];
$columnName = $row['name'];
$tableSQL = $sqlByTable[$row[self::TABLE_NAME_COLUMN]];

$tableSQL = $sqlByTable[$unqualifiedTableName] ??= $this->getCreateTableSQL($unqualifiedTableName);

Check warning on line 514 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L514

Added line #L514 was not covered by tests

$result[] = array_merge($row, [
'autoincrement' => isset($pkColumnNamesByTable[$unqualifiedTableName])
&& $pkColumnNamesByTable[$unqualifiedTableName] === [$columnName],
'autoincrement' => $this->parseColumnAutoIncrementFromSQL($columnName, $tableSQL),

Check warning on line 517 in src/Schema/SQLiteSchemaManager.php

Codecov / codecov/patch

src/Schema/SQLiteSchemaManager.php#L517

Added line #L517 was not covered by tests
'collation' => $this->parseColumnCollationFromSQL($columnName, $tableSQL),
'comment' => $this->parseColumnCommentFromSQL($columnName, $tableSQL),
]);
7 changes: 0 additions & 7 deletions tests/Functional/Schema/AlterTableTest.php
Original file line number Diff line number Diff line change
@@ -17,13 +17,6 @@ class AlterTableTest extends FunctionalTestCase
{
public function testAddPrimaryKeyOnExistingColumn(): void
{
if ($this->connection->getDatabasePlatform() instanceof SQLitePlatform) {
self::markTestSkipped(
'SQLite will automatically set up auto-increment behavior on the primary key column, which this test'
. ' does not expect.',
);
}

$table = new Table('alter_pk');
$table->addColumn('id', Types::INTEGER);
$table->addColumn('val', Types::INTEGER);
4 changes: 0 additions & 4 deletions tests/Functional/Schema/SchemaManagerTest.php
Original file line number Diff line number Diff line change
@@ -118,10 +118,6 @@ public function testAutoIncrementColumnIntrospection(bool $autoincrement): void
self::markTestSkipped('This test is only supported on platforms that have autoincrement');
}

if (! $autoincrement && $platform instanceof SQLitePlatform) {
self::markTestIncomplete('See https://github.com/doctrine/dbal/issues/6844');
}

$table = new Table('test_autoincrement');
$table->addColumn('id', Types::INTEGER, ['autoincrement' => $autoincrement]);
$table->setPrimaryKey(['id']);