Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upsert with partial index #57

Open
sakairyota opened this issue Apr 26, 2023 · 1 comment
Open

Upsert with partial index #57

sakairyota opened this issue Apr 26, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@sakairyota
Copy link

The combination of upsert and partial index is not working.
I think this is not a bug, but it may worth to support.
Reproduction information is below.

Versions:
larave/franework: 10.9.0
tpetry/laravel-postgresql-enhanced: 0.29.0

Migration file:

    public function up(): void
    {
        Schema::create('items', function (Blueprint $table) {
            $table->id();
            $table->string('code');
            $table->timestamps();
            $table->softDeletes();

            $table->uniqueIndex(['code'])
                ->where(fn (Builder $condition) => $condition->whereNull('deleted_at'));
        });
    }

Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Item extends Model
{
    use SoftDeletes;

    protected $fillable = ['code'];
}

Source Code (I ran it in tinker)

use App\Models\Item;
Item::upsert(['code' => 'item1'], ['code']);

Then an exception occuerd
Illuminate\Database\QueryException SQLSTATE[42P10]: Invalid column reference: 7 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification (Connection: pgsql, SQL: insert into "items" ("code", "created_at", "updated_at") values (item1, 2023-04-26 12:51:09, 2023-04-26 12:51:09) on conflict ("code") do update set "code" = "excluded"."code", "updated_at" = "excluded"."updated_at").

When I wrote on conflict with where manually, it was working. So we have to insert where before do update to upsert with partial index.

DB::statement('INSERT INTO "items" ("code", "created_at", "updated_at") VALUES (\'item1\', NOW(), NOW()) ON CONFLICT ("code") WHERE deleted_at IS NULL DO UPDATE SET "code" = "excluded"."code", "updated_at" = "excluded"."updated_at"');
# = true

But in compileUpsert method In Illuminate\Database\Query\Grammars\PostgresGrammar in laravel/framework, on conflict and do update set is wrote in single line and it's not customizable.

$sql .= ' on conflict ('.$this->columnize($uniqueBy).') do update set ';

If you support this feature, I think we have to override compileUpsert in PostgresGrammar.

@tpetry tpetry added the enhancement New feature or request label Apr 26, 2023
@sakairyota
Copy link
Author

After writing the issue, I noticed that this problem is not directly related this library.
But it may still worth to support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants