Просмотр исходного кода

add validator for using funcs in where & having clause

RockyJin 5 лет назад
Родитель
Сommit
0587210c7e
4 измененных файлов с 78 добавлено и 1 удалено
  1. 48 1
      xsql/ast.go
  2. 4 0
      xsql/parser.go
  3. 12 0
      xsql/parser_test.go
  4. 14 0
      xsql/sql_validator.go

+ 48 - 1
xsql/ast.go

@@ -1504,4 +1504,51 @@ func IsAggStatement(node Node) (bool) {
 		}
 		}
 	});
 	});
 	return r
 	return r
-}
+}
+
+func HasAggFuncs(node Node) bool {
+	if node == nil{
+		return false
+	}
+	var r bool = false
+	WalkFunc(node, func(n Node) {
+		if f, ok := n.(*Call); ok {
+			fn := strings.ToLower(f.Name)
+			if _, ok1 := aggFuncMap[fn]; ok1 {
+				r = true
+				return
+			}
+		}
+	});
+	return r
+}
+
+func HasNoAggFuncs(node Node) bool {
+	if node == nil{
+		return false
+	}
+	var r bool = false
+	WalkFunc(node, func(n Node) {
+		if f, ok := n.(*Call); ok {
+			fn := strings.ToLower(f.Name)
+			if _, ok1 := mathFuncMap[fn]; ok1 {
+				r = true
+				return
+			} else if _, ok1 := strFuncMap[fn]; ok1 {
+				r = true
+				return
+			} else if _, ok1 := convFuncMap[fn]; ok1 {
+				r = true
+				return
+			} else if _, ok1 := hashFuncMap[fn]; ok1 {
+				r = true
+				return
+			} else if _, ok1 := otherFuncMap[fn]; ok1 {
+				r = true
+				return
+			}
+		}
+	});
+	return r
+}
+

+ 4 - 0
xsql/parser.go

@@ -159,6 +159,10 @@ func (p *Parser) Parse() (*SelectStatement, error) {
 		return nil, fmt.Errorf("found %q, expected EOF.", lit)
 		return nil, fmt.Errorf("found %q, expected EOF.", lit)
 	}
 	}
 
 
+	if err := Validate(selects); err != nil {
+		return nil, err
+	}
+
 	return selects, nil
 	return selects, nil
 }
 }
 
 

+ 12 - 0
xsql/parser_test.go

@@ -871,6 +871,18 @@ func TestParser_ParseStatement(t *testing.T) {
 		},
 		},
 
 
 		{
 		{
+			s: `SELECT temp AS t, name FROM topic/sensor1 WHERE name = "dname" HAVING sin(name) > 0.3`,
+			stmt: nil,
+			err: "Not allowed to call none-aggregate functions in HAVING clause.",
+		},
+
+		{
+			s: `SELECT temp AS t, name FROM topic/sensor1 WHERE count(name) = 3`,
+			stmt: nil,
+			err: "Not allowed to call aggregate functions in WHERE clause.",
+		},
+
+		{
 			s: `SELECT s1.temp AS t, name FROM topic/sensor1 AS s1 WHERE t = "dname" GROUP BY s1.temp`,
 			s: `SELECT s1.temp AS t, name FROM topic/sensor1 AS s1 WHERE t = "dname" GROUP BY s1.temp`,
 			stmt: &SelectStatement{
 			stmt: &SelectStatement{
 				Fields:    []Field{
 				Fields:    []Field{

+ 14 - 0
xsql/sql_validator.go

@@ -0,0 +1,14 @@
+package xsql
+
+import "fmt"
+
+func Validate(stmt *SelectStatement) error {
+	if HasAggFuncs(stmt.Condition) {
+		return fmt.Errorf("Not allowed to call aggregate functions in WHERE clause.")
+	}
+
+	if HasNoAggFuncs(stmt.Having) {
+		return fmt.Errorf("Not allowed to call none-aggregate functions in HAVING clause.")
+	}
+	return nil
+}