diff --git a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php index 4372bae32791..1856b998ca01 100755 --- a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php @@ -442,6 +442,7 @@ protected function compileUpdateWithoutJoins(Builder $query, $table, $columns, $ * @param array $values * @return array */ + #[\Override] public function prepareBindingsForUpdate(array $bindings, array $values) { $values = (new Collection($values)) diff --git a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php index 615852e2ae7d..3a2a7b425f3c 100755 --- a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php @@ -618,6 +618,7 @@ protected function compileUpdateWithJoinsOrLimit(Builder $query, array $values) * @param array $values * @return array */ + #[\Override] public function prepareBindingsForUpdate(array $bindings, array $values) { $values = (new Collection($values))->map(function ($value, $column) { @@ -628,6 +629,8 @@ public function prepareBindingsForUpdate(array $bindings, array $values) $cleanBindings = Arr::except($bindings, 'select'); + $values = Arr::flatten(array_map(fn ($value) => value($value), $values)); + return array_values( array_merge($values, Arr::flatten($cleanBindings)) ); diff --git a/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php b/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php index a70571d2ceb9..f9a82febd948 100755 --- a/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php @@ -384,6 +384,7 @@ protected function compileUpdateWithJoinsOrLimit(Builder $query, array $values) * @param array $values * @return array */ + #[\Override] public function prepareBindingsForUpdate(array $bindings, array $values) { $groups = $this->groupJsonColumnsForUpdate($values); @@ -396,6 +397,8 @@ public function prepareBindingsForUpdate(array $bindings, array $values) $cleanBindings = Arr::except($bindings, 'select'); + $values = Arr::flatten(array_map(fn ($value) => value($value), $values)); + return array_values( array_merge($values, Arr::flatten($cleanBindings)) ); diff --git a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php index 45cebeaa8036..2cd0d15a0be5 100755 --- a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php @@ -453,10 +453,13 @@ public function compileUpsert(Builder $query, array $values, array $uniqueBy, ar * @param array $values * @return array */ + #[\Override] public function prepareBindingsForUpdate(array $bindings, array $values) { $cleanBindings = Arr::except($bindings, 'select'); + $values = Arr::flatten(array_map(fn ($value) => value($value), $values)); + return array_values( array_merge($values, Arr::flatten($cleanBindings)) ); diff --git a/tests/Integration/Database/QueryBuilderUpdateTest.php b/tests/Integration/Database/QueryBuilderUpdateTest.php index 4e87f19a343b..d8783ce8a250 100644 --- a/tests/Integration/Database/QueryBuilderUpdateTest.php +++ b/tests/Integration/Database/QueryBuilderUpdateTest.php @@ -19,8 +19,15 @@ protected function afterRefreshingDatabase() $table->string('name')->nullable(); $table->string('title')->nullable(); $table->string('status')->nullable(); + $table->integer('credits')->nullable(); $table->json('payload')->nullable(); }); + + Schema::create('example_credits', function (Blueprint $table) { + $table->increments('id'); + $table->unsignedBigInteger('example_id'); + $table->integer('credits'); + }); } #[DataProvider('jsonValuesDataProvider')] @@ -28,16 +35,59 @@ protected function afterRefreshingDatabase() public function testBasicUpdateForJson($column, $given, $expected) { DB::table('example')->insert([ + ['name' => 'Taylor Otwell', 'title' => 'Mr.'], + ]); + + DB::table('example')->update([ + $column => $given, + ]); + + $this->assertDatabaseHas('example', [ + 'name' => 'Taylor Otwell', + 'title' => 'Mr.', + $column => $column === 'payload' ? $this->castAsJson($expected) : $expected, + ]); + } + + #[RequiresDatabase(['sqlite', 'mysql', 'mariadb'])] + public function testSubqueryUpdate() + { + DB::table('example')->insert([ + ['name' => 'Taylor Otwell', 'title' => 'Mr.'], + ['name' => 'Tim MacDonald', 'title' => 'Mr.'], + ]); + + DB::table('example_credits')->insert([ + ['example_id' => 1, 'credits' => 10], + ['example_id' => 1, 'credits' => 20], + ]); + + $this->assertDatabaseHas('example', [ 'name' => 'Taylor Otwell', 'title' => 'Mr.', + 'credits' => null, + ]); + + $this->assertDatabaseHas('example', [ + 'name' => 'Tim MacDonald', + 'title' => 'Mr.', + 'credits' => null, ]); - DB::table('example')->update([$column => $given]); + DB::table('example')->update([ + 'credits' => DB::table('example_credits')->selectRaw('sum(credits)')->whereColumn('example_credits.example_id', 'example.id'), + ]); $this->assertDatabaseHas('example', [ 'name' => 'Taylor Otwell', 'title' => 'Mr.', - $column => $column === 'payload' ? $this->castAsJson($expected) : $expected, + 'credits' => 30, + ]); + + $this->assertDatabaseHas('example', [ + 'name' => 'Tim MacDonald', + 'title' => 'Mr.', + 'credits' => null, ]); }