From 8a70133665e87c237cb3de68ffe9e1d7d0589e77 Mon Sep 17 00:00:00 2001 From: Nikolay Novikov Date: Sat, 21 Sep 2024 15:06:56 +0300 Subject: [PATCH] minor updates --- src/Http/Middleware/Api/Locale.php | 33 ++++++ src/Providers/LaravelAtomServiceProvider.php | 20 ++++ src/Traits/OptimizeCheckerTrait.php | 63 +++++++++++ src/Traits/PostgresTrait.php | 106 +++++++++++++++++++ src/resources/config/bindings.php | 19 ++++ 5 files changed, 241 insertions(+) create mode 100644 src/Http/Middleware/Api/Locale.php create mode 100644 src/Traits/OptimizeCheckerTrait.php create mode 100644 src/Traits/PostgresTrait.php create mode 100644 src/resources/config/bindings.php diff --git a/src/Http/Middleware/Api/Locale.php b/src/Http/Middleware/Api/Locale.php new file mode 100644 index 0000000..80876ab --- /dev/null +++ b/src/Http/Middleware/Api/Locale.php @@ -0,0 +1,33 @@ +header($this->header), 0, 2); + $locale = mb_strtolower($locale); + + if (in_array($locale, $supportedLocales)) { + \App::setLocale($locale); + \Date::setLocale($locale); + } + + return $next($request); + } +} diff --git a/src/Providers/LaravelAtomServiceProvider.php b/src/Providers/LaravelAtomServiceProvider.php index fcdfb3b..c21f245 100644 --- a/src/Providers/LaravelAtomServiceProvider.php +++ b/src/Providers/LaravelAtomServiceProvider.php @@ -25,7 +25,26 @@ public function register() { // config $this->mergeConfigFrom(__DIR__.'/../resources/config/atom.php', 'atom'); + $this->mergeConfigFrom(__DIR__.'/../resources/config/bindings.php', 'bindings'); + // bindings + foreach (config('bindings') as $interface => $implementation) { + if (! isset($implementation['bind'])) { + continue; + } + + $this->app->singleton($interface, function ($app, $arguments = []) use ($interface, $implementation) { + $object = new $implementation['bind'](...$arguments); + + if (interface_exists($interface) && ! $object instanceof $interface) { + throw new \LogicException("{$implementation['bind']} is not instance of {$interface}"); + } + + return $object; + }); + } + + // sc $this->app->singleton(\AnourValar\LaravelAtom\Service::class, function ($app) { return new \AnourValar\LaravelAtom\Service(new \AnourValar\LaravelAtom\Registry()); }); @@ -43,6 +62,7 @@ public function boot() { // config $this->publishes([ __DIR__.'/../resources/config/atom.php' => config_path('atom.php')], 'config'); + $this->publishes([ __DIR__.'/../resources/config/bindings.php' => config_path('bindings.php')], 'config'); // langs $this->loadTranslationsFrom(__DIR__.'/../resources/lang/', 'laravel-atom'); diff --git a/src/Traits/OptimizeCheckerTrait.php b/src/Traits/OptimizeCheckerTrait.php new file mode 100644 index 0000000..f27ec63 --- /dev/null +++ b/src/Traits/OptimizeCheckerTrait.php @@ -0,0 +1,63 @@ +registerChecker(); + + \Queue::after(function ($job) { + \App::make(\Illuminate\Contracts\Cache\Repository::class)->getStore()->locks = []; + }); + + return $uses; + } + + /** + * @return void + */ + protected function registerChecker(): void + { + if (\DB::connection()->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql') { + \DB::update('SET enable_seqscan = 0'); + //$this->assertEquals('off', \DB::select("SHOW enable_seqscan")[0]->enable_seqscan); + } + + \DB::listen(function ($query) { + $sql = $query->sql; + + if (stripos($sql, 'select ') !== 0) { + return; + } + + if (! stripos($sql, ' where ')) { + return; + } + + $sql = preg_replace('|\s+limit\s+\d+\s*$|iu', '', $sql); + + foreach (\DB::select("EXPLAIN {$sql}", $query->bindings) as $item) { + $item = (array) $item; + $item = $item['QUERY PLAN']; + + if (mb_stripos($item, 'Seq Scan') !== false) { + $this->assertStringNotContainsString( + 'Seq Scan', + $item, + $sql . ' ['.implode(', ', $query->bindings).']' + ); + } + } + + }); + } +} diff --git a/src/Traits/PostgresTrait.php b/src/Traits/PostgresTrait.php new file mode 100644 index 0000000..22f52f9 --- /dev/null +++ b/src/Traits/PostgresTrait.php @@ -0,0 +1,106 @@ +getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql') { + Schema::getConnection()->statement( + "CREATE INDEX {$tableName}_{$column}_index ON {$tableName} USING gin ({$column} {$option});" + ); + } else { + $table->index($column); + } + }); + } + + /** + * Remove default value from the column + * + * @param string $tableName + * @param string $column + * @return void + */ + protected function removeDefault(string $tableName, string $column): void + { + \DB::statement("ALTER TABLE {$tableName} ALTER COLUMN {$column} DROP DEFAULT;"); + } + + /** + * Sync the auto-increment state + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return void + */ + protected function syncAutoIncrement(\Illuminate\Database\Eloquent\Model $model): void + { + if ($model->getConnection() instanceof \Illuminate\Database\PostgresConnection) { + $table = $model->getTable(); + $key = $model->getKeyName(); + + \DB::connection($model->getConnectionName()) + ->select("SELECT setval('{$table}_id_seq', max({$key})) FROM {$table}"); + } + } + + /** + * Enable pg_trgm extension + * + * @return void + */ + protected function installPgTrgm(): void + { + if (\DB::connection()->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql') { + \DB::statement('create extension if not exists pg_trgm;'); + } + } + + /** + * Create a conditional (not null) b-tree index + * + * @param string $tableName + * @param string $column + */ + protected function conditionalIndexNotNull(string $tableName, string $column) + { + \DB::statement(<<< HERE + CREATE INDEX {$tableName}_{$column}_index ON {$tableName} + USING btree ({$column}) WHERE ({$column} IS NOT NULL); + HERE); + } + + /** + * create a fulltext search (tsvector) column with RUM index + * + * @param string $tableName + * @param string $columnName + * @param string $locale + * @return void + */ + protected function addRumFullText(string $tableName, string $columnName = 'search_fulltext', string $locale = null): void + { + if (! $locale) { + $locale = config('app.fallback_locale'); + } + + \DB::statement("ALTER TABLE {$tableName} ADD COLUMN {$columnName} TSVECTOR"); + + \DB::statement(<<