Skip to content

Commit

Permalink
Improve performance on search (#1528)
Browse files Browse the repository at this point in the history
* improve queries

* add tests

* fix getColumnType field param type

* fix pgsql test

* pint
  • Loading branch information
luanfreitasdev authored May 5, 2024
1 parent 77ccb7c commit 4cff0b1
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 10 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"laradumps/laradumps-core": "^2.0",
"larastan/larastan": "^2.9.0",
"pestphp/pest": "^2.34.0",
"orchestra/testbench": "8.19|^9.0"
"orchestra/testbench": "8.19|^9.0",
"laradumps/laradumps": "^3.1"
},
"suggest": {
"openspout/openspout": "Required to export XLS and CSV"
Expand Down
40 changes: 33 additions & 7 deletions src/DataSource/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Illuminate\Database\Eloquent\{Builder as EloquentBuilder, RelationNotFoundException};
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\{Cache, DB, Schema};
use Illuminate\Support\Facades\{Cache, Schema};
use PowerComponents\LivewirePowerGrid\Components\Filters\{Builders\Number};
use PowerComponents\LivewirePowerGrid\{Column,
Components\Filters\Builders\Boolean,
Expand Down Expand Up @@ -147,16 +147,16 @@ public function filterContains(): Builder

$search = $this->getBeforeSearchMethod($field, $search);

$hasColumn = in_array($field, $columnList, true);
$hasColumn = isset($columnList[$field]);

$query->when($search, function () use ($column, $query, $search, $table, $field, $hasColumn) {
$query->when($search != '', function () use ($column, $query, $search, $table, $field, $hasColumn) {
if (($sqlRaw = strval(data_get($column, 'searchableRaw')))) {
$query->orWhereRaw($sqlRaw . ' ' . Sql::like($query) . ' \'%' . $search . '%\'');
}

if ($hasColumn && blank(data_get($column, 'searchableRaw')) && $search) {
if ($hasColumn && blank(data_get($column, 'searchableRaw'))) {
try {
$columnType = DB::getSchemaBuilder()->getColumnType($table, $field);
$columnType = $this->getColumnType($table, $field);

/** @phpstan-ignore-next-line */
$driverName = $query->getConnection()->getConfig('driver');
Expand Down Expand Up @@ -299,11 +299,37 @@ private function splitField(string $field): array
return [$table, $field];
}

private function getColumnType(string $modelTable, string $field): ?string
{
try {
return $this->getColumnList($modelTable)[$field] ?? null;
} catch (\Throwable $throwable) {
logger()->warning('PowerGrid [getColumnType] warning: ', [
'table' => $modelTable,
'field' => $field,
'throwable' => $throwable->getTrace(),
]);

return null;
}
}

private function getColumnList(string $modelTable): array
{
try {
return (array) Cache::remember('powergrid_columns_in_' . $modelTable, 600, fn () => Schema::getColumnListing($modelTable));
} catch (\Exception) {
return (array) Cache::remember(
'powergrid_columns_in_' . $modelTable,
60 * 60 * 3,
fn () => collect(Schema::getColumns($modelTable))
->pluck('type', 'name')
->toArray()
);
} catch (\Throwable $throwable) {
logger()->warning('PowerGrid [getColumnList] warning: ', [
'table' => $modelTable,
'throwable' => $throwable->getTrace(),
]);

return Schema::getColumnListing($modelTable);
}
}
Expand Down
16 changes: 16 additions & 0 deletions tests/Concerns/Components/DishesBeforeSearchTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PowerComponents\LivewirePowerGrid\Tests\Concerns\Components;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Dish;
use PowerComponents\LivewirePowerGrid\{Column, Footer, Header, PowerGrid, PowerGridComponent, PowerGridFields};

Expand All @@ -25,6 +26,18 @@ public function beforeSearchName(string $search): string
return 'Peixada';
}

public function beforeSearch(?string $field = null, ?string $search = null): ?string
{
if ($field === 'in_stock') {
return str($search)
->replace('without_stock', DB::getDriverName() === 'pgsql' ? 'false' : '0')
->replace('with_stock', DB::getDriverName() === 'pgsql' ? 'true' : '1')
->toString();
}

return $search;
}

public function datasource(): Builder
{
return Dish::query();
Expand All @@ -48,6 +61,9 @@ public function columns(): array
->searchable()
->sortable(),

Column::make('Stock', 'in_stock', 'dishes.in_stock')
->searchable(),

Column::action('Action'),
];
}
Expand Down
25 changes: 23 additions & 2 deletions tests/Feature/BeforeSearchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,30 @@
->assertSee('Peixada')
->set('search', '')
->assertSee('Peixada');
})->with('before_search_themes');
})->with([
'tailwind' => [DishesBeforeSearchTable::class, (object) ['theme' => 'tailwind']],
'bootstrap' => [DishesBeforeSearchTable::class, (object) ['theme' => 'bootstrap']],
]);

dataset('before_search_themes', [
it('can use beforeSearch in boolean field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
# without_stock => in_stock = 0
->set('search', 'without_stock')
->assertDontSee('Pastel de Nata')
->assertDontSee('Carne Louca')
->assertSee('Barco-Sushi Simples')
# with_stock => in_stock = 1
->set('search', 'with_stock')
->assertSee('Pastel de Nata')
->assertSee('Carne Louca')
->assertDontSee('Barco-Sushi Simples')
# without_stock => in_stock = 0
->set('search', 'without_stock')
->assertDontSee('Pastel de Nata')
->assertSee('Barco-Sushi Simples')
->assertDontSee('Pastel de Nata');
})->with([
'tailwind' => [DishesBeforeSearchTable::class, (object) ['theme' => 'tailwind']],
'bootstrap' => [DishesBeforeSearchTable::class, (object) ['theme' => 'bootstrap']],
]);

0 comments on commit 4cff0b1

Please sign in to comment.