From 18de0570298ee8a1361b4ea4c64c7c3340ec6a06 Mon Sep 17 00:00:00 2001 From: Jonas Staudenmeir Date: Wed, 10 Oct 2018 02:36:01 +0200 Subject: [PATCH 1/2] Remove table name from UPDATE queries on PostgreSQL --- .../Database/Query/Grammars/PostgresGrammar.php | 13 ++++++++----- tests/Database/DatabaseQueryBuilderTest.php | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php index d9350ef7bca0..439a69a758dc 100755 --- a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php @@ -173,7 +173,7 @@ public function compileUpdate(Builder $query, $values) // Each one of the columns in the update statements needs to be wrapped in the // keyword identifiers, also a place-holder needs to be created for each of // the values in the list of bindings so we can make the sets statements. - $columns = $this->compileUpdateColumns($values); + $columns = $this->compileUpdateColumns($query, $values); $from = $this->compileUpdateFrom($query); @@ -185,20 +185,23 @@ public function compileUpdate(Builder $query, $values) /** * Compile the columns for the update statement. * + * @param \Illuminate\Database\Query\Builder $query * @param array $values * @return string */ - protected function compileUpdateColumns($values) + protected function compileUpdateColumns($query, $values) { // When gathering the columns for an update statement, we'll wrap each of the // columns and convert it to a parameter value. Then we will concatenate a // list of the columns that can be added into this update query clauses. - return collect($values)->map(function ($value, $key) { + return collect($values)->map(function ($value, $key) use ($query) { + $column = Str::after($key, $query->from.'.'); + if ($this->isJsonSelector($key)) { - return $this->compileJsonUpdateColumn($key, $value); + return $this->compileJsonUpdateColumn($column, $value); } - return $this->wrap($key).' = '.$this->parameter($value); + return $this->wrap($column).' = '.$this->parameter($value); })->implode(', '); } diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index c8e8bc16af96..1a6e458cd63d 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -1801,7 +1801,7 @@ public function testUpdateMethodWithoutJoinsOnPostgres() { $builder = $this->getPostgresBuilder(); $builder->getConnection()->shouldReceive('update')->once()->with('update "users" set "email" = ?, "name" = ? where "id" = ?', ['foo', 'bar', 1])->andReturn(1); - $result = $builder->from('users')->where('id', '=', 1)->update(['email' => 'foo', 'name' => 'bar']); + $result = $builder->from('users')->where('id', '=', 1)->update(['users.email' => 'foo', 'name' => 'bar']); $this->assertEquals(1, $result); } @@ -2042,7 +2042,7 @@ public function testPostgresUpdateWrappingJson() $builder = $this->getPostgresBuilder(); $builder->getConnection()->shouldReceive('update') ->with('update "users" set "options" = jsonb_set("options"::jsonb, \'{"name","first_name"}\', ?)', ['"John"']); - $builder->from('users')->update(['options->name->first_name' => 'John']); + $builder->from('users')->update(['users.options->name->first_name' => 'John']); $builder = $this->getPostgresBuilder(); $builder->getConnection()->shouldReceive('update') From af5f90211837f3e7e6066e6cf009e4f3b09cf797 Mon Sep 17 00:00:00 2001 From: Jonas Staudenmeir Date: Wed, 10 Oct 2018 03:34:13 +0200 Subject: [PATCH 2/2] Fix ambiguous UPDATED_AT columns --- src/Illuminate/Database/Eloquent/Builder.php | 8 ++++--- .../Database/DatabaseEloquentBuilderTest.php | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 271e62cc1ecc..87e1204a462a 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -857,9 +857,11 @@ protected function addUpdatedAtColumn(array $values) return $values; } - return Arr::add( - $values, $this->model->getUpdatedAtColumn(), - $this->model->freshTimestampString() + $column = $this->qualifyColumn($this->model->getUpdatedAtColumn()); + + return array_merge( + [$column => $this->model->freshTimestampString()], + $values ); } diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php index e9d5ad97aa0c..913e483af1d6 100755 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ b/tests/Database/DatabaseEloquentBuilderTest.php @@ -5,6 +5,7 @@ use Closure; use stdClass; use Mockery as m; +use Carbon\Carbon; use PHPUnit\Framework\TestCase; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; @@ -1049,6 +1050,24 @@ public function testOldestWithColumn() $builder->oldest('foo'); } + public function testUpdate() + { + Carbon::setTestNow($now = '2017-10-10 10:10:10'); + + $query = new BaseBuilder(m::mock(ConnectionInterface::class), new Grammar, m::mock(Processor::class)); + $builder = new Builder($query); + $model = new EloquentBuilderTestStub; + $this->mockConnectionForModel($model, ''); + $builder->setModel($model); + $builder->getConnection()->shouldReceive('update')->once() + ->with('update "table" set "table"."updated_at" = ?, "foo" = ?', [$now, 'bar'])->andReturn(1); + + $result = $builder->update(['foo' => 'bar']); + $this->assertEquals(1, $result); + + Carbon::setTestNow(null); + } + protected function mockConnectionForModel($model, $database) { $grammarClass = 'Illuminate\Database\Query\Grammars\\'.$database.'Grammar'; @@ -1085,6 +1104,11 @@ protected function getMockQueryBuilder() } } +class EloquentBuilderTestStub extends Model +{ + protected $table = 'table'; +} + class EloquentBuilderTestScopeStub extends Model { public function scopeApproved($query)