Skip to content

Commit

Permalink
Refactor code for merge packages
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed Mar 16, 2022
1 parent 0d1e3aa commit a8104ae
Show file tree
Hide file tree
Showing 31 changed files with 439 additions and 381 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
"Staudenmeir\\EloquentEagerLimit\\Tests\\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable" : true
"prefer-stable": true
}
53 changes: 2 additions & 51 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,9 @@
namespace Staudenmeir\EloquentEagerLimit;

use Illuminate\Database\Query\Builder as Base;
use Staudenmeir\EloquentEagerLimit\Traits\BuildsGroupLimitQueries;

class Builder extends Base
{
/**
* The maximum number of records to return per group.
*
* @var array
*/
public $groupLimit;

/**
* Add a "group limit" clause to the query.
*
* @param int $value
* @param string $column
* @return $this
*/
public function groupLimit($value, $column)
{
if ($value >= 0) {
$this->groupLimit = compact('value', 'column');
}

return $this;
}

/**
* Execute the query as a "select" statement.
*
* @param array $columns
* @return \Illuminate\Support\Collection
*/
public function get($columns = ['*'])
{
$items = parent::get($columns);

if (!$this->groupLimit) {
return $items;
}

$column = last(explode('.', $this->groupLimit['column']));

$keys = [
'laravel_row',
'@laravel_partition := '.$this->grammar->wrap($column),
'@laravel_partition := '.$this->grammar->wrap('pivot_'.$column),
];

foreach ($items as $item) {
unset($item->{$keys[0]}, $item->{$keys[1]}, $item->{$keys[2]});
}

return $items;
}
use BuildsGroupLimitQueries;
}
83 changes: 2 additions & 81 deletions src/Grammars/MySqlGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,89 +2,10 @@

namespace Staudenmeir\EloquentEagerLimit\Grammars;

use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Grammars\MySqlGrammar as Base;
use Illuminate\Support\Str;
use PDO;
use Staudenmeir\EloquentEagerLimit\Grammars\Traits\CompilesMySqlGroupLimit;

