From 326ba018bd818f17f2b5632a0e5241f81582d315 Mon Sep 17 00:00:00 2001 From: Du Chuan Date: Mon, 26 Nov 2018 12:50:19 +0800 Subject: [PATCH] [parser] ast: Fix FrameBound.Accept (#51) --- parser/ast/dml.go | 2 +- parser/parser_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/parser/ast/dml.go b/parser/ast/dml.go index e7fbc19019679..82268cc7e6aa2 100644 --- a/parser/ast/dml.go +++ b/parser/ast/dml.go @@ -1201,7 +1201,7 @@ func (n *FrameBound) Accept(v Visitor) (Node, bool) { n.Expr = node.(ExprNode) } if n.Unit != nil { - node, ok := n.Expr.Accept(v) + node, ok := n.Unit.Accept(v) if !ok { return n, false } diff --git a/parser/parser_test.go b/parser/parser_test.go index bb5082b36146a..f7aae4472b514 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -2573,6 +2573,60 @@ func (s *testParserSuite) TestWindowFunctions(c *C) { s.RunTest(c, table) } +type windowFrameBoundChecker struct { + fb *ast.FrameBound + exprRc int + timeUnitRc int +} + +// Enter implements ast.Visitor interface. +func (wfc *windowFrameBoundChecker) Enter(inNode ast.Node) (outNode ast.Node, skipChildren bool) { + if _, ok := inNode.(*ast.FrameBound); ok { + wfc.fb = inNode.(*ast.FrameBound) + } + return inNode, false +} + +// Leave implements ast.Visitor interface. +func (wfc *windowFrameBoundChecker) Leave(inNode ast.Node) (node ast.Node, ok bool) { + if _, ok := inNode.(*ast.FrameBound); ok { + wfc.fb = nil + } + if wfc.fb != nil { + if inNode == wfc.fb.Expr { + wfc.exprRc += 1 + } else if inNode == wfc.fb.Unit { + wfc.timeUnitRc += 1 + } + } + return inNode, true +} + +// For issue #51 +// See https://github.com/pingcap/parser/pull/51 for details +func (s *testParserSuite) TestVisitFrameBound(c *C) { + parser := New() + parser.EnableWindowFunc() + table := []struct { + s string + exprRc int + timeUnitRc int + }{ + {`SELECT AVG(val) OVER (RANGE INTERVAL '2:30' MINUTE_SECOND PRECEDING) FROM t;`, 1, 1}, + {`SELECT AVG(val) OVER (RANGE 5 PRECEDING) FROM t;`, 1, 0}, + {`SELECT AVG(val) OVER () FROM t;`, 0, 0}, + } + for _, t := range table { + stmt, err := parser.ParseOneStmt(t.s, "", "") + c.Assert(err, IsNil) + checker := windowFrameBoundChecker{} + stmt.Accept(&checker) + c.Assert(checker.exprRc, Equals, t.exprRc) + c.Assert(checker.timeUnitRc, Equals, t.timeUnitRc) + } + +} + func (s *testParserSuite) TestFieldText(c *C) { parser := New() stmts, err := parser.Parse("select a from t", "", "")