Closed jinzhu closed 4 years ago
Can the array and map in postgresql be fully supported?
It is possible to fully support it like https://github.com/go-gorm/datatypes, but we haven't started to work on Postgres specified-thing, Pull Request welcome ;)
@jinzhu in v2 how can I get the model table name? Before I can do
db.NewScope(&user).TableName()
, but now?Hi @pioz, you can do it like this, btw, could you let me know your use case?
stmt := &gorm.Statement{DB: DB} stmt.Parse(value) stmt.Table
I need the table name to create a trigger.
I handy shortcut method should be great: db.TableName(&user) => "users"
@jinzhu Could you please add support for generation of migration files like djangos makemigrations? Django's orm is pretty stable, very useful and has lot of good features.
Ref: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-makemigrations
Example Django application with migrations:
https://github.com/stadtulm/cykel/tree/master/bikesharing/migrations
I have imp the migrations with gormV1 due to i am a pythoner as well .Btw Automigrate maybe a better way for modern app.
@jinzhu I am trying to migrate this model:
type User struct {
ID uint64 `gorm:"primary_key;type:bigint unsigned auto_increment"`
Username string
}
type Product struct {
ID uint64
Name string `gorm:"type:varchar(255)"`
CollectorNumber string
Condition string
BundleSize int `gorm:"type:smallint"`
Language string
PropertyType string
UserId uint64 `gorm:"not null;autoincrement:false"`
User *User `gorm:"foreignkey:UserId"`
}
But I get this error:
Error 1075: Incorrect table definition; there can be only one auto column and it must be defined as a key
[0.469ms] [rows:0] CREATE TABLE `products` (`id` bigint unsigned AUTO_INCREMENT,`name` varchar(255),`collector_number` longtext,`condition` longtext,`bundle_size` smallint,`language` longtext,`property_type` longtext,`user_id` bigint unsigned auto_increment NOT NULL,PRIMARY KEY (`id`),CONSTRAINT `fk_products_user` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`))
Seems that gorm try to add auto_increment
option to foreign_key column by default, also if I set in the tag AutoIncrement:false
.
Also, the default type for int
is BIGINT
and for string
is LONGTEXT
. In my opinion, it should be INT
and VARCHAR(255)
(Rails default types).
Seems that gorm try to add
auto_increment
option to foreign_key column by default, also if I set in the tagAutoIncrement:false
.
GORM WON'T add auto_increment
option to foreign_key column by default, but GORM will use your primary key's data type as foreign key's data type to make sure they are using same data type, then we can create a database foreign key.
The issue is caused by you are setting type:bigint unsigned auto_increment
to user's ID, change your User
model to this should be ok.
type User struct {
ID uint64 `gorm:"primary_key;type:bigint unsigned"` // unsigned bigint is uint64's default data type, so it is not necessary.
Username string
}
Also, the default type for
int
isBIGINT
You can use int32
or int16
and for
string
isLONGTEXT
. In my opinion, it should beINT
andVARCHAR(255)
(Rails default types).
Change the DefaultStringSize
when initializing MySQL driver
https://github.com/go-gorm/mysql/blob/544aababdcc9ddc4c75c4056ae46c7c01b07b911/mysql.go#L18-L25
@jinzhu I'm trying to migrate this model:
type User struct {
Id uint64
Email string `gorm:"type:varchar(255);not null;index:,unique"`
Username string `gorm:"type:varchar(255);not null;default:'foo'"`
}
But I get Error 1064: You have an error in your SQL syntax;
:
CREATE TABLE `users` (`id` bigint unsigned AUTO_INCREMENT,`email` varchar(255) NOT NULL,`username` varchar(255) NOT NULL DEFAULT foo,PRIMARY KEY (`id`),INDEX idx_users_email (`email`))
Seems that the default value is not quoted.
How can I set the default value? I need to set also the blank string as default value (name varchar(255) NOT NULL DEFAULT ''
).
Also the index on email field is not unique, also if the tag specify unique
.
Thank you!
@jinzhu I'm trying to migrate this model:
type User struct { Id uint64 Email string `gorm:"type:varchar(255);not null;index:,unique"` Username string `gorm:"type:varchar(255);not null;default:'foo'"` }
But I get
Error 1064: You have an error in your SQL syntax;
:CREATE TABLE `users` (`id` bigint unsigned AUTO_INCREMENT,`email` varchar(255) NOT NULL,`username` varchar(255) NOT NULL DEFAULT foo,PRIMARY KEY (`id`),INDEX idx_users_email (`email`))
Seems that the default value is not quoted. How can I set the default value? I need to set also the blank string as default value (
name varchar(255) NOT NULL DEFAULT ''
).Also the index on email field is not unique, also if the tag specify
unique
. Thank you!
tests passed, make sure you are using latest release of GORM and MySQL driver.
@jinzhu I'm trying to migrate this model:
type User struct { Id uint64 Email string `gorm:"type:varchar(255);not null;index:,unique"` Username string `gorm:"type:varchar(255);not null;default:'foo'"` }
But I get
Error 1064: You have an error in your SQL syntax;
:CREATE TABLE `users` (`id` bigint unsigned AUTO_INCREMENT,`email` varchar(255) NOT NULL,`username` varchar(255) NOT NULL DEFAULT foo,PRIMARY KEY (`id`),INDEX idx_users_email (`email`))
Seems that the default value is not quoted. How can I set the default value? I need to set also the blank string as default value (
name varchar(255) NOT NULL DEFAULT ''
). Also the index on email field is not unique, also if the tag specifyunique
. Thank you!tests passed, make sure you are using latest release of GORM and MySQL driver.
I've upgraded to gorm v0.2.15 and MySQL driver v0.2.6, but the issue persists (I can't find a way to specify a default value). This seems to happen only when I use type:VARCHAR(255);default:'foo'
.
The index is now created correctly (unique).
This seems to happen only when I use type:VARCHAR(255);default:'foo'.
Yes, I can reproduce it with the type:VARCHAR(255);
, fixed it in v0.2.16
.
BTW, it not necessary to set the data type like this, you can just set the size
then GORM can generate type compatible with all database drivers
type User struct {
Name string `gorm:"size:255;not null;index:,unique"`
}
For MySQL, if you want to change all string fields's default size to 255, you can initialize *gorm.DB
like this:
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local",
DefaultStringSize: 255,
}), &gorm.Config{})
This seems to happen only when I use type:VARCHAR(255);default:'foo'.
Yes, I can reproduce it with the
type:VARCHAR(255);
, fixed it inv0.2.16
.
@jinzhu Now works. But, if I use the following tag the default value is not set (default to blank string):
Name string `gorm:"size:255;not null;default:''"`
In this way when I run a query from cli I have to set the name field:
INSERT INTO users (email) VALUES ('foo@bar.com'); -- does not work
INSERT INTO users (email,name) VALUES ('foo@bar.com', '');
I think is this if
https://github.com/go-gorm/gorm/blob/c5feff1591518ba500898dc6d1a5b8eb7bee1092/migrator/migrator.go#L67
@jinzhu Now works. But, if I use the following tag the default value is not set (default to blank string):
Name string `gorm:"size:255;not null;default:''"`
Fixed it, update to v0.2.17, thank you for your report.
@jinzhu I have the follow schema:
CREATE TABLE `users` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`first_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`last_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_users_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
My GO model is:
type User struct {
ID uint64 `faker:"-"`
Email string `gorm:"size:255;not null;index:,unique" faker:"email,unique"`
Username string `gorm:"size:255;not null;default:''"`
FirstName string `gorm:"size:255;not null;default:''"`
LastName string `gorm:"size:255;not null;default:''"`
CreatedAt time.Time `gorm:"type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" faker:"-"`
UpdatedAt time.Time `gorm:"type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" faker:"-"`
}
Now I wish to create a new user with:
u := User{Email: "foo@bar.com"}
db.Create(&u)
but I get the following error:
Error 1292: Incorrect datetime value: '0000-00-00' for column 'created_at' at row 1
[0.544ms] [rows:0] INSERT INTO `users` (`email`,`username`,`first_name`,`last_name`,`created_at`,`updated_at`) VALUES ("foo@bar.com","","","","0000-00-00 00:00:00","0000-00-00 00:00:00")
(notice that is strange that the error message say ...Incorrect datetime value: '0000-00-00' for...
instead of ...Incorrect datetime value: '0000-00-00 00:00:00' for...
)
Is it possible to achieve this behavior, or I need to use a pointer *time.Time
?
I've seen that similar behavior works for string datatype:
type User struct {
ID uint64 `faker:"-"`
...
Username string `gorm:"size:255;not null;default:'foo'"`
...
}
u := User{Email: "foo@bar.com"}
db.Create(&u)
create a record with field username
equal to "foo" (the default value).
@jinzhu, it seems that ignored columns are not being ignored on select.
type Person struct {
Id uuid.UUID `gorm:"column:id;primary_key"`
Code string `gorm:"column:code"`
Name string `gorm:"column:name"`
Email string `gorm:"-"`
}
person := &Person{
Code: "abc",
Email: "test@test.com",
}
if err := db.Where(person).Find(person); err != nil {
panic(err)
}
pq: column person.Email does not exist
SELECT * FROM "person" WHERE "person"."code" = 'abc' AND "person"."Email" = 'test@test.com'
My real case is much more complex than that, I just can't simply not set the field.
@jinzhu I have the follow schema:
CREATE TABLE `users` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `first_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `last_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `idx_users_email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
My GO model is:
type User struct { ID uint64 `faker:"-"` Email string `gorm:"size:255;not null;index:,unique" faker:"email,unique"` Username string `gorm:"size:255;not null;default:''"` FirstName string `gorm:"size:255;not null;default:''"` LastName string `gorm:"size:255;not null;default:''"` CreatedAt time.Time `gorm:"type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" faker:"-"` UpdatedAt time.Time `gorm:"type:DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" faker:"-"` }
Now I wish to create a new user with:
u := User{Email: "foo@bar.com"} db.Create(&u)
but I get the following error:
Error 1292: Incorrect datetime value: '0000-00-00' for column 'created_at' at row 1 [0.544ms] [rows:0] INSERT INTO `users` (`email`,`username`,`first_name`,`last_name`,`created_at`,`updated_at`) VALUES ("foo@bar.com","","","","0000-00-00 00:00:00","0000-00-00 00:00:00")
(notice that is strange that the error message say
...Incorrect datetime value: '0000-00-00' for...
instead of...Incorrect datetime value: '0000-00-00 00:00:00' for...
)Is it possible to achieve this behavior, or I need to use a pointer
*time.Time
? I've seen that similar behavior works for string datatype:type User struct { ID uint64 `faker:"-"` ... Username string `gorm:"size:255;not null;default:'foo'"` ... }
u := User{Email: "foo@bar.com"} db.Create(&u)
create a record with field
username
equal to "foo" (the default value).
If you set the data type to *time.Time
or NullTime
it should work.
But for a CreatedAt
time field, GORM should set current time to the field when creating, it wasn't due to you customized its data type, have fixed this issue in v0.2.18
@jinzhu, it seems that ignored columns are not being ignored on select.
type Person struct { Id uuid.UUID `gorm:"column:id;primary_key"` Code string `gorm:"column:code"` Name string `gorm:"column:name"` Email string `gorm:"-"` } person := &Person{ Code: "abc", Email: "test@test.com", } if err := db.Where(person).Find(person); err != nil { panic(err) }
pq: column person.Email does not exist SELECT * FROM "person" WHERE "person"."code" = 'abc' AND "person"."Email" = 'test@test.com'
My real case is much more complex than that, I just can't simply not set the field.
We have introduced field permission support, supports: readonly, writeonly, createonly, updateonly, ignored
We should use readonly in this case.
type User struct {
Name string `gorm:"<-:create"` // allow read and create
Name string `gorm:"<-:update"` // allow read and update
Name string `gorm:"<-"` // allow read and write (create and update)
Name string `gorm:"->:false;<-:create"` // createonly
Name string `gorm:"->"` // readonly
Name string `gorm:"-"` // ignored
}
@jinzhu, it seems that ignored columns are not being ignored on select.
type Person struct { Id uuid.UUID `gorm:"column:id;primary_key"` Code string `gorm:"column:code"` Name string `gorm:"column:name"` Email string `gorm:"-"` } person := &Person{ Code: "abc", Email: "test@test.com", } if err := db.Where(person).Find(person); err != nil { panic(err) }
pq: column person.Email does not exist SELECT * FROM "person" WHERE "person"."code" = 'abc' AND "person"."Email" = 'test@test.com'
My real case is much more complex than that, I just can't simply not set the field.
We have introduced field permission support, supports: readonly, writeonly, createonly, updateonly, ignored
We should use readonly in this case.
type User struct { Name string `gorm:"<-:create"` // allow read and create Name string `gorm:"<-:update"` // allow read and update Name string `gorm:"<-"` // allow read and write (create and update) Name string `gorm:"->:false;<-:create"` // createonly Name string `gorm:"->"` // readonly Name string `gorm:"-"` // ignored }
I tried the readonly notation, same error.
pq: column person.email does not exist
[17.047ms] [rows:0] SELECT * FROM "person" WHERE "person"."code" = 'abc' AND "person"."email" = 'test@test.com'
The only difference is that the column name is parsed in lowercase.
I tried the readonly notation, same error.
Could you create a reproducible pull request here? https://github.com/go-gorm/playground
Thank you.
I tried the readonly notation, same error.
Could you create a reproducible pull request here? https://github.com/go-gorm/playground
Thank you.
@jinzhu Is the NewRecord method going to be included in v2?
@jinzhu, isn't gorm throwing ErrRecordNotFound anymore?
@jinzhu Is the NewRecord method going to be included in v2?
NewRecord
just checked the primary key value is blank or not, many people misused it, so we decided to remove this method.
@jinzhu, isn't gorm throwing ErrRecordNotFound anymore?
Only throw ErrRecordNotFound
error when you are using First
, Last
, Take
to find a record.
I just tried to convert a project from gorm v1 to gorm v2, the callback API seems to be harder to use, on V1, I was doing:
func beforeCreate(sfn *snowflake.Node) func(*gorm.Scope) {
return func(scope *gorm.Scope) {
id := sfn.Generate().Int64()
if err := scope.SetColumn("ID", id); err != nil {
panic(err)
}
}
}
on V2, this is how I made it work:
func beforeCreate(sfn *snowflake.Node) func(*gorm.DB) {
return func(db *gorm.DB) {
s := reflect.ValueOf(db.Statement.Dest).Elem()
if s.Kind() == reflect.Struct {
f := s.FieldByName("ID")
if f.IsValid() && f.CanSet() {
id := sfn.Generate().Int64()
f.SetInt(id)
}
}
}
}
in both cases, it's registered like this:
db.Callback().Create().Before("gorm:create").Register("snowflake_id", beforeCreate(sfn))
Is there already an easier method available? Do you have plans to add new helpers that may help?
Thank you
I just tried to convert a project from gorm v1 to gorm v2, the callback API seems to be harder to use, on V1, I was doing:
func beforeCreate(sfn *snowflake.Node) func(*gorm.Scope) { return func(scope *gorm.Scope) { id := sfn.Generate().Int64() if err := scope.SetColumn("ID", id); err != nil { panic(err) } } }
on V2, this is how I made it work:
func beforeCreate(sfn *snowflake.Node) func(*gorm.DB) { return func(db *gorm.DB) { s := reflect.ValueOf(db.Statement.Dest).Elem() if s.Kind() == reflect.Struct { f := s.FieldByName("ID") if f.IsValid() && f.CanSet() { id := sfn.Generate().Int64() f.SetInt(id) } } } }
in both cases, it's registered like this:
db.Callback().Create().Before("gorm:create").Register("snowflake_id", beforeCreate(sfn))
Is there already an easier method available? Do you have plans to add new helpers that may help?
Thank you
db.Statement.Schema.LookUpField("ID").Set(db.Statement.ReflectValue, sfn.Generate().Int64())
fyi, I needed to add some additional checks to avoid triggering panic in some cases:
func beforeCreate(sfn *snowflake.Node) func(*gorm.DB) {
return func(db *gorm.DB) {
if db.Statement == nil || db.Statement.Schema == nil || !db.Statement.ReflectValue.IsValid() {
return
}
db.Statement.Schema.LookUpField("ID").Set(db.Statement.ReflectValue, sfn.Generate().Int64())
}
}
@jinzhu, regarding many2many relationship
type User struct {
IdUser int64 `gorm:"column:idUser;primary_key"`
Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"`
}
type Company struct {
IdCompany int64 `gorm:"column:idCompany;primary_key"`
}
db, _ := gorm.Open(sqlite.Open("gorm"), &gorm.Config{
DryRun: true,
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{
LogLevel: logger.Info,
}),
})
db.Model(User{}).Association("Companies").Find([]Company{})
SELECT *
FROM `company`
JOIN `credentials` ON `credentials`.`company_id_company` = `company`.`idCompany`
AND `user_id_user` IN (NULL)
@jinzhu, regarding many2many relationship
type User struct { IdUser int64 `gorm:"column:idUser;primary_key"` Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"` } type Company struct { IdCompany int64 `gorm:"column:idCompany;primary_key"` } db, _ := gorm.Open(sqlite.Open("gorm"), &gorm.Config{ DryRun: true, NamingStrategy: schema.NamingStrategy{ SingularTable: true, }, Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ LogLevel: logger.Info, }), }) db.Model(User{}).Association("Companies").Find([]Company{})
SELECT * FROM `company` JOIN `credentials` ON `credentials`.`company_id_company` = `company`.`idCompany` AND `user_id_user` IN (NULL)
- Naming Strategy seems not to be working properly for junction table
- If I'm not mistaken, ForeignKey and References should do the trick when not following the naming convention
Fixed that, thank you for your report. https://github.com/go-gorm/gorm/commit/2d048d9ece097f86ecf77872ba050c0ce242bfc0
2.0是否支持查询后对数据处理? 类似于获取器的功能!!
I added the SetColumn
method back, also added a new method Changed
, please check out https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft#use-changed-to-check-fields-changed-or-not
@moul
Hi @jinzhu,
Is it possible to continue using the date function in queries in v2?
db.Model(&Object{}).Select("date(last_reading)").Group("date(in_objects.last_reading)")
First of all, Thanks!
@jinzhu, regarding many2many relationship
type User struct { IdUser int64 `gorm:"column:idUser;primary_key"` Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"` } type Company struct { IdCompany int64 `gorm:"column:idCompany;primary_key"` } db, _ := gorm.Open(sqlite.Open("gorm"), &gorm.Config{ DryRun: true, NamingStrategy: schema.NamingStrategy{ SingularTable: true, }, Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ LogLevel: logger.Info, }), }) db.Model(User{}).Association("Companies").Find([]Company{})
SELECT * FROM `company` JOIN `credentials` ON `credentials`.`company_id_company` = `company`.`idCompany` AND `user_id_user` IN (NULL)
- Naming Strategy seems not to be working properly for junction table
- If I'm not mistaken, ForeignKey and References should do the trick when not following the naming convention
Fixed that, thank you for your report. 2d048d9
@jinzhu
SingularTable looks good now, thank you! But I still have issues regarding column naming convention.
I expected this:
SELECT *
FROM `company`
JOIN `credential` ON `credential`.`idCompany` = `company`.`idCompany`
AND `credential`.`idUser` IN (NULL)
But I got this:
SELECT *
FROM `company`
JOIN `credential` ON `credential`.`company_id_company` = `company`.`idCompany`
AND `user_id_user` IN (NULL)
Am I doing something wrong here? Is it possible to set column name in junction table using tags?
Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"`
@jinzhu, regarding many2many relationship
type User struct { IdUser int64 `gorm:"column:idUser;primary_key"` Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"` } type Company struct { IdCompany int64 `gorm:"column:idCompany;primary_key"` } db, _ := gorm.Open(sqlite.Open("gorm"), &gorm.Config{ DryRun: true, NamingStrategy: schema.NamingStrategy{ SingularTable: true, }, Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ LogLevel: logger.Info, }), }) db.Model(User{}).Association("Companies").Find([]Company{})
SELECT * FROM `company` JOIN `credentials` ON `credentials`.`company_id_company` = `company`.`idCompany` AND `user_id_user` IN (NULL)
- Naming Strategy seems not to be working properly for junction table
- If I'm not mistaken, ForeignKey and References should do the trick when not following the naming convention
Fixed that, thank you for your report. 2d048d9
@jinzhu
SingularTable looks good now, thank you! But I still have issues regarding column naming convention.
I expected this:
SELECT * FROM `company` JOIN `credential` ON `credential`.`idCompany` = `company`.`idCompany` AND `credential`.`idUser` IN (NULL)
But I got this:
SELECT * FROM `company` JOIN `credential` ON `credential`.`company_id_company` = `company`.`idCompany` AND `user_id_user` IN (NULL)
Am I doing something wrong here? Is it possible to set column name in junction table using tags?
Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;References:IdCompany"`
https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft#association-improvements
Hi @jinzhu,
Is it possible to continue using the date function in queries in v2?
db.Model(&Object{}).Select("date(last_reading)").Group("date(in_objects.last_reading)")
First of all, Thanks!
Yes, it is expected to work, I just submitted a commit to supporting SQL function for Group. https://github.com/go-gorm/gorm/commit/ee1f46e3a1295f2342e72d5da9dc33f8a2a2a9d5
https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft#association-improvements
I tried using both tags before
Companies []Company `gorm:"many2many:credential;ForeignKey:IdUser;JoinForeignKey:IdUser;References:IdCompany;JoinReferences:IdCompany"`
But GORM still forces the naming convention
SELECT *
FROM `company`
JOIN `credential` ON `credential`.`id_company` = `company`.`idCompany`
AND `id_user` IN (NULL)
This is the expected behavior, GORM will use the default naming convention to convert the specified foreign key, change the default naming strategy here. https://github.com/go-gorm/gorm/blob/master/gorm.go#L22 @seriallink
use Count exec error
var all []Album
var count int64
if key == "*" {
if err := db.Model(&Album{}).Count(&count).Order("id desc").Limit(limit).Offset((page - 1) * limit).Find(&all).Error; err != nil {
return all, 0
}
return all, count
}
I use this code exec is error.
show the log
[0.129ms] [rows:1] SELECT count(1) FROM `albums`
[0.286ms] [rows:1] SELECT count(1) FROM `albums` ORDER BY id desc LIMIT 10
use Count exec error
var all []Album var count int64 if key == "*" { if err := db.Model(&Album{}).Count(&count).Order("id desc").Limit(limit).Offset((page - 1) * limit).Find(&all).Error; err != nil { return all, 0 } return all, count }
I use this code exec is error.
show the log
[0.129ms] [rows:1] SELECT count(1) FROM `albums` [0.286ms] [rows:1] SELECT count(1) FROM `albums` ORDER BY id desc LIMIT 10
Fixed that. https://github.com/go-gorm/gorm/commit/d02b592c6cd276c169ade515b8999132def9e555
@jinzhu We are eagerly waiting for the release of Go ORM V2.0. Lots of my headaches will be solved with version 2.0.
@jinzhu We are eagerly waiting for the release of Go ORM V2.0. Lots of my headaches will be solved with version 2.0.
Hi @SujalKokh, consider migrating your project to v2.0 now :) It has been used in some production services already, and if you found any issues, most of them should be resolved in less than 24 hours.
How do I integrate the Go ORM version 2.0 with my Go app? Running go get -u github.com/jinzhu/gorm
installs GORM version 1.9.14. Please help me.
When will the gorm.io docs be up to date?
@jinzhu will v2 work with qor admin?
Hi,jinzhu, I Use gorm.Model
in my struct and created this , and i Create data not set CreatedAt
and CreatedAt
value, exec this is error, report Trace: reflect: call of reflect.flag.mustBeExported on zero Value
@jinzhu will v2 work with qor admin?
QOR Admin will migrate to GORM v2, but I need to check with the current maintainer for its plan.
When will the gorm.io docs be up to date?
Working on it should be ready in the next two weeks
Hi,jinzhu, I Use
gorm.Model
in my struct and created this , and i Create data not setCreatedAt
andCreatedAt
value, exec this is error, reportTrace: reflect: call of reflect.flag.mustBeExported on zero Value
Please follow the document, if you believe there is an issue, create a PR here https://github.com/go-gorm/playground
@jinzhu Hi I encountered an issue with the JoinForeignKey
and JoinReferences
tags. I made a minimal reproducible test case :
package main
import (
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type ModelA struct {
ID []byte `gorm:"COLUMN:id;TYPE:BINARY(32);PRIMARY_KEY;NOT NULL" json:"id"`
}
type ModelB struct {
ID []byte `gorm:"COLUMN:id;TYPE:BINARY(10);PRIMARY_KEY;NOT NULL" json:"id"`
ModelAs []*ModelA `gorm:"Many2Many:model_a_model_b;ForeignKey:id;References:id;JoinForeignKey:model_a_id;JoinReferences:model_b_id" json:"model_as,omitempty"`
}
func main() {
db, err := gorm.Open(sqlite.Open(":memory:?_foreign_keys=1"), nil)
if err != nil {
log.Fatal(err)
}
err = db.AutoMigrate(
&ModelA{},
&ModelB{})
if err != nil {
log.Fatal(err)
}
}
Results in a panic
panic: reflect.StructOf: field "model_a_id" is unexported but missing PkgPath
goroutine 1 [running]:
reflect.runtimeStructField(0x6cbb6d, 0xa, 0x0, 0x0, 0x744d80, 0x6a7240, 0xc0000e6840, 0x35, 0x0, 0x0, ...)
/usr/lib/go/src/reflect/type.go:2769 +0x1df
reflect.StructOf(0xc00009d2b0, 0x2, 0x2, 0x0, 0x0)
/usr/lib/go/src/reflect/type.go:2385 +0x1e3f
gorm.io/gorm/schema.(*Schema).buildMany2ManyRelation(0xc00018e1c0, 0xc000182090, 0xc000083680, 0x6cbb32, 0xf)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/schema/relationship.go:249 +0xccc
gorm.io/gorm/schema.(*Schema).parseRelation(0xc00018e1c0, 0xc000083680)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/schema/relationship.go:77 +0x9d0
gorm.io/gorm/schema.Parse(0x6a0f00, 0xc0001597a0, 0xc0001595f0, 0x742f00, 0xc000180220, 0x0, 0x0, 0x0)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/schema/schema.go:212 +0x157e
gorm.io/gorm.(*Statement).Parse(0xc00009f1e0, 0x6a0f00, 0xc0001597a0, 0x0, 0x1)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/statement.go:332 +0x5f
gorm.io/gorm/migrator.Migrator.ReorderModels.func1(0x6a0f00, 0xc0001597a0, 0xc000100301)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/migrator/migrator.go:537 +0xce
gorm.io/gorm/migrator.Migrator.ReorderModels(0xc000168c01, 0xc000159620, 0x743a40, 0xc000165010, 0xc000180c20, 0x2, 0x2, 0xc000180c01, 0x20, 0x20, ...)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/migrator/migrator.go:585 +0x5c9
gorm.io/gorm/migrator.Migrator.AutoMigrate(0x5c2a01, 0xc000159620, 0x743a40, 0xc000165010, 0xc000180c20, 0x2, 0x2, 0x743a40, 0xc000165010)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/migrator/migrator.go:83 +0x95
gorm.io/gorm.(*DB).AutoMigrate(0xc000159620, 0xc000180c20, 0x2, 0x2, 0x0, 0x0)
/home/popsulfr/go/pkg/mod/gorm.io/gorm@v0.2.20-0.20200703022618-f93345afa8e1/migrator.go:17 +0x70
main.main()
/home/popsulfr/work/rezom/datascience/dsp2p/cmd/problem/main.go:26 +0x162
exit status 2
Without JoinForeignKey:model_a_id;JoinReferences:model_b_id
it otherwise works. Am I using them wrong ?
the value of JoinForeignKey:model_a_id;JoinReferences:model_b_id
needs to be upper case, but I have handled that in lastest commit. https://github.com/go-gorm/gorm/commit/d4f8a524423baf81aecfc6caf2780eb14e2eb187
Add a way for omitting some columns also on querying, not only on saving.
fyi, I needed to add some additional checks to avoid triggering panic in some cases:
func beforeCreate(sfn *snowflake.Node) func(*gorm.DB) { return func(db *gorm.DB) { if db.Statement == nil || db.Statement.Schema == nil || !db.Statement.ReflectValue.IsValid() { return } db.Statement.Schema.LookUpField("ID").Set(db.Statement.ReflectValue, sfn.Generate().Int64()) } }
I am setting below thing for each request in http middleware.
tx := db.Scopes(func(db *gorm.DB) *gorm.DB { db = db.Set("IP", IP) return db.Set("org_id", ctx.Value("org_id")) }) ctx = context.WithValue(ctx, "tx", tx)
db.Callback().Create().Before("gorm:update").Register("update_org", updateOrg)
db.Callback().Row().Before("gorm:row_query").Register("query_org", queryOrg)
func queryOrg(scope *gorm.DB) {
if scope.HasColumn("org_id") {
orgID, ok := scope.Get("org_id")
if !ok {
return
}
scope.Search.Where(scope.TableName()+".org_id = ?", orgID)
}
func updateOrg(scope *gorm.Scope) {
if scope.HasColumn("org_id") {
orgID, ok := scope.Get("org_id")
if !ok {
return
}
scope.Search.Where(scope.TableName()+".org_id = ?", orgID)
}
}
Can you please give the replacement for the above thing. @jinzhu @moul
I have finished the draft v2 documents, please check it out http://v2.gorm.io (will use http://gorm.io after the final release)
Closing this issue, please create a new issue on any bug report or suggestion.
Tried out GORM v2 and it is fantastic. However, I am having difficulty finding a proper way of implementing migrations. Can we expect a migration for v2 similar to that of Ruby on Rails/Django @jinzhu ? The problem is that once I run the auto-migration I need to manually delete or update the names of the column of tables if it requires changes.
Hello All,
GORM v2 is under active development (https://github.com/jinzhu/gorm/tree/v2_dev), going to release in the next two months.
Before that, I am NOT going to merge any pull requests based on the master branch.
V2 will be overwritten from scratch with similar public API, it would focus on performance, improve usability and fix fragile designs. We will provide a migration guide to help users migrate before the release.
With the new architecture, it opens the possibility to have a better migration tool, a static code generator that generates type-safe code with all the features of GORM, visualizes models and its relationships to help a new team member quickly understand your project, and even support Redis & MongoDB...
Your code review or suggestions would be much appreciated, please comment to this thread, thank you.