Commit 51358603 authored by Robin Appelman's avatar Robin Appelman Committed by Timo Bakx

allow creating PRIMARY KEY AUTOINCREMENT fields for sqlite

If a PRIMARY KEY field is defined in sqlite without autoincrement then
keys might be reused when rows are deleted, explicitly settings autoincrement
will prevent this.

Autoincrement is not enabled by default due to additional overhead introduced
with autoincrement bookkeeping and should only be enabled when the additional
uniqueness is required.
parent f3339a01
...@@ -307,9 +307,9 @@ class SqlitePlatform extends AbstractPlatform ...@@ -307,9 +307,9 @@ class SqlitePlatform extends AbstractPlatform
*/ */
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{ {
// sqlite autoincrement is implicit for integer PKs, but not when the field is unsigned // sqlite autoincrement is only possible for the primary key
if ( ! empty($columnDef['autoincrement'])) { if ( ! empty($columnDef['autoincrement'])) {
return ''; return ' PRIMARY KEY AUTOINCREMENT';
} }
return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : '';
...@@ -345,7 +345,10 @@ class SqlitePlatform extends AbstractPlatform ...@@ -345,7 +345,10 @@ class SqlitePlatform extends AbstractPlatform
if (isset($options['primary']) && ! empty($options['primary'])) { if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary'])); $keyColumns = array_unique(array_values($options['primary']));
$queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')'; // the primary key is already defined in the column definition for auto increment fields
if (count($keyColumns) > 1 || !$columns[$keyColumns[0]]['autoincrement']) {
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
} }
if (isset($options['foreignKeys'])) { if (isset($options['foreignKeys'])) {
......
...@@ -232,4 +232,63 @@ SQL; ...@@ -232,4 +232,63 @@ SQL;
array('bigint', true, true), array('bigint', true, true),
); );
} }
/**
* @group DBAL-2921
*/
public function testPrimaryKeyAutoIncrement()
{
$table = new Schema\Table('test_pk_auto_increment');
$table->addColumn('id', 'integer', [
'autoincrement' => true
]);
$table->addColumn('text', 'text');
$table->setPrimaryKey(['id']);
$this->_sm->dropAndCreateTable($table);
$this->_conn->insert('test_pk_auto_increment', ['text' => '1']);
$this->_conn->insert('test_pk_auto_increment', ['text' => '2']);
$this->_conn->insert('test_pk_auto_increment', ['text' => '3']);
$query = $this->_conn->query('SELECT id FROM test_pk_auto_increment WHERE text = "3"');
$query->execute();
$lastUsedIdBeforeDelete = (int)$query->fetchColumn();
$this->_conn->query('DELETE FROM test_pk_auto_increment');
$this->_conn->insert('test_pk_auto_increment', ['text' => '4']);
$query = $this->_conn->query('SELECT id FROM test_pk_auto_increment WHERE text = "4"');
$query->execute();
$lastUsedIdAfterDelete = (int)$query->fetchColumn();
$this->assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete);
}
/**
* @group DBAL-2921
*/
public function testPrimaryKeyNoAutoIncrement()
{
$table = new Schema\Table('test_pk_auto_increment');
$table->addColumn('id', 'integer');
$table->addColumn('text', 'text');
$table->setPrimaryKey(['id']);
$this->_sm->dropAndCreateTable($table);
$this->_conn->insert('test_pk_auto_increment', ['text' => '1']);
$this->_conn->insert('test_pk_auto_increment', ['text' => '2']);
$this->_conn->insert('test_pk_auto_increment', ['text' => '3']);
$this->_conn->query('DELETE FROM test_pk_auto_increment');
$this->_conn->insert('test_pk_auto_increment', ['text' => '4']);
$query = $this->_conn->query('SELECT id FROM test_pk_auto_increment WHERE text = "4"');
$query->execute();
$lastUsedIdAfterDelete = (int)$query->fetchColumn();
// with an empty table, non autoincrement rowid is always 1
$this->assertEquals(1, $lastUsedIdAfterDelete);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment