From dc2868d1ade6680ea72785d0d96b8360b21ad322 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Sat, 21 Apr 2018 20:13:03 +0800
Subject: [PATCH 1/7] Parser: fix issue-6092

---
 executor/executor_test.go |  4 +-
 parser/parser.y           | 96 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 95 insertions(+), 5 deletions(-)

diff --git a/executor/executor_test.go b/executor/executor_test.go
index 3f60f46c260bf..b164885073561 100644
--- a/executor/executor_test.go
+++ b/executor/executor_test.go
@@ -947,7 +947,9 @@ func (s *testSuite) TestUnion(c *C) {
 	tk.MustExec("create table t(a int)")
 	tk.MustExec("insert into t value(0),(0)")
 	tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1"))
-	tk.MustQuery("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp").Check(testkit.Rows("1", "1"))
+	tk.MustQuery("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp").Check(testkit.Rows("1"))
+	tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10"))
+	tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10"))
 	tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4"))
 }
 
diff --git a/parser/parser.y b/parser/parser.y
index 363ad3a9bd6e4..957d7685a7dbb 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -4548,16 +4548,104 @@ SelectLockOpt:
 		$$ = ast.SelectLockInShareMode
 	}
 
-// See https://dev.mysql.com/doc/refman/5.7/en/union.html
 UnionStmt:
-	UnionClauseList "UNION" UnionOpt SelectStmt
+	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList OrderByOptional SelectStmtLimit SelectLockOpt
 	{
+		sel := &ast.SelectStmt {
+			SelectStmtOpts: $5.(*ast.SelectStmtOpts),
+			Distinct:      $5.(*ast.SelectStmtOpts).Distinct,
+			Fields:        $6.(*ast.FieldList),
+		}
+		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
+		if lastField.Expr != nil && lastField.AsName.O == "" {
+			src := parser.src
+			var lastEnd = len(src)
+			if src[lastEnd-1] == ';' {
+				lastEnd--
+			}
+			lastField.SetText(src[lastField.Offset:lastEnd])
+		}
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-2])
+		endOffset := parser.endOffset(&yyS[yypt-7])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
-		union.SelectList.Selects = append(union.SelectList.Selects, $4.(*ast.SelectStmt))
+		union.SelectList.Selects = append(union.SelectList.Selects, sel)
+		if $7 != nil {
+		    union.OrderBy = $7.(*ast.OrderByClause)
+		}
+		if $8 != nil {
+		    union.Limit = $8.(*ast.Limit)
+		}
+		$$ = union
+	}
+|	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
+	{
+   		sel := &ast.SelectStmt {
+   			SelectStmtOpts: $5.(*ast.SelectStmtOpts),
+   			Distinct:      $5.(*ast.SelectStmtOpts).Distinct,
+   			Fields:        $6.(*ast.FieldList),
+   		}
+   		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
+   		if lastField.Expr != nil && lastField.AsName.O == "" {
+   			lastEnd := yyS[yypt-3].offset-1
+    		lastField.SetText(parser.src[lastField.Offset:lastEnd])
+    	}
+   		if $8 != nil {
+    		sel.Where = $8.(ast.ExprNode)
+   		}
+		union := $1.(*ast.UnionStmt)
+		union.Distinct = union.Distinct || $3.(bool)
+		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
+		endOffset := parser.endOffset(&yyS[yypt-8])
+		parser.setLastSelectFieldText(lastSelect, endOffset)
+		union.SelectList.Selects = append(union.SelectList.Selects, sel)
+		if $9 != nil {
+		    union.Limit = $9.(*ast.Limit)
+		}
+		$$ = union
+	}
+|	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList "FROM"
+   	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause OrderByOptional
+   	SelectStmtLimit SelectLockOpt
+	{
+		opts := $5.(*ast.SelectStmtOpts)
+    	st := &ast.SelectStmt{
+    		SelectStmtOpts: $5.(*ast.SelectStmtOpts),
+    		Distinct:		opts.Distinct,
+    		Fields:		$6.(*ast.FieldList),
+    		From:		$8.(*ast.TableRefsClause),
+    	}
+    	if opts.TableHints != nil {
+    		st.TableHints = opts.TableHints
+    	}
+    	lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
+    	if lastField.Expr != nil && lastField.AsName.O == "" {
+    	    lastEnd := parser.endOffset(&yyS[yypt-7])
+    	    lastField.SetText(parser.src[lastField.Offset:lastEnd])
+    	}
+    	if $9 != nil {
+    	    st.Where = $9.(ast.ExprNode)
+    	}
+    	if $10!= nil {
+    		st.GroupBy = $10.(*ast.GroupByClause)
+    	}
+    	if $11 != nil {
+    		st.Having = $11.(*ast.HavingClause)
+    	}
+
+		union := $1.(*ast.UnionStmt)
+		union.Distinct = union.Distinct || $3.(bool)
+		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
+		endOffset := parser.endOffset(&yyS[yypt-12])
+		parser.setLastSelectFieldText(lastSelect, endOffset)
+		union.SelectList.Selects = append(union.SelectList.Selects, st)
+    	if $12 != nil {
+    		union.OrderBy = $12.(*ast.OrderByClause)
+    	}
+    	if $13 != nil {
+    		union.Limit = $13.(*ast.Limit)
+    	}
 		$$ = union
 	}
 |	UnionClauseList "UNION" UnionOpt '(' SelectStmt ')' OrderByOptional SelectStmtLimit

