diff --git a/src/Db/Adapter/AbstractAdapter.php b/src/Db/Adapter/AbstractAdapter.php index 66f373c5..b2e0c80d 100644 --- a/src/Db/Adapter/AbstractAdapter.php +++ b/src/Db/Adapter/AbstractAdapter.php @@ -1,4 +1,5 @@ generateInsertSql($table, $row); + + if ($this->isDryRunEnabled()) { + $this->io->out($sql); + } else { + $vals = []; + foreach ($row as $value) { + $placeholder = '?'; + if ($value instanceof Literal || $value instanceof PhinxLiteral) { + $placeholder = (string)$value; + } + if ($placeholder === '?') { + $vals[] = $value; + } + } + $this->getConnection()->execute($sql, $vals); + } + } + + /** + * Generates the SQL for an insert. + * + * @param \Migrations\Db\Table\Table $table The table to insert into + * @param array $row The row to insert + * @return string + */ + protected function generateInsertSql(TableMetadata $table, array $row): string { $sql = sprintf( 'INSERT INTO %s ', @@ -618,22 +647,18 @@ public function insert(TableMetadata $table, array $row): void if ($this->isDryRunEnabled()) { $sql .= ' VALUES (' . implode(', ', array_map($this->quoteValue(...), $row)) . ');'; - $this->io->out($sql); + return $sql; } else { $values = []; - $vals = []; foreach ($row as $value) { $placeholder = '?'; if ($value instanceof Literal || $value instanceof PhinxLiteral) { $placeholder = (string)$value; } $values[] = $placeholder; - if ($placeholder === '?') { - $vals[] = $value; - } } $sql .= ' VALUES (' . implode(',', $values) . ')'; - $this->getConnection()->execute($sql, $vals); + return $sql; } } @@ -683,6 +708,39 @@ protected function quoteString(string $value): string * @inheritDoc */ public function bulkinsert(TableMetadata $table, array $rows): void + { + $sql = $this->generateBulkInsertSql($table, $rows); + + if ($this->isDryRunEnabled()) { + $this->io->out($sql); + } else { + $vals = []; + foreach ($rows as $row) { + foreach ($row as $v) { + $placeholder = '?'; + if ($v instanceof Literal || $v instanceof PhinxLiteral) { + $placeholder = (string)$v; + } + if ($placeholder == '?') { + if (is_bool($v)) { + $vals[] = $this->castToBool($v); + } else { + $vals[] = $v; + } + } + } + } + $this->getConnection()->execute($sql, $vals); + } + } + /** + * Generates the SQL for a bulk insert. + * + * @param \Migrations\Db\Table\Table $table The table to insert into + * @param array $rows The rows to insert + * @return string + */ + protected function generateBulkInsertSql(TableMetadata $table, array $rows): string { $sql = sprintf( 'INSERT INTO %s ', @@ -698,9 +756,8 @@ public function bulkinsert(TableMetadata $table, array $rows): void return '(' . implode(', ', array_map($this->quoteValue(...), $row)) . ')'; }, $rows); $sql .= implode(', ', $values) . ';'; - $this->io->out($sql); + return $sql; } else { - $vals = []; $queries = []; foreach ($rows as $row) { $values = []; @@ -710,19 +767,12 @@ public function bulkinsert(TableMetadata $table, array $rows): void $placeholder = (string)$v; } $values[] = $placeholder; - if ($placeholder == '?') { - if (is_bool($v)) { - $vals[] = $this->castToBool($v); - } else { - $vals[] = $v; - } - } } $query = '(' . implode(', ', $values) . ')'; $queries[] = $query; } $sql .= implode(',', $queries); - $this->getConnection()->execute($sql, $vals); + return $sql; } } diff --git a/src/Db/Adapter/SqlserverAdapter.php b/src/Db/Adapter/SqlserverAdapter.php index 738322ea..cb107c31 100644 --- a/src/Db/Adapter/SqlserverAdapter.php +++ b/src/Db/Adapter/SqlserverAdapter.php @@ -1,4 +1,5 @@ "field_name" to support AUTO_INCREMENT $column = new Column(); $column->setName($options['id']) - ->setType('integer') - ->setOptions(['identity' => true]); + ->setType('integer') + ->setOptions(['identity' => true]); array_unshift($columns, $column); if (isset($options['primary_key']) && (array)$options['id'] !== (array)$options['primary_key']) { @@ -337,11 +340,11 @@ public function getColumns(string $tableName): array $column = new Column(); $column->setName($columnInfo['name']) - ->setType($type) - ->setNull($columnInfo['null'] !== 'NO') - ->setDefault($this->parseDefault($columnInfo['default'])) - ->setIdentity($columnInfo['identity'] === '1') - ->setComment($this->getColumnComment($columnInfo['table_name'], $columnInfo['name'])); + ->setType($type) + ->setNull($columnInfo['null'] !== 'NO') + ->setDefault($this->parseDefault($columnInfo['default'])) + ->setIdentity($columnInfo['identity'] === '1') + ->setComment($this->getColumnComment($columnInfo['table_name'], $columnInfo['name'])); if (!empty($columnInfo['char_length'])) { $column->setLimit((int)$columnInfo['char_length']); @@ -652,7 +655,7 @@ public function hasIndexByName(string $tableName, string $indexName): bool foreach ($indexes as $name => $index) { if ($name === $indexName) { - return true; + return true; } } @@ -938,7 +941,7 @@ public function getSqlType(Literal|string $type, ?int $limit = null): array return ['name' => 'uniqueidentifier']; case static::PHINX_TYPE_FILESTREAM: return ['name' => 'varbinary', 'limit' => 'max']; - // Geospatial database types + // Geospatial database types case static::PHINX_TYPE_GEOGRAPHY: case static::PHINX_TYPE_POINT: case static::PHINX_TYPE_LINESTRING: @@ -946,7 +949,7 @@ public function getSqlType(Literal|string $type, ?int $limit = null): array // SQL Server stores all spatial data using a single data type. // Specific types (point, polygon, etc) are set at insert time. return ['name' => 'geography']; - // Geometry specific type + // Geometry specific type case static::PHINX_TYPE_GEOMETRY: return ['name' => 'geometry']; default: @@ -1312,4 +1315,82 @@ public function migrated(MigrationInterface $migration, string $direction, strin return parent::migrated($migration, $direction, $startTime, $endTime); } + /** + * @inheritDoc + */ + public function insert(TableMetadata $table, array $row): void + { + $sql = $this->generateInsertSql($table, $row); + + $sql = $this->updateSQLForIdentityInsert($table->getName(), $sql); + + + if ($this->isDryRunEnabled()) { + $this->io->out($sql); + } else { + $vals = []; + foreach ($row as $value) { + $placeholder = '?'; + if ($value instanceof Literal || $value instanceof PhinxLiteral) { + $placeholder = (string)$value; + } + if ($placeholder === '?') { + $vals[] = $value; + } + } + $this->getConnection()->execute($sql, $vals); + } + } + /** + * @inheritDoc + */ + public function bulkinsert(TableMetadata $table, array $rows): void + { + $sql = $this->generateBulkInsertSql($table, $rows); + + $sql = $this->updateSQLForIdentityInsert($table->getName(), $sql); + + if ($this->isDryRunEnabled()) { + $this->io->out($sql); + } else { + $vals = []; + foreach ($rows as $row) { + foreach ($row as $v) { + $placeholder = '?'; + if ($v instanceof Literal || $v instanceof PhinxLiteral) { + $placeholder = (string)$v; + } + if ($placeholder == '?') { + if (is_bool($v)) { + $vals[] = $this->castToBool($v); + } else { + $vals[] = $v; + } + } + } + } + $this->getConnection()->execute($sql, $vals); + } + } + /** + * @param string $tableName Table name + * @param string $sql SQL statement + * @return string + */ + private function updateSQLForIdentityInsert(string $tableName, string $sql): string + { + $options = $this->getOptions(); + if (isset($options['identity_insert']) && $options['identity_insert'] == true) { + $identityInsertStart = sprintf( + 'SET IDENTITY_INSERT %s ON', + $this->quoteTableName($tableName) + ); + $identityInsertEnd = sprintf( + 'SET IDENTITY_INSERT %s OFF', + $this->quoteTableName($tableName) + ); + $sql = $identityInsertStart . ';' . PHP_EOL . $sql . ';' . PHP_EOL . $identityInsertEnd; + } + return $sql; + } } diff --git a/tests/TestCase/Db/Adapter/SqlserverAdapterTest.php b/tests/TestCase/Db/Adapter/SqlserverAdapterTest.php index 53115f95..8c3c4f35 100644 --- a/tests/TestCase/Db/Adapter/SqlserverAdapterTest.php +++ b/tests/TestCase/Db/Adapter/SqlserverAdapterTest.php @@ -1,4 +1,5 @@ adapter); $table->addColumn('realname', 'string') - ->addColumn('email', 'integer') - ->save(); + ->addColumn('email', 'integer') + ->save(); $this->assertTrue($this->adapter->hasTable('ntable')); $this->assertTrue($this->adapter->hasColumn('ntable', 'id')); $this->assertTrue($this->adapter->hasColumn('ntable', 'realname')); @@ -127,8 +128,8 @@ public function testCreateTableWithSchema() $table = new Table('nschema.ntable', [], $this->adapter); $table->addColumn('realname', 'string') - ->addColumn('email', 'integer') - ->save(); + ->addColumn('email', 'integer') + ->save(); $this->assertTrue($this->adapter->hasTable('nschema.ntable')); $this->assertTrue($this->adapter->hasColumn('nschema.ntable', 'id')); $this->assertTrue($this->adapter->hasColumn('nschema.ntable', 'realname')); @@ -143,8 +144,8 @@ public function testCreateTableCustomIdColumn() { $table = new Table('ntable', ['id' => 'custom_id'], $this->adapter); $table->addColumn('realname', 'string') - ->addColumn('email', 'integer') - ->save(); + ->addColumn('email', 'integer') + ->save(); $this->assertTrue($this->adapter->hasTable('ntable')); $this->assertTrue($this->adapter->hasColumn('ntable', 'custom_id')); $this->assertTrue($this->adapter->hasColumn('ntable', 'realname')); @@ -155,8 +156,8 @@ public function testCreateTableCustomIdColumn() public function testCreateTableIdentityColumn() { $table = new Table('ntable', ['id' => false, 'primary_key' => 'id'], $this->adapter); - $table->addColumn('id', 'integer', ['identity' => true, 'seed' => 1, 'increment' => 10 ]) - ->save(); + $table->addColumn('id', 'integer', ['identity' => true, 'seed' => 1, 'increment' => 10]) + ->save(); $this->assertTrue($this->adapter->hasTable('ntable')); $this->assertTrue($this->adapter->hasColumn('ntable', 'id')); @@ -176,7 +177,7 @@ public function testCreateTableWithNoPrimaryKey() ]; $table = new Table('atable', $options, $this->adapter); $table->addColumn('user_id', 'integer') - ->save(); + ->save(); $this->assertFalse($this->adapter->hasColumn('atable', 'id')); } @@ -235,8 +236,8 @@ public function testCreateTableWithMultiplePrimaryKeys() ]; $table = new Table('table1', $options, $this->adapter); $table->addColumn('user_id', 'integer', ['null' => false]) - ->addColumn('tag_id', 'integer', ['null' => false]) - ->save(); + ->addColumn('tag_id', 'integer', ['null' => false]) + ->save(); $this->assertTrue($this->adapter->hasIndex('table1', ['user_id', 'tag_id'])); $this->assertTrue($this->adapter->hasIndex('table1', ['tag_id', 'USER_ID'])); $this->assertFalse($this->adapter->hasIndex('table1', ['tag_id', 'user_email'])); @@ -274,10 +275,10 @@ public function testCreateTableWithMultipleIndexes() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addColumn('name', 'string') - ->addIndex('email') - ->addIndex('name') - ->save(); + ->addColumn('name', 'string') + ->addIndex('email') + ->addIndex('name') + ->save(); $this->assertTrue($this->adapter->hasIndex('table1', ['email'])); $this->assertTrue($this->adapter->hasIndex('table1', ['name'])); $this->assertFalse($this->adapter->hasIndex('table1', ['email', 'user_email'])); @@ -288,8 +289,8 @@ public function testCreateTableWithUniqueIndexes() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addIndex('email', ['unique' => true]) - ->save(); + ->addIndex('email', ['unique' => true]) + ->save(); $this->assertTrue($this->adapter->hasIndex('table1', ['email'])); $this->assertFalse($this->adapter->hasIndex('table1', ['email', 'user_email'])); } @@ -298,8 +299,8 @@ public function testCreateTableWithNamedIndexes() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addIndex('email', ['name' => 'myemailindex']) - ->save(); + ->addIndex('email', ['name' => 'myemailindex']) + ->save(); $this->assertTrue($this->adapter->hasIndex('table1', ['email'])); $this->assertFalse($this->adapter->hasIndex('table1', ['email', 'user_email'])); $this->assertTrue($this->adapter->hasIndexByName('table1', 'myemailindex')); @@ -319,9 +320,9 @@ public function testCreateTableIndexWithWhere(): void $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addColumn('is_verified', 'boolean') - ->addIndex($index) - ->save(); + ->addColumn('is_verified', 'boolean') + ->addIndex($index) + ->save(); $queries = $this->out->messages(); $indexQuery = $queries[1]; $this->assertStringContainsString('CREATE UNIQUE INDEX active_email_index', $indexQuery); @@ -427,7 +428,7 @@ public function testAddColumn() $table->save(); $this->assertFalse($table->hasColumn('email')); $table->addColumn('email', 'string') - ->save(); + ->save(); $this->assertTrue($table->hasColumn('email')); } @@ -436,7 +437,7 @@ public function testAddColumnWithDefaultValue() $table = new Table('table1', [], $this->adapter); $table->save(); $table->addColumn('default_zero', 'string', ['default' => 'test']) - ->save(); + ->save(); $columns = $this->adapter->getColumns('table1'); foreach ($columns as $column) { if ($column->getName() === 'default_zero') { @@ -450,7 +451,7 @@ public function testAddColumnWithDefaultZero() $table = new Table('table1', [], $this->adapter); $table->save(); $table->addColumn('default_zero', 'integer', ['default' => 0]) - ->save(); + ->save(); $columns = $this->adapter->getColumns('table1'); foreach ($columns as $column) { if ($column->getName() === 'default_zero') { @@ -512,7 +513,7 @@ public function testRenameColumn() { $table = new Table('t', [], $this->adapter); $table->addColumn('column1', 'string') - ->save(); + ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); $this->assertFalse($this->adapter->hasColumn('t', 'column2')); $this->adapter->renameColumn('t', 'column1', 'column2'); @@ -524,7 +525,7 @@ public function testRenamingANonExistentColumn() { $table = new Table('t', [], $this->adapter); $table->addColumn('column1', 'string') - ->save(); + ->save(); try { $this->adapter->renameColumn('t', 'column2', 'column1'); @@ -543,7 +544,7 @@ public function testChangeColumnType() { $table = new Table('t', [], $this->adapter); $table->addColumn('column1', 'string') - ->save(); + ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); $newColumn1 = new Column(); $newColumn1->setName('column1') @@ -681,10 +682,10 @@ public function testAddIndex() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->save(); + ->save(); $this->assertFalse($table->hasIndex('email')); $table->addIndex('email') - ->save(); + ->save(); $this->assertTrue($table->hasIndex('email')); } @@ -692,11 +693,11 @@ public function testAddIndexWithSort() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addColumn('username', 'string') - ->save(); + ->addColumn('username', 'string') + ->save(); $this->assertFalse($table->hasIndexByName('table1_email_username')); $table->addIndex(['email', 'username'], ['name' => 'table1_email_username', 'order' => ['email' => 'DESC', 'username' => 'ASC']]) - ->save(); + ->save(); $this->assertTrue($table->hasIndexByName('table1_email_username')); $rows = $this->adapter->fetchAll("SELECT case when ic.is_descending_key = 1 then 'DESC' else 'ASC' end AS sort_order FROM sys.indexes AS i @@ -720,12 +721,12 @@ public function testAddIndexWithIncludeColumns() { $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addColumn('firstname', 'string') - ->addColumn('lastname', 'string') - ->save(); + ->addColumn('firstname', 'string') + ->addColumn('lastname', 'string') + ->save(); $this->assertFalse($table->hasIndex('email')); $table->addIndex(['email'], ['include' => ['firstname', 'lastname']]) - ->save(); + ->save(); $this->assertTrue($table->hasIndex('email')); $rows = $this->adapter->fetchAll("SELECT ic.is_included_column AS included FROM sys.indexes AS i @@ -758,10 +759,10 @@ public function testGetIndexes() // single column index $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addColumn('username', 'string') - ->addIndex('email') - ->addIndex(['email', 'username'], ['unique' => true, 'name' => 'email_username']) - ->save(); + ->addColumn('username', 'string') + ->addIndex('email') + ->addIndex(['email', 'username'], ['unique' => true, 'name' => 'email_username']) + ->save(); $indexes = $this->adapter->getIndexes('table1'); $this->assertArrayHasKey('PK_table1', $indexes); @@ -778,8 +779,8 @@ public function testDropIndex() // single column index $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addIndex('email') - ->save(); + ->addIndex('email') + ->save(); $this->assertTrue($table->hasIndex('email')); $this->adapter->dropIndex($table->getName(), 'email'); $this->assertFalse($table->hasIndex('email')); @@ -787,9 +788,9 @@ public function testDropIndex() // multiple column index $table2 = new Table('table2', [], $this->adapter); $table2->addColumn('fname', 'string') - ->addColumn('lname', 'string') - ->addIndex(['fname', 'lname']) - ->save(); + ->addColumn('lname', 'string') + ->addIndex(['fname', 'lname']) + ->save(); $this->assertTrue($table2->hasIndex(['fname', 'lname'])); $this->adapter->dropIndex($table2->getName(), ['fname', 'lname']); $this->assertFalse($table2->hasIndex(['fname', 'lname'])); @@ -797,8 +798,8 @@ public function testDropIndex() // index with name specified, but dropping it by column name $table3 = new Table('table3', [], $this->adapter); $table3->addColumn('email', 'string') - ->addIndex('email', ['name' => 'someindexname']) - ->save(); + ->addIndex('email', ['name' => 'someindexname']) + ->save(); $this->assertTrue($table3->hasIndex('email')); $this->adapter->dropIndex($table3->getName(), 'email'); $this->assertFalse($table3->hasIndex('email')); @@ -806,9 +807,9 @@ public function testDropIndex() // multiple column index with name specified $table4 = new Table('table4', [], $this->adapter); $table4->addColumn('fname', 'string') - ->addColumn('lname', 'string') - ->addIndex(['fname', 'lname'], ['name' => 'multiname']) - ->save(); + ->addColumn('lname', 'string') + ->addIndex(['fname', 'lname'], ['name' => 'multiname']) + ->save(); $this->assertTrue($table4->hasIndex(['fname', 'lname'])); $this->adapter->dropIndex($table4->getName(), ['fname', 'lname']); $this->assertFalse($table4->hasIndex(['fname', 'lname'])); @@ -819,8 +820,8 @@ public function testDropIndexByName() // single column index $table = new Table('table1', [], $this->adapter); $table->addColumn('email', 'string') - ->addIndex('email', ['name' => 'myemailindex']) - ->save(); + ->addIndex('email', ['name' => 'myemailindex']) + ->save(); $this->assertTrue($table->hasIndex('email')); $this->adapter->dropIndexByName($table->getName(), 'myemailindex'); $this->assertFalse($table->hasIndex('email')); @@ -828,12 +829,13 @@ public function testDropIndexByName() // multiple column index $table2 = new Table('table2', [], $this->adapter); $table2->addColumn('fname', 'string') - ->addColumn('lname', 'string') - ->addIndex( - ['fname', 'lname'], - ['name' => 'twocolumnuniqueindex', 'unique' => true], - ) - ->save(); + ->addColumn('lname', 'string') + ->addIndex( + ['fname', 'lname'], + ['name' => 'twocolumnuniqueindex', 'unique' => true] + ) + ->save(); + $this->assertTrue($table2->hasIndex(['fname', 'lname'])); $this->adapter->dropIndexByName($table2->getName(), 'twocolumnuniqueindex'); $this->assertFalse($table2->hasIndex(['fname', 'lname'])); @@ -849,9 +851,9 @@ public function testAddForeignKey() $fk = new ForeignKey(); $fk->setReferencedTable($refTable->getTable()) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']) - ->setName('fk1'); + ->setColumns(['ref_table_id']) + ->setReferencedColumns(['id']) + ->setName('fk1'); $this->adapter->addForeignKey($table->getTable(), $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'fk1')); @@ -1191,7 +1193,7 @@ public function testAddColumnComment() { $table = new Table('table1', [], $this->adapter); $table->addColumn('field1', 'string', ['comment' => $comment = 'Comments from column "field1"']) - ->save(); + ->save(); $resultComment = $this->adapter->getColumnComment('table1', 'field1'); @@ -1203,10 +1205,10 @@ public function testChangeColumnComment() { $table = new Table('table1', [], $this->adapter); $table->addColumn('field1', 'string', ['comment' => 'Comments from column "field1"']) - ->save(); + ->save(); $table->changeColumn('field1', 'string', ['comment' => $comment = 'New Comments from column "field1"']) - ->save(); + ->save(); $resultComment = $this->adapter->getColumnComment('table1', 'field1'); @@ -1218,10 +1220,10 @@ public function testRemoveColumnComment() { $table = new Table('table1', [], $this->adapter); $table->addColumn('field1', 'string', ['comment' => 'Comments from column "field1"']) - ->save(); + ->save(); $table->changeColumn('field1', 'string', ['comment' => 'null']) - ->save(); + ->save(); $resultComment = $this->adapter->getColumnComment('table1', 'field1'); @@ -1241,8 +1243,8 @@ public function testForignKeysArePropertlyEscaped() $foreign = new Table('sessions', ['id' => $sessionId], $this->adapter); $foreign->addColumn('user', 'integer') - ->addForeignKey('user', 'users', $userId) - ->create(); + ->addForeignKey('user', 'users', $userId) + ->create(); $this->assertTrue($foreign->hasForeignKey('user')); } @@ -1251,24 +1253,25 @@ public function testBulkInsertData() { $table = new Table('table1', [], $this->adapter); $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->save(); + ->addColumn('column2', 'integer') + ->save(); $table->insert([ - [ - 'column1' => 'value1', - 'column2' => 1, - ], - [ - 'column1' => 'value2', - 'column2' => 2, - ], - ]) - ->insert( - [ - 'column1' => 'value3', - 'column2' => 3, - ], - ); + [ + 'column1' => 'value1', + 'column2' => 1, + ], + [ + 'column1' => 'value2', + 'column2' => 2, + ], + ]) + ->insert( + [ + 'column1' => 'value3', + 'column2' => 3, + ] + ); + $this->adapter->bulkinsert($table->getTable(), $table->getData()); $table->reset(); @@ -1317,24 +1320,24 @@ public function testInsertData() { $table = new Table('table1', [], $this->adapter); $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->insert([ - [ - 'column1' => 'value1', - 'column2' => 1, - ], - [ - 'column1' => 'value2', - 'column2' => 2, - ], - ]) - ->insert( - [ - 'column1' => 'value3', - 'column2' => 3, - ], - ) - ->save(); + ->addColumn('column2', 'integer') + ->insert([ + [ + 'column1' => 'value1', + 'column2' => 1, + ], + [ + 'column1' => 'value2', + 'column2' => 2, + ], + ]) + ->insert( + [ + 'column1' => 'value3', + 'column2' => 3, + ] + ) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); @@ -1386,18 +1389,18 @@ public function testTruncateTable() { $table = new Table('table1', [], $this->adapter); $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->insert([ - [ - 'column1' => 'value1', - 'column2' => 1, - ], - [ - 'column1' => 'value2', - 'column2' => 2, - ], - ]) - ->save(); + ->addColumn('column2', 'integer') + ->insert([ + [ + 'column1' => 'value1', + 'column2' => 1, + ], + [ + 'column1' => 'value2', + 'column2' => 2, + ], + ]) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); $this->assertCount(2, $rows); @@ -1521,4 +1524,31 @@ public function testLiteralSupport() $this->assertCount(1, $columns); $this->assertEquals(Literal::from('smallmoney'), array_pop($columns)->getType()); } + + public function testIdentityInsert() + { + $table = new Table('table1', [], $this->adapter); + $table->addColumn('name', 'string') + ->save(); + $options = $table->getAdapter()->getOptions(); + $options['identity_insert'] = true; + $table->getAdapter()->setOptions($options); + $table->getAdapter()->beginTransaction(); + $table->insert([ + [ + 'id' => 20, + 'name' => 'test20', + ], + [ + 'id' => 50, + 'name' => 'test50', + ], + ])->saveData(); + $this->adapter->commitTransaction(); + + $countQuery = $this->adapter->query('SELECT * FROM table1'); + $res = $countQuery->fetchAll('assoc'); + $this->assertEquals(20, $res[0]['id']); + $this->assertEquals(50, $res[1]['id']); + } }