Files
gf/database/gdb/gdb_model.go

198 lines
6.0 KiB
Go
Raw Normal View History

// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
2018-04-20 23:23:42 +08:00
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
2018-04-20 23:23:42 +08:00
package gdb
import (
"time"
"github.com/gogf/gf/text/gstr"
2018-04-20 23:23:42 +08:00
)
// Model is the DAO for ORM.
2018-04-20 23:23:42 +08:00
type Model struct {
db DB // Underlying DB interface.
tx *TX // Underlying TX interface.
2020-01-07 22:14:32 +08:00
schema string // Custom database schema.
linkType int // Mark for operation on master or slave.
tablesInit string // Table names when model initialization.
tables string // Operation table names, which can be more than one table names and aliases, like: "user", "user u", "user u, user_detail ud".
fields string // Operation fields, multiple fields joined using char ','.
fieldsEx string // Excluded operation fields, multiple fields joined using char ','.
extraArgs []interface{} // Extra custom arguments for sql.
whereHolder []*whereHolder // Condition strings for where operation.
groupBy string // Used for "group by" statement.
orderBy string // Used for "order by" statement.
start int // Used for "select ... start, limit ..." statement.
limit int // Used for "select ... start, limit ..." statement.
option int // Option for extra operation features.
offset int // Offset statement for some databases grammar.
data interface{} // Data for operation, which can be type of map/[]map/struct/*struct/string, etc.
batch int // Batch number for batch Insert/Replace/Save operations.
filter bool // Filter data and where key-value pairs according to the fields of the table.
lockInfo string // Lock for update or in shared lock.
cacheEnabled bool // Enable sql result cache feature.
cacheDuration time.Duration // Cache TTL duration.
cacheName string // Cache name for custom operation.
safe bool // If true, it clones and returns a new model object whenever operation done; or else it changes the attribute of current model.
2019-10-21 19:13:25 +08:00
}
// whereHolder is the holder for where condition preparing.
type whereHolder struct {
operator int // Operator for this holder.
where interface{} // Where parameter.
args []interface{} // Arguments for where parameter.
2018-04-20 23:23:42 +08:00
}
2019-08-08 17:43:21 +08:00
const (
2019-10-21 19:13:25 +08:00
gLINK_TYPE_MASTER = 1
gLINK_TYPE_SLAVE = 2
gWHERE_HOLDER_WHERE = 1
gWHERE_HOLDER_AND = 2
gWHERE_HOLDER_OR = 3
OPTION_OMITEMPTY = 1 << iota
2019-09-26 20:01:48 +08:00
OPTION_ALLOWEMPTY
2019-08-08 17:43:21 +08:00
)
2020-01-10 23:48:19 +08:00
// Table creates and returns a new ORM model from given schema.
// The parameter <tables> can be more than one table names, like :
// "user", "user u", "user, user_detail", "user u, user_detail ud"
2020-03-08 00:17:42 +08:00
func (c *Core) Table(table string) *Model {
table = c.DB.QuotePrefixTableName(table)
2019-06-19 09:06:52 +08:00
return &Model{
2020-03-08 00:17:42 +08:00
db: c.DB,
2019-12-10 21:14:15 +08:00
tablesInit: table,
tables: table,
2019-06-19 09:06:52 +08:00
fields: "*",
start: -1,
offset: -1,
2019-11-28 23:23:11 +08:00
safe: false,
option: OPTION_ALLOWEMPTY,
}
2018-04-20 23:23:42 +08:00
}
2020-03-08 00:17:42 +08:00
// Model is alias of Core.Table.
// See Core.Table.
func (c *Core) Model(table string) *Model {
return c.DB.Table(table)
}
2020-03-08 00:17:42 +08:00
// From is alias of Core.Table.
// See Core.Table.
// Deprecated.
2020-03-08 00:17:42 +08:00
func (c *Core) From(table string) *Model {
return c.DB.Table(table)
2018-04-20 23:23:42 +08:00
}
2020-03-08 00:17:42 +08:00
// Table acts like Core.Table except it operates on transaction.
// See Core.Table.
2019-12-10 21:14:15 +08:00
func (tx *TX) Table(table string) *Model {
table = tx.db.QuotePrefixTableName(table)
return &Model{
2019-06-19 09:06:52 +08:00
db: tx.db,
tx: tx,
2019-12-10 21:14:15 +08:00
tablesInit: table,
tables: table,
fields: "*",
start: -1,
offset: -1,
2019-11-28 23:23:11 +08:00
safe: false,
option: OPTION_ALLOWEMPTY,
}
2018-04-20 23:23:42 +08:00
}
// Model is alias of tx.Table.
// See tx.Table.
2020-01-10 23:48:19 +08:00
func (tx *TX) Model(table string) *Model {
return tx.Table(table)
}
// From is alias of tx.Table.
// See tx.Table.
// Deprecated.
2020-01-10 23:48:19 +08:00
func (tx *TX) From(table string) *Model {
return tx.Table(table)
2018-04-20 23:23:42 +08:00
}
// As sets an alias name for current table.
func (m *Model) As(as string) *Model {
if m.tables != "" {
model := m.getModel()
model.tables = gstr.TrimRight(model.tables) + " AS " + as
return model
}
return m
}
2019-12-17 21:06:34 +08:00
// DB sets/changes the db object for current operation.
func (m *Model) DB(db DB) *Model {
model := m.getModel()
model.db = db
return model
}
// TX sets/changes the transaction for current operation.
func (m *Model) TX(tx *TX) *Model {
model := m.getModel()
model.tx = tx
return model
}
2020-01-07 22:14:32 +08:00
// Schema sets the schema for current operation.
func (m *Model) Schema(schema string) *Model {
model := m.getModel()
model.schema = schema
return model
}
// Clone creates and returns a new model which is a clone of current model.
// Note that it uses deep-copy for the clone.
func (m *Model) Clone() *Model {
2019-06-19 09:06:52 +08:00
newModel := (*Model)(nil)
if m.tx != nil {
newModel = m.tx.Table(m.tablesInit)
} else {
newModel = m.db.Table(m.tablesInit)
}
*newModel = *m
2019-11-21 22:21:57 +08:00
// Deep copy slice attributes.
if n := len(m.extraArgs); n > 0 {
newModel.extraArgs = make([]interface{}, n)
copy(newModel.extraArgs, m.extraArgs)
2019-11-21 22:21:57 +08:00
}
if n := len(m.whereHolder); n > 0 {
2019-11-21 22:21:57 +08:00
newModel.whereHolder = make([]*whereHolder, n)
copy(newModel.whereHolder, m.whereHolder)
2019-11-21 22:21:57 +08:00
}
2019-06-19 09:06:52 +08:00
return newModel
2018-12-14 10:09:45 +08:00
}
// Master marks the following operation on master node.
func (m *Model) Master() *Model {
model := m.getModel()
2019-08-08 17:43:21 +08:00
model.linkType = gLINK_TYPE_MASTER
return model
}
// Slave marks the following operation on slave node.
// Note that it makes sense only if there's any slave node configured.
func (m *Model) Slave() *Model {
model := m.getModel()
2019-08-08 17:43:21 +08:00
model.linkType = gLINK_TYPE_SLAVE
return model
}
// Safe marks this model safe or unsafe. If safe is true, it clones and returns a new model object
// whenever the operation done, or else it changes the attribute of current model.
func (m *Model) Safe(safe ...bool) *Model {
2019-06-19 09:06:52 +08:00
if len(safe) > 0 {
m.safe = safe[0]
2019-06-19 09:06:52 +08:00
} else {
m.safe = true
2019-06-19 09:06:52 +08:00
}
return m
2019-03-07 23:53:56 +08:00
}