作者 yangfu

高级查询优化

@@ -11,4 +11,5 @@ require ( @@ -11,4 +11,5 @@ require (
11 github.com/go-redis/redis v6.14.2+incompatible 11 github.com/go-redis/redis v6.14.2+incompatible
12 github.com/google/uuid v1.1.1 12 github.com/google/uuid v1.1.1
13 github.com/linmadan/egglib-go v0.0.0-20210827085852-177fa745932d 13 github.com/linmadan/egglib-go v0.0.0-20210827085852-177fa745932d
  14 + github.com/stretchr/testify v1.7.0
14 ) 15 )
@@ -5,26 +5,26 @@ import ( @@ -5,26 +5,26 @@ import (
5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/util/advance" 5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/util/advance"
6 ) 6 )
7 7
8 -type Model struct {  
9 - Columns []advance.Column `json:"columns"`  
10 - MapColumn advance.MapColumn `json:"-"`  
11 - Name string `json:"name"`  
12 -} 8 +type (
  9 + Model struct {
  10 + Columns []advance.Column `json:"columns"`
  11 + MapColumn advance.MapColumn `json:"-"`
  12 + Name string `json:"name"`
  13 + }
  14 + ModelInterface interface {
  15 + ModelName() string
  16 + Columns() []advance.Column
  17 + }
  18 +)
