From 71befb2b0690b9dcf93271d740251a59c1c877a9 Mon Sep 17 00:00:00 2001 From: Mathieu FERRE Date: Fri, 12 Apr 2024 15:16:03 +0200 Subject: [PATCH 1/5] Optimize simple queries --- src/QueryDataTable.php | 169 +++++++++++++++--------------- tests/Unit/QueryDataTableTest.php | 44 +++++++- 2 files changed, 124 insertions(+), 89 deletions(-) diff --git a/src/QueryDataTable.php b/src/QueryDataTable.php index b4406c2d..f60fb639 100644 --- a/src/QueryDataTable.php +++ b/src/QueryDataTable.php @@ -83,7 +83,7 @@ class QueryDataTable extends DataTableAbstract public function __construct(protected QueryBuilder $query) { $this->request = app('datatables.request'); - $this->config = app('datatables.config'); + $this->config = app('datatables.config'); $this->columns = $this->query->getColumns(); if ($this->config->isDebugging()) { @@ -102,11 +102,11 @@ public function getConnection(): Connection /** * Can the DataTable engine be created with these parameters. * - * @param mixed $source + * @param mixed $source */ public static function canCreate($source): bool { - return $source instanceof QueryBuilder && ! ($source instanceof EloquentBuilder); + return $source instanceof QueryBuilder && !($source instanceof EloquentBuilder); } /** @@ -117,9 +117,9 @@ public static function canCreate($source): bool public function make(bool $mDataSupport = true): JsonResponse { try { - $results = $this->prepareQuery()->results(); + $results = $this->prepareQuery()->results(); $processed = $this->processResults($results, $mDataSupport); - $data = $this->transform($results, $processed); + $data = $this->transform($results, $processed); return $this->render($data); } catch (\Exception $exception) { @@ -144,7 +144,7 @@ public function results(): Collection */ public function prepareQuery(): static { - if (! $this->prepared) { + if (!$this->prepared) { $this->totalRecords = $this->totalCount(); $this->filterRecords(); @@ -174,34 +174,35 @@ public function prepareCountQuery(): QueryBuilder if ($this->isComplexQuery($builder)) { $builder->select(DB::raw('1 as dt_row_count')); - if ($this->ignoreSelectInCountQuery || ! $this->isComplexQuery($builder)) { + $clone = $builder->clone(); + $clone->setBindings([]); + $clone->wheres = []; + if ($this->isComplexQuery($clone)) { + if (!$this->ignoreSelectInCountQuery) { + $builder = clone $this->query; + } + return $this->getConnection() - ->query() - ->fromRaw('('.$builder->toSql().') count_row_table') - ->setBindings($builder->getBindings()); + ->query() + ->fromRaw('(' . $builder->toSql() . ') count_row_table') + ->setBindings($builder->getBindings()); } - - $builder = clone $this->query; - - return $this->getConnection() - ->query() - ->fromRaw('('.$builder->toSql().') count_row_table') - ->setBindings($builder->getBindings()); } + $row_count = $this->wrap('row_count'); + $builder->select($this->getConnection()->raw("'1' as {$row_count}")); - $row_count = $this->wrap('row_count'); - $builder->select($this->getConnection()->raw("'1' as {$row_count}")); - if (! $this->keepSelectBindings) { + if (!$this->keepSelectBindings) { $builder->setBindings([], 'select'); } + return $builder; } /** * Check if builder query uses complex sql. * - * @param QueryBuilder|EloquentBuilder $query + * @param QueryBuilder|EloquentBuilder $query */ protected function isComplexQuery($query): bool { @@ -269,7 +270,7 @@ public function columnSearch(): void continue; } - if (! $this->request->isColumnSearchable($index) || $this->isBlacklisted($column) && ! $this->hasFilterColumn($column)) { + if (!$this->request->isColumnSearchable($index) || $this->isBlacklisted($column) && !$this->hasFilterColumn($column)) { continue; } @@ -277,7 +278,7 @@ public function columnSearch(): void $keyword = $this->getColumnSearchKeyword($index, true); $this->applyFilterColumn($this->getBaseQueryBuilder(), $column, $keyword); } else { - $column = $this->resolveRelationColumn($column); + $column = $this->resolveRelationColumn($column); $keyword = $this->getColumnSearchKeyword($index); $this->compileColumnSearch($index, $column, $keyword); } @@ -321,11 +322,11 @@ protected function getColumnNameByIndex(int $index): string /** * Apply filterColumn api search. * - * @param QueryBuilder $query + * @param QueryBuilder $query */ protected function applyFilterColumn($query, string $columnName, string $keyword, string $boolean = 'and'): void { - $query = $this->getBaseQueryBuilder($query); + $query = $this->getBaseQueryBuilder($query); $callback = $this->columnDef['filter'][$columnName]['method']; if ($this->query instanceof EloquentBuilder) { @@ -344,11 +345,11 @@ protected function applyFilterColumn($query, string $columnName, string $keyword /** * Get the base query builder instance. * - * @param QueryBuilder|EloquentBuilder|null $instance + * @param QueryBuilder|EloquentBuilder|null $instance */ protected function getBaseQueryBuilder($instance = null): QueryBuilder { - if (! $instance) { + if (!$instance) { $instance = $this->query; } @@ -396,20 +397,20 @@ protected function regexColumnSearch(string $column, string $keyword): void switch ($this->getConnection()->getDriverName()) { case 'oracle': - $sql = ! $this->config->isCaseInsensitive() - ? 'REGEXP_LIKE( '.$column.' , ? )' - : 'REGEXP_LIKE( LOWER('.$column.') , ?, \'i\' )'; + $sql = !$this->config->isCaseInsensitive() + ? 'REGEXP_LIKE( ' . $column . ' , ? )' + : 'REGEXP_LIKE( LOWER(' . $column . ') , ?, \'i\' )'; break; case 'pgsql': $column = $this->castColumn($column); - $sql = ! $this->config->isCaseInsensitive() ? $column.' ~ ?' : $column.' ~* ? '; + $sql = !$this->config->isCaseInsensitive() ? $column . ' ~ ?' : $column . ' ~* ? '; break; default: - $sql = ! $this->config->isCaseInsensitive() - ? $column.' REGEXP ?' - : 'LOWER('.$column.') REGEXP ?'; + $sql = !$this->config->isCaseInsensitive() + ? $column . ' REGEXP ?' + : 'LOWER(' . $column . ') REGEXP ?'; $keyword = Str::lower($keyword); } @@ -422,8 +423,8 @@ protected function regexColumnSearch(string $column, string $keyword): void protected function castColumn(string $column): string { return match ($this->getConnection()->getDriverName()) { - 'pgsql' => 'CAST('.$column.' as TEXT)', - 'firebird' => 'CAST('.$column.' as VARCHAR(255))', + 'pgsql' => 'CAST(' . $column . ' as TEXT)', + 'firebird' => 'CAST(' . $column . ' as VARCHAR(255))', default => $column, }; } @@ -431,39 +432,39 @@ protected function castColumn(string $column): string /** * Compile query builder where clause depending on configurations. * - * @param QueryBuilder|EloquentBuilder $query + * @param QueryBuilder|EloquentBuilder $query */ protected function compileQuerySearch($query, string $column, string $keyword, string $boolean = 'or'): void { $column = $this->addTablePrefix($query, $column); $column = $this->castColumn($column); - $sql = $column.' LIKE ?'; + $sql = $column . ' LIKE ?'; if ($this->config->isCaseInsensitive()) { - $sql = 'LOWER('.$column.') LIKE ?'; + $sql = 'LOWER(' . $column . ') LIKE ?'; } - $query->{$boolean.'WhereRaw'}($sql, [$this->prepareKeyword($keyword)]); + $query->{$boolean . 'WhereRaw'}($sql, [$this->prepareKeyword($keyword)]); } /** * Patch for fix about ambiguous field. * Ambiguous field error will appear when query use join table and search with keyword. * - * @param QueryBuilder|EloquentBuilder $query + * @param QueryBuilder|EloquentBuilder $query */ protected function addTablePrefix($query, string $column): string { - if (! str_contains($column, '.')) { - $q = $this->getBaseQueryBuilder($query); + if (!str_contains($column, '.')) { + $q = $this->getBaseQueryBuilder($query); $from = $q->from ?? ''; - if (! $from instanceof Expression) { - if (str_contains((string) $from, ' as ')) { - $from = explode(' as ', (string) $from)[1]; + if (!$from instanceof Expression) { + if (str_contains((string)$from, ' as ')) { + $from = explode(' as ', (string)$from)[1]; } - $column = $from.'.'.$column; + $column = $from . '.' . $column; } } @@ -497,7 +498,7 @@ protected function prepareKeyword(string $keyword): string /** * Add custom filter handler for the give column. * - * @param string $column + * @param string $column * @return $this */ public function filterColumn($column, callable $callback): static @@ -510,8 +511,8 @@ public function filterColumn($column, callable $callback): static /** * Order each given columns versus the given custom sql. * - * @param string $sql - * @param array $bindings + * @param string $sql + * @param array $bindings * @return $this */ public function orderColumns(array $columns, $sql, $bindings = []): static @@ -526,9 +527,9 @@ public function orderColumns(array $columns, $sql, $bindings = []): static /** * Override default column ordering. * - * @param string $column - * @param string|\Closure $sql - * @param array $bindings + * @param string $column + * @param string|\Closure $sql + * @param array $bindings * @return $this * * @internal string $1 Special variable that returns the requested order direction of the column. @@ -557,7 +558,7 @@ public function orderByNullsLast(): static */ public function paging(): void { - $start = $this->request->start(); + $start = $this->request->start(); $length = $this->request->length(); $limit = $length > 0 ? $length : 10; @@ -586,9 +587,9 @@ public function limit(callable $callback): static /** * Add column in collection. * - * @param string $name - * @param string|callable $content - * @param bool|int $order + * @param string $name + * @param string|callable $content + * @param bool|int $order * @return $this */ public function addColumn($name, $content, $order = false): static @@ -648,7 +649,7 @@ protected function defaultOrdering(): void return $orderable; }) - ->reject(fn ($orderable) => $this->isBlacklisted($orderable['name']) && ! $this->hasOrderColumn($orderable['name'])) + ->reject(fn($orderable) => $this->isBlacklisted($orderable['name']) && !$this->hasOrderColumn($orderable['name'])) ->each(function ($orderable) { $column = $this->resolveRelationColumn($orderable['name']); @@ -658,8 +659,8 @@ protected function defaultOrdering(): void $this->applyOrderColumn($column, $orderable); } else { $nullsLastSql = $this->getNullsLastSql($column, $orderable['direction']); - $normalSql = $this->wrap($column).' '.$orderable['direction']; - $sql = $this->nullsLast ? $nullsLastSql : $normalSql; + $normalSql = $this->wrap($column) . ' ' . $orderable['direction']; + $sql = $this->nullsLast ? $nullsLastSql : $normalSql; $this->query->orderByRaw($sql); } }); @@ -686,7 +687,7 @@ protected function applyOrderColumn(string $column, array $orderable): void if (is_callable($sql)) { call_user_func($sql, $this->query, $orderable['direction']); } else { - $sql = str_replace('$1', $orderable['direction'], (string) $sql); + $sql = str_replace('$1', $orderable['direction'], (string)$sql); $bindings = $this->columnDef['order'][$column]['bindings']; $this->query->orderByRaw($sql, $bindings); } @@ -695,8 +696,8 @@ protected function applyOrderColumn(string $column, array $orderable): void /** * Get NULLS LAST SQL. * - * @param string $column - * @param string $direction + * @param string $column + * @param string $direction * * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface @@ -725,9 +726,9 @@ protected function globalSearch(string $keyword): void $this->query->where(function ($query) use ($keyword) { collect($this->request->searchableColumnIndex()) - ->map(fn ($index) => $this->getColumnName($index)) + ->map(fn($index) => $this->getColumnName($index)) ->filter() - ->reject(fn ($column) => $this->isBlacklisted($column) && ! $this->hasFilterColumn($column)) + ->reject(fn($column) => $this->isBlacklisted($column) && !$this->hasFilterColumn($column)) ->each(function ($column) use ($keyword, $query) { if ($this->hasFilterColumn($column)) { $this->applyFilterColumn($query, $column, $keyword, 'or'); @@ -742,7 +743,7 @@ protected function globalSearch(string $keyword): void * Perform multi-term search by splitting keyword into * individual words and searches for each of them. * - * @param string $keyword + * @param string $keyword */ protected function smartGlobalSearch($keyword): void { @@ -767,7 +768,7 @@ protected function showDebugger(array $output): array }); $output['queries'] = $query_log; - $output['input'] = $this->request->all(); + $output['input'] = $this->request->all(); return $output; } @@ -838,17 +839,17 @@ public function ordering(): void public function enableScoutSearch(string $model, int $max_hits = 1000): static { $scout_model = new $model; - if (! class_exists($model) || ! ($scout_model instanceof Model)) { + if (!class_exists($model) || !($scout_model instanceof Model)) { throw new \Exception("$model must be an Eloquent Model."); } - if (! method_exists($scout_model, 'searchableAs') || ! method_exists($scout_model, 'getScoutKeyName')) { + if (!method_exists($scout_model, 'searchableAs') || !method_exists($scout_model, 'getScoutKeyName')) { throw new \Exception("$model must use the Searchable trait."); } - $this->scoutModel = $scout_model; + $this->scoutModel = $scout_model; $this->scoutMaxHits = $max_hits; - $this->scoutIndex = $this->scoutModel->searchableAs(); - $this->scoutKey = $this->scoutModel->getScoutKeyName(); + $this->scoutIndex = $this->scoutModel->searchableAs(); + $this->scoutKey = $this->scoutModel->getScoutKeyName(); return $this; } @@ -916,13 +917,13 @@ protected function applyFixedOrderingToQuery(string $keyName, array $orderedKeys $driverName = $connection->getDriverName(); // Escape keyName and orderedKeys - $keyName = $connection->getQueryGrammar()->wrap($keyName); + $keyName = $connection->getQueryGrammar()->wrap($keyName); $orderedKeys = collect($orderedKeys) - ->map(fn ($value) => $connection->escape($value)); + ->map(fn($value) => $connection->escape($value)); switch ($driverName) { case 'mysql': - $this->query->orderByRaw("FIELD($keyName, ".$orderedKeys->implode(',').')'); + $this->query->orderByRaw("FIELD($keyName, " . $orderedKeys->implode(',') . ')'); return true; @@ -932,7 +933,7 @@ protected function applyFixedOrderingToQuery(string $keyName, array $orderedKeys 'CASE ' . $orderedKeys - ->map(fn ($value, $index) => "WHEN $keyName=$value THEN $index") + ->map(fn($value, $index) => "WHEN $keyName=$value THEN $index") ->implode(' ') . ' END' @@ -946,7 +947,7 @@ protected function applyFixedOrderingToQuery(string $keyName, array $orderedKeys "CASE $keyName " . $orderedKeys - ->map(fn ($value, $index) => "WHEN $value THEN $index") + ->map(fn($value, $index) => "WHEN $value THEN $index") ->implode(' ') . ' END' @@ -967,7 +968,7 @@ protected function applyFixedOrderingToQuery(string $keyName, array $orderedKeys */ protected function performScoutSearch(string $searchKeyword, mixed $searchFilters = []): array { - if (! class_exists(\Laravel\Scout\EngineManager::class)) { + if (!class_exists(\Laravel\Scout\EngineManager::class)) { throw new \Exception('Laravel Scout is not installed.'); } $engine = app(\Laravel\Scout\EngineManager::class)->engine(); @@ -977,9 +978,9 @@ protected function performScoutSearch(string $searchKeyword, mixed $searchFilter $search_results = $engine ->index($this->scoutIndex) ->rawSearch($searchKeyword, [ - 'limit' => $this->scoutMaxHits, + 'limit' => $this->scoutMaxHits, 'attributesToRetrieve' => [$this->scoutKey], - 'filter' => $searchFilters, + 'filter' => $searchFilters, ]); /** @var array> $hits */ @@ -993,11 +994,11 @@ protected function performScoutSearch(string $searchKeyword, mixed $searchFilter $algolia = $engine->initIndex($this->scoutIndex); $search_results = $algolia->search($searchKeyword, [ - 'offset' => 0, - 'length' => $this->scoutMaxHits, - 'attributesToRetrieve' => [$this->scoutKey], + 'offset' => 0, + 'length' => $this->scoutMaxHits, + 'attributesToRetrieve' => [$this->scoutKey], 'attributesToHighlight' => [], - 'filters' => $searchFilters, + 'filters' => $searchFilters, ]); /** @var array> $hits */ diff --git a/tests/Unit/QueryDataTableTest.php b/tests/Unit/QueryDataTableTest.php index 0fee6802..f834a45a 100644 --- a/tests/Unit/QueryDataTableTest.php +++ b/tests/Unit/QueryDataTableTest.php @@ -74,7 +74,29 @@ public function test_complex_query_can_ignore_select_in_count() $this->assertEquals(20, $dataTable->count()); } - public function test_simple_queries_with_complexe_select_are_wrapped_without_selects() + public function test_complexe_queries_with_complexe_select_are_wrapped_without_selects() + { + /** @var \Yajra\DataTables\QueryDataTable $dataTable */ + $dataTable = app('datatables')->of( + DB::table('users') + ->select(['users.*', DB::raw('count(*) as posts_count')]) + ->addSelect([ + 'last_post_id' => DB::table('posts') + ->whereColumn('posts.user_id', 'users.id') + ->orderBy('created_at') + ->select('id'), + ]) + ->join('posts', 'posts.user_id', 'users.id') + ->groupBy('users.id') + ); + + + $this->assertQueryWrapped(true, $dataTable->prepareCountQuery()); + $this->assertQueryHasNoSelect(false, $dataTable->prepareCountQuery()); + $this->assertEquals(20, $dataTable->count()); + } + + public function test_simple_queries_with_complexe_select_are_not_wrapped() { /** @var \Yajra\DataTables\QueryDataTable $dataTable */ $dataTable = app('datatables')->of( @@ -88,8 +110,8 @@ public function test_simple_queries_with_complexe_select_are_wrapped_without_sel ]) ); - $this->assertQueryWrapped(true, $dataTable->prepareCountQuery()); - $this->assertQueryHasNoSelect(true, $dataTable->prepareCountQuery()); + $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); + $this->assertQueryIsFromSub(false, $dataTable->prepareCountQuery()); $this->assertEquals(20, $dataTable->count()); } @@ -134,8 +156,20 @@ protected function assertQueryWrapped($expected, $query) */ public function assertQueryHasNoSelect($expected, $query) { - $sql = $query->toSql(); + $sql = $query->select(DB::raw('count(*)'))->toSql(); + + $this->assertSame($expected, Str::startsWith($sql, 'select count(*) from (select 1 as dt_row_count from'), "'{$sql}' has select"); + } + + /** + * @param $expected bool + * @param $query \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder + * @return void + */ + public function assertQueryIsFromSub($expected, $query) + { + $sql = $query->select(DB::raw('count(*)'))->toSql(); - $this->assertSame($expected, Str::startsWith($sql, 'select * from (select 1 as dt_row_count from'), "'{$sql}' is not wrapped"); + $this->assertSame($expected, Str::startsWith($sql, 'select count(*) from (select'), "'{$sql}' is from sub query"); } } From 7bdd78471f112460139577c35692f4653282d0f1 Mon Sep 17 00:00:00 2001 From: Mathieu FERRE Date: Fri, 12 Apr 2024 15:25:56 +0200 Subject: [PATCH 2/5] Update QueryDataTableTest.php --- tests/Unit/QueryDataTableTest.php | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tests/Unit/QueryDataTableTest.php b/tests/Unit/QueryDataTableTest.php index f834a45a..988c3ae1 100644 --- a/tests/Unit/QueryDataTableTest.php +++ b/tests/Unit/QueryDataTableTest.php @@ -4,6 +4,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use Yajra\DataTables\Tests\Models\Post; use Yajra\DataTables\Tests\Models\User; use Yajra\DataTables\Tests\TestCase; @@ -111,10 +112,27 @@ public function test_simple_queries_with_complexe_select_are_not_wrapped() ); $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); - $this->assertQueryIsFromSub(false, $dataTable->prepareCountQuery()); $this->assertEquals(20, $dataTable->count()); } + public function test_simple_queries_with_complexe_where_are_not_wrapped() + { + /** @var \Yajra\DataTables\QueryDataTable $dataTable */ + $dataTable = app('datatables')->of( + DB::table('users') + ->select('users.*') + ->where( + DB::table('posts') + ->whereColumn('posts.user_id', 'users.id') + ->orderBy('created_at') + ->select('title'), 'User-1 Post-1' + ) + ); + + $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); + $this->assertEquals(1, $dataTable->prepareCountQuery()->first()->row_count); + } + public function test_simple_queries_are_not_wrapped_and_countable() { /** @var \Yajra\DataTables\QueryDataTable $dataTable */ @@ -160,16 +178,4 @@ public function assertQueryHasNoSelect($expected, $query) $this->assertSame($expected, Str::startsWith($sql, 'select count(*) from (select 1 as dt_row_count from'), "'{$sql}' has select"); } - - /** - * @param $expected bool - * @param $query \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder - * @return void - */ - public function assertQueryIsFromSub($expected, $query) - { - $sql = $query->select(DB::raw('count(*)'))->toSql(); - - $this->assertSame($expected, Str::startsWith($sql, 'select count(*) from (select'), "'{$sql}' is from sub query"); - } } From e9623284024b0f35c9eb69151e7cf569babbfa9d Mon Sep 17 00:00:00 2001 From: Mathieu FERRE Date: Fri, 12 Apr 2024 15:49:15 +0200 Subject: [PATCH 3/5] Update QueryDataTableTest.php --- tests/Unit/QueryDataTableTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/QueryDataTableTest.php b/tests/Unit/QueryDataTableTest.php index 988c3ae1..294f4149 100644 --- a/tests/Unit/QueryDataTableTest.php +++ b/tests/Unit/QueryDataTableTest.php @@ -130,7 +130,7 @@ public function test_simple_queries_with_complexe_where_are_not_wrapped() ); $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); - $this->assertEquals(1, $dataTable->prepareCountQuery()->first()->row_count); + $this->assertEquals(1, $dataTable->prepareCountQuery()->count()); } public function test_simple_queries_are_not_wrapped_and_countable() From f814ae955df488d2d9d93ca788b75b39e11fd332 Mon Sep 17 00:00:00 2001 From: Mathieu FERRE Date: Fri, 12 Apr 2024 15:49:17 +0200 Subject: [PATCH 4/5] Update QueryDataTable.php --- src/QueryDataTable.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/QueryDataTable.php b/src/QueryDataTable.php index f60fb639..b9001732 100644 --- a/src/QueryDataTable.php +++ b/src/QueryDataTable.php @@ -176,7 +176,12 @@ public function prepareCountQuery(): QueryBuilder $builder->select(DB::raw('1 as dt_row_count')); $clone = $builder->clone(); $clone->setBindings([]); - $clone->wheres = []; + if ($clone instanceof EloquentBuilder) { + $clone->getQuery()->wheres = []; + } else { + $clone->wheres = []; + } + if ($this->isComplexQuery($clone)) { if (!$this->ignoreSelectInCountQuery) { $builder = clone $this->query; @@ -188,8 +193,8 @@ public function prepareCountQuery(): QueryBuilder ->setBindings($builder->getBindings()); } } - $row_count = $this->wrap('row_count'); - $builder->select($this->getConnection()->raw("'1' as {$row_count}")); + $row_count = $this->wrap('row_count'); + $builder->select($this->getConnection()->raw("'1' as {$row_count}")); if (!$this->keepSelectBindings) { $builder->setBindings([], 'select'); From b3b14144f715775d8890cb830a97a389c46fcb8c Mon Sep 17 00:00:00 2001 From: Mathieu FERRE Date: Fri, 12 Apr 2024 15:59:46 +0200 Subject: [PATCH 5/5] Update QueryDataTableTest.php --- tests/Unit/QueryDataTableTest.php | 38 ++++++++++++++----------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/tests/Unit/QueryDataTableTest.php b/tests/Unit/QueryDataTableTest.php index 294f4149..7c7812a7 100644 --- a/tests/Unit/QueryDataTableTest.php +++ b/tests/Unit/QueryDataTableTest.php @@ -74,52 +74,48 @@ public function test_complex_query_can_ignore_select_in_count() $this->assertQueryHasNoSelect(true, $dataTable->prepareCountQuery()); $this->assertEquals(20, $dataTable->count()); } - - public function test_complexe_queries_with_complexe_select_are_wrapped_without_selects() + + public function test_simple_queries_with_complexe_select_are_not_wrapped() { /** @var \Yajra\DataTables\QueryDataTable $dataTable */ $dataTable = app('datatables')->of( - DB::table('users') - ->select(['users.*', DB::raw('count(*) as posts_count')]) + DB::table('users') + ->select('users.*') ->addSelect([ 'last_post_id' => DB::table('posts') ->whereColumn('posts.user_id', 'users.id') ->orderBy('created_at') ->select('id'), ]) - ->join('posts', 'posts.user_id', 'users.id') - ->groupBy('users.id') ); - - $this->assertQueryWrapped(true, $dataTable->prepareCountQuery()); - $this->assertQueryHasNoSelect(false, $dataTable->prepareCountQuery()); + $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); $this->assertEquals(20, $dataTable->count()); } - public function test_simple_queries_with_complexe_select_are_not_wrapped() + public function test_simple_queries_with_complexe_where_are_not_wrapped() { /** @var \Yajra\DataTables\QueryDataTable $dataTable */ $dataTable = app('datatables')->of( DB::table('users') ->select('users.*') - ->addSelect([ - 'last_post_id' => DB::table('posts') + ->where( + DB::table('posts') ->whereColumn('posts.user_id', 'users.id') ->orderBy('created_at') - ->select('id'), - ]) + ->select('title'), 'User-1 Post-1' + ) ); $this->assertQueryWrapped(false, $dataTable->prepareCountQuery()); - $this->assertEquals(20, $dataTable->count()); + $this->assertEquals(1, $dataTable->prepareCountQuery()->count()); } - public function test_simple_queries_with_complexe_where_are_not_wrapped() + public function test_simple_eloquent_queries_with_complexe_where_are_not_wrapped() { /** @var \Yajra\DataTables\QueryDataTable $dataTable */ $dataTable = app('datatables')->of( - DB::table('users') + User::query() ->select('users.*') ->where( DB::table('posts') @@ -157,10 +153,10 @@ public function test_complexe_queries_can_be_wrapped_and_countable() /** * @param $expected bool - * @param $query \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder + * @param $query \Illuminate\Contracts\Database\Query\Builder * @return void */ - protected function assertQueryWrapped($expected, $query) + protected function assertQueryWrapped($expected, $query): void { $sql = $query->toSql(); @@ -169,10 +165,10 @@ protected function assertQueryWrapped($expected, $query) /** * @param $expected bool - * @param $query \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder + * @param $query \Illuminate\Contracts\Database\Query\Builder * @return void */ - public function assertQueryHasNoSelect($expected, $query) + public function assertQueryHasNoSelect($expected, $query): void { $sql = $query->select(DB::raw('count(*)'))->toSql();