class MySqlGrammar extends Base
{
use CompilesGroupLimit {
compileGroupLimit as compileGroupLimitParent;
}

/**
* Determine whether to use a group limit clause for MySQL < 8.0.
*
* @param \Illuminate\Database\Query\Builder $query
* @return bool
*/
public function useLegacyGroupLimit(Builder $query)
{
$version = $query->getConnection()->getReadPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

return version_compare($version, '8.0.11') < 0 && !Str::contains($version, 'MariaDB');
}

/**
* Compile a group limit clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileGroupLimit(Builder $query)
{
return $this->useLegacyGroupLimit($query)
? $this->compileLegacyGroupLimit($query)
: $this->compileGroupLimitParent($query);
}

/**
* Compile a group limit clause for MySQL < 8.0.
*
* Derived from https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileLegacyGroupLimit(Builder $query)
{
$limit = (int) $query->groupLimit['value'];

$offset = $query->offset;

if (isset($offset)) {
$limit += (int) $offset;

$query->offset = null;
}

$column = last(explode('.', $query->groupLimit['column']));

$column = $this->wrap($column);

$partition = ', @laravel_row := if(@laravel_partition = '.$column.', @laravel_row + 1, 1) as laravel_row';

$partition .= ', @laravel_partition := '.$column;

$orders = (array) $query->orders;

array_unshift($orders, ['column' => $query->groupLimit['column'], 'direction' => 'asc']);

$query->orders = $orders;

$components = $this->compileComponents($query);

$sql = $this->concatenate($components);

$from = '(select @laravel_row := 0, @laravel_partition := 0) as laravel_vars, ('.$sql.') as laravel_table';

$sql = 'select laravel_table.*'.$partition.' from '.$from.' having laravel_row <= '.$limit;

if (isset($offset)) {
$sql .= ' and laravel_row > '.(int) $offset;
}

return $sql.' order by laravel_row';
}
use CompilesMySqlGroupLimit;
}
3 changes: 2 additions & 1 deletion src/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Staudenmeir\EloquentEagerLimit\Grammars;

use Illuminate\Database\Query\Grammars\PostgresGrammar as Base;
use Staudenmeir\EloquentEagerLimit\Grammars\Traits\CompilesPostgresGroupLimit;

class PostgresGrammar extends Base
{
use CompilesGroupLimit;
use CompilesPostgresGroupLimit;
}
26 changes: 2 additions & 24 deletions src/Grammars/SQLiteGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,10 @@

namespace Staudenmeir\EloquentEagerLimit\Grammars;

use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Grammars\SQLiteGrammar as Base;
use PDO;
use Staudenmeir\EloquentEagerLimit\Grammars\Traits\CompilesSQLiteGroupLimit;

class SQLiteGrammar extends Base
{
use CompilesGroupLimit {
compileGroupLimit as compileGroupLimitParent;
}

/**
* Compile a group limit clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileGroupLimit(Builder $query)
{
$version = $query->getConnection()->getReadPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

if (version_compare($version, '3.25.0') >= 0) {
return $this->compileGroupLimitParent($query);
}

$query->groupLimit = null;

return $this->compileSelect($query);
}
use CompilesSQLiteGroupLimit;
}
21 changes: 2 additions & 19 deletions src/Grammars/SqlServerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,9 @@
namespace Staudenmeir\EloquentEagerLimit\Grammars;

use Illuminate\Database\Query\Grammars\SqlServerGrammar as Base;
use Staudenmeir\EloquentEagerLimit\Grammars\Traits\CompilesSqlServerGroupLimit;

class SqlServerGrammar extends Base
{
use CompilesGroupLimit {
compileRowNumber as compileRowNumberParent;
}

/**
* Compile a row number clause.
*
* @param string $partition
* @param string $orders
* @return string
*/
protected function compileRowNumber($partition, $orders)
{
if (empty($orders)) {
$orders = 'order by (select 0)';
}

return $this->compileRowNumberParent($partition, $orders);
}
use CompilesSqlServerGroupLimit;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Staudenmeir\EloquentEagerLimit\Grammars;
namespace Staudenmeir\EloquentEagerLimit\Grammars\Traits;

use Illuminate\Database\Query\Builder;

Expand Down
89 changes: 89 additions & 0 deletions src/Grammars/Traits/CompilesMySqlGroupLimit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Staudenmeir\EloquentEagerLimit\Grammars\Traits;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Str;
use PDO;

trait CompilesMySqlGroupLimit
{
use CompilesGroupLimit {
compileGroupLimit as compileGroupLimitParent;
}

/**
* Determine whether to use a group limit clause for MySQL < 8.0.
*
* @param \Illuminate\Database\Query\Builder $query
* @return bool
*/
public function useLegacyGroupLimit(Builder $query)
{
$version = $query->getConnection()->getReadPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

return version_compare($version, '8.0.11') < 0 && !Str::contains($version, 'MariaDB');
}

/**
* Compile a group limit clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileGroupLimit(Builder $query)
{
return $this->useLegacyGroupLimit($query)
? $this->compileLegacyGroupLimit($query)
: $this->compileGroupLimitParent($query);
}

/**
* Compile a group limit clause for MySQL < 8.0.
*
* Derived from https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileLegacyGroupLimit(Builder $query)
{
$limit = (int) $query->groupLimit['value'];

$offset = $query->offset;

if (isset($offset)) {
$limit += (int) $offset;

$query->offset = null;
}

$column = last(explode('.', $query->groupLimit['column']));

$column = $this->wrap($column);

$partition = ', @laravel_row := if(@laravel_partition = '.$column.', @laravel_row + 1, 1) as laravel_row';

$partition .= ', @laravel_partition := '.$column;

$orders = (array) $query->orders;

array_unshift($orders, ['column' => $query->groupLimit['column'], 'direction' => 'asc']);

$query->orders = $orders;

$components = $this->compileComponents($query);

$sql = $this->concatenate($components);

$from = '(select @laravel_row := 0, @laravel_partition := 0) as laravel_vars, ('.$sql.') as laravel_table';

$sql = 'select laravel_table.*'.$partition.' from '.$from.' having laravel_row <= '.$limit;

if (isset($offset)) {
$sql .= ' and laravel_row > '.(int) $offset;
}

return $sql.' order by laravel_row';
}
}
8 changes: 8 additions & 0 deletions src/Grammars/Traits/CompilesPostgresGroupLimit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Staudenmeir\EloquentEagerLimit\Grammars\Traits;

trait CompilesPostgresGroupLimit
{
use CompilesGroupLimit;
}
32 changes: 32 additions & 0 deletions src/Grammars/Traits/CompilesSQLiteGroupLimit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Staudenmeir\EloquentEagerLimit\Grammars\Traits;

use Illuminate\Database\Query\Builder;
use PDO;

trait CompilesSQLiteGroupLimit
{
use CompilesGroupLimit {
compileGroupLimit as compileGroupLimitParent;
}

/**
* Compile a group limit clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileGroupLimit(Builder $query)
{
$version = $query->getConnection()->getReadPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);

if (version_compare($version, '3.25.0') >= 0) {
return $this->compileGroupLimitParent($query);
}

$query->groupLimit = null;

return $this->compileSelect($query);
}
}
Loading

0 comments on commit a8104ae

Please sign in to comment.