Skip to content

Commit

Permalink
Support updateFrom() on PostgreSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed Nov 25, 2022
1 parent 0d08036 commit 05a1d5c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 4 deletions.
33 changes: 33 additions & 0 deletions src/Query/Grammars/Traits/CompilesPostgresExpressions.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Staudenmeir\LaravelCte\Query\Grammars\Traits;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Str;

trait CompilesPostgresExpressions
{
Expand Down Expand Up @@ -44,6 +45,38 @@ public function getBindingsForUpdate(Builder $query, array $bindings, array $val
return $this->prepareBindingsForUpdate($bindings, $values);
}

/**
* Compile an update from statement into SQL.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $values
* @return string
*/
public function compileUpdateFrom(Builder $query, $values)
{
$compiled = parent::compileUpdateFrom($query, $values);

return (string) Str::of($compiled)
->prepend($this->compileExpressions($query, $query->expressions), ' ')
->trim();
}

/**
* Prepare the bindings for an update statement.
*
* @param array $bindings
* @param array $values
* @return array
*/
public function prepareBindingsForUpdateFrom(array $bindings, array $values)
{
$values = array_merge($bindings['expressions'], $values);

unset($bindings['expressions']);

return parent::prepareBindingsForUpdateFrom($bindings, $values);
}

/**
* Compile a delete statement into SQL.
*
Expand Down
19 changes: 18 additions & 1 deletion src/Query/Traits/BuildsExpressionQueries.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public function insertUsing(array $columns, $query)
/**
* Update records in the database.
*
* @param array $values
* @param array $values
* @return int
*/
public function update(array $values)
Expand All @@ -217,4 +217,21 @@ public function update(array $values)
$this->grammar->getBindingsForUpdate($this, $this->bindings, $values)
));
}

/**
* Update records in a PostgreSQL database using the update from syntax.
*
* @param array $values
* @return int
*/
public function updateFrom(array $values)
{
$this->applyBeforeQueryCallbacks();

$sql = $this->grammar->compileUpdateFrom($this, $values);

return $this->connection->update($sql, $this->cleanBindings(
$this->grammar->prepareBindingsForUpdateFrom($this->bindings, $values)
));
}
}
16 changes: 16 additions & 0 deletions tests/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,22 @@ public function testUpdateWithLimit()
$this->assertEquals([1, 0], DB::table('posts')->orderBy('id')->pluck('views')->all());
}

public function testUpdateFrom()
{
if ($this->database !== 'pgsql') {
$this->markTestSkipped();
}

DB::table('posts')
->withExpression('u', DB::table('users')->where('id', '>', 1))
->join('u', 'u.id', '=', 'posts.user_id')
->updateFrom([
'views' => DB::raw('"u"."followers"'),
]);

$this->assertEquals([0, 20], DB::table('posts')->orderBy('id')->pluck('views')->all());
}

public function testDelete()
{
if ($this->database === 'mariadb') {
Expand Down
7 changes: 4 additions & 3 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ protected function setUp(): void
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('parent_id')->nullable();
$table->unsignedBigInteger('followers');
$table->timestamps();
});

Expand All @@ -36,9 +37,9 @@ protected function setUp(): void

Model::unguard();

User::create(['parent_id' => null]);
User::create(['parent_id' => 1]);
User::create(['parent_id' => 2]);
User::create(['parent_id' => null, 'followers' => 10]);
User::create(['parent_id' => 1, 'followers' => 20]);
User::create(['parent_id' => 2, 'followers' => 30]);

Post::create(['user_id' => 1]);
Post::create(['user_id' => 2]);
Expand Down

0 comments on commit 05a1d5c

Please sign in to comment.