Skip to content

Commit

Permalink
[6.x] SQL Server fix backport (#33453)
Browse files Browse the repository at this point in the history
* improve SQL Server last insert id retrieval

* formatting

Co-authored-by: Rodrigo Pedra Brum <[email protected]>
Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
3 people authored Jul 7, 2020
1 parent 7e8d08e commit b35452d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 31 deletions.
13 changes: 13 additions & 0 deletions src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ public function compileExists(Builder $query)
return $this->compileSelect($existsQuery->selectRaw('1 [exists]')->limit(1));
}

/**
* Compile an insert and get ID statement into SQL.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $values
* @param string $sequence
* @return string
*/
public function compileInsertGetId(Builder $query, $values, $sequence)
{
return 'set nocount on;'.$this->compileInsert($query, $values).';select scope_identity() as '.$this->wrap($sequence ?: 'id');
}

/**
* Compile an update statement with joins into SQL.
*
Expand Down
35 changes: 5 additions & 30 deletions src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Illuminate\Database\Query\Processors;

use Exception;
use Illuminate\Database\Connection;
use Illuminate\Database\Query\Builder;

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

$connection->insert($sql, $values);
$connection->recordsHaveBeenModified();

if ($connection->getConfig('odbc') === true) {
$id = $this->processInsertGetIdForOdbc($connection);
} else {
$id = $connection->getPdo()->lastInsertId();
}
$result = $connection->selectFromWriteConnection($sql, $values)[0];

return is_numeric($id) ? (int) $id : $id;
}
$sequence = $sequence ?: 'id';

/**
* Process an "insert get ID" query for ODBC.
*
* @param \Illuminate\Database\Connection $connection
* @return int
*
* @throws \Exception
*/
protected function processInsertGetIdForOdbc(Connection $connection)
{
$result = $connection->selectFromWriteConnection(
'SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS int) AS insertid'
);

if (! $result) {
throw new Exception('Unable to retrieve lastInsertID for ODBC.');
}
$id = is_object($result) ? $result->{$sequence} : $result[$sequence];

$row = $result[0];

return is_object($row) ? $row->insertid : $row['insertid'];
return is_numeric($id) ? (int) $id : $id;
}

/**
Expand Down
10 changes: 9 additions & 1 deletion tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2071,7 +2071,7 @@ public function testInsertGetIdWithEmptyValues()
$builder->from('users')->insertGetId([]);

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

Expand Down Expand Up @@ -2410,6 +2410,14 @@ public function testPostgresInsertGetId()
$this->assertEquals(1, $result);
}

public function testSqlServerInsertGetId()
{
$builder = $this->getSqlServerBuilder();
$builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'set nocount on;insert into [users] ([email]) values (?);select scope_identity() as [id]', ['foo'], 'id')->andReturn(1);
$result = $builder->from('users')->insertGetId(['email' => 'foo'], 'id');
$this->assertEquals(1, $result);
}

public function testMySqlWrapping()
{
$builder = $this->getMySqlBuilder();
Expand Down

0 comments on commit b35452d

Please sign in to comment.