From e6bf537b86cb0a88872171bc0ebc1f45e1572705 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Tue, 24 Apr 2018 22:15:52 +0800
Subject: [PATCH 2/7] Refine SelectStmt

---
 parser/parser.y | 160 ++++++++++++++++++++++--------------------------
 1 file changed, 74 insertions(+), 86 deletions(-)

diff --git a/parser/parser.y b/parser/parser.y
index 957d7685a7dbb..f9d5c1ab30c83 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -694,6 +694,7 @@ import (
 	SelectStmtFieldList		"SELECT statement field list"
 	SelectStmtLimit			"SELECT statement optional LIMIT clause"
 	SelectStmtOpts			"Select statement options"
+	SelectStmtPart1			"SELECT statement part 1"
 	SelectStmtGroup			"SELECT statement optional GROUP BY clause"
 	ShowTargetFilterable    	"Show target that can be filtered by WHERE or LIKE"
 	ShowDatabaseNameOpt		"Show tables/columns statement database name option"
@@ -4034,24 +4035,31 @@ RollbackStmt:
 		$$ = &ast.RollbackStmt{}
 	}
 
-SelectStmt:
-	"SELECT" SelectStmtOpts SelectStmtFieldList OrderByOptional SelectStmtLimit SelectLockOpt
-	{
+SelectStmtPart1:
+    "SELECT" SelectStmtOpts SelectStmtFieldList
+    {
 		st := &ast.SelectStmt {
 			SelectStmtOpts: $2.(*ast.SelectStmtOpts),
 			Distinct:      $2.(*ast.SelectStmtOpts).Distinct,
 			Fields:        $3.(*ast.FieldList),
-			LockTp:	       $6.(ast.SelectLockType),
 		}
+		$$ = st
+    }
+
+SelectStmt:
+	SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
+	{
+	    st := $1.(*ast.SelectStmt)
+		st.LockTp = $4.(ast.SelectLockType)
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {
 			src := parser.src
 			var lastEnd int
-			if $4 != nil {
+			if $2 != nil {
 				lastEnd = yyS[yypt-2].offset-1
-			} else if $5 != nil {
+			} else if $3 != nil {
 				lastEnd = yyS[yypt-1].offset-1
-			} else if $6 != ast.SelectLockNone {
+			} else if $4 != ast.SelectLockNone {
 				lastEnd = yyS[yypt].offset-1
 			} else {
 				lastEnd = len(src)
@@ -4061,69 +4069,62 @@ SelectStmt:
 			}
 			lastField.SetText(src[lastField.Offset:lastEnd])
 		}
-		if $4 != nil {
-			st.OrderBy = $4.(*ast.OrderByClause)
+		if $2 != nil {
+			st.OrderBy = $2.(*ast.OrderByClause)
 		}
-		if $5 != nil {
-			st.Limit = $5.(*ast.Limit)
+		if $3 != nil {
+			st.Limit = $3.(*ast.Limit)
 		}
 		$$ = st
 	}
-|	"SELECT" SelectStmtOpts SelectStmtFieldList FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
+|	SelectStmtPart1 FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
 	{
-		st := &ast.SelectStmt {
-			SelectStmtOpts: $2.(*ast.SelectStmtOpts),
-			Distinct:      $2.(*ast.SelectStmtOpts).Distinct,
-			Fields:        $3.(*ast.FieldList),
-			LockTp:	       $7.(ast.SelectLockType),
-		}
+	    st := $1.(*ast.SelectStmt)
+		st.LockTp = $5.(ast.SelectLockType)
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {
 			lastEnd := yyS[yypt-3].offset-1
 			lastField.SetText(parser.src[lastField.Offset:lastEnd])
 		}
-		if $5 != nil {
-			st.Where = $5.(ast.ExprNode)
+		if $3 != nil {
+			st.Where = $3.(ast.ExprNode)
 		}
-		if $6 != nil {
-			st.Limit = $6.(*ast.Limit)
+		if $4 != nil {
+			st.Limit = $4.(*ast.Limit)
 		}
 		$$ = st
 	}
-|	"SELECT" SelectStmtOpts SelectStmtFieldList "FROM"
+|	SelectStmtPart1 "FROM"
 	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause OrderByOptional
 	SelectStmtLimit SelectLockOpt
 	{
-		opts := $2.(*ast.SelectStmtOpts)
-		st := &ast.SelectStmt{
-			SelectStmtOpts: $2.(*ast.SelectStmtOpts),
-			Distinct:		opts.Distinct,
-			Fields:		$3.(*ast.FieldList),
-			From:		$5.(*ast.TableRefsClause),
-			LockTp:		$11.(ast.SelectLockType),
-		}
-		if opts.TableHints != nil {
-			st.TableHints = opts.TableHints
+	    st := $1.(*ast.SelectStmt)
+		st.LockTp = $9.(ast.SelectLockType)
+		st.From = $3.(*ast.TableRefsClause)
+		if st.SelectStmtOpts.TableHints != nil {
+			st.TableHints = st.SelectStmtOpts.TableHints
 		}
+
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {
 			lastEnd := parser.endOffset(&yyS[yypt-7])
 			lastField.SetText(parser.src[lastField.Offset:lastEnd])
 		}
+
+		if $4 != nil {
+			st.Where = $4.(ast.ExprNode)
+		}
+		if $5 != nil {
+			st.GroupBy = $5.(*ast.GroupByClause)
+		}
 		if $6 != nil {
-			st.Where = $6.(ast.ExprNode)
+			st.Having = $6.(*ast.HavingClause)
 		}
 		if $7 != nil {
-			st.GroupBy = $7.(*ast.GroupByClause)
+			st.OrderBy = $7.(*ast.OrderByClause)
 		}
 		if $8 != nil {
-			st.Having = $8.(*ast.HavingClause)
-		}
-		if $9 != nil {
-			st.OrderBy = $9.(*ast.OrderByClause)
-		}
-		if $10 != nil {
-			st.Limit = $10.(*ast.Limit)
+			st.Limit = $8.(*ast.Limit)
 		}
 		$$ = st
 	}
@@ -4549,13 +4550,9 @@ SelectLockOpt:
 	}
 
 UnionStmt:
-	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList OrderByOptional SelectStmtLimit SelectLockOpt
+	UnionClauseList "UNION" UnionOpt SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
-		sel := &ast.SelectStmt {
-			SelectStmtOpts: $5.(*ast.SelectStmtOpts),
-			Distinct:      $5.(*ast.SelectStmtOpts).Distinct,
-			Fields:        $6.(*ast.FieldList),
-		}
+	    sel := $4.(*ast.SelectStmt)
 		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {
 			src := parser.src
@@ -4568,83 +4565,74 @@ UnionStmt:
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-7])
+		endOffset := parser.endOffset(&yyS[yypt-5])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, sel)
-		if $7 != nil {
-		    union.OrderBy = $7.(*ast.OrderByClause)
+		if $5 != nil {
+		    union.OrderBy = $5.(*ast.OrderByClause)
 		}
-		if $8 != nil {
-		    union.Limit = $8.(*ast.Limit)
+		if $6 != nil {
+		    union.Limit = $6.(*ast.Limit)
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
+|	UnionClauseList "UNION" UnionOpt SelectStmtPart1 FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
 	{
-   		sel := &ast.SelectStmt {
-   			SelectStmtOpts: $5.(*ast.SelectStmtOpts),
-   			Distinct:      $5.(*ast.SelectStmtOpts).Distinct,
-   			Fields:        $6.(*ast.FieldList),
-   		}
+	    sel := $4.(*ast.SelectStmt)
    		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
    		if lastField.Expr != nil && lastField.AsName.O == "" {
    			lastEnd := yyS[yypt-3].offset-1
     		lastField.SetText(parser.src[lastField.Offset:lastEnd])
     	}
-   		if $8 != nil {
-    		sel.Where = $8.(ast.ExprNode)
+   		if $6 != nil {
+    		sel.Where = $6.(ast.ExprNode)
    		}
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-8])
+		endOffset := parser.endOffset(&yyS[yypt-6])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, sel)
-		if $9 != nil {
-		    union.Limit = $9.(*ast.Limit)
+		if $7 != nil {
+		    union.Limit = $7.(*ast.Limit)
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt "SELECT" SelectStmtOpts SelectStmtFieldList "FROM"
+|	UnionClauseList "UNION" UnionOpt SelectStmtPart1 "FROM"
    	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause OrderByOptional
    	SelectStmtLimit SelectLockOpt
 	{
-		opts := $5.(*ast.SelectStmtOpts)
-    	st := &ast.SelectStmt{
-    		SelectStmtOpts: $5.(*ast.SelectStmtOpts),
-    		Distinct:		opts.Distinct,
-    		Fields:		$6.(*ast.FieldList),
-    		From:		$8.(*ast.TableRefsClause),
-    	}
-    	if opts.TableHints != nil {
-    		st.TableHints = opts.TableHints
-    	}
+	    st := $4.(*ast.SelectStmt)
+		if st.SelectStmtOpts.TableHints != nil {
+			st.TableHints = st.SelectStmtOpts.TableHints
+		}
+		st.From = $6.(*ast.TableRefsClause)
     	lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
     	if lastField.Expr != nil && lastField.AsName.O == "" {
     	    lastEnd := parser.endOffset(&yyS[yypt-7])
     	    lastField.SetText(parser.src[lastField.Offset:lastEnd])
     	}
-    	if $9 != nil {
-    	    st.Where = $9.(ast.ExprNode)
+    	if $7 != nil {
+    	    st.Where = $7.(ast.ExprNode)
     	}
-    	if $10!= nil {
-    		st.GroupBy = $10.(*ast.GroupByClause)
+    	if $8!= nil {
+    		st.GroupBy = $8.(*ast.GroupByClause)
     	}
-    	if $11 != nil {
-    		st.Having = $11.(*ast.HavingClause)
+    	if $9 != nil {
+    		st.Having = $9.(*ast.HavingClause)
     	}
 
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-12])
+		endOffset := parser.endOffset(&yyS[yypt-10])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
-    	if $12 != nil {
-    		union.OrderBy = $12.(*ast.OrderByClause)
+    	if $10 != nil {
+    		union.OrderBy = $10.(*ast.OrderByClause)
     	}
-    	if $13 != nil {
-    		union.Limit = $13.(*ast.Limit)
+    	if $11 != nil {
+    		union.Limit = $11.(*ast.Limit)
     	}
 		$$ = union
 	}

From de218345bc257b002748bf5c269bdefcb653ff30 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Tue, 24 Apr 2018 23:47:23 +0800
Subject: [PATCH 3/7] Refine SelectStmt && UnionStmt. Part II

---
 parser/parser.y | 161 +++++++++++++++++++++---------------------------
 1 file changed, 69 insertions(+), 92 deletions(-)

diff --git a/parser/parser.y b/parser/parser.y
index f9d5c1ab30c83..1b2397c2f5077 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -695,6 +695,8 @@ import (
 	SelectStmtLimit			"SELECT statement optional LIMIT clause"
 	SelectStmtOpts			"Select statement options"
 	SelectStmtPart1			"SELECT statement part 1"
+	SelectStmtPart2			"SELECT statement part 2"
+	SelectStmtPart3			"SELECT statement part 3"
 	SelectStmtGroup			"SELECT statement optional GROUP BY clause"
 	ShowTargetFilterable    	"Show target that can be filtered by WHERE or LIKE"
 	ShowDatabaseNameOpt		"Show tables/columns statement database name option"
@@ -4046,6 +4048,47 @@ SelectStmtPart1:
 		$$ = st
     }
 
+SelectStmtPart2:
+    SelectStmtPart1 FromDual WhereClauseOptional
+    {
+	    st := $1.(*ast.SelectStmt)
+		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
+		if lastField.Expr != nil && lastField.AsName.O == "" {
+			lastEnd := yyS[yypt-1].offset-1
+			lastField.SetText(parser.src[lastField.Offset:lastEnd])
+		}
+		if $3 != nil {
+			st.Where = $3.(ast.ExprNode)
+		}
+    }
+
+
+SelectStmtPart3:
+	SelectStmtPart1 "FROM"
+	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause
+	{
+	    st := $1.(*ast.SelectStmt)
+		st.From = $3.(*ast.TableRefsClause)
+		if st.SelectStmtOpts.TableHints != nil {
+			st.TableHints = st.SelectStmtOpts.TableHints
+		}
+		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
+		if lastField.Expr != nil && lastField.AsName.O == "" {
+			lastEnd := parser.endOffset(&yyS[yypt-4])
+			lastField.SetText(parser.src[lastField.Offset:lastEnd])
+		}
+		if $4 != nil {
+			st.Where = $4.(ast.ExprNode)
+		}
+		if $5 != nil {
+			st.GroupBy = $5.(*ast.GroupByClause)
+		}
+		if $6 != nil {
+			st.Having = $6.(*ast.HavingClause)
+		}
+		$$ = st
+	}
+
 SelectStmt:
 	SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
@@ -4077,54 +4120,24 @@ SelectStmt:
 		}
 		$$ = st
 	}
-|	SelectStmtPart1 FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
+|	SelectStmtPart2 SelectStmtLimit SelectLockOpt
 	{
 	    st := $1.(*ast.SelectStmt)
-		st.LockTp = $5.(ast.SelectLockType)
-		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
-		if lastField.Expr != nil && lastField.AsName.O == "" {
-			lastEnd := yyS[yypt-3].offset-1
-			lastField.SetText(parser.src[lastField.Offset:lastEnd])
-		}
-		if $3 != nil {
-			st.Where = $3.(ast.ExprNode)
-		}
-		if $4 != nil {
-			st.Limit = $4.(*ast.Limit)
+		st.LockTp = $3.(ast.SelectLockType)
+		if $2 != nil {
+			st.Limit = $2.(*ast.Limit)
 		}
 		$$ = st
 	}
-|	SelectStmtPart1 "FROM"
-	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause OrderByOptional
-	SelectStmtLimit SelectLockOpt
+|	SelectStmtPart3 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
 	    st := $1.(*ast.SelectStmt)
-		st.LockTp = $9.(ast.SelectLockType)
-		st.From = $3.(*ast.TableRefsClause)
-		if st.SelectStmtOpts.TableHints != nil {
-			st.TableHints = st.SelectStmtOpts.TableHints
-		}
-
-		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
-		if lastField.Expr != nil && lastField.AsName.O == "" {
-			lastEnd := parser.endOffset(&yyS[yypt-7])
-			lastField.SetText(parser.src[lastField.Offset:lastEnd])
-		}
-
-		if $4 != nil {
-			st.Where = $4.(ast.ExprNode)
-		}
-		if $5 != nil {
-			st.GroupBy = $5.(*ast.GroupByClause)
-		}
-		if $6 != nil {
-			st.Having = $6.(*ast.HavingClause)
-		}
-		if $7 != nil {
-			st.OrderBy = $7.(*ast.OrderByClause)
+		st.LockTp = $4.(ast.SelectLockType)
+		if $2 != nil {
+			st.OrderBy = $2.(*ast.OrderByClause)
 		}
-		if $8 != nil {
-			st.Limit = $8.(*ast.Limit)
+		if $3 != nil {
+			st.Limit = $3.(*ast.Limit)
 		}
 		$$ = st
 	}
@@ -4549,25 +4562,17 @@ SelectLockOpt:
 		$$ = ast.SelectLockInShareMode
 	}
 
+// See https://dev.mysql.com/doc/refman/5.7/en/union.html
 UnionStmt:
 	UnionClauseList "UNION" UnionOpt SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
-	    sel := $4.(*ast.SelectStmt)
-		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
-		if lastField.Expr != nil && lastField.AsName.O == "" {
-			src := parser.src
-			var lastEnd = len(src)
-			if src[lastEnd-1] == ';' {
-				lastEnd--
-			}
-			lastField.SetText(src[lastField.Offset:lastEnd])
-		}
+	    st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-5])
+		endOffset := parser.endOffset(&yyS[yypt-3])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
-		union.SelectList.Selects = append(union.SelectList.Selects, sel)
+		union.SelectList.Selects = append(union.SelectList.Selects, st)
 		if $5 != nil {
 		    union.OrderBy = $5.(*ast.OrderByClause)
 		}
@@ -4576,63 +4581,35 @@ UnionStmt:
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt SelectStmtPart1 FromDual WhereClauseOptional SelectStmtLimit SelectLockOpt
+|	UnionClauseList "UNION" UnionOpt SelectStmtPart2 SelectStmtLimit SelectLockOpt
 	{
-	    sel := $4.(*ast.SelectStmt)
-   		lastField := sel.Fields.Fields[len(sel.Fields.Fields)-1]
-   		if lastField.Expr != nil && lastField.AsName.O == "" {
-   			lastEnd := yyS[yypt-3].offset-1
-    		lastField.SetText(parser.src[lastField.Offset:lastEnd])
-    	}
-   		if $6 != nil {
-    		sel.Where = $6.(ast.ExprNode)
-   		}
+	    st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-6])
+		endOffset := parser.endOffset(&yyS[yypt-2])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
-		union.SelectList.Selects = append(union.SelectList.Selects, sel)
-		if $7 != nil {
-		    union.Limit = $7.(*ast.Limit)
+		union.SelectList.Selects = append(union.SelectList.Selects, st)
+		if $5 != nil {
+		    union.Limit = $5.(*ast.Limit)
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt SelectStmtPart1 "FROM"
-   	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause OrderByOptional
+|	UnionClauseList "UNION" UnionOpt SelectStmtPart3 OrderByOptional
    	SelectStmtLimit SelectLockOpt
 	{
 	    st := $4.(*ast.SelectStmt)
-		if st.SelectStmtOpts.TableHints != nil {
-			st.TableHints = st.SelectStmtOpts.TableHints
-		}
-		st.From = $6.(*ast.TableRefsClause)
-    	lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
-    	if lastField.Expr != nil && lastField.AsName.O == "" {
-    	    lastEnd := parser.endOffset(&yyS[yypt-7])
-    	    lastField.SetText(parser.src[lastField.Offset:lastEnd])
-    	}
-    	if $7 != nil {
-    	    st.Where = $7.(ast.ExprNode)
-    	}
-    	if $8!= nil {
-    		st.GroupBy = $8.(*ast.GroupByClause)
-    	}
-    	if $9 != nil {
-    		st.Having = $9.(*ast.HavingClause)
-    	}
-
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-10])
+		endOffset := parser.endOffset(&yyS[yypt-3])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
-    	if $10 != nil {
-    		union.OrderBy = $10.(*ast.OrderByClause)
+    	if $5 != nil {
+    		union.OrderBy = $5.(*ast.OrderByClause)
     	}
-    	if $11 != nil {
-    		union.Limit = $11.(*ast.Limit)
+    	if $6 != nil {
+    		union.Limit = $6.(*ast.Limit)
     	}
 		$$ = union
 	}

From 61e2c5d28a4582889a62e6ff1719a418aa5c1976 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Wed, 25 Apr 2018 00:55:33 +0800
Subject: [PATCH 4/7] code fmt refine

---
 parser/parser.y | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/parser/parser.y b/parser/parser.y
index 1b2397c2f5077..0821bd488fa6d 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -4038,20 +4038,20 @@ RollbackStmt:
 	}
 
 SelectStmtPart1:
-    "SELECT" SelectStmtOpts SelectStmtFieldList
-    {
+	"SELECT" SelectStmtOpts SelectStmtFieldList
+	{
 		st := &ast.SelectStmt {
 			SelectStmtOpts: $2.(*ast.SelectStmtOpts),
 			Distinct:      $2.(*ast.SelectStmtOpts).Distinct,
 			Fields:        $3.(*ast.FieldList),
 		}
 		$$ = st
-    }
+	}
 
 SelectStmtPart2:
-    SelectStmtPart1 FromDual WhereClauseOptional
-    {
-	    st := $1.(*ast.SelectStmt)
+	SelectStmtPart1 FromDual WhereClauseOptional
+	{
+		st := $1.(*ast.SelectStmt)
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {
 			lastEnd := yyS[yypt-1].offset-1
@@ -4060,14 +4060,14 @@ SelectStmtPart2:
 		if $3 != nil {
 			st.Where = $3.(ast.ExprNode)
 		}
-    }
+	}
 
 
 SelectStmtPart3:
 	SelectStmtPart1 "FROM"
 	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause
 	{
-	    st := $1.(*ast.SelectStmt)
+		st := $1.(*ast.SelectStmt)
 		st.From = $3.(*ast.TableRefsClause)
 		if st.SelectStmtOpts.TableHints != nil {
 			st.TableHints = st.SelectStmtOpts.TableHints
@@ -4122,7 +4122,7 @@ SelectStmt:
 	}
 |	SelectStmtPart2 SelectStmtLimit SelectLockOpt
 	{
-	    st := $1.(*ast.SelectStmt)
+		st := $1.(*ast.SelectStmt)
 		st.LockTp = $3.(ast.SelectLockType)
 		if $2 != nil {
 			st.Limit = $2.(*ast.Limit)
@@ -4131,7 +4131,7 @@ SelectStmt:
 	}
 |	SelectStmtPart3 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
-	    st := $1.(*ast.SelectStmt)
+		st := $1.(*ast.SelectStmt)
 		st.LockTp = $4.(ast.SelectLockType)
 		if $2 != nil {
 			st.OrderBy = $2.(*ast.OrderByClause)
@@ -4566,7 +4566,7 @@ SelectLockOpt:
 UnionStmt:
 	UnionClauseList "UNION" UnionOpt SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
-	    st := $4.(*ast.SelectStmt)
+		st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
@@ -4583,7 +4583,7 @@ UnionStmt:
 	}
 |	UnionClauseList "UNION" UnionOpt SelectStmtPart2 SelectStmtLimit SelectLockOpt
 	{
-	    st := $4.(*ast.SelectStmt)
+		st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
@@ -4598,19 +4598,19 @@ UnionStmt:
 |	UnionClauseList "UNION" UnionOpt SelectStmtPart3 OrderByOptional
    	SelectStmtLimit SelectLockOpt
 	{
-	    st := $4.(*ast.SelectStmt)
+		st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
 		endOffset := parser.endOffset(&yyS[yypt-3])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
-    	if $5 != nil {
-    		union.OrderBy = $5.(*ast.OrderByClause)
-    	}
-    	if $6 != nil {
-    		union.Limit = $6.(*ast.Limit)
-    	}
+		if $5 != nil {
+			union.OrderBy = $5.(*ast.OrderByClause)
+		}
+		if $6 != nil {
+			union.Limit = $6.(*ast.Limit)
+		}
 		$$ = union
 	}
 |	UnionClauseList "UNION" UnionOpt '(' SelectStmt ')' OrderByOptional SelectStmtLimit

From 0a5569ca2791a84eccbd325758768a64105858c0 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Wed, 25 Apr 2018 00:58:28 +0800
Subject: [PATCH 5/7] Code format refine

---
 parser/parser.y | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/parser/parser.y b/parser/parser.y
index 0821bd488fa6d..a9da6f188a89b 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -4092,7 +4092,7 @@ SelectStmtPart3:
 SelectStmt:
 	SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
 	{
-	    st := $1.(*ast.SelectStmt)
+		st := $1.(*ast.SelectStmt)
 		st.LockTp = $4.(ast.SelectLockType)
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
 		if lastField.Expr != nil && lastField.AsName.O == "" {

From b67a4263a3c7c405621b135762b32f126117bacb Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Wed, 25 Apr 2018 19:31:47 +0800
Subject: [PATCH 6/7] Fix field text

---
 parser/parser.y | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/parser/parser.y b/parser/parser.y
index a9da6f188a89b..6a57d6966e043 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -4570,7 +4570,7 @@ UnionStmt:
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-3])
+		endOffset := parser.endOffset(&yyS[yypt-5])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
 		if $5 != nil {
@@ -4587,7 +4587,7 @@ UnionStmt:
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-2])
+		endOffset := parser.endOffset(&yyS[yypt-4])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
 		if $5 != nil {
@@ -4602,7 +4602,7 @@ UnionStmt:
 		union := $1.(*ast.UnionStmt)
 		union.Distinct = union.Distinct || $3.(bool)
 		lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1]
-		endOffset := parser.endOffset(&yyS[yypt-3])
+		endOffset := parser.endOffset(&yyS[yypt-5])
 		parser.setLastSelectFieldText(lastSelect, endOffset)
 		union.SelectList.Selects = append(union.SelectList.Selects, st)
 		if $5 != nil {

From ae6ebef9bfcb4cd95ec24efd8d8cf6dcb3609910 Mon Sep 17 00:00:00 2001
From: spongedc <duchuangucas@live.com>
Date: Wed, 9 May 2018 02:48:54 +0800
Subject: [PATCH 7/7] Code refine

---
 parser/parser.y | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/parser/parser.y b/parser/parser.y
index 2f623adedbf56..de7dd63428a32 100644
--- a/parser/parser.y
+++ b/parser/parser.y
@@ -699,9 +699,9 @@ import (
 	SelectStmtFieldList		"SELECT statement field list"
 	SelectStmtLimit			"SELECT statement optional LIMIT clause"
 	SelectStmtOpts			"Select statement options"
-	SelectStmtPart1			"SELECT statement part 1"
-	SelectStmtPart2			"SELECT statement part 2"
-	SelectStmtPart3			"SELECT statement part 3"
+	SelectStmtBasic			"SELECT statement from constant value"
+	SelectStmtFromDual			"SELECT statement from dual"
+	SelectStmtFromTable			"SELECT statement from table"
 	SelectStmtGroup			"SELECT statement optional GROUP BY clause"
 	ShowTargetFilterable    	"Show target that can be filtered by WHERE or LIKE"
 	ShowDatabaseNameOpt		"Show tables/columns statement database name option"
@@ -4070,7 +4070,7 @@ RollbackStmt:
 		$$ = &ast.RollbackStmt{}
 	}
 
-SelectStmtPart1:
+SelectStmtBasic:
 	"SELECT" SelectStmtOpts SelectStmtFieldList
 	{
 		st := &ast.SelectStmt {
@@ -4081,8 +4081,8 @@ SelectStmtPart1:
 		$$ = st
 	}
 
-SelectStmtPart2:
-	SelectStmtPart1 FromDual WhereClauseOptional
+SelectStmtFromDual:
+	SelectStmtBasic FromDual WhereClauseOptional
 	{
 		st := $1.(*ast.SelectStmt)
 		lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
@@ -4096,8 +4096,8 @@ SelectStmtPart2:
 	}
 
 
-SelectStmtPart3:
-	SelectStmtPart1 "FROM"
+SelectStmtFromTable:
+	SelectStmtBasic "FROM"
 	TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause
 	{
 		st := $1.(*ast.SelectStmt)
@@ -4123,7 +4123,7 @@ SelectStmtPart3:
 	}
 
 SelectStmt:
-	SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
+	SelectStmtBasic OrderByOptional SelectStmtLimit SelectLockOpt
 	{
 		st := $1.(*ast.SelectStmt)
 		st.LockTp = $4.(ast.SelectLockType)
@@ -4153,7 +4153,7 @@ SelectStmt:
 		}
 		$$ = st
 	}
-|	SelectStmtPart2 SelectStmtLimit SelectLockOpt
+|	SelectStmtFromDual SelectStmtLimit SelectLockOpt
 	{
 		st := $1.(*ast.SelectStmt)
 		st.LockTp = $3.(ast.SelectLockType)
@@ -4162,7 +4162,7 @@ SelectStmt:
 		}
 		$$ = st
 	}
-|	SelectStmtPart3 OrderByOptional SelectStmtLimit SelectLockOpt
+|	SelectStmtFromTable OrderByOptional SelectStmtLimit SelectLockOpt
 	{
 		st := $1.(*ast.SelectStmt)
 		st.LockTp = $4.(ast.SelectLockType)
@@ -4597,7 +4597,7 @@ SelectLockOpt:
 
 // See https://dev.mysql.com/doc/refman/5.7/en/union.html
 UnionStmt:
-	UnionClauseList "UNION" UnionOpt SelectStmtPart1 OrderByOptional SelectStmtLimit SelectLockOpt
+	UnionClauseList "UNION" UnionOpt SelectStmtBasic OrderByOptional SelectStmtLimit SelectLockOpt
 	{
 		st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
@@ -4614,7 +4614,7 @@ UnionStmt:
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt SelectStmtPart2 SelectStmtLimit SelectLockOpt
+|	UnionClauseList "UNION" UnionOpt SelectStmtFromDual SelectStmtLimit SelectLockOpt
 	{
 		st := $4.(*ast.SelectStmt)
 		union := $1.(*ast.UnionStmt)
@@ -4628,7 +4628,7 @@ UnionStmt:
 		}
 		$$ = union
 	}
-|	UnionClauseList "UNION" UnionOpt SelectStmtPart3 OrderByOptional
+|	UnionClauseList "UNION" UnionOpt SelectStmtFromTable OrderByOptional
    	SelectStmtLimit SelectLockOpt
 	{
 		st := $4.(*ast.SelectStmt)