Files
aorm/builder/builder.go
tangpanqing 9beffba8ed update
2023-01-06 07:12:36 +08:00

255 lines
6.3 KiB
Go

package builder
import (
"fmt"
"reflect"
"strings"
"unicode"
)
var RawEq = "rawEq"
var TableMap = make(map[uintptr]string)
var FieldMap = make(map[uintptr]FieldInfo)
type FieldInfo struct {
TablePointer uintptr
Name string
}
type GroupItem struct {
Prefix string
Field interface{}
}
type WhereItem struct {
FuncName string
Prefix string
Field interface{}
Opt string
Val interface{}
}
type SelectItem struct {
FuncName string
Prefix string
Field interface{}
FieldNew interface{}
}
type JoinItem struct {
joinType string
table interface{}
tableAlias string
condition []JoinCondition
}
type OrderItem struct {
Prefix string
Field interface{}
OrderType string
}
type JoinCondition struct {
FieldOfCurrentTable interface{}
Opt string
FieldOfOtherTable interface{}
AliasOfOtherTable string
}
func Store(destList ...interface{}) {
for i := 0; i < len(destList); i++ {
dest := destList[i]
valueOf := reflect.ValueOf(dest)
typeof := reflect.TypeOf(dest)
tablePointer := valueOf.Pointer()
TableMap[tablePointer] = typeof.String()
for j := 0; j < valueOf.Elem().NumField(); j++ {
addr := valueOf.Elem().Field(j).Addr().Pointer()
name := typeof.Elem().Field(j).Name
FieldMap[addr] = FieldInfo{
TablePointer: tablePointer,
Name: name,
}
}
}
}
func GenJoinCondition(fieldOfCurrentTable interface{}, opt string, fieldOfOtherTable interface{}, aliasOfOtherTable ...string) JoinCondition {
alias := ""
if len(aliasOfOtherTable) > 0 {
alias = aliasOfOtherTable[0]
}
return JoinCondition{
FieldOfCurrentTable: fieldOfCurrentTable,
Opt: opt,
FieldOfOtherTable: fieldOfOtherTable,
AliasOfOtherTable: alias,
}
}
//func (b *Builder) GetOne(dest interface{}) {
// var paramList []interface{}
//
// table := getTableName(b.table)
// selectStr, paramList := b.handleSelect(paramList)
// joinStr, paramList := b.handleJoin(paramList)
// whereStr, paramList := b.handleWhere(paramList)
//
// var sql = "SELECT " + selectStr + " FROM " + table + " " + b.tableAlias + joinStr + whereStr
//
// fmt.Println(sql)
// //fmt.Println(paramList)
//}
func (b *Builder) handleSelect(paramList []interface{}) (string, []interface{}) {
if len(b.selectList) == 0 {
return "*", paramList
}
var sqlList []string
for i := 0; i < len(b.selectList); i++ {
nameOfField := ""
typeOfField := reflect.TypeOf(b.selectList[i].Field)
valueOfField := reflect.ValueOf(b.selectList[i].Field)
if reflect.String == typeOfField.Kind() {
nameOfField = fmt.Sprintf("%v", b.selectList[i].Field)
} else if reflect.Ptr == typeOfField.Kind() {
nameOfField = UnderLine(FieldMap[valueOfField.Pointer()].Name)
} else {
panic("其他类型")
}
nameOfFieldNew := ""
if b.selectList[i].FieldNew != nil {
typeOfFieldNew := reflect.TypeOf(b.selectList[i].FieldNew)
valueOfFieldNew := reflect.ValueOf(b.selectList[i].FieldNew)
if reflect.String == typeOfFieldNew.Kind() {
nameOfFieldNew = fmt.Sprintf("%v", b.selectList[i].FieldNew)
} else if reflect.Ptr == typeOfFieldNew.Kind() {
nameOfFieldNew = UnderLine(FieldMap[valueOfFieldNew.Pointer()].Name)
} else {
panic("其他类型")
}
if nameOfFieldNew != "" {
nameOfFieldNew = " AS " + nameOfFieldNew
}
}
sqlList = append(sqlList, b.selectList[i].Prefix+"."+nameOfField+nameOfFieldNew)
}
return strings.Join(sqlList, ","), paramList
}
//func (b *Builder) handleWhere(paramList []interface{}) (string, []interface{}) {
// if len(b.whereList) == 0 {
// return "", paramList
// }
//
// str, paramList := getWhereStr(b.whereList, paramList)
//
// return " WHERE " + str, paramList
//}
func getPrefixByField(field interface{}, alias ...string) string {
str := ""
if len(alias) > 0 {
str = alias[0]
} else {
str = getTableNameByField(field)
}
return str
}
func UnderLine(s string) string {
var output []rune
for i, r := range s {
if i == 0 {
output = append(output, unicode.ToLower(r))
continue
}
if unicode.IsUpper(r) {
output = append(output, '_')
}
output = append(output, unicode.ToLower(r))
}
return string(output)
}
func getTableNameByTable(table interface{}) string {
if table == nil {
panic("当前table不能是nil")
}
tableName := TableMap[reflect.ValueOf(table).Pointer()]
strArr := strings.Split(tableName, ".")
return UnderLine(strArr[len(strArr)-1])
}
func getTableNameByField(field interface{}) string {
valueOf := reflect.ValueOf(field)
if reflect.Ptr == valueOf.Kind() {
tablePointer := FieldMap[reflect.ValueOf(field).Pointer()].TablePointer
tableName := TableMap[tablePointer]
strArr := strings.Split(tableName, ".")
return UnderLine(strArr[len(strArr)-1])
} else {
return fmt.Sprintf("%v", field)
}
}
func getWhereStrForJoin(aliasOfCurrentTable string, joinCondition []JoinCondition, paramList []interface{}) (string, []interface{}) {
var sqlList []string
for i := 0; i < len(joinCondition); i++ {
fieldNameOfCurrentTable := getFieldName(joinCondition[i].FieldOfCurrentTable)
if joinCondition[i].Opt == RawEq {
if aliasOfCurrentTable == "" {
aliasOfCurrentTable = getPrefixByField(joinCondition[i].FieldOfCurrentTable)
}
aliasOfOtherTable := joinCondition[i].AliasOfOtherTable
if aliasOfOtherTable == "" {
aliasOfOtherTable = getPrefixByField(joinCondition[i].FieldOfOtherTable)
}
fieldNameOfOtherTable := getFieldName(joinCondition[i].FieldOfOtherTable)
sqlList = append(sqlList, aliasOfCurrentTable+"."+fieldNameOfCurrentTable+"="+aliasOfOtherTable+"."+fieldNameOfOtherTable)
}
}
return strings.Join(sqlList, " AND "), paramList
}
func getFieldName(field interface{}) string {
valueOf := reflect.ValueOf(field)
if reflect.Ptr == valueOf.Kind() {
return UnderLine(FieldMap[reflect.ValueOf(field).Pointer()].Name)
} else {
return fmt.Sprintf("%v", field)
}
}
func getWhereStr(whereList []WhereItem, paramList []interface{}) (string, []interface{}) {
var sqlList []string
for i := 0; i < len(whereList); i++ {
prefix := whereList[i].Prefix
field := getFieldName(whereList[i].Field)
if whereList[i].Opt == "=" {
sqlList = append(sqlList, prefix+"."+field+"="+"?")
paramList = append(paramList, whereList[i].Val)
}
if whereList[i].Opt == "rawEq" {
value := getFieldName(whereList[i].Val)
sqlList = append(sqlList, prefix+"."+field+"="+value)
}
}
return strings.Join(sqlList, " AND "), paramList
}