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('*')
	}
}

 

posted @   codestacklinuxer  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示