Migrations are failing - postgresql

I'm getting the following error while migrating
2021/06/08 11:01:40 /go/pkg/mod/gorm.io/driver/postgres#v1.1.0/migrator.go:157 ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index" (SQLSTATE 23505)
[18.041ms] [rows:0] CREATE TABLE "users" ("id" bigserial,"created_at" timestamptz,"updated_at" timestamptz,"deleted_at" timestamptz,"email" text UNIQUE,"password" text,PRIMARY KEY ("id"))
2021/06/08 11:01:40 Migration error: ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index" (SQLSTATE 23505)
FAIL github.com/dhis2-sre/instance-manager-api/tests/handler/authentication 0.059s
I suspect that there's an issue with the way I've defined my model. Possible in relation to how I define the relationship between User and Group.
type Group struct {
gorm.Model
Name string `gorm:"unique;"`
Users []User `gorm:"many2many:user_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ClusterConfiguration ClusterConfiguration `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
type ClusterConfiguration struct {
gorm.Model
GroupID uint
KubernetesConfiguration SopsPair `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
// AWSCredentials SopsPair
// AWSConfiguration SopsPair
}
type SopsPair struct {
gorm.Model
ClusterConfigurationID uint
Data string
Format string
}
type Instance struct {
gorm.Model
Name string `gorm:"unique;"`
UserID uint
GroupID uint
StackID uint
RequiredParameters []InstanceRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
OptionalParameters []InstanceOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
}
type InstanceRequiredParameter struct {
gorm.Model
InstanceID uint `gorm:"index:idx_instance_required_parameter,unique"`
StackRequiredParameterID uint `gorm:"index:idx_instance_required_parameter,unique"`
StackRequiredParameter StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
Value string
}
type InstanceOptionalParameter struct {
gorm.Model
InstanceID uint `gorm:"index:idx_instance_optional_parameter,unique"`
StackOptionalParameterID uint `gorm:"index:idx_instance_optional_parameter,unique"`
StackOptionalParameter StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
Value string
}
type Stack struct {
gorm.Model
Name string `gorm:"unique;"`
RequiredParameters []StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
OptionalParameters []StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
type StackRequiredParameter struct {
gorm.Model
StackID uint `gorm:"index:idx_name_required_parameter,unique"`
Name string `gorm:"index:idx_name_required_parameter,unique"`
}
type StackOptionalParameter struct {
gorm.Model
StackID uint `gorm:"index:idx_name_optional_parameter,unique"`
Name string `gorm:"index:idx_name_optional_parameter,unique"`
}
type User struct {
gorm.Model
Email string `gorm:"unique;"`
Password string `json:"-"`
Groups []Group `gorm:"many2many:user_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
Please let me if I should post additional parts of my code.

Related

How to retrieve parent table using child table in Gorm

i'm new to Golang and facing retriving child table data that container id refer to parent table id. In the documentation shows that only the parent can retrieve child using preload method but didn't show how to retrieve reversed back.
(one to many relationship)
Parent Table
type User struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
Email string `json:"email"`
Gender string `json:"gender"`
Alias string `json:"alias"`
RefreshToken *string `json:"refresh_token,omitempty"`
AccessToken *string `json:"access_token,omitempty"`
DateOfBirth *time.Time `json:"date_of_birth"`
LastLoggedIn *time.Time `json:"last_logged_in"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Account []Account `json:"account"`
}
Child Table
type Account struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Name string `json:"name"`
Balance float32 `json:"balance"`
UserId string `json:"user_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Was hoping that can return json like this:
[{
"Id":"xxx",
....
User: {"Id":"xxx"}
}]
I'm not sure is this possible or not but prisma did it, sorry for disturb your time and have a nice day!
You can add which fields you want to preload and how deep to go. Check nested preloading.
In your case, you could do it like the below.
add User field to Account struct:
type Account struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Name string `json:"name"`
Balance float32 `json:"balance"`
UserId string `json:"user_id"`
User *User `json:"user"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
in your method:
var users []User
// Preload Account field inside User struct, and User field inside Account struct
err := db.Preload("Account.User").Find(&users).Error

How to write a migration to add not null in table field GOLANG

I want to alter a column in User Model
type User struct {
gorm.Model
Email string `gorm:"unique;type:varchar(50)"`
Password string
Active bool
FirstName string `gorm:"type:varchar(10)"`
LastName string `gorm:"type:varchar(10)"`
Age int
Gender bool `gorm:"type:boolean"`
MaritalStatus bool `gorm:"type:boolean"`
Address string `gorm:"type:varchar(10)"`
City string `gorm:"type:varchar(10)"`
State string `gorm:"type:varchar(10)"`
Country string `gorm:"type:varchar(10)"`
ContactNoOne string `gorm:"type:varchar(13)"`
ContactNoTwo string `gorm:"type:varchar(13)"`
}
I want to make Email field as not nullable. How to write migration for that?
add not null on tag gorm
type User struct {
...
Email string `gorm:"unique;type:varchar(50);not null"`
...
}
doc : https://gorm.io/docs/models.html
Edit your model, then us AutoMigrate
db.AutoMigrate(&User{})
Documentation: https://gorm.io/docs/migration.html

GORM Change time format in postgresql

I have a problem with time in postgresql table with generic GORM model
gorm.Model
with fields
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
all dates in table have format 2020-04-21 22:05:07.067446
Please Can I change to timstamp(LONG) or something without .067446
Thanks for any Help
You can use BeforeCreate and BeforeUpdate hook for gorm.Model to manually set the value for the database.
Create BaseModel since you can't use type receiver for other package type.
type BaseModel struct {
gorm.Model
}
Then manually set the value CreatedAt and UpdatedAt without nanoseconds
func (b *BaseModel) BeforeCreate() (err error) {
b.CreatedAt = time.Unix(time.Now().Unix(), 0) // Calculate without nanosec
return
}
func (b *BaseModel) BeforeUpdate() (err error) {
b.UpdatedAt = time.Unix(time.Now().Unix(), 0) // Calculate without nanosec
return
}
And then use BaseModel in your DB Model
type Data struct {
BaseModel
Name string
}

how to make correctly has many associations in Golang with go

let say one teacher has many students and student only has one teacher, how to implement it on Gorm Golang ?
my opinion is
type Teacher struct {
gorm.Model
Name string
Student []Student
}
type Student struct {
gorm.Model
Name string
}
is those correct ?? and if not how to make it to be associated? and how about if we query it to create ? should I create another StudentID on it ?
type Teacher struct {
gorm.Model
Name string
}
type Student struct {
gorm.Model
Name string
TeacherId uint `gorm:"TYPE:integer REFERENCES teachers;index"`
}

Do I need to have two different objects to read and to write in my database using gorm (golang)?

gorm tell in the documentation that "Base model definition gorm.Model, including fields ID, CreatedAt, UpdatedAt, DeletedAt, you could embed it in your model, or only write those fields you want":
// Base Model's definition
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
// Add fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`
type User struct {
gorm.Model
Name string
}
// Only need field `ID`, `CreatedAt`
type User struct {
ID uint
CreatedAt time.Time
Name string
}
Following the documentation, I expect to have only one definition of User, so I create an object like that:
type User struct {
gorm.Model
ID uint
CreatedAt time.Time
Name string
}
But if I do a DB.CreateTable(&User{}), I get the following errors from postgres:
(pq: column "id" specified more than once)
(pq: column "created_at" specified more than once)
So I have to have two different objects :
type CreateUser struct {
gorm.Model
Name string
}
type RetrieveUser struct {
gorm.Model
ID uint
CreatedAt time.Time
Name string
}
So I can do a DB.CreateTable(&CreateUser{})
It is very ugly and I must be missing something, any idea?
Ok, just read the code behind gorm.Model and I got my answer.
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
It means I just learned how inheritance works in go !