Skip to content

Commit

Permalink
better example and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dirac-lee committed Jun 7, 2023
1 parent 6ad62cf commit 504b922
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 59 deletions.
10 changes: 6 additions & 4 deletions example/dal/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
// @Description:
package model

import "time"
import (
"time"
)

// User db model struct, will be mapped to row of db by ORM.
type User struct {
Expand Down Expand Up @@ -34,9 +36,9 @@ type UserWhere struct {
type UserUpdate struct {
ID *int64 `sql_field:"id"`
Name *string `sql_field:"name"`
Balance *int64 `gorm:"column:balance"`
BalanceAdd *int64 `gorm:"column:balance" sql_expr:"+"`
BalanceMinus *int64 `gorm:"column:balance" sql_expr:"-"`
Balance *int64 `sql_field:"balance"`
BalanceAdd *int64 `sql_field:"balance" sql_expr:"+"`
BalanceMinus *int64 `sql_field:"balance" sql_expr:"-"`
UpdateTime *time.Time `sql_field:"update_time"`
Deleted *bool `sql_field:"deleted"`
}
118 changes: 83 additions & 35 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,35 @@ import (
"github.com/dirac-lee/gdal/example/dal"
"github.com/dirac-lee/gdal/example/dal/model"
"github.com/dirac-lee/gdal/gutil/gptr"
"github.com/luci/go-render/render"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
"os"
"time"
)

var (
DB *gorm.DB
)

const (
DemoDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
MysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
)

func main() {
debug := os.Getenv("DEBUG")
fmt.Println(debug)
db, err := gorm.Open(mysql.Open(DemoDSN))
var err error
DB, err = gorm.Open(mysql.Open(MysqlDSN))
if err != nil {
panic(err)
}

RunMigrations()

ctx := context.Background()
userDAL := dal.NewUserDAL(db)
userDAL := dal.NewUserDAL(DB)

{ //创建单条记录
{ // create single record
now := time.Now()
po := model.User{
ID: 110,
Expand All @@ -38,10 +45,11 @@ func main() {
UpdateTime: now,
Deleted: false,
}
userDAL.Create(ctx, &po)
err := userDAL.Create(ctx, &po)
fmt.Println(err)
}

{ // 创建多条记录
{ // multiple create
now := time.Now()
pos := []*model.User{
{
Expand All @@ -61,71 +69,72 @@ func main() {
Deleted: false,
},
}
userDAL.MCreate(ctx, &pos)
}

{ // 物理删除
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
userDAL.Delete(ctx, where)
}

{ // 通过ID物理删除
userDAL.DeleteByID(ctx, 130)
numCreated, err := userDAL.MCreate(ctx, &pos)
fmt.Println(numCreated)
fmt.Println(err)
}

{ // 更新
{ // update by where condition
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
update := &model.UserUpdate{
BalanceAdd: gptr.Of[int64](10),
}
userDAL.MUpdate(ctx, where, update)
numUpdate, err := userDAL.MUpdate(ctx, where, update)
fmt.Println(numUpdate)
fmt.Println(err)
}

{ // 通过 ID 更新
{ // update by id
update := &model.UserUpdate{
BalanceMinus: gptr.Of[int64](20),
}
userDAL.UpdateByID(ctx, 130, update)
err := userDAL.UpdateByID(ctx, 130, update)
fmt.Println(err)
}

{ // 通用查询
{ // general query
var pos []*model.User
where := &model.UserWhere{
NameLike: gptr.Of("dirac"),
}
userDAL.Find(ctx, &pos, where, gdal.WithDebug())
err := userDAL.Find(ctx, &pos, where, gdal.WithDebug())
fmt.Println(err)
fmt.Println(render.Render(pos))
}

{ // 查询多条记录
{ // multiple query
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
pos, err := userDAL.MQuery(ctx, where, gdal.WithDebug(), gdal.WithMaster())
println(pos, err)
fmt.Println(err)
fmt.Println(render.Render(pos))
}

{ // 分页查询1
{ // query by paging: method 1
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
pos, total, err := userDAL.MQueryByPaging(ctx, where, gptr.Of[int64](5), nil, gptr.Of("create_time desc"))
println(pos, total, err)
fmt.Println(err)
fmt.Println(total)
fmt.Println(render.Render(pos))
}

{ // 分页查询2
{ // query by paging: method 2
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
pos, total, err := userDAL.MQueryByPagingOpt(ctx, where, gdal.WithLimit(5), gdal.WithOrder("create_time desc"), gdal.WithDebug())
println(pos, total, err)
fmt.Println(err)
fmt.Println(total)
fmt.Println(render.Render(pos))
}

{
finalErr := db.Transaction(func(tx *gorm.DB) error {
{ // transaction
finalErr := DB.Transaction(func(tx *gorm.DB) error {

update := &model.UserUpdate{
BalanceMinus: gptr.Of[int64](20),
Expand All @@ -142,6 +151,45 @@ func main() {

return nil // commit
})
println(finalErr)
fmt.Println(finalErr)
}

{ // 物理删除
where := &model.UserWhere{
IDIn: []int64{110, 120},
}
numDeleted, err := userDAL.Delete(ctx, where)
fmt.Println(numDeleted)
fmt.Println(err)
}

{ // 通过ID物理删除
numDeleted, err := userDAL.DeleteByID(ctx, 130)
fmt.Println(numDeleted)
fmt.Println(err)
}
}

func RunMigrations() {
var err error
allModels := []interface{}{&model.User{}}

DB.Migrator().DropTable("user_friends", "user_speaks")

if err = DB.Migrator().DropTable(allModels...); err != nil {
log.Printf("Failed to drop table, got error %v\n", err)
os.Exit(1)
}

if err = DB.AutoMigrate(allModels...); err != nil {
log.Printf("Failed to auto migrate, but got error %v\n", err)
os.Exit(1)
}

for _, m := range allModels {
if !DB.Migrator().HasTable(m) {
log.Printf("Failed to create table for %#v\n", m)
os.Exit(1)
}
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.18

require (
github.com/bytedance/mockey v1.2.4
github.com/luci/go-render v0.0.0-20160219211803-9a04cc21af0f
github.com/smartystreets/goconvey v1.8.0
gorm.io/driver/mysql v1.5.1
gorm.io/driver/postgres v1.5.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/luci/go-render v0.0.0-20160219211803-9a04cc21af0f h1:WVPqVsbUsrzAebTEgWRAZMdDOfkFx06iyhbIoyMgtkE=
github.com/luci/go-render v0.0.0-20160219211803-9a04cc21af0f/go.mod h1:aS446i8akEg0DAtNKTVYpNpLPMc0SzsZ0RtGhjl0uFM=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
Expand Down
3 changes: 3 additions & 0 deletions gutil/genv/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ package genv

import "os"

// InDebugEnv
//
// @Description: where has "DEBUG" environment.
func InDebugEnv() bool {
return len(os.Getenv("DEBUG")) > 0
}
58 changes: 50 additions & 8 deletions gutil/greflect/greflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,38 @@ import (
)

// Implements
// @Description: 类型 T 是否实现了 Interface 接口
// @return Interface: 如果实现了,返回填入类型 T 零值的该接口;如果没实现,返回 nil
// @return bool: 是否了实现该接口
//
// @Description: whether type `T` implements `Interface`
//
// @return Interface: return zero value of `T` if implements; otherwise, nil
//
// @return bool: whether implements
func Implements[Interface any](v any) (Interface, bool) {
i, ok := v.(Interface)
return i, ok
}

// GetElemValueTypeOfPtr
//
// @Description: get the element struct Value and Type if `rv` is a pointer to struct; otherwise, return `rv`'s.
//
// @param rv: pointer (maybe deep) to struct
//
// @return reflect.Value: element struct Value
//
// @return reflect.Type: element struct Type
//
// @return error: when `rv` is invalid or element is not a struct
//
// @example
//
// u := &User{ ID: 110, Name: "Bob" }
// rv := reflect.ValueOf(&u)
// elemRv, elemRt, err := GetElemValueTypeOfPtr(rv)
//
// then `elemRv` is `User{ ID: 110, Name: "Bob" }`
// `elemRt` is User
// `err` is nil
func GetElemValueTypeOfPtr(rv reflect.Value) (reflect.Value, reflect.Type, error) {
rv, err := GetElemValueOfPtr(rv)
if err != nil {
Expand All @@ -24,13 +48,20 @@ func GetElemValueTypeOfPtr(rv reflect.Value) (reflect.Value, reflect.Type, error

// GetElemValueOfPtr
//
// @Description: 获取指针底层 struct 数据类型。
// @Description: get the element struct Value if `rv` is a pointer to struct; otherwise, return `rv`'s.
//
// @param rv: 底层 struct 数据类型
// @param rv: pointer (maybe deep) to struct
//
// @return reflect.Value:
// @return reflect.Value: element struct Value
//
// @example
//
// u := &User{ ID: 110, Name: "Bob" }
// rv := reflect.ValueOf(&u)
// elemRv, err := GetElemValueOfPtr(rv)
//
// then `elemRv` is `User{ ID: 110, Name: "Bob" }`
// `err` is nil
func GetElemValueOfPtr(rv reflect.Value) (reflect.Value, error) {
if !rv.IsValid() {
return rv, gerror.InvalidReflectValueErr(rv)
Expand All @@ -49,12 +80,23 @@ func GetElemValueOfPtr(rv reflect.Value) (reflect.Value, error) {
//
// @Description: 获取指针、切片、数组底层 struct 数据类型。
//
// @param rt: 底层 struct 数据类型
// @param rt: embedding of pointer (maybe deep), slice or array to struct.
//
// @return reflect.Type:
// @return reflect.Type: element struct Type
//
// @example
//
// u := []User{{ID: 110, Name: "Bob"}, {ID: 120, Name: "Dirac"}}
// rv := reflect.TypeOf(&u)
// elemRt, err := GetElemStructType(rv)
//
// then `elemRt` is `User`
// `err` is nil
func GetElemStructType(rt reflect.Type) (reflect.Type, error) {
type User struct {
ID int64
Name string
}
switch rt.Kind() {
case reflect.Struct:
return rt, nil
Expand Down
Loading

0 comments on commit 504b922

Please sign in to comment.