From 9e519369b015711252d9a8cc04d8fbcabd13a5c0 Mon Sep 17 00:00:00 2001 From: denghy Date: Wed, 28 Nov 2018 19:09:47 +0800 Subject: [PATCH] upsert --- .../Real/Commands/Sync/ActivateSync.php | 2 +- app/Domains/Real/Commands/Sync/BlocSync.php | 2 +- .../Real/Commands/Sync/CompanySync.php | 2 +- .../Real/Commands/Sync/OrderBaseSync.php | 6 +-- .../Real/Commands/Sync/OrderCustomSync.php | 6 +-- .../Real/Commands/Sync/PackageSync.php | 2 +- .../src/Database/DatabaseServiceProvider.php | 30 ++++++++++--- .../foundation/src/Database/MySqlGrammar.php | 2 +- .../src/Database/PostgresGrammar.php | 45 +++++++++++++++++++ 9 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 vendor/dipper/foundation/src/Database/PostgresGrammar.php diff --git a/app/Domains/Real/Commands/Sync/ActivateSync.php b/app/Domains/Real/Commands/Sync/ActivateSync.php index bee0045d..f0cf88ab 100644 --- a/app/Domains/Real/Commands/Sync/ActivateSync.php +++ b/app/Domains/Real/Commands/Sync/ActivateSync.php @@ -62,7 +62,7 @@ class ActivateSync extends Command foreach (array_chunk($list, 3000) as $data) { echo '.'; - Card::updateBatch($data, 'sim'); + Card::upsert($data, 'sim'); } $this->line('更新数据成功'); diff --git a/app/Domains/Real/Commands/Sync/BlocSync.php b/app/Domains/Real/Commands/Sync/BlocSync.php index 8cb0f59a..c65ff54e 100644 --- a/app/Domains/Real/Commands/Sync/BlocSync.php +++ b/app/Domains/Real/Commands/Sync/BlocSync.php @@ -35,7 +35,7 @@ class BlocSync extends Command unset($item['del']); } - Bloc::replace($blocs); + Bloc::upsert($blocs, 'id'); app(BlocRepository::class)->forgetCached(); } diff --git a/app/Domains/Real/Commands/Sync/CompanySync.php b/app/Domains/Real/Commands/Sync/CompanySync.php index 37d7e2e3..5888fc0a 100644 --- a/app/Domains/Real/Commands/Sync/CompanySync.php +++ b/app/Domains/Real/Commands/Sync/CompanySync.php @@ -34,7 +34,7 @@ class CompanySync extends Command unset($item['del']); } - Company::replace($data); + Company::upsert($data, 'id'); app(CompanyRepository::class)->forgetCached(); } diff --git a/app/Domains/Real/Commands/Sync/OrderBaseSync.php b/app/Domains/Real/Commands/Sync/OrderBaseSync.php index fcab1c27..c15c3ec2 100644 --- a/app/Domains/Real/Commands/Sync/OrderBaseSync.php +++ b/app/Domains/Real/Commands/Sync/OrderBaseSync.php @@ -44,7 +44,7 @@ class OrderBaseSync extends Command $this->line('插入订单数据,条数:'.count($dataOrders)); foreach (array_chunk($dataOrders, $this->chunks) as $data) { echo '.'; - Order::replace($data); + Order::upsert($data, 'id'); } app(OrderRepository::class)->forgetCached(); unset($dataOrders); @@ -53,7 +53,7 @@ class OrderBaseSync extends Command $this->line('插入卡数据,条数:'.count($dataCards)); foreach (array_chunk($dataCards, $this->chunks) as $data) { echo '.'; - Card::replace($data); + Card::upsert($data, 'sim'); } app(CardRepository::class)->forgetCached(); unset($dataCards); @@ -62,7 +62,7 @@ class OrderBaseSync extends Command $this->line('插入订单关联数据,条数:'.count($dataOrderCards)); foreach (array_chunk($dataOrderCards, $this->chunks) as $data) { echo '.'; - DB::table('real_order_base_cards')->replace($data); + DB::table('real_order_base_cards')->upsert($data, 'sim'); } unset($dataOrderCards); $this->line('插入订单关联数据成功'); diff --git a/app/Domains/Real/Commands/Sync/OrderCustomSync.php b/app/Domains/Real/Commands/Sync/OrderCustomSync.php index dd828743..2f240912 100644 --- a/app/Domains/Real/Commands/Sync/OrderCustomSync.php +++ b/app/Domains/Real/Commands/Sync/OrderCustomSync.php @@ -65,7 +65,7 @@ class OrderCustomSync extends Command $this->line('插入订单数据,条数:'.count($dataOrders)); foreach (array_chunk($dataOrders, $this->chunks) as $data) { echo '.'; - Order::replace($data); + Order::upsert($data, 'id'); } app(OrderRepository::class)->forgetCached(); @@ -83,7 +83,7 @@ class OrderCustomSync extends Command foreach ($dataOrderCards as $type => $orderCards) { foreach (array_chunk($orderCards, $this->chunks) as $data) { echo '.'; - DB::table($tables[$type])->replace($data); + DB::table($tables[$type])->upsert($data, 'sim'); } } unset($dataOrderCards); @@ -101,7 +101,7 @@ class OrderCustomSync extends Command foreach ($dataPackageCards as $type => $packageCards) { foreach (array_chunk($packageCards, $this->chunks) as $data) { echo '.'; - DB::table($tables[$type])->replace($data); + DB::table($tables[$type])->upsert($data, 'sim'); } } unset($dataPackageCards); diff --git a/app/Domains/Real/Commands/Sync/PackageSync.php b/app/Domains/Real/Commands/Sync/PackageSync.php index 0a71cef1..a91e0bb7 100644 --- a/app/Domains/Real/Commands/Sync/PackageSync.php +++ b/app/Domains/Real/Commands/Sync/PackageSync.php @@ -50,7 +50,7 @@ class PackageSync extends Command $packages = array_merge($basePackages, $renewalPackages, $flowPackages, $optionalPackages, $additionalPackages); - Package::replace($packages); + Package::upsert($packages, 'id'); app(PackageRepository::class)->forgetCached(); } diff --git a/vendor/dipper/foundation/src/Database/DatabaseServiceProvider.php b/vendor/dipper/foundation/src/Database/DatabaseServiceProvider.php index cd2ab27f..9445267b 100644 --- a/vendor/dipper/foundation/src/Database/DatabaseServiceProvider.php +++ b/vendor/dipper/foundation/src/Database/DatabaseServiceProvider.php @@ -4,8 +4,11 @@ namespace Dipper\Foundation\Database; use Closure; use Illuminate\Support\Arr; +use Illuminate\Database\Connection; use Illuminate\Support\ServiceProvider; +use Dipper\Foundation\Database\PostgresGrammar; use Illuminate\Database\Query\Builder as QueryBuilder; +use Dipper\Foundation\Database\MySqlGrammar; class DatabaseServiceProvider extends ServiceProvider { @@ -16,11 +19,12 @@ class DatabaseServiceProvider extends ServiceProvider */ public function register() { + QueryBuilder::macro('upsert', $this->macroUpsert()); QueryBuilder::macro('replace', $this->macroReplace()); QueryBuilder::macro('insertUpdate', $this->macroInsertUpdate()); QueryBuilder::macro('createOrIgnore', $this->macroCreateOrIgnore()); QueryBuilder::macro('createNotExist', $this->macroCreateNotExist()); - QueryBuilder::macro('updateBatch', $this->macroUpdateBatch()); + QueryBuilder::macro('updateBatch', $this->macroUpsert()); } /** @@ -158,7 +162,7 @@ class DatabaseServiceProvider extends ServiceProvider * * @return void */ - public function macroUpdateBatch() + public function macroUpsert() { return function (array $values, $filed = 'id') { if (empty($values)) { @@ -172,13 +176,27 @@ class DatabaseServiceProvider extends ServiceProvider $values[$key] = $value; } } - - $grammar = new MySqlGrammar(); - + + $grammar = DatabaseServiceProvider::getGrammar($this->connection); + return $this->connection->affectingStatement( - $grammar->compileUpdateBatch($this, $values, $filed), + $grammar->compileUpsert($this, $values, $filed), $this->cleanBindings(Arr::flatten($values, 1)) ); }; } + + public static function getGrammar(Connection $connection) + { + $driver = $connection->getDriverName(); + + switch ($driver) { + case 'mysql': + return new MySqlGrammar(); + case 'pgsql': + return new PostgresGrammar(); + } + + throw new \InvalidArgumentException("Unsupported driver [{$driver}]"); + } } diff --git a/vendor/dipper/foundation/src/Database/MySqlGrammar.php b/vendor/dipper/foundation/src/Database/MySqlGrammar.php index 82105a7c..cae94aa6 100644 --- a/vendor/dipper/foundation/src/Database/MySqlGrammar.php +++ b/vendor/dipper/foundation/src/Database/MySqlGrammar.php @@ -161,7 +161,7 @@ class MySqlGrammar extends Grammar * @param string $filed * @return string */ - public function compileUpdateBatch(QueryBuilder $query, array $values, $filed = 'id') + public function compileUpsert(QueryBuilder $query, array $values, $filed = 'id') { // Essentially we will force every insert to be treated as a batch insert which // simply makes creating the SQL easier for us since we can utilize the same diff --git a/vendor/dipper/foundation/src/Database/PostgresGrammar.php b/vendor/dipper/foundation/src/Database/PostgresGrammar.php new file mode 100644 index 00000000..5be7553c --- /dev/null +++ b/vendor/dipper/foundation/src/Database/PostgresGrammar.php @@ -0,0 +1,45 @@ +compileInsert($query, $values); + + if (! is_array(reset($values))) { + $values = [$values]; + } + + $row = current($values); + + $keys = array_keys(reset($values)); + + // 指定更新字段,默认id字段,不存在时选用第一个字段。 + $reference = isset($row[$filed]) ? $filed : current($keys); + + // excluded fields are all fields except $unique one that will be updated + // also created_at should be excluded since record already exists + $excluded = array_filter($keys, function ($e) use ($reference) { + return $e != $reference && $e != 'created_at'; + }); + + $update = join(', ', array_map(function ($e) { + return "\"$e\" = \"excluded\".\"$e\""; + }, $excluded)); + + return "$insert on conflict ($reference) do update set $update"; + } +}