Gorm - upgrading columns constraint with migration - go

How do you perform a Migration with gorm? For example, I need to add a constraint to a column. I changed my model (simplified example below), but the AutoMigrate method, according to the docs, will not change column's constraints.
How do you achieve it then? I cannot find anything useful in the docs
Starting model:
type User struct {
gorm.Model
Name string
}
I would like to update it like this:
type User struct {
gorm.Model
Name string `gorm:"not null"`
}

When adding a not null constraint, then a default value will also need to be added for when the existing records do not meet the new criteria. The definition could be something like:
type User struct {
gorm.Model
Name string `gorm:"not null;default:'fillertext'"`
}
As #putu said, ALTER TABLE will certainly work, but you would still need to add a default value initially to ensure the non-comforming rows meet the new requirements. Once this has been done you can remove the default value if you desire and the migration will work as intended from that point on.

Related

Should I explicitly create a relation symmetrical to "Belongs To" or "Has Many"?

I am new to ORM (and GORM) so apologies if this is an obvious question, but it does not seem to be covered by the documentation.
I will be using the examples from the documentation as a base to my questions
Question 1: Belongs To
// `User` belongs to `Company`, `CompanyID` is the foreign key
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
ID int
Name string
}
A User belongs to one Company only → this is handled by the code
above
A Company has many User → is this implied by the code
above? Or should I add somehow a relation O2M in Company?
Question 2: Has Many
// User has many CreditCards, UserID is the foreign key
type User struct {
gorm.Model
CreditCards []CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
A User has 1+ CreditCard→ this is handled by the code
A CreditCard can belong to several users (say, a shared family CC) → is it implied? (if not: how to set up the O2M relationship).
Or is it, instead, a case where a CreditCard is explicitly configured to belong to only one user?
Q1: Based on how you defined your structs, you don't need an explicit O2M relationship in the Company struct, but when loading Company details, if you want to load all users that are assigned to that specific company, you need to add that field as well. It will need an additional function call like Preload or Joins, but you shouldn't need an explicit definition of this relationship.
type Company struct {
ID int
Name string
Users []User
}
Q2: The way the relationship is defined now, it is configured so that a CreditCard belongs to only one user. If you want a many2many relationship, you need to specify the relation table. There is more documentation on it here, but it should look something like this:
type User struct {
gorm.Model
CreditCards []CreditCard `gorm:"many2many:users_creditcards"`
}
type CreditCard struct {
gorm.Model
Number string
}

Gorm not giving correct inserted record's primary key ID

I am using GORM with GO.
I have an entity User
type User struct {
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
Name string `json:"name"`
gorm.Model
}
My Create record code is
user := User{}
user.Name = "Afzal"
DB.Create(&user)
Now as per Doc user.ID should return inserted data's primary key
But it's returning 0 which is the default value when struct User was initialized.
User.Id will have the correct value, because you've added that field and tagged it as being the primary key. user.ID actually accesses user.Model.ID. This, too, has the primaryKey tag, but it's superseded by the Id field on your User type.
You've embedded the gorm.Model type (as per the docs, I imagine), but that means your User type actually looks like this:
User{
Id int
Name string
gorm.Model{
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}
}
So when you look at user.ID, you're accessing the embedded ID field. Either check the Id field (lower-case d), or remove the Id field you've added, and rely on the ID from the embedded Model.
If you do want to keep your own Id field, I think the gorm.Model is right to make it a uint. If you're needing to faff around with negative ID elements in your data, you're probably doing something wrong... I've seen negative ID's being used, but every time I saw it happen, it was some absolutely horrible hack.

Defining Belongs To relation for anonymous field using GORM

I wanted to create relationnal database structure in a using the go package Gorm.
I wanted to add foreign keys to my structure, it works perfectly on regular field, but it does not seem to work when I want to make foreign key for anonymous fields.
Here is some simplified code to demonstrate my case
type StructA struct {
gorm.Model
SimpleFieldID int // appears in database as foreign key
SimpleField StructB
TranslationID int // appears in database as a regular int
Translation
}
type StructB struct {
gorm.Model
SomeField string
SomeOtherField string
}
type Translation struct {
gorm.Model
En string
Fr string
}
I wanted to have anonymous field in the first place to be able to call some GetName() method on any object that has the Translation attribute.
I found this question, but the given anwser was for the has-one relation, where I want to use a belongs-to relation.

Go migration doesn't create a foreign key

My first day with Go. I try to develop a migration mechanism with GORM within Revel.
These are my model structs:
type Role struct {
gorm.Model
Name string
}
type User struct {
gorm.Model
Name string
Role Role `gorm:"foreignkey:RoleIdForRole;association_foreignkey:Id"`
}
I simply automigrate both structs as follows, which work fine. I see tables called users and roles but users table doesn't have a field role_id or roleID
db.AutoMigrate(&models.Role{})
db.AutoMigrate(&models.User{})
What am I missing?
I found a solution.
First of all, although Tim Brown's answer is a valid answer compatible with documentation, it doesn't work. As mentioned in many forum posts and github issues, GORM foreign key is not autogenerated as told in the documentation.
But this helps:
db.Model(&models.User{}).AddForeignKey("role_id", "roles(id)", "RESTRICT", "RESTRICT")
Shortly you need to set foreign keys just after migrating the tables.
You need a RoleID column, and if you name it that you wouldn't need to declare the foreignkey either.
type User struct {
gorm.Model
Name string
RoleID int `gorm:"column:RoleIdForRole"`
Role Role
}
See this page for more info

Go-Gorm: will the foreignkey be auto-populated when I set an object?

In the documentation we have this example:
type User struct {
gorm.Model
Name string
}
// `Profile` belongs to `User`, `UserID` is the foreign key
type Profile struct {
gorm.Model
UserID int
User User
Name string
}
If I do something like profile.User = &user, will that automatically populate the UserID field? Is it recommended to set both? Like:
profile.User = &user
profile.UserID = &user.ID
Or is that pointless? Furthermore, could I alternatively just set the UserID field and ignore the User field entirely?
If I do something like profile.User = &user, will that automatically populate the UserID field?
Just writing profile.User = &user will not populate the UserID field. Once you add the profile to the database. gorm will automatically populate the foreign key.
Is it recommended to set both?
Nope. In fact, you should not set the UserID yourself. This answers the last question as well.

Resources