gorm阅读 5
var user dot1xDataItem
user.UserName = "test11"
dot1xDb.Find(&user)
执行路径:一样
只是在 BuildQuerySQL的时候 会解析传进来参数里面的values,有值就当做where exp eq 处理
func BuildQuerySQL(db *gorm.DB) {
if db.Statement.Schema != nil {
for _, c := range db.Statement.Schema.QueryClauses {
db.Statement.AddClause(c)
}
}
if db.Statement.SQL.Len() == 0 {
db.Statement.SQL.Grow(100)
clauseSelect := clause.Select{Distinct: db.Statement.Distinct}
if db.Statement.ReflectValue.Kind() == reflect.Struct && db.Statement.ReflectValue.Type() == db.Statement.Schema.ModelType {
var conds []clause.Expression
for _, primaryField := range db.Statement.Schema.PrimaryFields {
if v, isZero := primaryField.ValueOf(db.Statement.Context, db.Statement.ReflectValue); !isZero {
conds = append(conds, clause.Eq{Column: clause.Column{Table: db.Statement.Table, Name: primaryField.DBName}, Value: v})
}/*/此时传进来的dest 参数是有值的user_name=”test11“
/ 就会组装 clause.Eq
// Eq equal to for where
type Eq struct {
Column interface{}
Value interface{}
}
*/
}
if len(conds) > 0 {
db.Statement.AddClause(clause.Where{Exprs: conds})
// 将eq 添加到where Clauses
}
}
db.Statement.AddClauseIfNotExists(clauseSelect) //select
db.Statement.Build(db.Statement.BuildClauses...)
}
}
// Where where clause
type Where struct {
Exprs []Expression
}
clause.Where{Exprs: conds} ---》构建一个 []exprs
db.Statement.AddClause(clause.Where{Exprs: conds})---》将当前
Clauses map[string]clause.Clause
where = map["where"] -->clause.Clause
// Clause
type Clause struct {
Name string // WHERE
BeforeExpression Expression
AfterNameExpression Expression
AfterExpression Expression
Expression Expression---》指向一个接口---》接口指向一个Exprs []Expression 相互叠加
Builder ClauseBuilder
}
where.Exprs = exprs
clause.Expression = where
stmt.Clauses[name] = Clause
// Expression expression interface
type Expression interface {
Build(builder Builder)
}
只能select;
type APIUser struct {
TunnelType string `gorm:"column:tunnel_type"`
TunnelMediumType string `gorm:"column:tunnel_medtype"`
TunnelPrivateGroupID string `gorm:"column:tunnel_pgid"`
FilterId string `gorm:"column:filter_id"`
}
fmt.Printf("\n\n\n\n\n************\n")
var resuser APIUser
dot1xDb.Model(&user1).Find(&resuser)
fmt.Printf(" resuser:%v \n", resuser)
fmt.Printf("*************\n\n\n\n")
根据以前分析 Execute(db *DB) 可知:
stmt 必须有model,如果mode 为空就使用find 传进来的Dest
// assign model values
if stmt.Model == nil {
stmt.Model = stmt.Dest
} else if stmt.Dest == nil {
stmt.Dest = stmt.Model
}
// parse model values // 根据Model 查找对应之前创建schema
if stmt.Model != nil {
if err := stmt.Parse(stmt.Model);
// assign stmt.ReflectValue 根据Dest 传进来的参数 获取对应的值,也就是需要select 返回的东西
if stmt.Dest != nil {
stmt.ReflectValue = reflect.ValueOf(stmt.Dest)
for stmt.ReflectValue.Kind() == reflect.Ptr {
stmt.ReflectValue = stmt.ReflectValue.Elem()
}
由于之前Model == Dest 使用select * from ;但是这次 Model != Dest 来看下query逻辑是怎样走的
由于 queryFields = db.Statement.ReflectValue.Type() != db.Statement.Schema.ModelType 也就是Model 和stmt 两个struct不一样,需要根据dest 重parse 创建对应的schema;
对于mode 必须是db 里面table存在表 schema,否则一开始的scheam就找不到Db里面存在的tab,而是会创建一个新的table scheam。此时select xxx from tab就会导致 tab不存在
func Query(db *gorm.DB) {
BuildQuerySQL(db)
----->/*
if queryFields { true <---> queryFields = db.Statement.ReflectValue.Type() != db.Statement.Schema.ModelType
stmt := gorm.Statement{DB: db}
// smaller struct
if err := stmt.Parse(db.Statement.Dest); err == nil && (db.QueryFields || stmt.Schema.ModelType != db.Statement.Schema.ModelType) {
clauseSelect.Columns = make([]clause.Column, len(stmt.Schema.DBNames))
for idx, dbName := range stmt.Schema.DBNames {
clauseSelect.Columns[idx] = clause.Column{Table: db.Statement.Table, Name: dbName}
}
}
}
*/
rows=QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
gorm.Scan(rows, db, 0)
}
在BuildQuerySql的时候由于dest 和model 不一样,就会根据dest 重新parse,stmt.Parse(db.Statement.Dest)
根据queryFields 将新的stmt.Schema 的字段存储在clauseSelect
最后执行 db.Statement.AddClauseIfNotExists(clauseSelect) 将clause select add 进去
// Select select attrs when querying, updating, creating
type Select struct {
Distinct bool
Columns []Column
Expression Expression
}
可知 当select 的Columns有值时,就会变成select a, b, c 否则就变成select * from
func (s Select) Build(builder Builder) {
if len(s.Columns) > 0 {
if s.Distinct {
builder.WriteString("DISTINCT ")
}
for idx, column := range s.Columns {
if idx > 0 {
builder.WriteByte(',')
}
builder.WriteQuoted(column)
}
} else {
builder.WriteByte('*')
}
}
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!