Browse Source

'fix'

master
u 2 years ago
parent
commit
6c18af9a2d
  1. 294
      builder2.go
  2. 44
      builder2_test.go

294
builder2.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语句")
}

44
builder2_test.go

@ -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)
}
Loading…
Cancel
Save