Skip to content

Commit 200fcdb

Browse files
committed
improve SQL Server last insert id retrieval
1 parent 1d2055b commit 200fcdb

File tree

3 files changed

+29
-31
lines changed

3 files changed

+29
-31
lines changed

src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,21 @@ public function compileExists(Builder $query)
323323
return $this->compileSelect($existsQuery->selectRaw('1 [exists]')->limit(1));
324324
}
325325

326+
/**
327+
* Compile an insert and get ID statement into SQL.
328+
*
329+
* @param \Illuminate\Database\Query\Builder $query
330+
* @param array $values
331+
* @param string $sequence
332+
* @return string
333+
*/
334+
public function compileInsertGetId(Builder $query, $values, $sequence)
335+
{
336+
$sql = $this->compileInsert($query, $values);
337+
338+
return 'set nocount on;'.$sql.';select scope_identity() as '.$this->wrap($sequence ?: 'id');
339+
}
340+
326341
/**
327342
* Compile an update statement with joins into SQL.
328343
*

src/Illuminate/Database/Query/Processors/SqlServerProcessor.php

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace Illuminate\Database\Query\Processors;
44

5-
use Exception;
6-
use Illuminate\Database\Connection;
75
use Illuminate\Database\Query\Builder;
86

97
class SqlServerProcessor extends Processor
@@ -21,38 +19,15 @@ public function processInsertGetId(Builder $query, $sql, $values, $sequence = nu
2119
{
2220
$connection = $query->getConnection();
2321

24-
$connection->insert($sql, $values);
22+
$connection->recordsHaveBeenModified();
2523

26-
if ($connection->getConfig('odbc') === true) {
27-
$id = $this->processInsertGetIdForOdbc($connection);
28-
} else {
29-
$id = $connection->getPdo()->lastInsertId();
30-
}
24+
$result = $connection->selectFromWriteConnection($sql, $values)[0];
3125

32-
return is_numeric($id) ? (int) $id : $id;
33-
}
26+
$sequence = $sequence ?: 'id';
3427

35-
/**
36-
* Process an "insert get ID" query for ODBC.
37-
*
38-
* @param \Illuminate\Database\Connection $connection
39-
* @return int
40-
*
41-
* @throws \Exception
42-
*/
43-
protected function processInsertGetIdForOdbc(Connection $connection)
44-
{
45-
$result = $connection->selectFromWriteConnection(
46-
'SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS int) AS insertid'
47-
);
48-
49-
if (! $result) {
50-
throw new Exception('Unable to retrieve lastInsertID for ODBC.');
51-
}
28+
$id = is_object($result) ? $result->{$sequence} : $result[$sequence];
5229

53-
$row = $result[0];
54-
55-
return is_object($row) ? $row->insertid : $row['insertid'];
30+
return is_numeric($id) ? (int) $id : $id;
5631
}
5732

5833
/**

tests/Database/DatabaseQueryBuilderTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2130,7 +2130,7 @@ public function testInsertGetIdWithEmptyValues()
21302130
$builder->from('users')->insertGetId([]);
21312131

21322132
$builder = $this->getSqlServerBuilder();
2133-
$builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into [users] default values', [], null);
2133+
$builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'set nocount on;insert into [users] default values;select scope_identity() as [id]', [], null);
21342134
$builder->from('users')->insertGetId([]);
21352135
}
21362136

@@ -2474,6 +2474,14 @@ public function testPostgresInsertGetId()
24742474
$this->assertEquals(1, $result);
24752475
}
24762476

2477+
public function testSqlServerInsertGetId()
2478+
{
2479+
$builder = $this->getSqlServerBuilder();
2480+
$builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'set nocount on;insert into [users] ([email]) values (?);select scope_identity() as [id]', ['foo'], 'id')->andReturn(1);
2481+
$result = $builder->from('users')->insertGetId(['email' => 'foo'], 'id');
2482+
$this->assertEquals(1, $result);
2483+
}
2484+
24772485
public function testMySqlWrapping()
24782486
{
24792487
$builder = $this->getMySqlBuilder();

0 commit comments

Comments
 (0)