go-gorm / gen Goto Github PK
View Code? Open in Web Editor NEWGen: Friendly & Safer GORM powered by Code Generation
Home Page: https://gorm.io/gen/
License: MIT License
Gen: Friendly & Safer GORM powered by Code Generation
Home Page: https://gorm.io/gen/
License: MIT License
support custom field types
希望在DIY method中支持更多语法,例如数组遍历:
type Method interface {
/* select * from @@table
{{where}}
{{ range $idx, $elem := @names }}
{{ if $idx }} or {{ end }} name={{ $elem }}
{{ end }}
{{end}}
*/
FindByNames(names []string) ([]gen.T, error)
}
如果能像go template一样注册自定义函数就更好了
DIY method编写raw sql能力受限
希望在关联查询时,可以指定select字段,例如有下面两个表:
type A struct {
gorm.Model
B *B
... // other fields
}
type B struct {
gorm.Model
AID uint
Config string
... // other fields
}
关联查询b表:
ax := a.WithContext(ctx).Joins(a.B)
ax.Where(a.ID.Eq(1)).Take()
当b表字段较多时,希望select b表的指定字段,例如:
ax := a.WithContext(ctx).Joins(a.B.Select(b.Config))
ax.Where(a.ID.Eq(1)).Take()
不支持这样的写法:
ax := a.WithContext(ctx).Select(a.ALL, b.Config).Joins(a.B)
ax.Where(a.ID.Eq(1)).Take()
type Method interface {
// select * from @@table where id=@id
FindUserById(id int64) (gen.T, error)
}
g.ApplyInterface(
func(method models.Method) {},
g.GenerateModel("user"),
g.GenerateModel("role"),
)
I want the interface Method to apply only to user, but now it will generate two func FindUserById applied to user and role, respectively.
How to distinguish func for different model in interface Method
How to use for update
in gen
?
When I use Clauses(clause.Locking{Strength: "UPDATE"}).Find()
just like in gorm
, I got a err clause FOR is banned
create examples folder in project
Add exists model only has relationship, and gorm tag should be -
gen.FieldRelateModel("has", "A", model.A{}, &field.RelateConfig{GORMTag: "-"})
Wanna simplify this part of code, and change "has" to constant
For example: Preloading..........
SQL: update a set b = b + 1, c = c + 1 where d = 4
Code:
Updates(map[string]interface{}{
q.B.ColumnName().String(): q.B.Add(1)).RawExpr(),
q.C.ColumnName().String(): q.C.Add(1).RawExpr(),
})
Provide a way to simply this action to reduce code
批量生成数据表(所有表、部分表)的CURD。并支持go generate
提供一个二进制的可执行文件,在当前目录下执行,获取当前目录
通过cmd
传入:dbDSN tableList(为空则默认生成全部DB的) 输出路径(./Dal/query) 等Args来生成Safe CURD
依赖gorm 的go-gorm/gorm#4841
@dino-ma 自己提的Issue 自己解决。
我是用的组合得到如下sql:
q.User.Preload(q.User.UserInfo).
Where(q.User.ID.Eq(1)).
Or(q.User.Username.Eq("a")).
Or(q.User.Token.Eq("b")).
Select(q.User.ID.Sum().As("count")).
Scan(&ud)
SELECT SUM(users
.id
) AS count
FROM users
WHERE (users
.id
= 1 OR users
.username
= 'a' OR users
.token
= 'b') AND users
.deleted_at
IS NULL
但是我想要得到这样的sql:
SELECT SUM(users
.id
) AS count
FROM users
WHERE users
.id
= 1 AND ( users
.username
= 'a' OR users
.token
= 'b') AND users
.deleted_at
IS NULL
将两个or与其余的条件用and连接
u := query.Use(db).User
do := u.WithContext(ctx)
do.Where(u.ID.Eq(1)).Updates(model.User{ID: 1, Name:"first"})
// UPDATE `users` SET `name`='first' WHERE `users`.`id` = 1
do.Where(u.ID.Eq(2)).Updates(model.User{Name:"second"})
// UPDATE `users` SET `name`='second' WHERE `users`.`id` = 1 AND `id` = 2
生成的 GetFieldByName()
方法返回的对象为field.Expr
无法调用
func (e expr) Desc() Expr {
return e.setE(clause.Expr{SQL: "? DESC", Vars: []interface{}{e.RawExpr()}})
}
导致前端发送的对某个字段的Desc
排序需求我无法实现,因为获取不到具体的 field.type。
How to use gorm.io/datatypes
JSON type and JSONQueryExpression?
How to achieve the previous effect?
gen code by the https://github.com/go-gorm/gen#quick-start, RT
最新版
代码:
var total int64
u.WithContext(ctx).SELECT(u.xxx.Sum()).Scan(&total)
当 sum 的列值为 null 时报错:
GORM LOG SELECT SUM(`xxx`) FROM `table` WHERE `condition`, Error: sql: Scan error on column index 0, name "SUM(`xxx`)": converting NULL to int64 is unsupported
// gorm version: v1.21.15
// gen version: v0.0.16
user := query.NewUser(db)
_, _, _ = user.Model(&models.User{}).FindByPage(0, 5) // is ok
_, _, _ = user.FindByPage(0, 5) // is ok
_, _, _ = user.Model(&models.User{}).Where(user.ID.In(1, 2)).FindByPage(0, 5) // is ok
_, _, _ = user.Where(user.ID.In(1, 2)).FindByPage(0, 5) // panic
I found that using Where and FindByPage at the same time will panic.
I hope to fix it ASAP.
非常赞的的发现已经加上 example 了, 同时使用了一下, 发现 model 也是一并生成的, 理解这个对于已经存在的使用 gorm 的项目不是很友好? 因为会重新生成 model, 所以想问下是否可以仅生成 query
In the method func (t tDo) FindInBatches)
generated for each of models by the template below:
gen/internal/template/method.go
Lines 154 to 156 in d2560a6
Could the 1st parameter result
need to be an pointer to slice? Otherwise the caller can't read the result of each batch.
希望可以在where语句中支持raw sql查询,例如对于q表:
id | config |
---|---|
1 | {"id_list": [1,2,3]} |
2 | {"id_list": [2,3,4]} |
执行如下查询:
select * from q where JSON_CONTAINS(q.config, 1, "$.id_list")
一种预期调用方式:
id := 1
cond := q.Config.CondRaw(`JSON_CONTAINS(@col, ?, "$.id_list")`, id)
q.WithContext(ctx).Where(cond).Take()
这样就可以实现复杂条件的组合,例如:
qx := q.WithContext(ctx)
idList := []int{1, 2, 3}
for _, id := range idList {
cond := q.Config.CondRaw(`JSON_CONTAINS(@col, ?, "$.id_list")`, id)
qx = qx.Or(cond)
}
qx.Take()
也可以融合到更复杂的join条件中,例如:
px := p.WithContext(ctx).LeftJoin(q, q.ID.EqCol(p.QID))
px = px.Where(p.ID.Eq(1))
idList := []int{1, 2, 3}
for _, id := range idList {
cond := q.Config.CondRaw(`JSON_CONTAINS(@col, ?, "$.id_list")`, id)
px = px.Where(cond)
}
px.Take()
DIY method不能很好支持复杂SQL查询
通过 query.Use(db) 拿到的 Query 对象放在全局变量里使用,还是需要在每次使用的时候重新获取一下。
当我将Query放到全局变量后,有时会在在构建查询时多出一些不在当前查询里的where条件出现。
Provide a field option combine all field options like FieldRename/FieldType/FieldJSONTag...
Configure table field more conveniently
SQL:
": syntax error [0.042ms] [rows:0] CREATE TABLE
abc_table (
id integer,
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
emr_time datetime NOT NULL DEFAULT 0000-00-00 00:00:00,PRIMARY KEY (
id)) Error: AutoMigrate(&model.Diagnose{}) fail: near "-": syntax error=== RUN Test_diagnoseQuery
I think we need to support datetime
在编码过程中,经常会遇到用某个数值来表示某种状态、类型或者阶段的情况,比如有这样一个枚举:
public enum ComputerState {
OPEN(10), //开启
CLOSE(11), //关闭
OFF_LINE(12), //离线
FAULT(200), //故障
UNKNOWN(255); //未知
private int code;
ComputerState(int code) { this.code = code; }
}
通常我们希望将表示状态的数值存入数据库,即ComputerState.OPEN存入数据库取值为10。
能否通过field comment的中备注,来生成对应枚举值
比如可以约定注释检查规则的正则表达式如下
REMARKS_PATTERN = ".*\\s*\\[\\s*(\\w+\\s*\\(\\s*[\\u4e00-\\u9fa5_\\-a-zA-Z0-9]+\\s*\\)\\s*:\\s*[\\u4e00-\\u9fa5_\\-a-zA-Z0-9]+\\s*\\,?\\s*)+\\s*\\]\\s*.*";
CREATE TABLE `tb` (
`type` smallint(3) COMMENT '注释[success(0):成功, fail(1):失败]',
);
提取出字段属性相应的枚举
type Type int
const (
Success Type = 0 //成功
Fail Type = 1 //失败
)
database:Mysql
i want gen SQL like this:
SELECT
IFNULL(AVG(IF(ad_d.fix_cost_time > 0, ad_d.duration, NULL)), 0) AS avg_duration,
IFNULL(AVG(IF(ad_d.fix_cost_time > 0, ad_d.fix_cost_time, NULL)), 0) AS avg_fix_cost_time
FROM xxxx
Where
-- omit
i write code like:
query.Q.XXXX.WithContext(ctx).Select(XXX.FixCostTime.Avg())......
How do I pass conditions to aggregation function?
JSON tag naming style can be configurable,
various options like (e.g. snake case or camel case), by default use columnName
希望可以增加一个生成Paginate方法的功能
感觉分页数据的查询一直是一个头疼的问题
例如:
g.ApplyPaginate(&model.User{})
生成的方法:
type Paginator struct {
TotalItem int
TotalPage int
Page int
Items []gen.T
}
type Param struct{
Size int
Page int
}
Paginate(param *Param) (result *Paginator, err error) {}
使用:
u := query.Use(db).User
u.Paginate(&query.Param{Size:10,Page:1})
Accept config file and parse config from file. And accept command line parameters in the meanwhile.
Command line has higher priority.
gentool -c ./conf/gen.yml
# specify dsn instead of using configuration in file
gentool -c ./conf/gen.yml -dsn <dsn>
使用 gorm.DB 执行没有问题
func (r Repo) GetSimpleInfo1(ctx context.Context, search ...func(db *gorm.DB) *gorm.DB) ([]*model.Staffs, error) {
db := r.data.GetDb(ctx)
var result []model.Staffs
db.WithContext(ctx).
Scopes(search...).Find(&result)
fmt.Printf("result:%v", result)
return nil, apiErrors.ErrorAuthErr("ssss")
}
sql : SELECT * FROM oa_staffs
WHERE ((real_name like '%' or username like '%')) AND id IN (1,2) LIMIT 5
使用gen.Scopes 出现 search 查询条件重复,重复参数对应 search请求次数
func (r Repo) GetStaffsTotal(ctx context.Context, search ...func(dao gen.Dao) gen.Dao) (int32, error) {
this := r.data.Query(ctx).Staffs
total, err := this.WithContext(ctx).Scopes(search...).Count()
if err != nil {
return 0, err
}
return int32(total), nil
}
sql SELECT count(*) FROM oa_staffs
WHERE oa_staffs
.id
IN (1,2) AND oa_staffs
.id
IN (1,2) AND oa_staffs
.id
IN (1,2)"
The association already supports existing models, so how to support generation?
Able to complete the use of association
add a new function to support update multiple columns from subquery
we always need to update multiple columns of one table and set these columns' value from a subquery, like following sql:
UPDATE table1
SET (column_name1, column_name2... ) = (
SELECT (column_name1, column_name2...)
FROM table2
WHERE column_name = value )
WHERE column_name = value
Why can't I use custom datatype(implement clause.Expression interface) ?
How to use DIY condition?
Separate gorm_generated.go file into query.go and others.
Just want to separate the files for easy opening and viewing, its file row count will expand rapidly as the table grows now
对象有效,可以从DB中获取数据。
但是传入gen后,没办法读取表结构。
//查询返回的数据
orderData.ID: 1384821646614859776
//gen执行的过程
2021/11/03 17:47:50.269758 generator.go:262: got 0 columns from table
2021/11/03 17:47:50.320858 generator.go:262: got 0 columns from table <orders_medical_advice>
2021/11/03 17:47:50.336705 generator.go:262: generate query file: /Users/mashengjie03/Work/code/heytea/cmd/dal/query/gen.go
2021/11/03 17:47:50.336723 generator.go:262: Generate code done.
wechat 9393103
panic: generate struct fail
goroutine 1 [running]:
gorm.io/gen.(*Generator).GenerateModelAs(0xc000166f00, {0xbf0003, 0x31}, {0xc00032b810, 0x0}, {0x0, 0x0, 0xc000322150})
/home/xxx/xxx/go/pkg/mod/gorm.io/[email protected]/generator.go:166 +0x2cd
gorm.io/gen.(*Generator).GenerateModel(0xc000166f00, {0xbf0003, 0x12}, {0x0, 0x0, 0x0})
/home/xxx/xxx/go/pkg/mod/gorm.io/[email protected]/generator.go:150 +0x73
main.main()
/home/xxx/xxx/GolandProjects/sdk-server/cmd/generate/generate.go:19 +0xc5
Does it support clickhouse, i used driver that gorm/clickhouse.
method里的自定义方法并不是适用于所有的model,但是现在好像所有方法里都生成了
SQL: update a set b = b + 1, c = c + 1 where d = 4
I checked the docs and I can't seem to find the relevant method
A solution to build
很多公司都要求单测90%,而其中DB这一层要么使用Mock要么使用SQLLite去写单测,既然已经有了GEN这个基于GORM的工具,那么是否可以把单测也直接搞定。
how to Override References?
When you assign credit cards to a user, GORM will save the user’s ID into credit cards’ UserNumber field.
type User struct {
gorm.Model
MemberNumber string
CreditCards []CreditCard gorm:"foreignKey:UserNumber"
}
type CreditCard struct {
gorm.Model
Number string
UserNumber string
}
i want able to change it with tag references, e.g:
type User struct {
gorm.Model
MemberNumber string
CreditCards []CreditCard gorm:"foreignKey:UserNumber;references:MemberNumber"
}
type CreditCard struct {
gorm.Model
Number string
UserNumber string
}
gen.FieldRelate
use check.BaseStruct
which is in an internal package.
So end users will get use of internal package gorm.io/gen/internal/check not allowed
希望有一个能生成所有table对应的model ,谢谢
db, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
g.UseDB(db)
g.ApplyBasic(生成所有table对应的model)
what's the difference between gorm and gen? what's their usage differences?
// definition
// ...
Visible bool `json:"visible" gorm:"column:visible"`
Shareable bool `json:"shareable" gorm:"column:shareable"`
// ...
problem, err := p.Where(p.Visible.Is(true)).Where(p.ID.Eq(id)).First()
err:
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? AND `problem`.`id` = ? ORDER BY `problem`.`id` LIMIT 1' at line 1
debug sql:
SELECT * FROM `problem` WHERE `problem`.`visible` IS true AND `problem`.`id` = 1 ORDER BY `problem`.`id` LIMIT 1
I use this sql in cli is ok.
How to use bool type in query?
当我使用全局变量*Query是,preload预加载的on条件会错误:
q := query.Use(db)
go func() {
u := q.User
ui := q.UserInfo
ctx1 := context.Background()
u.WithContext(ctx1).
Preload(u.UserInfo.WithContext(ctx1).On(ui.ShopID.Eq(11))).
Where(u.ID.Eq(1)).
First()
}()
go func() {
u := q.User
ui := q.UserInfo
ctx2 := context.Background()
u.WithContext(ctx2).
Preload(u.UserInfo.WithContext(ctx2).On(ui.ShopID.Eq(12))).
Where(u.ID.Eq(2)).
First()
}()
这时的sql是这样的:
SELECT * FROM `user_infos` WHERE `user_infos`.`user_id` = 2 AND `user_infos`.`shop_id` = 12
SELECT * FROM `users` WHERE `users`.`id` = 2 AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
SELECT * FROM `user_infos` WHERE `user_infos`.`user_id` = 1 AND `user_infos`.`shop_id` = 12 AND `user_infos`.`shop_id` = 11
SELECT * FROM `users` WHERE `users`.`id` = 1 AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
可以看到,其中一个user_infos的查询条件中带入了另一个的条件。
但是当我在每个协程中都重新拿到query对象时就是正常的,比如:
go func() {
q := query.Use(db)
u := q.User
ui := q.UserInfo
ctx1 := context.Background()
u.WithContext(ctx1).
Preload(u.UserInfo.WithContext(ctx1).On(ui.ShopID.Eq(11))).
Where(u.ID.Eq(1)).
First()
}()
go func() {
q := query.Use(db)
u := q.User
ui := q.UserInfo
ctx2 := context.Background()
u.WithContext(ctx2).
Preload(u.UserInfo.WithContext(ctx2).On(ui.ShopID.Eq(12))).
Where(u.ID.Eq(2)).
First()
}()
这样的话表现就一切正常
Support adding custom tag, and optional naming strategy(camelcase, underscore etc)
Share model to support bson
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.