diff --git a/Cake/Database/Schema/SqliteSchema.php b/Cake/Database/Schema/SqliteSchema.php index 5514973c02b..bcb546bfa6c 100644 --- a/Cake/Database/Schema/SqliteSchema.php +++ b/Cake/Database/Schema/SqliteSchema.php @@ -24,6 +24,13 @@ */ class SqliteSchema extends BaseSchema { +/** + * Whether or not this connection contains sequences + * + * @return boolean + */ + protected $_hasSequences; + /** * Convert a column definition to the abstract types. * @@ -327,10 +334,31 @@ public function createTableSql(Table $table, $columns, $constraints, $indexes) { */ public function truncateTableSql(Table $table) { $name = $table->name(); - return [ - sprintf('DELETE FROM sqlite_sequence WHERE name="%s"', $name), - sprintf('DELETE FROM "%s"', $name) - ]; + $sql = []; + if ($this->hasSequences()) { + $sql[] = sprintf('DELETE FROM sqlite_sequence WHERE name="%s"', $name); + } + + $sql[] = sprintf('DELETE FROM "%s"', $name); + return $sql; + } + +/** + * Returns whether there is any table in this connection to SQLite contianing + * sequences + * + * @return void + */ + public function hasSequences() { + if ($this->_hasSequences !== null) { + return $this->_hasSequences; + } + $result = $this->_driver + ->prepare('SELECT 1 FROM sqlite_master WHERE name = "sqlite_sequence"'); + $result->execute(); + $this->_hasSequences = (bool)$result->rowCount(); + $result->closeCursor(); + return $this->_hasSequences; } } diff --git a/Cake/Test/TestCase/Database/Schema/SqliteSchemaTest.php b/Cake/Test/TestCase/Database/Schema/SqliteSchemaTest.php index 73a6cc410ef..2a5f79f524f 100644 --- a/Cake/Test/TestCase/Database/Schema/SqliteSchemaTest.php +++ b/Cake/Test/TestCase/Database/Schema/SqliteSchemaTest.php @@ -674,6 +674,18 @@ public function testTruncateSql() { $connection->expects($this->any())->method('driver') ->will($this->returnValue($driver)); + $statement = $this->getMock( + '\PDOStatement', + ['execute', 'rowCount', 'closeCursor', 'fetch'] + ); + $driver->connection()->expects($this->once())->method('prepare') + ->with('SELECT 1 FROM sqlite_master WHERE name = "sqlite_sequence"') + ->will($this->returnValue($statement)); + $statement->expects($this->at(0))->method('fetch') + ->will($this->returnValue(['1'])); + $statement->expects($this->at(2))->method('fetch') + ->will($this->returnValue(false)); + $table = new Table('articles'); $result = $table->truncateSql($connection); $this->assertCount(2, $result); @@ -681,6 +693,33 @@ public function testTruncateSql() { $this->assertEquals('DELETE FROM "articles"', $result[1]); } +/** + * Test truncateSql() with no sequences + * + * @return void + */ + public function testTruncateSqlNoSequences() { + $driver = $this->_getMockedDriver(); + $connection = $this->getMock('Cake\Database\Connection', [], [], '', false); + $connection->expects($this->any())->method('driver') + ->will($this->returnValue($driver)); + + $statement = $this->getMock( + '\PDOStatement', + ['execute', 'rowCount', 'closeCursor', 'fetch'] + ); + $driver->connection()->expects($this->once())->method('prepare') + ->with('SELECT 1 FROM sqlite_master WHERE name = "sqlite_sequence"') + ->will($this->returnValue($statement)); + $statement->expects($this->once())->method('fetch') + ->will($this->returnValue(false)); + + $table = new Table('articles'); + $result = $table->truncateSql($connection); + $this->assertCount(1, $result); + $this->assertEquals('DELETE FROM "articles"', $result[0]); + } + /** * Get a schema instance with a mocked driver/pdo instances * @@ -688,7 +727,7 @@ public function testTruncateSql() { */ protected function _getMockedDriver() { $driver = new \Cake\Database\Driver\Sqlite(); - $mock = $this->getMock('FakePdo', ['quote', 'quoteIdentifier']); + $mock = $this->getMock('FakePdo', ['quote', 'quoteIdentifier', 'prepare']); $mock->expects($this->any()) ->method('quote') ->will($this->returnCallback(function ($value) {