diff --git a/src/Db/Adapter/SqliteAdapter.php b/src/Db/Adapter/SqliteAdapter.php index 91847376..93729cf1 100644 --- a/src/Db/Adapter/SqliteAdapter.php +++ b/src/Db/Adapter/SqliteAdapter.php @@ -1343,13 +1343,16 @@ protected function getAddPrimaryKeyInstructions(TableMetadata $table, string $co $instructions->addPostStep(function ($state) use ($column) { $quotedColumn = preg_quote($column); $columnPattern = "`{$quotedColumn}`|\"{$quotedColumn}\"|\[{$quotedColumn}\]"; - $matchPattern = "/($columnPattern)\s+(\w+(\(\d+\))?)(\s+(NOT )?NULL)?/"; + $matchPattern = "/($columnPattern)\s+(\w+(\(\d+\))?)(\s+(NOT )?NULL)?(\s+(?:PRIMARY KEY\s+)?AUTOINCREMENT)?/i"; $sql = $state['createSQL']; if (preg_match($matchPattern, $state['createSQL'], $matches)) { if (isset($matches[2])) { - if ($matches[2] === 'INTEGER') { + $hasAutoIncrement = isset($matches[6]) && stripos($matches[6], 'AUTOINCREMENT') !== false; + + if ($matches[2] === 'INTEGER' && $hasAutoIncrement) { + // Only add AUTOINCREMENT if the column already had it $replace = '$1 INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT'; } else { $replace = '$1 $2 NOT NULL PRIMARY KEY'; diff --git a/tests/TestCase/Db/Adapter/SqliteAdapterTest.php b/tests/TestCase/Db/Adapter/SqliteAdapterTest.php index 4c92a8b4..ef42a23c 100644 --- a/tests/TestCase/Db/Adapter/SqliteAdapterTest.php +++ b/tests/TestCase/Db/Adapter/SqliteAdapterTest.php @@ -428,6 +428,51 @@ public function testChangePrimaryKeyNonInteger() $this->assertTrue($this->adapter->hasPrimaryKey('table1', ['column2'])); } + public function testChangePrimaryKeyWithoutAutoIncrement() + { + // Create table with id_1 as PK without AUTOINCREMENT keyword + $this->adapter->execute('CREATE TABLE table1 (id_1 INTEGER NOT NULL PRIMARY KEY, id_2 INTEGER NOT NULL)'); + + // Verify initial SQL does not have AUTOINCREMENT + $result = $this->adapter->fetchRow("SELECT sql FROM sqlite_master WHERE type='table' AND name='table1'"); + $this->assertStringNotContainsString('AUTOINCREMENT', $result['sql']); + + // Change primary key to id_2 + $table = new Table('table1', [], $this->adapter); + $table->changePrimaryKey('id_2')->save(); + + // Verify primary key changed + $this->assertFalse($this->adapter->hasPrimaryKey('table1', ['id_1'])); + $this->assertTrue($this->adapter->hasPrimaryKey('table1', ['id_2'])); + + // Verify the SQL does NOT have AUTOINCREMENT added to id_2 + $result = $this->adapter->fetchRow("SELECT sql FROM sqlite_master WHERE type='table' AND name='table1'"); + $this->assertStringNotContainsString('AUTOINCREMENT', $result['sql'], 'AUTOINCREMENT should not be added when changing PK to a column that did not have it'); + } + + public function testChangePrimaryKeyFromAutoIncrementColumn() + { + // Create table with id_1 as PK with AUTOINCREMENT + $this->adapter->execute('CREATE TABLE table1 (id_1 INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id_2 INTEGER NOT NULL)'); + + // Verify initial SQL has AUTOINCREMENT + $result = $this->adapter->fetchRow("SELECT sql FROM sqlite_master WHERE type='table' AND name='table1'"); + $this->assertStringContainsString('AUTOINCREMENT', $result['sql']); + + // Change primary key to id_2 (should NOT get AUTOINCREMENT since id_2 doesn't have it) + $table = new Table('table1', [], $this->adapter); + $table->changePrimaryKey('id_2')->save(); + + // Verify primary key changed + $this->assertFalse($this->adapter->hasPrimaryKey('table1', ['id_1'])); + $this->assertTrue($this->adapter->hasPrimaryKey('table1', ['id_2'])); + + // Verify the SQL does NOT have AUTOINCREMENT on id_2 + // (id_1 lost its AUTOINCREMENT when PK was dropped, and id_2 never had it) + $result = $this->adapter->fetchRow("SELECT sql FROM sqlite_master WHERE type='table' AND name='table1'"); + $this->assertStringNotContainsString('AUTOINCREMENT', $result['sql'], 'AUTOINCREMENT should not be added when changing PK to a column that never had it'); + } + public function testDropPrimaryKey() { $table = new Table('table1', ['id' => false, 'primary_key' => 'column1'], $this->adapter);