github.com/XiaoMi/Gaea@v1.2.5/parser/ast/dml_test.go (about) 1 // Copyright 2017 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package ast_test 15 16 import ( 17 . "github.com/pingcap/check" 18 19 . "github.com/XiaoMi/Gaea/parser/ast" 20 ) 21 22 var _ = Suite(&testDMLSuite{}) 23 24 type testDMLSuite struct { 25 } 26 27 func (ts *testDMLSuite) TestDMLVisitorCover(c *C) { 28 ce := &checkExpr{} 29 30 tableRefsClause := &TableRefsClause{TableRefs: &Join{Left: &TableSource{Source: &TableName{}}, On: &OnCondition{Expr: ce}}} 31 32 stmts := []struct { 33 node Node 34 expectedEnterCnt int 35 expectedLeaveCnt int 36 }{ 37 {&DeleteStmt{TableRefs: tableRefsClause, Tables: &DeleteTableList{}, Where: ce, 38 Order: &OrderByClause{}, Limit: &Limit{Count: ce, Offset: ce}}, 4, 4}, 39 {&ShowStmt{Table: &TableName{}, Column: &ColumnName{}, Pattern: &PatternLikeExpr{Expr: ce, Pattern: ce}, Where: ce}, 3, 3}, 40 {&LoadDataStmt{Table: &TableName{}, Columns: []*ColumnName{{}}, FieldsInfo: &FieldsClause{}, LinesInfo: &LinesClause{}}, 0, 0}, 41 {&Assignment{Column: &ColumnName{}, Expr: ce}, 1, 1}, 42 {&ByItem{Expr: ce}, 1, 1}, 43 {&GroupByClause{Items: []*ByItem{{Expr: ce}, {Expr: ce}}}, 2, 2}, 44 {&HavingClause{Expr: ce}, 1, 1}, 45 {&Join{Left: &TableSource{Source: &TableName{}}}, 0, 0}, 46 {&Limit{Count: ce, Offset: ce}, 2, 2}, 47 {&OnCondition{Expr: ce}, 1, 1}, 48 {&OrderByClause{Items: []*ByItem{{Expr: ce}, {Expr: ce}}}, 2, 2}, 49 {&SelectField{Expr: ce, WildCard: &WildCardField{}}, 1, 1}, 50 {&TableName{}, 0, 0}, 51 {tableRefsClause, 1, 1}, 52 {&TableSource{Source: &TableName{}}, 0, 0}, 53 {&WildCardField{}, 0, 0}, 54 55 // TODO: cover childrens 56 {&InsertStmt{Table: tableRefsClause}, 1, 1}, 57 {&UnionStmt{}, 0, 0}, 58 {&UpdateStmt{TableRefs: tableRefsClause}, 1, 1}, 59 {&SelectStmt{}, 0, 0}, 60 {&FieldList{}, 0, 0}, 61 {&UnionSelectList{}, 0, 0}, 62 {&WindowSpec{}, 0, 0}, 63 {&PartitionByClause{}, 0, 0}, 64 {&FrameClause{}, 0, 0}, 65 {&FrameBound{}, 0, 0}, 66 } 67 68 for _, v := range stmts { 69 ce.reset() 70 v.node.Accept(checkVisitor{}) 71 c.Check(ce.enterCnt, Equals, v.expectedEnterCnt) 72 c.Check(ce.leaveCnt, Equals, v.expectedLeaveCnt) 73 v.node.Accept(visitor1{}) 74 } 75 } 76 77 func (ts *testDMLSuite) TestTableNameRestore(c *C) { 78 testCases := []NodeRestoreTestCase{ 79 {"dbb.`tbb1`", "`dbb`.`tbb1`"}, 80 {"`tbb2`", "`tbb2`"}, 81 {"tbb3", "`tbb3`"}, 82 {"dbb.`hello-world`", "`dbb`.`hello-world`"}, 83 {"`dbb`.`hello-world`", "`dbb`.`hello-world`"}, 84 {"`dbb.HelloWorld`", "`dbb.HelloWorld`"}, 85 } 86 extractNodeFunc := func(node Node) Node { 87 return node.(*CreateTableStmt).Table 88 } 89 RunNodeRestoreTest(c, testCases, "CREATE TABLE %s (id VARCHAR(128) NOT NULL);", extractNodeFunc) 90 } 91 92 func (ts *testDMLSuite) TestTableNameIndexHintsRestore(c *C) { 93 testCases := []NodeRestoreTestCase{ 94 {"t use index (hello)", "`t` USE INDEX (`hello`)"}, 95 {"t use index (hello, world)", "`t` USE INDEX (`hello`, `world`)"}, 96 {"t use index ()", "`t` USE INDEX ()"}, 97 {"t use key ()", "`t` USE INDEX ()"}, 98 {"t ignore key ()", "`t` IGNORE INDEX ()"}, 99 {"t force key ()", "`t` FORCE INDEX ()"}, 100 {"t use index for order by (idx1)", "`t` USE INDEX FOR ORDER BY (`idx1`)"}, 101 102 {"t use index (hello, world, yes) force key (good)", "`t` USE INDEX (`hello`, `world`, `yes`) FORCE INDEX (`good`)"}, 103 {"t use index (hello, world, yes) use index for order by (good)", "`t` USE INDEX (`hello`, `world`, `yes`) USE INDEX FOR ORDER BY (`good`)"}, 104 {"t ignore key (hello, world, yes) force key (good)", "`t` IGNORE INDEX (`hello`, `world`, `yes`) FORCE INDEX (`good`)"}, 105 106 {"t use index for group by (idx1) use index for order by (idx2)", "`t` USE INDEX FOR GROUP BY (`idx1`) USE INDEX FOR ORDER BY (`idx2`)"}, 107 {"t use index for group by (idx1) ignore key for order by (idx2)", "`t` USE INDEX FOR GROUP BY (`idx1`) IGNORE INDEX FOR ORDER BY (`idx2`)"}, 108 {"t use index for group by (idx1) ignore key for group by (idx2)", "`t` USE INDEX FOR GROUP BY (`idx1`) IGNORE INDEX FOR GROUP BY (`idx2`)"}, 109 {"t use index for order by (idx1) ignore key for group by (idx2)", "`t` USE INDEX FOR ORDER BY (`idx1`) IGNORE INDEX FOR GROUP BY (`idx2`)"}, 110 111 {"t use index for order by (idx1) ignore key for group by (idx2) use index (idx3)", "`t` USE INDEX FOR ORDER BY (`idx1`) IGNORE INDEX FOR GROUP BY (`idx2`) USE INDEX (`idx3`)"}, 112 {"t use index for order by (idx1) ignore key for group by (idx2) use index (idx3)", "`t` USE INDEX FOR ORDER BY (`idx1`) IGNORE INDEX FOR GROUP BY (`idx2`) USE INDEX (`idx3`)"}, 113 114 {"t use index (`foo``bar`) force index (`baz``1`, `xyz`)", "`t` USE INDEX (`foo``bar`) FORCE INDEX (`baz``1`, `xyz`)"}, 115 {"t force index (`foo``bar`) ignore index (`baz``1`, xyz)", "`t` FORCE INDEX (`foo``bar`) IGNORE INDEX (`baz``1`, `xyz`)"}, 116 {"t ignore index (`foo``bar`) force key (`baz``1`, xyz)", "`t` IGNORE INDEX (`foo``bar`) FORCE INDEX (`baz``1`, `xyz`)"}, 117 {"t ignore index (`foo``bar`) ignore key for group by (`baz``1`, xyz)", "`t` IGNORE INDEX (`foo``bar`) IGNORE INDEX FOR GROUP BY (`baz``1`, `xyz`)"}, 118 {"t ignore index (`foo``bar`) ignore key for order by (`baz``1`, xyz)", "`t` IGNORE INDEX (`foo``bar`) IGNORE INDEX FOR ORDER BY (`baz``1`, `xyz`)"}, 119 120 {"t use index for group by (`foo``bar`) use index for order by (`baz``1`, `xyz`)", "`t` USE INDEX FOR GROUP BY (`foo``bar`) USE INDEX FOR ORDER BY (`baz``1`, `xyz`)"}, 121 {"t use index for group by (`foo``bar`) ignore key for order by (`baz``1`, `xyz`)", "`t` USE INDEX FOR GROUP BY (`foo``bar`) IGNORE INDEX FOR ORDER BY (`baz``1`, `xyz`)"}, 122 {"t use index for group by (`foo``bar`) ignore key for group by (`baz``1`, `xyz`)", "`t` USE INDEX FOR GROUP BY (`foo``bar`) IGNORE INDEX FOR GROUP BY (`baz``1`, `xyz`)"}, 123 {"t use index for order by (`foo``bar`) ignore key for group by (`baz``1`, `xyz`)", "`t` USE INDEX FOR ORDER BY (`foo``bar`) IGNORE INDEX FOR GROUP BY (`baz``1`, `xyz`)"}, 124 } 125 extractNodeFunc := func(node Node) Node { 126 return node.(*SelectStmt).From.TableRefs.Left.(*TableSource).Source.(*TableName) 127 } 128 RunNodeRestoreTest(c, testCases, "SELECT * FROM %s", extractNodeFunc) 129 } 130 131 func (ts *testDMLSuite) TestLimitRestore(c *C) { 132 testCases := []NodeRestoreTestCase{ 133 {"limit 10", "LIMIT 10"}, 134 {"limit 10,20", "LIMIT 10,20"}, 135 {"limit 20 offset 10", "LIMIT 10,20"}, 136 } 137 extractNodeFunc := func(node Node) Node { 138 return node.(*SelectStmt).Limit 139 } 140 RunNodeRestoreTest(c, testCases, "SELECT 1 %s", extractNodeFunc) 141 } 142 143 func (ts *testDMLSuite) TestWildCardFieldRestore(c *C) { 144 testCases := []NodeRestoreTestCase{ 145 {"*", "*"}, 146 {"t.*", "`t`.*"}, 147 {"testdb.t.*", "`testdb`.`t`.*"}, 148 } 149 extractNodeFunc := func(node Node) Node { 150 return node.(*SelectStmt).Fields.Fields[0].WildCard 151 } 152 RunNodeRestoreTest(c, testCases, "SELECT %s", extractNodeFunc) 153 } 154 155 func (ts *testDMLSuite) TestSelectFieldRestore(c *C) { 156 testCases := []NodeRestoreTestCase{ 157 {"*", "*"}, 158 {"t.*", "`t`.*"}, 159 {"testdb.t.*", "`testdb`.`t`.*"}, 160 {"col as a", "`col` AS `a`"}, 161 {"col + 1 a", "`col`+1 AS `a`"}, 162 } 163 extractNodeFunc := func(node Node) Node { 164 return node.(*SelectStmt).Fields.Fields[0] 165 } 166 RunNodeRestoreTest(c, testCases, "SELECT %s", extractNodeFunc) 167 } 168 169 func (ts *testDMLSuite) TestFieldListRestore(c *C) { 170 testCases := []NodeRestoreTestCase{ 171 {"*", "*"}, 172 {"t.*", "`t`.*"}, 173 {"testdb.t.*", "`testdb`.`t`.*"}, 174 {"col as a", "`col` AS `a`"}, 175 {"`t`.*, s.col as a", "`t`.*, `s`.`col` AS `a`"}, 176 } 177 extractNodeFunc := func(node Node) Node { 178 return node.(*SelectStmt).Fields 179 } 180 RunNodeRestoreTest(c, testCases, "SELECT %s", extractNodeFunc) 181 } 182 183 func (ts *testDMLSuite) TestTableSourceRestore(c *C) { 184 testCases := []NodeRestoreTestCase{ 185 {"tbl", "`tbl`"}, 186 {"tbl as t", "`tbl` AS `t`"}, 187 {"(select * from tbl) as t", "(SELECT * FROM `tbl`) AS `t`"}, 188 {"(select * from a union select * from b) as t", "(SELECT * FROM `a` UNION SELECT * FROM `b`) AS `t`"}, 189 } 190 extractNodeFunc := func(node Node) Node { 191 return node.(*SelectStmt).From.TableRefs.Left 192 } 193 RunNodeRestoreTest(c, testCases, "select * from %s", extractNodeFunc) 194 } 195 196 func (ts *testDMLSuite) TestOnConditionRestore(c *C) { 197 testCases := []NodeRestoreTestCase{ 198 {"on t1.a=t2.a", "ON `t1`.`a`=`t2`.`a`"}, 199 {"on t1.a=t2.a and t1.b=t2.b", "ON `t1`.`a`=`t2`.`a` AND `t1`.`b`=`t2`.`b`"}, 200 } 201 extractNodeFunc := func(node Node) Node { 202 return node.(*SelectStmt).From.TableRefs.On 203 } 204 RunNodeRestoreTest(c, testCases, "select * from t1 join t2 %s", extractNodeFunc) 205 } 206 207 func (ts *testDMLSuite) TestJoinRestore(c *C) { 208 testCases := []NodeRestoreTestCase{ 209 {"t1 natural join t2", "`t1` NATURAL JOIN `t2`"}, 210 {"t1 natural left join t2", "`t1` NATURAL LEFT JOIN `t2`"}, 211 {"t1 natural right outer join t2", "`t1` NATURAL RIGHT JOIN `t2`"}, 212 {"t1 straight_join t2", "`t1` STRAIGHT_JOIN `t2`"}, 213 {"t1 straight_join t2 on t1.a>t2.a", "`t1` STRAIGHT_JOIN `t2` ON `t1`.`a`>`t2`.`a`"}, 214 {"t1 cross join t2", "`t1` JOIN `t2`"}, 215 {"t1 cross join t2 on t1.a>t2.a", "`t1` JOIN `t2` ON `t1`.`a`>`t2`.`a`"}, 216 {"t1 inner join t2 using (b)", "`t1` JOIN `t2` USING (`b`)"}, 217 {"t1 join t2 using (b,c) left join t3 on t1.a>t3.a", "(`t1` JOIN `t2` USING (`b`,`c`)) LEFT JOIN `t3` ON `t1`.`a`>`t3`.`a`"}, 218 {"t1 natural join t2 right outer join t3 using (b,c)", "(`t1` NATURAL JOIN `t2`) RIGHT JOIN `t3` USING (`b`,`c`)"}, 219 {"(a al left join b bl on al.a1 > bl.b1) join (a ar right join b br on ar.a1 > br.b1)", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"}, 220 {"a al left join b bl on al.a1 > bl.b1, a ar right join b br on ar.a1 > br.b1", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"}, 221 {"t1, t2", "(`t1`) JOIN `t2`"}, 222 {"t1, t2, t3", "((`t1`) JOIN `t2`) JOIN `t3`"}, 223 } 224 extractNodeFunc := func(node Node) Node { 225 return node.(*SelectStmt).From.TableRefs 226 } 227 RunNodeRestoreTest(c, testCases, "select * from %s", extractNodeFunc) 228 } 229 230 func (ts *testDMLSuite) TestTableRefsClauseRestore(c *C) { 231 testCases := []NodeRestoreTestCase{ 232 {"t", "`t`"}, 233 {"t1 join t2", "`t1` JOIN `t2`"}, 234 {"t1, t2", "(`t1`) JOIN `t2`"}, 235 } 236 extractNodeFunc := func(node Node) Node { 237 return node.(*SelectStmt).From 238 } 239 RunNodeRestoreTest(c, testCases, "select * from %s", extractNodeFunc) 240 } 241 242 func (ts *testDMLSuite) TestDeleteTableListRestore(c *C) { 243 testCases := []NodeRestoreTestCase{ 244 {"t1,t2", "`t1`,`t2`"}, 245 } 246 extractNodeFunc := func(node Node) Node { 247 return node.(*DeleteStmt).Tables 248 } 249 RunNodeRestoreTest(c, testCases, "DELETE %s FROM t1, t2;", extractNodeFunc) 250 RunNodeRestoreTest(c, testCases, "DELETE FROM %s USING t1, t2;", extractNodeFunc) 251 } 252 253 func (ts *testExpressionsSuite) TestByItemRestore(c *C) { 254 testCases := []NodeRestoreTestCase{ 255 {"a", "`a`"}, 256 {"a desc", "`a` DESC"}, 257 {"NULL", "NULL"}, 258 } 259 extractNodeFunc := func(node Node) Node { 260 return node.(*SelectStmt).OrderBy.Items[0] 261 } 262 RunNodeRestoreTest(c, testCases, "select * from t order by %s", extractNodeFunc) 263 } 264 265 func (ts *testExpressionsSuite) TestGroupByClauseRestore(c *C) { 266 testCases := []NodeRestoreTestCase{ 267 {"GROUP BY a,b desc", "GROUP BY `a`,`b` DESC"}, 268 {"GROUP BY 1 desc,b", "GROUP BY 1 DESC,`b`"}, 269 } 270 extractNodeFunc := func(node Node) Node { 271 return node.(*SelectStmt).GroupBy 272 } 273 RunNodeRestoreTest(c, testCases, "select * from t %s", extractNodeFunc) 274 } 275 276 func (ts *testDMLSuite) TestOrderByClauseRestore(c *C) { 277 testCases := []NodeRestoreTestCase{ 278 {"ORDER BY a", "ORDER BY `a`"}, 279 {"ORDER BY a,b", "ORDER BY `a`,`b`"}, 280 } 281 extractNodeFunc := func(node Node) Node { 282 return node.(*SelectStmt).OrderBy 283 } 284 RunNodeRestoreTest(c, testCases, "SELECT 1 FROM t1 %s", extractNodeFunc) 285 286 extractNodeFromUnionStmtFunc := func(node Node) Node { 287 return node.(*UnionStmt).OrderBy 288 } 289 RunNodeRestoreTest(c, testCases, "SELECT 1 FROM t1 UNION SELECT 2 FROM t2 %s", extractNodeFromUnionStmtFunc) 290 } 291 292 func (ts *testDMLSuite) TestAssignmentRestore(c *C) { 293 testCases := []NodeRestoreTestCase{ 294 {"a=1", "`a`=1"}, 295 {"b=1+2", "`b`=1+2"}, 296 } 297 extractNodeFunc := func(node Node) Node { 298 return node.(*UpdateStmt).List[0] 299 } 300 RunNodeRestoreTest(c, testCases, "UPDATE t1 SET %s", extractNodeFunc) 301 } 302 303 func (ts *testDMLSuite) TestHavingClauseRestore(c *C) { 304 testCases := []NodeRestoreTestCase{ 305 {"HAVING a", "HAVING `a`"}, 306 {"HAVING NULL", "HAVING NULL"}, 307 {"HAVING a>b", "HAVING `a`>`b`"}, 308 } 309 extractNodeFunc := func(node Node) Node { 310 return node.(*SelectStmt).Having 311 } 312 RunNodeRestoreTest(c, testCases, "select 1 from t1 group by 1 %s", extractNodeFunc) 313 } 314 315 func (ts *testDMLSuite) TestFrameBoundRestore(c *C) { 316 testCases := []NodeRestoreTestCase{ 317 {"CURRENT ROW", "CURRENT ROW"}, 318 {"UNBOUNDED PRECEDING", "UNBOUNDED PRECEDING"}, 319 {"1 PRECEDING", "1 PRECEDING"}, 320 {"? PRECEDING", "? PRECEDING"}, 321 {"INTERVAL 5 DAY PRECEDING", "INTERVAL 5 DAY PRECEDING"}, 322 {"UNBOUNDED FOLLOWING", "UNBOUNDED FOLLOWING"}, 323 {"1 FOLLOWING", "1 FOLLOWING"}, 324 {"? FOLLOWING", "? FOLLOWING"}, 325 {"INTERVAL '2:30' MINUTE_SECOND FOLLOWING", "INTERVAL '2:30' MINUTE_SECOND FOLLOWING"}, 326 } 327 extractNodeFunc := func(node Node) Node { 328 return &node.(*SelectStmt).Fields.Fields[0].Expr.(*WindowFuncExpr).Spec.Frame.Extent.Start 329 } 330 RunNodeRestoreTest(c, testCases, "select avg(val) over (rows between %s and current row) from t", extractNodeFunc) 331 } 332 333 func (ts *testDMLSuite) TestFrameClauseRestore(c *C) { 334 testCases := []NodeRestoreTestCase{ 335 {"ROWS CURRENT ROW", "ROWS BETWEEN CURRENT ROW AND CURRENT ROW"}, 336 {"ROWS UNBOUNDED PRECEDING", "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW"}, 337 {"ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING", "ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"}, 338 {"RANGE BETWEEN ? PRECEDING AND ? FOLLOWING", "RANGE BETWEEN ? PRECEDING AND ? FOLLOWING"}, 339 {"RANGE BETWEEN INTERVAL 5 DAY PRECEDING AND INTERVAL '2:30' MINUTE_SECOND FOLLOWING", "RANGE BETWEEN INTERVAL 5 DAY PRECEDING AND INTERVAL '2:30' MINUTE_SECOND FOLLOWING"}, 340 } 341 extractNodeFunc := func(node Node) Node { 342 return node.(*SelectStmt).Fields.Fields[0].Expr.(*WindowFuncExpr).Spec.Frame 343 } 344 RunNodeRestoreTest(c, testCases, "select avg(val) over (%s) from t", extractNodeFunc) 345 } 346 347 func (ts *testDMLSuite) TestPartitionByClauseRestore(c *C) { 348 testCases := []NodeRestoreTestCase{ 349 {"PARTITION BY a", "PARTITION BY `a`"}, 350 {"PARTITION BY NULL", "PARTITION BY NULL"}, 351 {"PARTITION BY a, b", "PARTITION BY `a`, `b`"}, 352 } 353 extractNodeFunc := func(node Node) Node { 354 return node.(*SelectStmt).Fields.Fields[0].Expr.(*WindowFuncExpr).Spec.PartitionBy 355 } 356 RunNodeRestoreTest(c, testCases, "select avg(val) over (%s rows current row) from t", extractNodeFunc) 357 } 358 359 func (ts *testDMLSuite) TestWindowSpecRestore(c *C) { 360 testCases := []NodeRestoreTestCase{ 361 {"w as ()", "`w` AS ()"}, 362 {"w as (w1)", "`w` AS (`w1`)"}, 363 {"w as (w1 order by country)", "`w` AS (`w1` ORDER BY `country`)"}, 364 {"w as (partition by a order by b rows current row)", "`w` AS (PARTITION BY `a` ORDER BY `b` ROWS BETWEEN CURRENT ROW AND CURRENT ROW)"}, 365 } 366 extractNodeFunc := func(node Node) Node { 367 return &node.(*SelectStmt).WindowSpecs[0] 368 } 369 RunNodeRestoreTest(c, testCases, "select rank() over w from t window %s", extractNodeFunc) 370 371 testCases = []NodeRestoreTestCase{ 372 {"w", "(`w`)"}, 373 {"()", "()"}, 374 {"(w PARTITION BY country)", "(`w` PARTITION BY `country`)"}, 375 {"(PARTITION BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)", "(PARTITION BY `a` ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)"}, 376 } 377 extractNodeFunc = func(node Node) Node { 378 return &node.(*SelectStmt).Fields.Fields[0].Expr.(*WindowFuncExpr).Spec 379 } 380 RunNodeRestoreTest(c, testCases, "select rank() over %s from t window w as (order by a)", extractNodeFunc) 381 }