Join table with non-primary key in GORM - go

I am trying to retrieve the information of an author based on a field in BookData that is not a primary key. Below you can see I have AuthorId in my BookData table and I am trying to get the author based on that AuthorId even though it is not the primary key. It seems GORM does not support this type of join, is there a way to do this?
You can also see below that I am able to properly get the PublisherProperty information because it's foreign key is BookData's primary key. I am just wondering how to do it if it not the primary key. Thanks in advance!
type BookData struct {
Id string `gorm:"primary_key;column:book_id"`
AuthorId string `gorm:"column:author_id"`
Author AuthorData `gorm:"foreignkey:AuthorId"`
PublisherProperty []PublisherProperty `gorm:"foreignkey:Id"`
}
type AuthorData struct {
Id string `gorm:"primary_key;column:author_id"`
Name string `gorm:"column:author_name"`
}
type PublisherProperty struct {
Id string `gorm:"primary_key;column:book_id"`
PublisherId string `gorm:"primary_key;column:publisher_id"`
PublisherTxt string `gorm:"column:publisher_txt"`
}

Related

How to insert a empty string to foreign key in gorm?

I have a Test table in gorm that looks like this:
type Test struct {
gorm.Model
UserID string `gorm:"index"`
TradeID string // another table foreign key
Description string
}
And I'm trying to insert a data with a empty trade from frontend form:
// front json, trade_id is empty
{
"user_id":"user-1",
"trade_id":"",
"description":"test"
}
This fails because the Test structs defaults the string value of the key to "" so the insert fails at the db level because foreign key constraint fails.
How can I do this?

Gorm belongs-to relation with same foreignKey and referenced primary key name

Gorm have a strange bug when i'm unable to use automatic table creation. If i use same primary key field name as referenced foreign key from other table, it can't handle it properly.
Working example - User.ComID references to Company.ID:
type User struct {
gorm.Model
ComID string
Company Company `gorm:"foreignKey:ComID;references:ID"`
}
type Company struct {
ID string `gorm:"primaryKey"`
}
produces followin auto-migration sequence with:
CREATE TABLE "companies" ("id" text,"name" text,PRIMARY KEY ("id"))
CREATE TABLE "users" ("id" bigserial,"created_at" timestamptz,"updated_at" timestamptz,"deleted_at" timestamptz,"name" text,"com_id" text,PRIMARY KEY ("id"),CONSTRAINT "fk_users_company" FOREIGN KEY ("com_id") REFERENCES "companies"("id"))
but if i change ID of second table to ComID
type User struct {
ComID string
Company Company `gorm:"foreignKey:ComID;references:ComID"`
}
type Company struct {
ComID string `gorm:"primaryKey"`
}
everything stops working. Gorm try to execute incorrect sql code, table users does not exists at that moment.
CREATE TABLE "companies" ("com_id" text,"name" text,PRIMARY KEY ("com_id"),CONSTRAINT "fk_users_company" FOREIGN KEY ("com_id") REFERENCES "users"("com_id"))
Any ideas how i can supply gorm with correct description (except creating different column names)?
If it matters, the dialect of sql is Postgres in this case.
gorm don't allow it:
references include self fields
you can change the code: relationship.go line 559
if ref.OwnPrimaryKey {
constraint.Schema = ref.ForeignKey.Schema
constraint.ReferenceSchema = rel.Schema
} else {
constraint.Schema = rel.Schema
constraint.ReferenceSchema = ref.PrimaryKey.Schema
}
to
if false {
constraint.Schema = ref.ForeignKey.Schema
constraint.ReferenceSchema = rel.Schema
} else {
constraint.Schema = rel.Schema
constraint.ReferenceSchema = ref.PrimaryKey.Schema
}
and if you run
db.Debug().AutoMigrate(User{})
you will see it:
CREATE TABLE "companies" ("com_id" text,"name" text,PRIMARY KEY ("com_id"),CONSTRAINT "fk_users_company" FOREIGN KEY ("com_id") REFERENCES "users"("com_id"))

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.

One-to-many recursive relationship in GORM

I need to have an Organization which have relation to parent one. Something like this:
type Organization struct {
gorm.Model
Parent *Organization `gorm:"ForeignKey:ParentId"`
Name string `gorm:"size:30"`
Description string `gorm:"size:100"`
}
I want to have ParentId field which will be referenced to id field in the same table. But as I see there is no field and relation.
How can I fix it ?
I have solved it like this, but I am not sure that it is a correct way:
type Organization struct {
gorm.Model
Parent *Organization
ParentId int `gorm:"TYPE:integer REFERENCES organizations"`
Name string `gorm:"size:30"`
Description string `gorm:"size:100"`
}

How to create self-referenced association field

I'm trying to create self-reference field using gorm:
type Post struct {
ID uint `gorm:"primary_key" json:"id"`
Post *Post `json:"post" xml:"post" sql:"default:null"`
}
db.AutoMigrate(&Post{})
Column post_id is not created in DB. Tried several struct field names, no luck.
Which is the correct way to handle self-refrenced associations?
Thank you.
The Gorm magic isn't in the association (foreign key) part but in the data part.
Gorm will do the sql joins to retrieve the related Post row based on PostID It will then store that data in the nested Post field in Post.
If you only provide Post without PostID Gorm will do nothing as there is no foreign key for it to work with.
type Post struct {
ID uint `gorm:"primary_key" json:"id"`
Post *Post `json:"post" xml:"post" sql:"default:null"`
PostID uint `json:"post_id" xml:"post_id"`
}
db.AutoMigrate(&Post{})

Resources