Skip to content

Commit

Permalink
Fix sql server paging problems (laravel#47763)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelharkes committed Jul 17, 2023
1 parent 28b0d9e commit 53b02b3
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 36 deletions.
34 changes: 1 addition & 33 deletions src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
Expand Up @@ -48,7 +48,7 @@ class SqlServerGrammar extends Grammar
public function compileSelect(Builder $query)
{
// An order by clause is required for SQL Server offset to function...
if ($query->offset && empty($query->orders)) {
if (($query->offset || $query->limit) && empty($query->orders)) {
$query->orders[] = ['sql' => '(SELECT 0)'];
}

Expand Down Expand Up @@ -266,38 +266,6 @@ protected function compileHavingBitwise($having)
return '('.$column.' '.$having['operator'].' '.$parameter.') != 0';
}

/**
* Move the order bindings to be after the "select" statement to account for an order by subquery.
*
* @param \Illuminate\Database\Query\Builder $query
* @return array
*/
protected function sortBindingsForSubqueryOrderBy($query)
{
return Arr::sort($query->bindings, function ($bindings, $key) {
return array_search($key, ['select', 'order', 'from', 'join', 'where', 'groupBy', 'having', 'union', 'unionOrder']);
});
}

/**
* Compile the limit / offset row constraint for a query.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileRowConstraint($query)
{
$start = (int) $query->offset + 1;

if ($query->limit > 0) {
$finish = (int) $query->offset + (int) $query->limit;

return "between {$start} and {$finish}";
}

return ">= {$start}";
}

/**
* Compile a delete statement without joins into SQL.
*
Expand Down
6 changes: 3 additions & 3 deletions tests/Database/DatabaseQueryBuilderTest.php
Expand Up @@ -2690,7 +2690,7 @@ public function testAggregateFunctions()
public function testSqlServerExists()
{
$builder = $this->getSqlServerBuilder();
$builder->getConnection()->shouldReceive('select')->once()->with('select top 1 1 [exists] from [users]', [], true)->andReturn([['exists' => 1]]);
$builder->getConnection()->shouldReceive('select')->once()->with('select top 1 1 [exists] from [users] order by (SELECT 0)', [], true)->andReturn([['exists' => 1]]);
$results = $builder->from('users')->exists();
$this->assertTrue($results);
}
Expand Down Expand Up @@ -3856,7 +3856,7 @@ public function testSqlServerLimitsAndOffsets()
{
$builder = $this->getSqlServerBuilder();
$builder->select('*')->from('users')->take(10);
$this->assertSame('select top 10 * from [users]', $builder->toSql());
$this->assertSame('select top 10 * from [users] order by (SELECT 0)', $builder->toSql());

$builder = $this->getSqlServerBuilder();
$builder->select('*')->from('users')->skip(10)->orderBy('email', 'desc');
Expand All @@ -3875,7 +3875,7 @@ public function testSqlServerLimitsAndOffsets()
return $query->select('created_at')->from('logins')->where('users.name', 'nameBinding')->whereColumn('user_id', 'users.id')->limit(1);
};
$builder->select('*')->from('users')->where('email', 'emailBinding')->orderBy($subQuery)->skip(10)->take(10);
$this->assertSame('select * from [users] where [email] = ? order by (select top 1 [created_at] from [logins] where [users].[name] = ? and [user_id] = [users].[id]) asc offset 10 rows fetch next 10 rows only', $builder->toSql());
$this->assertSame('select * from [users] where [email] = ? order by (select top 1 [created_at] from [logins] where [users].[name] = ? and [user_id] = [users].[id] order by (SELECT 0)) asc offset 10 rows fetch next 10 rows only', $builder->toSql());
$this->assertEquals(['emailBinding', 'nameBinding'], $builder->getBindings());

$builder = $this->getSqlServerBuilder();
Expand Down

0 comments on commit 53b02b3

Please sign in to comment.