xorm的sql builder


最近在使用xorm,並使用了sql builder來構建sql查詢沒想到升級后原來可以使用的代碼居然報錯了。

0x00 代碼

sql, args, _ := builder.Select("*").
		From("user").
		Where(builder.Eq{"uid": 1}).
		ToSQL()
res, err := orm.QueryString(sql, args...)

0x01 對比

發現xorm在0.6.3 和 0.6.4間做了改動,如圖
0.6.3

0.6.4

原來如此,去掉了第一個參數,改為全部可變參數了,於是機智的把args...,改為了args
關於可變參數的問題,可以參考我的這篇文章

0x02 新錯誤

沒想到編譯沒錯,運行時報錯了,提示

sql: converting argument $1 type: unsupported type []interface {}, a slice of interface

即類型錯誤。繼續追蹤代碼,發現session_query.go里有生成sql的函數,代碼如下:

func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) {
	if len(sqlorArgs) > 0 {
		return sqlorArgs[0].(string), sqlorArgs[1:], nil
	}
    //省略
}

由於sqlorArgs是slice,而且builder.ToSql的args也是slice,那么sqlorArgs[1:]又創建了一個新的slice,就讓最后返回的slice變成了二元slice了,所以出現了上面的類型錯誤。

0x03 解決辦法

想了一下,其實我覺得上一個版本的函數簽名更好,兩個參數,一個負責接受sql語句,一個負責接收sql變量。給作者提了issue,或許作者有更好的解決方案。
下面是我的臨時解決方法:

func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) {
	if len(sqlorArgs) > 0 {
		if len(sqlorArgs) == 2 && reflect.TypeOf(sqlorArgs[1]).Kind() == reflect.Slice {
			return sqlorArgs[0].(string), sqlorArgs[1].([]interface{}), nil
		}
		return sqlorArgs[0].(string), sqlorArgs[1:], nil
	}
    //省略
}

作者已經更新,方法更加巧妙,增加了builder類型

用法,直接傳builder即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM