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