|
|
package vql
import ( "encoding/json" "fmt" "strings"
"github.com/tidwall/gjson" )
type Builder2 struct { As string `json:"as"` Select interface{} `json:"select"` From interface{} `json:"from"` Join interface{} `json:"join"` Where interface{} `json:"where"` Group interface{} `json:"group"` Having interface{} `json:"having"` Order interface{} `json:"order"` }
func NewBuilder2() *Builder2 { return &Builder2{} }
func (b *Builder2) Select2(selects ...interface{}) *Builder2 { b.Select = selects return b }
func (b *Builder2) Sql() (string, error) { selectSql, err := toSelectSql(b.Select) if err != nil { return "", err }
fromSql, err := toFromSql(b.From) if err != nil { return "", err }
joinSql, err := toJoinSql(b.Join) if err != nil { return "", err }
whereSql, err := toWhereSql(b.Where) if err != nil { return "", err }
groupSql, err := toGroupSql(b.Group) if err != nil { return "", err }
havingSql, err := toHavingSql(b.Having) if err != nil { return "", err }
orderSql, err := toOrderSql(b.Order) if err != nil { return "", err }
sql := fmt.Sprintf("select %s from %s ", selectSql, fromSql) if joinSql != "" { sql += fmt.Sprintf(" %s ", joinSql) } if whereSql != "" { sql += fmt.Sprintf(" where %s ", whereSql) } if groupSql != "" { sql += fmt.Sprintf(" group by %s ", groupSql) } if havingSql != "" { sql += fmt.Sprintf(" having %s ", havingSql) } if orderSql != "" { sql += fmt.Sprintf(" order by %s ", orderSql) }
return sql, nil
}
func toSelectSql(selects interface{}) (string, error) {
selectSql := "" if selectSql, ok := selects.(string); ok { return selectSql, nil }
selectGjson := gjson.Parse(jsonEncode(selects)) if selectGjson.IsArray() { ses := []string{} for _, se := range selectGjson.Array() { ses = append(ses, se.String()) } selectSql = strings.Join(ses, ",") } else { selectSql = selectGjson.String() } return selectSql, nil }
func toFromSql(from interface{}) (string, error) { fromSql := "" if fromSql, ok := from.(string); ok { return fromSql, nil }
fromGjson := gjson.Parse(jsonEncode(from)) if fromGjson.IsObject() { nb := NewBuilder2() json.Unmarshal([]byte(fromGjson.Raw), &nb) ns, err := nb.Sql() if err != nil { return "", err } if nb.As != "" { fromSql = fmt.Sprintf("( %s ) as %s", ns, nb.As) } else { fromSql = fmt.Sprintf("( %s )", ns) } } else { fromSql = fromGjson.String() } return fromSql, nil }
func toJoinSql(join interface{}) (string, error) { if join == nil { return "", nil } // joinSql := ""
if joinSql, ok := join.(string); ok { return joinSql, nil }
joinGjson := gjson.Parse(jsonEncode(join)) if joinGjson.IsArray() { js := []string{} for _, j := range joinGjson.Array() { nj, err := toJoinSql(j.Value()) if err != nil { return "", err } js = append(js, nj) } return strings.Join(js, " "), nil } else { return "", fmt.Errorf("目前仅支持数组或者字符串") }
// joinGjson := gjson.Parse(jsonEncode(join))
// if joinGjson.IsArray() {
// js := []string{}
// for _, j := range joinGjson.Array() {
// if j.IsObject() {
// return
// } else {
// js = append(js, j.String())
// }
// }
// joinSql = strings.Join(js, " ")
// } else {
// joinSql = joinGjson.String()
// }
// return joinSql
}
func toWhereSql(where interface{}) (string, error) { if where == nil { return "", nil } whereSql := "" if whereSql, ok := where.(string); ok { return whereSql, nil }
whereGjson := gjson.Parse(jsonEncode(where))
//[ "a=","1","and",[["c=","3"],"and",["d=","4"]],"or",["b=","2"]]
if whereGjson.IsArray() { ws := []string{} expression := whereGjson.Array()
if len(expression) == 0 { return "", nil }
if expression[0].String() == "and" || expression[0].String() == "or" {
operator := "and"
for _, w := range expression { if w.Type == gjson.String { if whereSql == "" && (w.String() == "and" || w.String() == "or") { operator = w.String() } else { ws = append(ws, w.String()) } } else { newExp, err := toWhereSql(w.Value()) if err != nil { return "", err } ws = append(ws, newExp) }
whereSql = strings.Join(ws, fmt.Sprintf(" %s ", operator)) } } else { for _, w := range expression { if w.Type == gjson.String { ws = append(ws, w.String()) } else { newExp, err := toWhereSql(w.Value()) if err != nil { return "", err } ws = append(ws, newExp) }
whereSql = strings.Join(ws, " ") } } } else if whereGjson.IsObject() { newValue := []interface{}{ "and", }
ops := []string{"=", ">", ">=", "<", "<=", "<>", "!="}
for k, v := range whereGjson.Map() { if v.Value() == nil { continue }
prefix := k mop := "="
for _, op := range ops { if strings.HasSuffix(k, op) { prefix = strings.TrimSuffix(k, op) mop = op break } }
newValue = append(newValue, []string{prefix, mop, v.String()}) }
return toWhereSql(newValue) } else { whereSql = whereGjson.String() } return fmt.Sprintf("( %s )", whereSql), nil }
func toGroupSql(group interface{}) (string, error) { if group == nil { return "", nil } // groupSql := ""
if groupSql, ok := group.(string); ok { return groupSql, nil } return "", fmt.Errorf("暂时不支持非字符串类型的group语句") }
func toHavingSql(having interface{}) (string, error) { if having == nil { return "", nil } // havingSql := ""
if havingSql, ok := having.(string); ok { return havingSql, nil } return "", fmt.Errorf("暂时不支持非字符串类型的having语句") }
func toOrderSql(order interface{}) (string, error) { if order == nil { return "", nil } // orderSql := ""
if orderSql, ok := order.(string); ok { return orderSql, nil } return "", fmt.Errorf("暂时不支持非字符串类型的order语句") }
|