13 19
14 var registerModels = make(map[string]Model) 20 var registerModels = make(map[string]Model)
15 21
16 -func RegisModel(m Model) {  
17 - if _, ok := registerModels[m.Name]; ok {  
18 - panic("register modes exists:" + m.Name)  
19 - }  
20 - registerModels[m.Name] = m  
21 -}  
22 - 22 +// AdvancedQuerySql 高级查询语句生成
23 func AdvancedQuerySql(model string, quires advance.AdvancedQueries) string { 23 func AdvancedQuerySql(model string, quires advance.AdvancedQueries) string {
24 if len(quires) == 0 { 24 if len(quires) == 0 {
25 return "" 25 return ""
26 } 26 }
27 - fixQueries := fixAdvanceQueries(model, quires) 27 + fixQueries := mergeDuplicateQueries(model, quires)
28 sql, err := advance.AdvancedQuerySql(fixQueries) 28 sql, err := advance.AdvancedQuerySql(fixQueries)
29 if err != nil { 29 if err != nil {
30 log.Logger.Error(err.Error()) 30 log.Logger.Error(err.Error())
@@ -32,7 +32,7 @@ func AdvancedQuerySql(model string, quires advance.AdvancedQueries) string { @@ -32,7 +32,7 @@ func AdvancedQuerySql(model string, quires advance.AdvancedQueries) string {
32 return sql 32 return sql
33 } 33 }
34 34
35 -func fixAdvanceQueries(model string, quires advance.AdvancedQueries) []advance.AdvancedQuery { 35 +func mergeDuplicateQueries(model string, quires advance.AdvancedQueries) []advance.AdvancedQuery {
36 m, ok := GetModel(model) 36 m, ok := GetModel(model)
37 response := make([]advance.AdvancedQuery, 0) 37 response := make([]advance.AdvancedQuery, 0)
38 mapResponse := make(map[string]advance.AdvancedQuery) 38 mapResponse := make(map[string]advance.AdvancedQuery)
@@ -57,11 +57,6 @@ func fixAdvanceQueries(model string, quires advance.AdvancedQueries) []advance.A @@ -57,11 +57,6 @@ func fixAdvanceQueries(model string, quires advance.AdvancedQueries) []advance.A
57 return response 57 return response
58 } 58 }
59 59
60 -func GetModel(name string) (Model, bool) {  
61 - m, ok := registerModels[name]  
62 - return m, ok  
63 -}  
64 -  
65 func NewModel(m ModelInterface) Model { 60 func NewModel(m ModelInterface) Model {
66 return Model{ 61 return Model{
67 Name: m.ModelName(), 62 Name: m.ModelName(),
@@ -70,14 +65,22 @@ func NewModel(m ModelInterface) Model { @@ -70,14 +65,22 @@ func NewModel(m ModelInterface) Model {
70 } 65 }
71 } 66 }
72 67
73 -type ModelInterface interface {  
74 - ModelName() string  
75 - Columns() []advance.Column 68 +func RegisModel(m Model) {
  69 + if _, ok := registerModels[m.Name]; ok {
  70 + panic("register modes exists:" + m.Name)
  71 + }
  72 + registerModels[m.Name] = m
  73 +}
  74 +
  75 +func GetModel(name string) (Model, bool) {
  76 + m, ok := registerModels[name]
  77 + return m, ok
76 } 78 }
77 79
78 /*User*/ 80 /*User*/
79 type UserModel struct{} 81 type UserModel struct{}
80 82
  83 +// 实现接口 ModelInterface
81 func (u UserModel) ModelName() string { return "user" } 84 func (u UserModel) ModelName() string { return "user" }
82 func (u UserModel) Columns() []advance.Column { 85 func (u UserModel) Columns() []advance.Column {
83 return []advance.Column{ 86 return []advance.Column{
@@ -160,7 +160,7 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -160,7 +160,7 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
160 exceptSql string 160 exceptSql string
161 ok bool 161 ok bool
162 }{ 162 }{
163 - // in 163 + // in (equal)
164 { 164 {
165 col: columnChar, 165 col: columnChar,
166 name: "in zero item", 166 name: "in zero item",
@@ -212,6 +212,19 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -212,6 +212,19 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
212 ok: true, 212 ok: true,
213 }, 213 },
214 214
  215 + // not in (not equal)
  216 + {
  217 + col: columnNumber,
  218 + name: "not equal many item (number)",
  219 + ins: []Expr{
  220 + {OpChar: NotEqual, Value: []interface{}{1, 2, 3, 4}},
  221 + {OpChar: NotEqual, Value: []interface{}{5, 6}},
  222 + },
  223 + except: nil,
  224 + exceptSql: "(age not in (1,2,3,4,5,6))",
  225 + ok: true,
  226 + },
  227 +
215 // range 228 // range
216 { 229 {
217 col: columnChar, 230 col: columnChar,
@@ -241,7 +254,7 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -241,7 +254,7 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
241 {OpChar: LessThanEqual, Value: []interface{}{Infinity, 80}}, 254 {OpChar: LessThanEqual, Value: []interface{}{Infinity, 80}},
242 }, 255 },
243 except: nil, 256 except: nil,
244 - exceptSql: "(( age <= 80 ))", 257 + exceptSql: "(( age <= 60 ))",
245 ok: true, 258 ok: true,
246 }, 259 },
247 { 260 {
@@ -254,7 +267,19 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -254,7 +267,19 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
254 {OpChar: LessThanEqual, Value: []interface{}{Infinity, 70}}, 267 {OpChar: LessThanEqual, Value: []interface{}{Infinity, 70}},
255 }, 268 },
256 except: nil, 269 except: nil,
257 - exceptSql: "(( age <= 70 ) or ( age >= 80 ))", 270 + exceptSql: "", // 或集 (( age <= 70 ) or ( age >= 80 )) 并集 ""
  271 + ok: true,
  272 + },
  273 + {
  274 + col: columnNumber,
  275 + name: "range many item (Between $<=n<=$)",
  276 + ins: []Expr{
  277 + {OpChar: GreaterThanEqual, Value: []interface{}{80, Infinity}},
  278 + {OpChar: LessThanEqual, Value: []interface{}{Infinity, 200}},
  279 + {OpChar: LessThan, Value: []interface{}{Infinity, 150}},
  280 + },
  281 + except: nil,
  282 + exceptSql: "(( age >= 80 and age < 150 ))",
258 ok: true, 283 ok: true,
259 }, 284 },
260 { 285 {
@@ -275,9 +300,10 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -275,9 +300,10 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
275 {OpChar: Range, Value: []interface{}{120, 220}, LeftOp: GreaterThanEqual, RightOp: LessThan}, 300 {OpChar: Range, Value: []interface{}{120, 220}, LeftOp: GreaterThanEqual, RightOp: LessThan},
276 {OpChar: Range, Value: []interface{}{100, 200}, LeftOp: GreaterThanEqual, RightOp: LessThanEqual}, 301 {OpChar: Range, Value: []interface{}{100, 200}, LeftOp: GreaterThanEqual, RightOp: LessThanEqual},
277 {OpChar: Range, Value: []interface{}{80, 100}, LeftOp: GreaterThan, RightOp: LessThanEqual}, 302 {OpChar: Range, Value: []interface{}{80, 100}, LeftOp: GreaterThan, RightOp: LessThanEqual},
  303 + {OpChar: Range, Value: []interface{}{300, 500}, LeftOp: GreaterThan, RightOp: LessThanEqual},
278 }, 304 },
279 except: nil, 305 except: nil,
280 - exceptSql: "(( age > 80 and age < 220 ))", 306 + exceptSql: "(( age > 80 and age < 220 ) or ( age > 300 and age <= 500 ))",
281 ok: true, 307 ok: true,
282 }, 308 },
283 309
@@ -322,6 +348,18 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -322,6 +348,18 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
322 exceptSql: "((age::text like '%10%' or age::text like '%20%'))", 348 exceptSql: "((age::text like '%10%' or age::text like '%20%'))",
323 ok: true, 349 ok: true,
324 }, 350 },
  351 +
  352 + // error input
  353 + {
  354 + col: columnChar,
  355 + name: "invalid input",
  356 + ins: []Expr{
  357 + {OpChar: Like, Value: []interface{}{"dsger?*"}},
  358 + },
  359 + except: nil,
  360 + exceptSql: "",
  361 + ok: false,
  362 + },
325 } 363 }
326 364
327 for i := range tables { 365 for i := range tables {
@@ -333,7 +371,6 @@ func TestAdvancedQuerySql_PG(t *testing.T) { @@ -333,7 +371,6 @@ func TestAdvancedQuerySql_PG(t *testing.T) {
333 } 371 }
334 t.Run(tables[i].name, func(t *testing.T) { 372 t.Run(tables[i].name, func(t *testing.T) {
335 sql, err := AdvancedQuerySql(q) 373 sql, err := AdvancedQuerySql(q)
336 - assert.Equal(t, tables[i].except, err)  
337 assert.Equal(t, tables[i].exceptSql, sql) 374 assert.Equal(t, tables[i].exceptSql, sql)
338 if tables[i].ok { 375 if tables[i].ok {
339 assert.Nil(t, err) 376 assert.Nil(t, err)
@@ -3,6 +3,8 @@ package advance @@ -3,6 +3,8 @@ package advance
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "fmt" 5 "fmt"
  6 + "regexp"
  7 + "strconv"
6 "strings" 8 "strings"
7 ) 9 )
8 10
@@ -65,7 +67,7 @@ func ComputeColumnExpr(queries []AdvancedQuery) []ColumnExprResult { @@ -65,7 +67,7 @@ func ComputeColumnExpr(queries []AdvancedQuery) []ColumnExprResult {
65 } 67 }
66 68
67 func JoinColumnExprNumber(expr []Expr) []ExprResult { 69 func JoinColumnExprNumber(expr []Expr) []ExprResult {
68 - var ec = []exprCompute{NewInExprCompute(expr, ValueNumber), NewRangeExprCompute(expr, ValueNumber), NewNotEqualExprCompute(expr, ValueNumber), NewLikeExprCompute(expr, ValueNumber)} 70 + var ec = []exprCompute{NewInExprCompute(expr, ValueNumber), NewRangeExprCompute(expr, ValueNumber), NewLessGreaterExprCompute(expr, ValueNumber), NewNotEqualExprCompute(expr, ValueNumber), NewLikeExprCompute(expr, ValueNumber)}
69 return joinExprResult(ec) 71 return joinExprResult(ec)
70 } 72 }
71 73
@@ -98,12 +100,15 @@ func (m MapColumn) FindItem(col string) Column { @@ -98,12 +100,15 @@ func (m MapColumn) FindItem(col string) Column {
98 100
99 type PgSqlGenerator struct{} 101 type PgSqlGenerator struct{}
100 102
101 -func (p PgSqlGenerator) SqlGen(q ColumnExprResult) string { 103 +func (p PgSqlGenerator) SqlGen(q ColumnExprResult) (string, error) {
102 sql := bytes.NewBuffer(nil) 104 sql := bytes.NewBuffer(nil)
103 sql.WriteString("(") 105 sql.WriteString("(")
104 var wheres []string 106 var wheres []string
105 for i := range q.Result { 107 for i := range q.Result {
106 item := q.Result[i] 108 item := q.Result[i]
  109 + if err := p.PreCheckAndFormat(&item); err != nil {
  110 + return "", err
  111 + }
107 var where string 112 var where string
108 switch item.OpChar { 113 switch item.OpChar {
109 case In: 114 case In:
@@ -124,9 +129,34 @@ func (p PgSqlGenerator) SqlGen(q ColumnExprResult) string { @@ -124,9 +129,34 @@ func (p PgSqlGenerator) SqlGen(q ColumnExprResult) string {
124 } 129 }
125 sql.WriteString(strings.Join(wheres, sepOr)) 130 sql.WriteString(strings.Join(wheres, sepOr))
126 sql.WriteString(")") 131 sql.WriteString(")")
127 - return sql.String() 132 + return sql.String(), nil
  133 +}
  134 +func (p PgSqlGenerator) PreCheckAndFormat(rs *ExprResult) error {
  135 + if rs.ValueType == ValueNumber || rs.ValueType == ValueDate {
  136 + for i := range rs.Value {
  137 + v := rs.Value[i]
  138 + if isInfinity(v) {
  139 + continue
  140 + }
  141 + if _, err := strconv.ParseFloat(fmt.Sprintf("%v", v), 64); err != nil {
  142 + return fmt.Errorf("不是有效的数值类型:%v", v)
  143 + }
  144 + }
  145 + }
  146 + if rs.ValueType == ValueChars {
  147 + for i := range rs.Value {
  148 + v, ok := rs.Value[i].(string)
  149 + err := fmt.Errorf("不是有效的字符串类型:%v", v)
  150 + if !ok {
  151 + return err
  152 + }
  153 + if ok, e := regexp.MatchString("[!%&()*+,-/=?^`'{|}~]", v); ok || e != nil {
  154 + return fmt.Errorf("非法字符:%v", v)
  155 + }
  156 + }
  157 + }
  158 + return nil
128 } 159 }
129 -  
130 func (p PgSqlGenerator) In(c Column, values []interface{}) string { 160 func (p PgSqlGenerator) In(c Column, values []interface{}) string {
131 if len(values) < 1 { 161 if len(values) < 1 {
132 return "" 162 return ""
@@ -207,11 +237,18 @@ func AdvancedQuerySql(queries []AdvancedQuery) (string, error) { @@ -207,11 +237,18 @@ func AdvancedQuerySql(queries []AdvancedQuery) (string, error) {
207 sql := bytes.NewBuffer(nil) 237 sql := bytes.NewBuffer(nil)
208 var wheres []string 238 var wheres []string
209 for i := range results { 239 for i := range results {
210 - wheres = append(wheres, gen.SqlGen(results[i])) 240 + condition, err := gen.SqlGen(results[i])
  241 + if err != nil {
  242 + return "", err
  243 + }
  244 + wheres = append(wheres, condition)
211 } 245 }
212 sql.WriteString(strings.Join(wheres, sepAnd)) 246 sql.WriteString(strings.Join(wheres, sepAnd))
213 // 空条件 () 247 // 空条件 ()
214 - if len(sql.String()) == 2 { 248 + if sql.String() == "()" {
  249 + return "", nil
  250 + }
  251 + if sql.String() == "(())" {
215 return "", nil 252 return "", nil
216 } 253 }
217 return sql.String(), nil 254 return sql.String(), nil
@@ -53,10 +53,10 @@ type ( @@ -53,10 +53,10 @@ type (
53 } 53 }
54 Expr struct { 54 Expr struct {
55 // 操作符 55 // 操作符
56 - OpChar OpType `json:"oc"` 56 + OpChar OpType `json:"op"`
57 // 如果 OpChar=range ,LeftOp、RightOp需要有值 57 // 如果 OpChar=range ,LeftOp、RightOp需要有值
58 - LeftOp OpType `json:"loc"` // "<= <"  
59 - RightOp OpType `json:"roc"` // ">= >" 58 + LeftOp OpType `json:"lop"` // "<= <"
  59 + RightOp OpType `json:"rop"` // ">= >"
60 // 值 60 // 值
61 Value []interface{} `json:"values"` 61 Value []interface{} `json:"values"`
62 } 62 }
@@ -98,6 +98,10 @@ type ( @@ -98,6 +98,10 @@ type (
98 valueType ValueType 98 valueType ValueType
99 OpType OpType 99 OpType OpType
100 } 100 }
  101 + LessGreaterExprCompute struct {
  102 + expr []Expr
  103 + valueType ValueType
  104 + }
101 ) 105 )
102 106
103 // in合并 107 // in合并
@@ -151,7 +155,7 @@ func combine(arr []interface{}) []interface{} { @@ -151,7 +155,7 @@ func combine(arr []interface{}) []interface{} {
151 func NewRangeExprCompute(expr []Expr, valueType ValueType) exprCompute { 155 func NewRangeExprCompute(expr []Expr, valueType ValueType) exprCompute {
152 rec := RangeNumberExprCompute{valueType: valueType} 156 rec := RangeNumberExprCompute{valueType: valueType}
153 for i := range expr { 157 for i := range expr {
154 - if expr[i].OpChar == Range || expr[i].OpChar == LessThanEqual || expr[i].OpChar == GreaterThanEqual || expr[i].OpChar == LessThan || expr[i].OpChar == GreaterThan { 158 + if expr[i].OpChar == Range { // || expr[i].OpChar == LessThanEqual || expr[i].OpChar == GreaterThanEqual || expr[i].OpChar == LessThan || expr[i].OpChar == GreaterThan
155 rec.expr = append(rec.expr, expr[i]) 159 rec.expr = append(rec.expr, expr[i])
156 } 160 }
157 } 161 }
@@ -178,14 +182,14 @@ func (ex RangeNumberExprCompute) Append(result []ExprResult) []ExprResult { @@ -178,14 +182,14 @@ func (ex RangeNumberExprCompute) Append(result []ExprResult) []ExprResult {
178 arr.RightOp = ex.expr[0].RightOp 182 arr.RightOp = ex.expr[0].RightOp
179 } 183 }
180 for i := 1; i < len(ex.expr); i++ { 184 for i := 1; i < len(ex.expr); i++ {
181 - if !arr.NumberCompare(ex.expr[i]) { 185 + if !arr.Compare(ex.expr[i]) {
182 result = append(result, *arr) 186 result = append(result, *arr)
183 arr.Value = ex.expr[i].Value 187 arr.Value = ex.expr[i].Value
184 arr.LeftOp = ex.expr[i].OpChar 188 arr.LeftOp = ex.expr[i].OpChar
185 arr.RightOp = ex.expr[i].OpChar 189 arr.RightOp = ex.expr[i].OpChar
186 - //if len(ex.expr[0].LeftOp) != 0 {  
187 - // arr.LeftOp = ex.expr[0].LeftOp  
188 - //} 190 + if len(ex.expr[0].LeftOp) != 0 {
  191 + arr.LeftOp = ex.expr[0].LeftOp
  192 + }
189 if len(ex.expr[0].RightOp) != 0 { 193 if len(ex.expr[0].RightOp) != 0 {
190 arr.RightOp = ex.expr[0].RightOp 194 arr.RightOp = ex.expr[0].RightOp
191 } 195 }
@@ -196,6 +200,60 @@ func (ex RangeNumberExprCompute) Append(result []ExprResult) []ExprResult { @@ -196,6 +200,60 @@ func (ex RangeNumberExprCompute) Append(result []ExprResult) []ExprResult {
196 return result 200 return result
197 } 201 }
198 202
  203 +//范围合并
  204 +func NewLessGreaterExprCompute(expr []Expr, valueType ValueType) exprCompute {
  205 + rec := LessGreaterExprCompute{valueType: valueType}
  206 + for i := range expr {
  207 + if expr[i].OpChar == LessThanEqual || expr[i].OpChar == LessThan || expr[i].OpChar == GreaterThanEqual || expr[i].OpChar == GreaterThan {
  208 + rec.expr = append(rec.expr, expr[i])
  209 + }
  210 + }
  211 + if len(rec.expr) == 0 {
  212 + return nil
  213 + }
  214 + var exprSort = exprSortable(rec.expr)
  215 + sort.Sort(exprSort)
  216 + rec.expr = exprSort
  217 + return rec
  218 +}
  219 +func (ex LessGreaterExprCompute) Append(result []ExprResult) []ExprResult {
  220 + arr := &ExprResult{
  221 + OpChar: Range,
  222 + ValueType: ex.valueType,
  223 + Value: ex.expr[0].Value,
  224 + LeftOp: ex.expr[0].OpChar,
  225 + RightOp: ex.expr[0].OpChar,
  226 + }
  227 + x0, x1 := toFloat64(arr.Value[0], arr.Value[1])
  228 + for i := 1; i < len(ex.expr); i++ {
  229 + compare := ex.expr[i]
  230 + y0, y1 := toFloat64(compare.Value[0], compare.Value[1])
  231 + if compare.OpChar == LessThanEqual || compare.OpChar == LessThan {
  232 + if isInfinity(x1) {
  233 + arr.Value[1] = y0
  234 + arr.RightOp = compare.OpChar
  235 + } else if x1 > y1 {
  236 + arr.Value[0] = y0
  237 + arr.LeftOp = compare.OpChar
  238 + }
  239 + }
  240 + if compare.OpChar == GreaterThan || compare.OpChar == GreaterThanEqual {
  241 + if isInfinity(x0) {
  242 + arr.Value[0] = y0
  243 + arr.LeftOp = compare.OpChar
  244 + } else if y0 > x0 {
  245 + arr.Value[0] = y0
  246 + arr.LeftOp = compare.OpChar
  247 + }
  248 + }
  249 + }
  250 + if _, ok := less(arr.Value[0], arr.Value[1]); !ok {
  251 + arr.Value[0], arr.Value[1] = Infinity, Infinity
  252 + }
  253 + result = append(result, *arr)
  254 + return result
  255 +}
  256 +
199 // recent范围 257 // recent范围
200 func NewRecentDateExprCompute(expr []Expr, valueType ValueType) exprCompute { 258 func NewRecentDateExprCompute(expr []Expr, valueType ValueType) exprCompute {
201 inExpr := RecentDateExprCompute{valueType: valueType} 259 inExpr := RecentDateExprCompute{valueType: valueType}
@@ -268,18 +326,24 @@ func (ex NotEqualExprCompute) Append(result []ExprResult) []ExprResult { @@ -268,18 +326,24 @@ func (ex NotEqualExprCompute) Append(result []ExprResult) []ExprResult {
268 return result 326 return result
269 } 327 }
270 328
271 -func (er *ExprResult) NumberCompare(expr Expr) bool {  
272 - if len(expr.Value) != 2 { 329 +// Compare 比较两个范围的值
  330 +// eg: [80,&] [&,200]
  331 +// 排序 [&,200]
  332 +// [80,&]
  333 +// false:开启新的范围
  334 +// true:继续这个范围
  335 +func (er *ExprResult) Compare(compare Expr) bool {
  336 + if len(compare.Value) != 2 {
273 return false 337 return false
274 } 338 }
275 - _, x2 := toFloat64(er.Value[0], er.Value[1])  
276 - y1, _ := toFloat64(expr.Value[0], expr.Value[1])  
277 - if y1 <= x2 {  
278 - er.Value[1] = max(er.Value[1], expr.Value[1])  
279 - if isEqual(er.Value[1], expr.Value[1]) {  
280 - er.RightOp = expr.OpChar  
281 - if len(expr.RightOp) != 0 {  
282 - er.RightOp = expr.RightOp 339 + _, x1 := toFloat64(er.Value[0], er.Value[1])
  340 + y0, _ := toFloat64(compare.Value[0], compare.Value[1])
  341 + if y0 <= x1 {
  342 + er.Value[1] = max(er.Value[1], compare.Value[1])
  343 + if isEqual(er.Value[1], compare.Value[1]) {
  344 + er.RightOp = compare.OpChar
  345 + if len(compare.RightOp) != 0 {
  346 + er.RightOp = compare.RightOp
283 } 347 }
284 } 348 }
285 return true 349 return true
@@ -349,6 +413,20 @@ func max(x, y interface{}) interface{} { @@ -349,6 +413,20 @@ func max(x, y interface{}) interface{} {
349 return math.Max(fx, fy) 413 return math.Max(fx, fy)
350 } 414 }
351 415
  416 +func less(x, y interface{}) (interface{}, bool) {
  417 + if isInfinity(x) {
  418 + return x, true
  419 + }
  420 + if isInfinity(y) {
  421 + return y, true
  422 + }
  423 + fx, fy := toFloat64(x, y)
  424 + if fx < fy {
  425 + return x, true
  426 + }
  427 + return fy, false
  428 +}
  429 +
352 func isInfinity(val interface{}) bool { 430 func isInfinity(val interface{}) bool {
353 v := fmt.Sprintf("%v", val) 431 v := fmt.Sprintf("%v", val)
354 inf := fmt.Sprintf("%v", Infinity) 432 inf := fmt.Sprintf("%v", Infinity)