代码拉取完成,页面将自动刷新
同步操作将从 unsafe-rust/sq 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
package sq
import (
"context"
"fmt"
"log"
"reflect"
"strconv"
)
var (
mapper = NewReflectMapper("db")
AutoCreateTimeFields = []string{ //插入数据库自动更新字段
"create_time",
"create_at",
"created_at",
"update_time",
"update_at",
"updated_at",
}
AutoUpdateTimeFields = []string{ //更新数据库自动更新字段
"update_time",
"update_at",
"updated_at",
}
)
type (
ModelWrapper struct {
dbList map[string]*DB
model interface{}
}
ModelWrapperFactory func(m interface{}) *ModelWrapper
)
func NewModelWrapper(dbList map[string]*DB, model interface{}) *ModelWrapper {
return &ModelWrapper{dbList: dbList, model: model}
}
func (m *ModelWrapper) GetRelationDB(connect string) *DB {
return m.dbList[connect]
}
func (m *ModelWrapper) UnWrap() interface{} {
return m.model
}
// Model interface
type IModel interface {
TableName() string
PK() string
}
// Builder 模型结构体
type Builder struct {
db *DB
model interface{} //存数据的容器
value reflect.Value
entity IModel
ctx context.Context
wrapper *ModelWrapper
SqlBuilder
}
// Model 从结构体构造SQL
func Model(model interface{}) *Builder {
return &Builder{
model: model,
db: &DB{database: GetDB(defaultLink)},
}
}
// Model construct SQL from Struct with context
func (b *Builder) Model(model interface{}) *Builder {
b.model = model
return b
}
// ShowSQL 输出单条SQL
func (b *Builder) ShowSQL() *Builder {
b.db.logging = true
return b
}
// Model construct SQL from Struct with context
func Ctx(ctx context.Context) *Builder {
w := Use(defaultLink)
return &Builder{db: w, SqlBuilder: SqlBuilder{dialect: newDialect(w.DriverName())}, ctx: ctx}
}
func (b *Builder) initModel() {
if b.model == nil {
log.Panicf("model argument must not nil")
} else if m, ok := b.model.(IModel); ok {
b.entity = m
b.table = m.TableName()
b.value = reflect.ValueOf(m)
b.dialect = newDialect(b.db.DriverName())
} else {
value := reflect.ValueOf(b.model)
if value.Kind() != reflect.Ptr {
log.Panicf("model argument must pass a pointer, not a value %#v", b.model)
}
if value.IsNil() {
log.Panicf("model argument cannot be nil pointer passed")
}
tp := reflect.Indirect(value).Type()
if tp.Kind() == reflect.Interface {
tp = reflect.Indirect(value).Elem().Type()
}
if tp.Kind() != reflect.Slice {
log.Panicf("model argument must slice, but get %#v", b.model)
}
tpEl := tp.Elem()
// Compatible with []*Struct or []Struct
if tpEl.Kind() == reflect.Ptr {
tpEl = tpEl.Elem()
}
if k, v := reflect.New(tpEl).Interface().(IModel); v {
b.entity = k
b.table = k.TableName()
b.value = reflect.ValueOf(k)
b.dialect = newDialect(b.db.DriverName())
} else {
log.Panicf("model argument must implementation IModel interface or slice []IModel and pointer,but get %#v", b.model)
}
}
}
// Hint is set TDDL "/*+TDDL:slave()*/"
func (b *Builder) Hint(hint string) *Builder {
b.hint = hint
return b
}
// ForceIndex
func (b *Builder) ForceIndex(i string) *Builder {
b.forceIndex = i
return b
}
// Where for example Where("id = ? and name = ?",1,"test")
func (b *Builder) Where(str string, args ...interface{}) *Builder {
b.SqlBuilder.Where(str, args...)
return b
}
// Cols filter column
func (b *Builder) Cols(fields string) *Builder {
b.fields = fields
return b
}
// Limit
func (b *Builder) Limit(i int) *Builder {
b.limit = strconv.Itoa(i)
return b
}
// Offset
func (b *Builder) Offset(i int) *Builder {
b.offset = strconv.Itoa(i)
return b
}
// OrderBy for example "id desc"
func (b *Builder) OrderBy(str string) *Builder {
b.order = str
return b
}
func (b *Builder) generateWhere(m map[string]interface{}) {
for k, v := range m {
b.Where(fmt.Sprintf("%s=?", k), v)
}
}
func (b *Builder) generateWhereForPK(m map[string]interface{}) {
pk := b.entity.PK()
pval, has := m[pk]
if b.where == "" && has {
b.Where(fmt.Sprintf("%s=?", pk), pval)
delete(m, pk)
}
}
func (b *Builder) reflectModel(autoTime []string) map[string]reflect.Value {
fields := mapper.FieldMap(b.value)
if autoTime != nil {
structAutoTime(fields, autoTime)
}
return fields
}
//Count sq.Model(&User{}).Where("status = 0").Count()
func (b *Builder) Count(zeroValues ...string) (num int64, err error) {
b.initModel()
m := zeroValueFilter(b.reflectModel(nil), zeroValues)
// If where is empty, the primary key where condition is generated automatically
b.generateWhere(m)
err = b.db.Take(&num, b.countString(), b.args...)
return num, err
}
// Relation 关联表构建器句柄
func (b *Builder) Relation(fieldName string, fn BuildFunc) *Builder {
if b.db.RelationMap == nil {
b.db.RelationMap = make(map[string]BuildFunc)
}
b.db.RelationMap[fieldName] = fn
return b
}
// Insert 插入一条记录。
// 例如: sq.Model(&User{Id:1}).Insert()
func (b *Builder) Insert() (lastInsertId int64, err error) {
b.initModel()
hook := NewHook(b.ctx, b.db)
hook.callMethod("BeforeChange", b.value)
hook.callMethod("BeforeCreate", b.value)
if hook.HasError() {
return 0, hook.Error()
}
fields := b.reflectModel(AutoCreateTimeFields)
m := structToMap(fields)
result, err := b.db.Exec(b.insertString(m), b.args...)
if err != nil {
return 0, err
}
hook.callMethod("AfterCreate", b.value)
hook.callMethod("AfterChange", b.value)
if hook.HasError() {
return 0, hook.Error()
}
lastId, err := result.LastInsertId()
if err != nil {
return 0, err
}
if v, ok := fields[b.entity.PK()]; ok {
fillPrimaryKey(v, lastId)
}
return lastId, err
}
// Delete 删除一条记录。参数<zeroValues>即使是0值,也会被强制执行。
// 例如: sq.Model(&User{Id:1}).Delete()。
func (b *Builder) Delete(zeroValues ...string) (affected int64, err error) {
b.initModel()
hook := NewHook(b.ctx, b.db)
hook.callMethod("BeforeChange", b.value)
hook.callMethod("BeforeDelete", b.value)
if hook.HasError() {
return 0, hook.Error()
}
m := zeroValueFilter(b.reflectModel(nil), zeroValues)
// If where is empty, the primary key where condition is generated automatically
b.generateWhere(m)
result, err := b.db.Exec(b.deleteString(), b.args...)
if err != nil {
return 0, err
}
hook.callMethod("AfterDelete", b.value)
hook.callMethod("AfterChange", b.value)
if hook.HasError() {
return 0, hook.Error()
}
return result.RowsAffected()
}
// Update 更新一条记录。参数<zeroValues>即使是0值,也会被强制执行。
// 例如: sq.Model(&User{Id:1,Status:0}).Update("status")
func (b *Builder) Update(zeroValues ...string) (affected int64, err error) {
b.initModel()
hook := NewHook(b.ctx, b.db)
hook.callMethod("BeforeChange", b.value)
hook.callMethod("BeforeUpdate", b.value)
if hook.HasError() {
return 0, hook.Error()
}
fields := b.reflectModel(AutoUpdateTimeFields)
m := zeroValueFilter(fields, zeroValues)
// If where is empty, the primary key where condition is generated automatically
b.generateWhereForPK(m)
result, err := b.db.Exec(b.updateString(m), b.args...)
if err != nil {
return 0, err
}
hook.callMethod("AfterUpdate", b.value)
hook.callMethod("AfterChange", b.value)
if hook.HasError() {
return 0, hook.Error()
}
return result.RowsAffected()
}
// Take 查询一条记录。参数<zeroValues>即使是0值,也会被强制执行。
// 例如: user := &Users{Id:1,Status:0}
// sq.Model(&user).Take("status")
func (b *Builder) Take(zeroValues ...string) (err error) {
b.initModel()
m := zeroValueFilter(b.reflectModel(nil), zeroValues)
// 如果where为空,则自动生成条件的主键
b.generateWhere(m)
if b.wrapper != nil {
return b.db.Take(b.wrapper, b.queryString(), b.args...)
}
return b.db.Take(b.model, b.queryString(), b.args...)
}
// Select 查询多条记录。
func (b *Builder) Select() (err error) {
b.initModel()
if b.wrapper != nil {
return b.db.Select(b.wrapper, b.queryString(), b.args...)
}
return b.db.Select(b.model, b.queryString(), b.args...)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。