uptrace / bun

SQL-first Golang ORM
https://bun.uptrace.dev
BSD 2-Clause "Simplified" License
3.65k stars 221 forks source link

Bulk update with uuid #905

Open fabl3ss opened 1 year ago

fabl3ss commented 1 year ago

Hi!

When attempting to perform a bulk update on my entities, I encountered an error from PostgreSQL. I would appreciate any guidance or suggestions on how to resolve this issue.

The specific error message I'm encountering is:

ERROR:  operator does not exist: uuid = bytea at character 738
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

DDL:

create table refunds
(
    transaction_id uuid                  not null
        primary key,
    order_id       uuid                  not null,
    created_at     timestamp             not null,
    is_notified    boolean default false not null
);

Struct:

import (
    "github.com/google/uuid"
    // some more imports
)

type Refund struct {
    bun.BaseModel `bun:"table:notification.refunds"`

    TransactionId uuid.UUID `bun:",pk"`
    OrderId       uuid.UUID
    IsNotified    bool
    CreatedAt     time.Time
}

Usage:

func (r *RefundRepository) UpdateBulk(ctx context.Context, refunds []*notification_model.Refund) error {
    _, err := r.db.NewUpdate().
        Model(&refunds).
        Bulk().
        Exec(ctx)

    return errors.WithStack(err)
}

Resulting SQL query:

WITH "_data" ("transaction_id",
              "order_id",
              "is_notified",
              "created_at") AS (
                                VALUES ('9bc92b7c-f273-46a4-b21f-47e28d514eb2'::BYTEA,
                                        'bcdc23bc-87ac-4e5a-932c-2dd27eb46794'::BYTEA,
                                        TRUE::BOOLEAN,
                                        '2006-01-02 15:04:05+00:00'::TIMESTAMPTZ), ('3c845e12-6286-43c5-8e92-5a3ec43a4734'::BYTEA,
                                                                                    'c5d817a6-8352-4948-b8b0-7937c5f6ec03'::BYTEA,
                                                                                    TRUE::BOOLEAN,
                                                                                    '2006-01-02 15:05:05+00:00'::TIMESTAMPTZ), ('b23c4111-8550-4768-bd69-6d857a0ee30b'::BYTEA,
                                                                                                                                '2352cdc0-c92a-4c3c-a3bc-94b00adda01e'::BYTEA,
                                                                                                                                TRUE::BOOLEAN,
                                                                                                                                '2006-01-02 15:06:05+00:00'::TIMESTAMPTZ))
UPDATE "notification"."refunds" AS "refund"
SET "order_id" = _data."order_id",
    "is_notified" = _data."is_notified",
    "created_at" = _data."created_at"
FROM _data
WHERE ("refund"."transaction_id" = _data."transaction_id")
mogita commented 5 months ago

Can confirm this issue exists. Following snippet from docs generated SQL query with the UUID fields as '3189cd28-d404-4b9c-87c6-9a4d6577959d'::BYTEA.

Kichiyaki commented 4 days ago

Workaround: Just add type:uuid to struct fields. The same goes for custom database types (e.g. enums).

import (
    "github.com/google/uuid"
    // some more imports
)

type Refund struct {
    bun.BaseModel `bun:"table:notification.refunds"`

    TransactionId uuid.UUID `bun:",pk,type:uuid"`
    OrderId       uuid.UUID `bun:",type:uuid"`
    IsNotified    bool
    CreatedAt     time.Time
}

Docs.