u
2 years ago
2 changed files with 338 additions and 0 deletions
-
294builder2.go
-
44builder2_test.go
@ -0,0 +1,294 @@ |
|||||
|
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语句") |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
package vql |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"log" |
||||
|
"testing" |
||||
|
) |
||||
|
|
||||
|
func Test_toOrderSql(t *testing.T) { |
||||
|
text := `{ |
||||
|
"as": "test", |
||||
|
"select": [ |
||||
|
"col1", |
||||
|
"col2" |
||||
|
], |
||||
|
"from": { |
||||
|
"as": "test", |
||||
|
"select": [ |
||||
|
"col1", |
||||
|
"col2" |
||||
|
], |
||||
|
"from": "table1" |
||||
|
}, |
||||
|
"join": "left join table2 on table1.id = table2.id", |
||||
|
"where": { |
||||
|
"col1": "value1", |
||||
|
"col2": "value2", |
||||
|
"col3": 12 |
||||
|
} |
||||
|
}` |
||||
|
|
||||
|
var builder Builder2 |
||||
|
err := json.Unmarshal([]byte(text), &builder) |
||||
|
if err != nil { |
||||
|
t.Error(err) |
||||
|
} |
||||
|
|
||||
|
sql, err := builder.Sql() |
||||
|
if err != nil { |
||||
|
t.Error(err) |
||||
|
} |
||||
|
|
||||
|
log.Println(sql) |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue