Your Question
After bumping up the version of Gorm from 1.24 to 1.25, I noticed a breaking change in behaviour, when using Google uuid.UUID as primary key.
Considering this model:
type Foo struct {
Id uuid.UUID
Name string
}
On 1.24 the following command:
entity := &Foo{Name: "ACME"}
Clauses(clause.Returning{}).Create(entity)
Would have generated an INSERT INTO ... (id, name) VALUES (nil, 'ACME') RETURNING *, which would return the ID of the new record, generated by the DB.
However, in 1.25, the same command on the same model, generates INSERT INTO ... (id, name) VALUES ('0000-0000-0000-0000', 'ACME') RETUNING * which is a valid UUID from the DB point of view and saves the record without returning the ID.
Of course, one option is to always generate the Id on the model not rely on DB generated keys. Another option is always using *uuid.UUID which I assume would continue passing in nil into the INSERT statement. However, I would like to know why this change was made before refactoring a large codebase to reflect it.
The document you expected this should be explained
I would expect to see a CHANGELOG for this, but I don't think there is one.
Expected answer
I can't locate the Scan / Value interface for Google's uuid.UUID in the codebase so I can't tell why the zero uuid.Nil behaviour should change.
NOTES:
I use PG and I can see that Gorm uses jackc/pgx under the hood. However, pgx has its own uuid which is not the same as Google's uuid.UUID which I use.
Comment From: khash
Upon further investigation, the issue is resolved if default:uuid_generate_v4() is added to the model:
type Foo struct {
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()"`
Name string
}
I thought default: is used for migrations for table creation ie id uuid DEFAULT uuid_generate_v4() in SQL. However from 1.24 to 1.25 it affects the behavior of if the primary key is included in the CREATE or not (oddly it's not primary_key tag that has this effect).
So since v1.25, without default: tag, the insert statement will include the id which, if the key is generated in DB, will be passed in as 0000-0000-0000-0000 causing the second insert to violate primary key uniqueness.
With default, id is omitted from the insert statement.
I still don't understand why this was changed and I think this should be documented.