mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
improve with feature for package gdb
This commit is contained in:
66
.example/database/gdb/mysql/gdb_with_insert.go
Normal file
66
.example/database/gdb/mysql/gdb_with_insert.go
Normal file
@ -0,0 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/database/gdb"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/util/gmeta"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type UserDetail struct {
|
||||
gmeta.Meta `orm:"table:user_detail"`
|
||||
Uid int `json:"uid"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type UserScore struct {
|
||||
gmeta.Meta `orm:"table:user_score"`
|
||||
Id int `json:"id"`
|
||||
Uid int `json:"uid"`
|
||||
Score int `json:"score"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gmeta.Meta `orm:"table:user"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
UserDetail *UserDetail `orm:"with:uid=id"`
|
||||
UserScores []*UserScore `orm:"with:uid=id"`
|
||||
}
|
||||
|
||||
db := g.DB()
|
||||
db.Transaction(func(tx *gdb.TX) error {
|
||||
for i := 1; i <= 5; i++ {
|
||||
// User.
|
||||
user := User{
|
||||
Name: fmt.Sprintf(`name_%d`, i),
|
||||
}
|
||||
lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Detail.
|
||||
userDetail := UserDetail{
|
||||
Uid: int(lastInsertId),
|
||||
Address: fmt.Sprintf(`address_%d`, lastInsertId),
|
||||
}
|
||||
_, err = db.Model(userDetail).Data(userDetail).OmitEmpty().Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Scores.
|
||||
for j := 1; j <= 5; j++ {
|
||||
userScore := UserScore{
|
||||
Uid: int(lastInsertId),
|
||||
Score: j,
|
||||
}
|
||||
_, err = db.Model(userScore).Data(userScore).OmitEmpty().Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
37
.example/database/gdb/mysql/gdb_with_slect.go
Normal file
37
.example/database/gdb/mysql/gdb_with_slect.go
Normal file
@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/util/gmeta"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type UserDetail struct {
|
||||
gmeta.Meta `orm:"table:user_detail"`
|
||||
Uid int `json:"uid"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type UserScore struct {
|
||||
gmeta.Meta `orm:"table:user_score"`
|
||||
Id int `json:"id"`
|
||||
Uid int `json:"uid"`
|
||||
Score int `json:"score"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gmeta.Meta `orm:"table:user"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
UserDetail *UserDetail `orm:"with:uid=id"`
|
||||
UserScores []*UserScore `orm:"with:uid=id"`
|
||||
}
|
||||
|
||||
db := g.DB()
|
||||
var user *User
|
||||
err := db.Model(user).WithAll().Where("id", 3).Scan(&user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
g.Dump(user)
|
||||
}
|
||||
@ -37,7 +37,7 @@ type DB interface {
|
||||
// relational databases but also for NoSQL databases in the future. The name
|
||||
// "Table" is not proper for that purpose any more.
|
||||
// Also see Core.Table.
|
||||
Table(table ...string) *Model
|
||||
Table(tableNameOrStruct ...interface{}) *Model
|
||||
|
||||
// Model creates and returns a new ORM model from given schema.
|
||||
// The parameter `table` can be more than one table names, and also alias name, like:
|
||||
@ -48,7 +48,7 @@ type DB interface {
|
||||
// Model("user u, user_detail ud")
|
||||
// 2. Model name with alias: Model("user", "u")
|
||||
// Also see Core.Model.
|
||||
Model(table ...string) *Model
|
||||
Model(tableNameOrStruct ...interface{}) *Model
|
||||
|
||||
// Schema creates and returns a schema.
|
||||
// Also see Core.Schema.
|
||||
@ -56,7 +56,7 @@ type DB interface {
|
||||
|
||||
// With creates and returns an ORM model based on meta data of given object.
|
||||
// Also see Core.With.
|
||||
With(object interface{}) *Model
|
||||
With(objects ...interface{}) *Model
|
||||
|
||||
// Open creates a raw connection object for database with given node configuration.
|
||||
// Note that it is not recommended using the this function manually.
|
||||
|
||||
@ -235,7 +235,7 @@ func DataToMapDeep(value interface{}) map[string]interface{} {
|
||||
name = ""
|
||||
fieldTag = rtField.Tag
|
||||
for _, tag := range structTagPriority {
|
||||
if s := fieldTag.Get(tag); s != "" {
|
||||
if s := fieldTag.Get(tag); s != "" && gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, s) {
|
||||
name = s
|
||||
break
|
||||
}
|
||||
|
||||
@ -70,53 +70,71 @@ const (
|
||||
// Table is alias of Core.Model.
|
||||
// See Core.Model.
|
||||
// Deprecated, use Model instead.
|
||||
func (c *Core) Table(table ...string) *Model {
|
||||
return c.db.Model(table...)
|
||||
func (c *Core) Table(tableNameOrStruct ...interface{}) *Model {
|
||||
return c.db.Model(tableNameOrStruct...)
|
||||
}
|
||||
|
||||
// Model creates and returns a new ORM model from given schema.
|
||||
// The parameter `table` can be more than one table names, and also alias name, like:
|
||||
// The parameter `tableNameOrStruct` can be more than one table names, and also alias name, like:
|
||||
// 1. Model names:
|
||||
// Model("user")
|
||||
// Model("user u")
|
||||
// Model("user, user_detail")
|
||||
// Model("user u, user_detail ud")
|
||||
// 2. Model name with alias: Model("user", "u")
|
||||
func (c *Core) Model(table ...string) *Model {
|
||||
tables := ""
|
||||
if len(table) > 1 {
|
||||
tables = fmt.Sprintf(
|
||||
`%s AS %s`, c.db.QuotePrefixTableName(table[0]), c.db.QuoteWord(table[1]),
|
||||
func (c *Core) Model(tableNameOrStruct ...interface{}) *Model {
|
||||
// With feature checks.
|
||||
if len(tableNameOrStruct) > 0 {
|
||||
if _, ok := tableNameOrStruct[0].(string); !ok {
|
||||
return c.With(tableNameOrStruct...)
|
||||
}
|
||||
}
|
||||
// Normal model creation.
|
||||
var (
|
||||
tableStr = ""
|
||||
tableNames = make([]string, len(tableNameOrStruct))
|
||||
)
|
||||
for k, v := range tableNameOrStruct {
|
||||
if s, ok := v.(string); ok {
|
||||
tableNames[k] = s
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(tableNames) > 1 {
|
||||
tableStr = fmt.Sprintf(
|
||||
`%s AS %s`, c.db.QuotePrefixTableName(tableNames[0]), c.db.QuoteWord(tableNames[1]),
|
||||
)
|
||||
} else if len(table) == 1 {
|
||||
tables = c.db.QuotePrefixTableName(table[0])
|
||||
} else if len(tableNames) == 1 {
|
||||
tableStr = c.db.QuotePrefixTableName(tableNames[0])
|
||||
}
|
||||
return &Model{
|
||||
db: c.db,
|
||||
tablesInit: tables,
|
||||
tables: tables,
|
||||
tablesInit: tableStr,
|
||||
tables: tableStr,
|
||||
fields: "*",
|
||||
start: -1,
|
||||
offset: -1,
|
||||
option: OptionAllowEmpty,
|
||||
filter: true,
|
||||
}
|
||||
}
|
||||
|
||||
// With creates and returns an ORM model based on meta data of given object.
|
||||
func (c *Core) With(object interface{}) *Model {
|
||||
return c.db.Model().With(object)
|
||||
func (c *Core) With(objects ...interface{}) *Model {
|
||||
return c.db.Model().With(objects...)
|
||||
}
|
||||
|
||||
// Table is alias of tx.Model.
|
||||
// Deprecated, use Model instead.
|
||||
func (tx *TX) Table(table ...string) *Model {
|
||||
return tx.Model(table...)
|
||||
func (tx *TX) Table(tableNameOrStruct ...interface{}) *Model {
|
||||
return tx.Model(tableNameOrStruct...)
|
||||
}
|
||||
|
||||
// Model acts like Core.Model except it operates on transaction.
|
||||
// See Core.Model.
|
||||
func (tx *TX) Model(table ...string) *Model {
|
||||
model := tx.db.Model(table...)
|
||||
func (tx *TX) Model(tableNameOrStruct ...interface{}) *Model {
|
||||
model := tx.db.Model(tableNameOrStruct...)
|
||||
model.db = tx.db
|
||||
model.tx = tx
|
||||
return model
|
||||
|
||||
@ -72,6 +72,7 @@ func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model {
|
||||
|
||||
// Filter marks filtering the fields which does not exist in the fields of the operated table.
|
||||
// Note that this function supports only single table operations.
|
||||
// Deprecated, filter feature is automatically enabled from GoFrame v1.16.0, it is so no longer used.
|
||||
func (m *Model) Filter() *Model {
|
||||
if gstr.Contains(m.tables, " ") {
|
||||
panic("function Filter supports only single table operations")
|
||||
|
||||
@ -32,13 +32,17 @@ import (
|
||||
// db.With(User{}.UserDetail).With(User{}.UserDetail).Scan(xxx)
|
||||
// Or:
|
||||
// db.With(UserDetail{}).With(UserDetail{}).Scan(xxx)
|
||||
func (m *Model) With(object interface{}) *Model {
|
||||
// Or:
|
||||
// db.With(UserDetail{}, UserDetail{}).Scan(xxx)
|
||||
func (m *Model) With(objects ...interface{}) *Model {
|
||||
model := m.getModel()
|
||||
if m.tables == "" {
|
||||
m.tables = m.db.QuotePrefixTableName(getTableNameFromOrmTag(object))
|
||||
return model
|
||||
for _, object := range objects {
|
||||
if m.tables == "" {
|
||||
m.tables = m.db.QuotePrefixTableName(getTableNameFromOrmTag(object))
|
||||
return model
|
||||
}
|
||||
model.withArray = append(model.withArray, object)
|
||||
}
|
||||
model.withArray = append(model.withArray, object)
|
||||
return model
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ func Test_Table_Relation_With_Scan(t *testing.T) {
|
||||
var (
|
||||
tableUser = "user"
|
||||
tableUserDetail = "user_detail"
|
||||
tableUserScores = "user_scores"
|
||||
tableUserScores = "user_score"
|
||||
)
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE IF NOT EXISTS %s (
|
||||
@ -60,8 +60,8 @@ PRIMARY KEY (id)
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type UserScores struct {
|
||||
gmeta.Meta `orm:"table:user_scores"`
|
||||
type UserScore struct {
|
||||
gmeta.Meta `orm:"table:user_score"`
|
||||
Id int `json:"id"`
|
||||
Uid int `json:"uid"`
|
||||
Score int `json:"score"`
|
||||
@ -69,34 +69,61 @@ PRIMARY KEY (id)
|
||||
|
||||
type User struct {
|
||||
gmeta.Meta `orm:"table:user"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
UserDetail *UserDetail `orm:"with:uid=id"`
|
||||
UserScores []*UserScores `orm:"with:uid=id"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
UserDetail *UserDetail `orm:"with:uid=id"`
|
||||
UserScores []*UserScore `orm:"with:uid=id"`
|
||||
}
|
||||
|
||||
// Initialize the data.
|
||||
var err error
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
for i := 1; i <= 5; i++ {
|
||||
// User.
|
||||
user := User{
|
||||
Name: fmt.Sprintf(`name_%d`, i),
|
||||
}
|
||||
lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId()
|
||||
t.AssertNil(err)
|
||||
// Detail.
|
||||
userDetail := UserDetail{
|
||||
Uid: int(lastInsertId),
|
||||
Address: fmt.Sprintf(`address_%d`, lastInsertId),
|
||||
}
|
||||
_, err = db.Model(userDetail).Data(userDetail).OmitEmpty().Insert()
|
||||
t.AssertNil(err)
|
||||
// Scores.
|
||||
for j := 1; j <= 5; j++ {
|
||||
userScore := UserScore{
|
||||
Uid: int(lastInsertId),
|
||||
Score: j,
|
||||
}
|
||||
_, err = db.Model(userScore).Data(userScore).OmitEmpty().Insert()
|
||||
t.AssertNil(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
for i := 1; i <= 5; i++ {
|
||||
// User.
|
||||
_, err = db.Insert(tableUser, g.Map{
|
||||
"id": i,
|
||||
"name": fmt.Sprintf(`name_%d`, i),
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
user := User{
|
||||
Name: fmt.Sprintf(`name_%d`, i),
|
||||
}
|
||||
lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId()
|
||||
gtest.AssertNil(err)
|
||||
// Detail.
|
||||
_, err = db.Insert(tableUserDetail, g.Map{
|
||||
"uid": i,
|
||||
"address": fmt.Sprintf(`address_%d`, i),
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
userDetail := UserDetail{
|
||||
Uid: int(lastInsertId),
|
||||
Address: fmt.Sprintf(`address_%d`, lastInsertId),
|
||||
}
|
||||
_, err = db.Model(userDetail).Data(userDetail).Insert()
|
||||
gtest.AssertNil(err)
|
||||
// Scores.
|
||||
for j := 1; j <= 5; j++ {
|
||||
_, err = db.Insert(tableUserScores, g.Map{
|
||||
"uid": i,
|
||||
"score": j,
|
||||
})
|
||||
gtest.Assert(err, nil)
|
||||
userScore := UserScore{
|
||||
Uid: int(lastInsertId),
|
||||
Score: j,
|
||||
}
|
||||
_, err = db.Model(userScore).Data(userScore).Insert()
|
||||
gtest.AssertNil(err)
|
||||
}
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -139,7 +166,7 @@ PRIMARY KEY (id)
|
||||
var user *User
|
||||
err := db.With(User{}).
|
||||
With(UserDetail{}).
|
||||
With(UserScores{}).
|
||||
With(UserScore{}).
|
||||
Where("id", 4).
|
||||
Scan(&user)
|
||||
t.AssertNil(err)
|
||||
|
||||
@ -274,30 +274,31 @@ func Test_DB_Upadte_KeyFieldNameMapping(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_DB_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Passport string
|
||||
Password string
|
||||
Nickname string
|
||||
CreateTime string
|
||||
NoneExistField string
|
||||
}
|
||||
data := User{
|
||||
Id: 1,
|
||||
Passport: "user_1",
|
||||
Password: "pass_1",
|
||||
Nickname: "name_1",
|
||||
CreateTime: "2020-10-10 12:00:01",
|
||||
}
|
||||
_, err := db.Insert(table, data)
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
// This is no longer used as the filter feature is automatically enabled from GoFrame v1.16.0.
|
||||
//func Test_DB_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
||||
// table := createTable()
|
||||
// defer dropTable(table)
|
||||
//
|
||||
// gtest.C(t, func(t *gtest.T) {
|
||||
// type User struct {
|
||||
// Id int
|
||||
// Passport string
|
||||
// Password string
|
||||
// Nickname string
|
||||
// CreateTime string
|
||||
// NoneExistField string
|
||||
// }
|
||||
// data := User{
|
||||
// Id: 1,
|
||||
// Passport: "user_1",
|
||||
// Password: "pass_1",
|
||||
// Nickname: "name_1",
|
||||
// CreateTime: "2020-10-10 12:00:01",
|
||||
// }
|
||||
// _, err := db.Insert(table, data)
|
||||
// t.AssertNE(err, nil)
|
||||
// })
|
||||
//}
|
||||
|
||||
func Test_DB_InsertIgnore(t *testing.T) {
|
||||
table := createInitTable()
|
||||
|
||||
@ -240,30 +240,31 @@ func Test_Model_Update_KeyFieldNameMapping(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Passport string
|
||||
Password string
|
||||
Nickname string
|
||||
CreateTime string
|
||||
NoneExistFiled string
|
||||
}
|
||||
data := User{
|
||||
Id: 1,
|
||||
Passport: "user_1",
|
||||
Password: "pass_1",
|
||||
Nickname: "name_1",
|
||||
CreateTime: "2020-10-10 12:00:01",
|
||||
}
|
||||
_, err := db.Model(table).Data(data).Insert()
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
// This is no longer used as the filter feature is automatically enabled from GoFrame v1.16.0.
|
||||
//func Test_Model_Insert_KeyFieldNameMapping_Error(t *testing.T) {
|
||||
// table := createTable()
|
||||
// defer dropTable(table)
|
||||
//
|
||||
// gtest.C(t, func(t *gtest.T) {
|
||||
// type User struct {
|
||||
// Id int
|
||||
// Passport string
|
||||
// Password string
|
||||
// Nickname string
|
||||
// CreateTime string
|
||||
// NoneExistFiled string
|
||||
// }
|
||||
// data := User{
|
||||
// Id: 1,
|
||||
// Passport: "user_1",
|
||||
// Password: "pass_1",
|
||||
// Nickname: "name_1",
|
||||
// CreateTime: "2020-10-10 12:00:01",
|
||||
// }
|
||||
// _, err := db.Model(table).Data(data).Insert()
|
||||
// t.AssertNE(err, nil)
|
||||
// })
|
||||
//}
|
||||
|
||||
func Test_Model_Insert_Time(t *testing.T) {
|
||||
table := createTable()
|
||||
|
||||
@ -97,18 +97,13 @@ func DB(name ...string) gdb.DB {
|
||||
// relational databases but also for NoSQL databases in the future. The name
|
||||
// "Table" is not proper for that purpose any more.
|
||||
// Deprecated, use Model instead.
|
||||
func Table(tables ...string) *gdb.Model {
|
||||
return DB().Model(tables...)
|
||||
func Table(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
return DB().Model(tableNameOrStruct...)
|
||||
}
|
||||
|
||||
// Model creates and returns a model based on configuration of default database group.
|
||||
func Model(tables ...string) *gdb.Model {
|
||||
return DB().Model(tables...)
|
||||
}
|
||||
|
||||
// With creates and returns an ORM model based on meta data of given object.
|
||||
func With(object interface{}) *gdb.Model {
|
||||
return DB().With(object)
|
||||
func Model(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
return DB().Model(tableNameOrStruct...)
|
||||
}
|
||||
|
||||
// Redis returns an instance of redis client with specified configuration group name.
|
||||
|
||||
Reference in New Issue
Block a user