vitess.io/vitess@v0.16.2/go/vt/sqlparser/parse_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqlparser 18 19 import ( 20 "bufio" 21 "bytes" 22 "compress/gzip" 23 "fmt" 24 "io" 25 "math/rand" 26 "os" 27 "path" 28 "strings" 29 "sync" 30 "testing" 31 32 "vitess.io/vitess/go/test/utils" 33 34 "github.com/google/go-cmp/cmp" 35 36 "github.com/stretchr/testify/assert" 37 "github.com/stretchr/testify/require" 38 ) 39 40 var ( 41 validSQL = []struct { 42 input string 43 output string 44 partialDDL bool 45 ignoreNormalizerTest bool 46 }{{ 47 input: "create table x(location GEOMETRYCOLLECTION DEFAULT POINT(7.0, 3.0))", 48 output: "create table x", 49 partialDDL: true, 50 }, { 51 input: "create table t (id int primary key, dt datetime DEFAULT (CURRENT_TIMESTAMP))", 52 output: "create table t (\n\tid int primary key,\n\tdt datetime default current_timestamp()\n)", 53 }, { 54 input: "create table t (id int primary key, dt datetime DEFAULT now())", 55 output: "create table t (\n\tid int primary key,\n\tdt datetime default now()\n)", 56 }, { 57 input: "create table t (id int primary key, dt datetime DEFAULT (now()))", 58 output: "create table t (\n\tid int primary key,\n\tdt datetime default now()\n)", 59 }, { 60 input: "create table x (e enum('red','yellow') null collate 'utf8_bin')", 61 output: "create table x (\n\te enum('red', 'yellow') collate 'utf8_bin' null\n)", 62 }, { 63 input: "create table 3t2 (c1 bigint not null, c2 text, primary key(c1))", 64 output: "create table `3t2` (\n\tc1 bigint not null,\n\tc2 text,\n\tprimary key (c1)\n)", 65 }, { 66 input: "select 1 from t1 where exists (select 1) = TRUE", 67 output: "select 1 from t1 where exists (select 1 from dual) = true", 68 }, { 69 input: "select 1 from t1 where exists (select 1) = FALSE", 70 output: "select 1 from t1 where exists (select 1 from dual) = false", 71 }, { 72 input: "select 1 from t1 where exists (select 1) = 1", 73 output: "select 1 from t1 where exists (select 1 from dual) = 1", 74 }, { 75 input: "create table x(location GEOMETRY DEFAULT (POINT(7.0, 3.0)))", 76 output: "create table x (\n\tlocation GEOMETRY default (POINT(7.0, 3.0))\n)", 77 }, { 78 input: "select 1", 79 output: "select 1 from dual", 80 }, { 81 input: "SELECT EXTRACT(YEAR FROM '2019-07-02')", 82 output: "select extract(year from '2019-07-02') from dual", 83 }, { 84 input: "SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03')", 85 output: "select extract(year_month from '2019-07-02 01:02:03') from dual", 86 }, { 87 input: "select extract(year from \"21-10-22 12:00:00\")", 88 output: "select extract(year from '21-10-22 12:00:00') from dual", 89 }, { 90 input: "SELECT EXTRACT(DAY_MINUTE FROM '2019-07-02 01:02:03')", 91 output: "select extract(day_minute from '2019-07-02 01:02:03') from dual", 92 }, { 93 input: "SELECT EXTRACT(MICROSECOND FROM '2003-01-02 10:30:00.000123')", 94 output: "select extract(microsecond from '2003-01-02 10:30:00.000123') from dual", 95 }, { 96 input: "CREATE TABLE t2 (b BLOB DEFAULT 'abc')", 97 output: "create table t2 (\n\tb BLOB default ('abc')\n)", 98 }, { 99 input: "CREATE TABLE t2 (b blob DEFAULT 'abc')", 100 output: "create table t2 (\n\tb blob default ('abc')\n)", 101 }, { 102 input: "CREATE TABLE t2 (b BLOB DEFAULT ('abc'))", 103 output: "create table t2 (\n\tb BLOB default ('abc')\n)", 104 }, { 105 input: "CREATE TABLE t2 (b TINYBLOB DEFAULT 'abc')", 106 output: "create table t2 (\n\tb TINYBLOB default ('abc')\n)", 107 }, { 108 input: "CREATE TABLE t2 (b TINYBLOB DEFAULT ('abc'))", 109 output: "create table t2 (\n\tb TINYBLOB default ('abc')\n)", 110 }, { 111 input: "CREATE TABLE t2 (b MEDIUMBLOB DEFAULT 'abc')", 112 output: "create table t2 (\n\tb MEDIUMBLOB default ('abc')\n)", 113 }, { 114 input: "CREATE TABLE t2 (b MEDIUMBLOB DEFAULT ('abc'))", 115 output: "create table t2 (\n\tb MEDIUMBLOB default ('abc')\n)", 116 }, { 117 input: "CREATE TABLE t2 (b LONGBLOB DEFAULT 'abc')", 118 output: "create table t2 (\n\tb LONGBLOB default ('abc')\n)", 119 }, { 120 input: "CREATE TABLE t2 (b LONGBLOB DEFAULT ('abc'))", 121 output: "create table t2 (\n\tb LONGBLOB default ('abc')\n)", 122 }, { 123 input: "CREATE TABLE t2 (b TEXT DEFAULT 'abc')", 124 output: "create table t2 (\n\tb TEXT default ('abc')\n)", 125 }, { 126 input: "CREATE TABLE t2 (b TEXT DEFAULT ('abc'))", 127 output: "create table t2 (\n\tb TEXT default ('abc')\n)", 128 }, { 129 input: "CREATE TABLE t2 (b TINYTEXT DEFAULT 'abc')", 130 output: "create table t2 (\n\tb TINYTEXT default ('abc')\n)", 131 }, { 132 input: "CREATE TABLE t2 (b TINYTEXT DEFAULT ('abc'))", 133 output: "create table t2 (\n\tb TINYTEXT default ('abc')\n)", 134 }, { 135 input: "CREATE TABLE t2 (b MEDIUMTEXT DEFAULT 'abc')", 136 output: "create table t2 (\n\tb MEDIUMTEXT default ('abc')\n)", 137 }, { 138 input: "CREATE TABLE t2 (b MEDIUMTEXT DEFAULT ('abc'))", 139 output: "create table t2 (\n\tb MEDIUMTEXT default ('abc')\n)", 140 }, { 141 input: "CREATE TABLE t2 (b LONGTEXT DEFAULT 'abc')", 142 output: "create table t2 (\n\tb LONGTEXT default ('abc')\n)", 143 }, { 144 input: "CREATE TABLE t2 (b LONGTEXT DEFAULT ('abc'))", 145 output: "create table t2 (\n\tb LONGTEXT default ('abc')\n)", 146 }, { 147 input: "CREATE TABLE t2 (b JSON DEFAULT null)", 148 output: "create table t2 (\n\tb JSON default null\n)", 149 }, { 150 input: "CREATE TABLE t2 (b JSON DEFAULT (null))", 151 output: "create table t2 (\n\tb JSON default null\n)", 152 }, { 153 input: "CREATE TABLE t2 (b JSON DEFAULT '{name:abc}')", 154 output: "create table t2 (\n\tb JSON default ('{name:abc}')\n)", 155 }, { 156 input: "CREATE TABLE t2 (b JSON DEFAULT ('{name:abc}'))", 157 output: "create table t2 (\n\tb JSON default ('{name:abc}')\n)", 158 }, { 159 input: "create table x(location POINT DEFAULT 7.0)", 160 output: "create table x (\n\tlocation POINT default (7.0)\n)", 161 }, { 162 input: "create table x(location POINT DEFAULT (7.0))", 163 output: "create table x (\n\tlocation POINT default (7.0)\n)", 164 }, { 165 input: "create table x(location LINESTRING DEFAULT (POINT(7.0, 3.0)))", 166 output: "create table x (\n\tlocation LINESTRING default (POINT(7.0, 3.0))\n)", 167 }, { 168 input: "create table x(location POLYGON DEFAULT (POINT(7.0, 3.0)))", 169 output: "create table x (\n\tlocation POLYGON default (POINT(7.0, 3.0))\n)", 170 }, { 171 input: "create table x(location MULTIPOINT DEFAULT (POINT(7.0, 3.0)))", 172 output: "create table x (\n\tlocation MULTIPOINT default (POINT(7.0, 3.0))\n)", 173 }, { 174 input: "create table x(location MULTILINESTRING DEFAULT (POINT(7.0, 3.0)))", 175 output: "create table x (\n\tlocation MULTILINESTRING default (POINT(7.0, 3.0))\n)", 176 }, { 177 input: "create table x(location MULTIPOLYGON DEFAULT (POINT(7.0, 3.0)))", 178 output: "create table x (\n\tlocation MULTIPOLYGON default (POINT(7.0, 3.0))\n)", 179 }, { 180 input: "create table x(location GEOMETRYCOLLECTION DEFAULT (POINT(7.0, 3.0)))", 181 output: "create table x (\n\tlocation GEOMETRYCOLLECTION default (POINT(7.0, 3.0))\n)", 182 }, { 183 input: "WITH RECURSIVE odd_num_cte (id, n) AS (SELECT 1, 1 union all SELECT id+1, n+2 from odd_num_cte where id < 5) SELECT * FROM odd_num_cte", 184 output: "with recursive odd_num_cte(id, n) as (select 1, 1 from dual union all select id + 1, n + 2 from odd_num_cte where id < 5) select * from odd_num_cte", 185 }, { 186 input: "WITH topsales2003 AS (SELECT salesRepEmployeeNumber employeeNumber, SUM(quantityOrdered * priceEach) sales FROM orders INNER JOIN orderdetails USING (orderNumber) INNER JOIN customers USING (customerNumber) WHERE YEAR(shippedDate) = 2003 AND status = 'Shipped' GROUP BY salesRepEmployeeNumber ORDER BY sales DESC LIMIT 5)SELECT employeeNumber, firstName, lastName, sales FROM employees JOIN topsales2003 USING (employeeNumber)", 187 output: "with topsales2003 as (select salesRepEmployeeNumber as employeeNumber, sum(quantityOrdered * priceEach) as sales from orders join orderdetails using (orderNumber) join customers using (customerNumber) where YEAR(shippedDate) = 2003 and `status` = 'Shipped' group by salesRepEmployeeNumber order by sales desc limit 5) select employeeNumber, firstName, lastName, sales from employees join topsales2003 using (employeeNumber)", 188 }, { 189 input: "select 1 from t", 190 }, { 191 input: "select * from (select 1) as x(user)", 192 output: "select * from (select 1 from dual) as x(`user`)", 193 }, { 194 input: "select user from (select id from users ) as x(user)", 195 output: "select `user` from (select id from users) as x(`user`)", 196 }, { 197 input: "select n, d from something", 198 }, { 199 input: "insert into sys_message_assign(message_id, assign_user_id, read_state, id, is_delete, create_time, update_time, remark) values (N'3477028275831808', N'4104487936', N'1', N'0', N'0', '2021-09-22 14:24:17.922', '2021-09-22 14:24:17.922', null), (N'3477028275831808', N'3454139190608923', N'1', N'0', N'0', '2021-09-22 14:24:17.922', '2021-09-22 14:24:17.922', null)", 200 /*We need to ignore this test because, after the normalizer, we change the produced NChar 201 string into an introducer expression, so the vttablet will never see a NChar string */ 202 ignoreNormalizerTest: true, 203 }, { 204 input: "select name, numbers from (select * from users) as x(name, numbers)", 205 output: "select `name`, numbers from (select * from users) as x(`name`, numbers)", 206 }, { 207 input: "select 0b010, 0b0111, b'0111', b'011'", 208 output: "select B'010', B'0111', B'0111', B'011' from dual", 209 }, { 210 input: "select 0x010, 0x0111, x'0111'", 211 output: "select 0x010, 0x0111, X'0111' from dual", 212 }, { 213 input: "select date'2022-10-03'", 214 output: "select date'2022-10-03' from dual", 215 }, { 216 input: "select date, time, timestamp from t", 217 output: "select `date`, `time`, `timestamp` from t", 218 }, { 219 input: "select time'12:34:56'", 220 output: "select time'12:34:56' from dual", 221 }, { 222 input: "select timestamp'2012-12-31 11:30:45'", 223 output: "select timestamp'2012-12-31 11:30:45' from dual", 224 }, { 225 input: "select * from information_schema.columns", 226 output: "select * from information_schema.`columns`", 227 }, { 228 input: "select * from information_schema.processlist", 229 output: "select * from information_schema.`processlist`", 230 }, { 231 input: "select .1 from t", 232 }, { 233 input: "select 1.2e1 from t", 234 }, { 235 input: "select 1.2e+1 from t", 236 }, { 237 input: "select 1.2e-1 from t", 238 }, { 239 input: "select 08.3 from t", 240 }, { 241 input: "select -1 from t where b = -2", 242 }, { 243 input: "select - -1 from t", 244 output: "select - -1 from t", 245 }, { 246 input: "select a from t", 247 }, { 248 input: "select $ from t", 249 }, { 250 // shift/reduce conflict on CHARSET, should throw an error on shifting which will be ignored as it is a DDL 251 input: "alter database charset = 'utf16';", 252 output: "alter database", 253 partialDDL: true, 254 }, { 255 input: "alter database charset charset = 'utf16'", 256 output: "alter database `charset` character set 'utf16'", 257 }, { 258 input: "create table t(id int unique)", 259 output: "create table t (\n\tid int unique\n)", 260 }, { 261 input: "create table t(id int key)", 262 output: "create table t (\n\tid int key\n)", 263 }, { 264 input: "create table t(id int unique key)", 265 output: "create table t (\n\tid int unique key\n)", 266 }, { 267 input: "select a.b as a$b from $test$", 268 }, { 269 input: "select 1 from t // aa\n", 270 output: "select 1 from t", 271 }, { 272 input: "select 1 from t -- aa\n", 273 output: "select 1 from t", 274 }, { 275 input: "select 1 from t # aa\n", 276 output: "select 1 from t", 277 }, { 278 input: "select 1 -- aa\nfrom t", 279 output: "select 1 from t", 280 }, { 281 input: "select 1 #aa\nfrom t", 282 output: "select 1 from t", 283 }, { 284 input: "select /* simplest */ 1 from t", 285 }, { 286 input: "select /* double star **/ 1 from t", 287 }, { 288 input: "select /* double */ /* comment */ 1 from t", 289 }, { 290 input: "select /* back-quote keyword */ `By` from t", 291 }, { 292 input: "select /* back-quote num */ `2a` from t", 293 }, { 294 input: "select /* back-quote . */ `a.b` from t", 295 }, { 296 input: "select /* back-quote back-quote */ `a``b` from t", 297 }, { 298 input: "select /* back-quote unnecessary */ 1 from `t`", 299 output: "select /* back-quote unnecessary */ 1 from t", 300 }, { 301 input: "select /* back-quote idnum */ 1 from `a1`", 302 output: "select /* back-quote idnum */ 1 from a1", 303 }, { 304 input: "select /* @ */ @@a from b", 305 }, { 306 input: "select /* \\0 */ '\\0' from a", 307 }, { 308 input: "select 1 /* drop this comment */ from t", 309 output: "select 1 from t", 310 }, { 311 input: "select /* union */ 1 from t union select 1 from t", 312 }, { 313 input: "select /* double union */ 1 from t union select 1 from t union select 1 from t", 314 }, { 315 input: "select /* union all */ 1 from t union all select 1 from t", 316 }, { 317 input: "select /* union distinct */ 1 from t union distinct select 1 from t", 318 output: "select /* union distinct */ 1 from t union select 1 from t", 319 }, { 320 input: "(select /* union parenthesized select */ 1 from t order by a) union select 1 from t", 321 output: "(select /* union parenthesized select */ 1 from t order by a asc) union select 1 from t", 322 }, { 323 input: "select /* union parenthesized select 2 */ 1 from t union (select 1 from t)", 324 output: "select /* union parenthesized select 2 */ 1 from t union select 1 from t", 325 }, { 326 input: "select /* union order by */ 1 from t union select 1 from t order by a", 327 output: "select /* union order by */ 1 from t union select 1 from t order by a asc", 328 }, { 329 input: "select /* union order by limit lock */ 1 from t union select 1 from t order by a limit 1 for update", 330 output: "select /* union order by limit lock */ 1 from t union select 1 from t order by a asc limit 1 for update", 331 }, { 332 input: "(select id, a from t order by id limit 1) union (select id, b as a from s order by id limit 1) order by a limit 1", 333 output: "(select id, a from t order by id asc limit 1) union (select id, b as a from s order by id asc limit 1) order by a asc limit 1", 334 }, { 335 input: "select a from (select 1 as a from tbl1 union select 2 from tbl2) as t", 336 output: "select a from (select 1 as a from tbl1 union select 2 from tbl2) as t", 337 }, { 338 input: "select * from t1 join (select * from t2 union select * from t3) as t", 339 }, { 340 // Ensure this doesn't generate: ""select * from t1 join t2 on a = b join t3 on a = b". 341 input: "select * from t1 join t2 on a = b join t3", 342 }, { 343 input: "select * from t1 where col in (select 1 from dual union select 2 from dual)", 344 output: "select * from t1 where col in (select 1 from dual union select 2 from dual)", 345 }, { 346 input: "select * from t1 where exists (select a from t2 union select b from t3)", 347 }, { 348 input: "select 1 from dual union select 2 from dual union all select 3 from dual union select 4 from dual union all select 5 from dual", 349 output: "select 1 from dual union select 2 from dual union all select 3 from dual union select 4 from dual union all select 5 from dual", 350 }, { 351 input: "(select 1 from dual) order by 1 asc limit 2", 352 output: "select 1 from dual order by 1 asc limit 2", 353 }, { 354 input: "(select 1 from dual order by 1 desc) order by 1 asc limit 2", 355 output: "select 1 from dual order by 1 asc limit 2", 356 }, { 357 input: "(select 1 from dual)", 358 output: "select 1 from dual", 359 }, { 360 input: "((select 1 from dual))", 361 output: "select 1 from dual", 362 }, { 363 input: "select 1 from (select 1 from dual) as t", 364 }, { 365 input: "select 1 from (select 1 from dual union select 2 from dual) as t", 366 output: "select 1 from (select 1 from dual union select 2 from dual) as t", 367 }, { 368 input: "select 1 from ((select 1 from dual) union select 2 from dual) as t", 369 output: "select 1 from (select 1 from dual union select 2 from dual) as t", 370 }, { 371 input: "select /* distinct */ distinct 1 from t", 372 }, { 373 input: "select /* straight_join */ straight_join 1 from t", 374 }, { 375 input: "select /* for update */ 1 from t for update", 376 }, { 377 input: "select /* lock in share mode */ 1 from t lock in share mode", 378 }, { 379 input: "select /* select list */ 1, 2 from t", 380 }, { 381 input: "select /* * */ * from t", 382 }, { 383 input: "select /* a.* */ a.* from t", 384 }, { 385 input: "select /* a.b.* */ a.b.* from t", 386 }, { 387 input: "select /* column alias */ a b from t", 388 output: "select /* column alias */ a as b from t", 389 }, { 390 input: "select /* column alias with as */ a as b from t", 391 }, { 392 input: "select /* keyword column alias */ a as `By` from t", 393 }, { 394 input: "select /* column alias as string */ a as \"b\" from t", 395 output: "select /* column alias as string */ a as b from t", 396 }, { 397 input: "select /* column alias as string without as */ a \"b\" from t", 398 output: "select /* column alias as string without as */ a as b from t", 399 }, { 400 input: "select /* column alias with non_reserved keyword */ a as auto_increment from t", 401 output: "select /* column alias with non_reserved keyword */ a as `auto_increment` from t", 402 }, { 403 input: "select /* a.* */ a.* from t", 404 }, { 405 input: "select next value for t", 406 output: "select next 1 values from t", 407 }, { 408 input: "select next value from t", 409 output: "select next 1 values from t", 410 }, { 411 input: "select next 10 values from t", 412 }, { 413 input: "select next :a values from t", 414 }, { 415 input: "select /* `By`.* */ `By`.* from t", 416 }, { 417 input: "select /* select with bool expr */ a = b from t", 418 }, { 419 input: "select /* case_when */ case when a = b then c end from t", 420 }, { 421 input: "select /* case_when_else */ case when a = b then c else d end from t", 422 }, { 423 input: "select /* case_when_when_else */ case when a = b then c when b = d then d else d end from t", 424 }, { 425 input: "select /* case */ case aa when a = b then c end from t", 426 }, { 427 input: "select /* parenthesis */ 1 from (t)", 428 }, { 429 input: "select /* parenthesis multi-table */ 1 from (t1, t2)", 430 }, { 431 input: "select /* table list */ 1 from t1, t2", 432 }, { 433 input: "select /* parenthessis in table list 1 */ 1 from (t1), t2", 434 }, { 435 input: "SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a", 436 output: "select * from t1 use index (i1) ignore index for order by (i2) order by a asc", 437 }, { 438 input: "SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2)", 439 output: "select * from t1 use index for join (i1) force index for join (i2)", 440 }, { 441 input: "SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2) IGNORE KEY FOR GROUP BY (i1, i2)", 442 output: "select * from t1 use index for join (i1) force index for join (i2) ignore index for group by (i1, i2)", 443 }, { 444 input: "SELECT * FROM t1 USE KEY (), t2 FORCE KEY (i2), t3 IGNORE INDEX FOR GROUP BY (i1, i2)", 445 output: "select * from t1 use index (), t2 force index (i2), t3 ignore index for group by (i1, i2)", 446 }, { 447 input: "select /* parenthessis in table list 2 */ 1 from t1, (t2)", 448 }, { 449 input: "select /* use */ 1 from t1 use index (a) where b = 1", 450 }, { 451 input: "select /* use */ 1 from t1 use index () where b = 1", 452 }, { 453 input: "select /* keyword index */ 1 from t1 use index (`By`) where b = 1", 454 }, { 455 input: "select /* ignore */ 1 from t1 as t2 ignore index (a), t3 use index (b) where b = 1", 456 }, { 457 input: "select /* use */ 1 from t1 as t2 use index (a), t3 use index (b) where b = 1", 458 }, { 459 input: "select /* force */ 1 from t1 as t2 force index (a), t3 force index (b) where b = 1", 460 }, { 461 input: "select /* table alias */ 1 from t t1", 462 output: "select /* table alias */ 1 from t as t1", 463 }, { 464 input: "select /* table alias with as */ 1 from t as t1", 465 }, { 466 input: "select /* string table alias */ 1 from t as 't1'", 467 output: "select /* string table alias */ 1 from t as t1", 468 }, { 469 input: "select /* string table alias without as */ 1 from t 't1'", 470 output: "select /* string table alias without as */ 1 from t as t1", 471 }, { 472 input: "select /* keyword table alias */ 1 from t as `By`", 473 }, { 474 input: "select /* join */ 1 from t1 join t2", 475 }, { 476 input: "select /* join on */ 1 from t1 join t2 on a = b", 477 }, { 478 input: "select /* join on */ 1 from t1 join t2 using (a)", 479 }, { 480 input: "select /* inner join */ 1 from t1 inner join t2", 481 output: "select /* inner join */ 1 from t1 join t2", 482 }, { 483 input: "select /* cross join */ 1 from t1 cross join t2", 484 output: "select /* cross join */ 1 from t1 join t2", 485 }, { 486 input: "select /* straight_join */ 1 from t1 straight_join t2", 487 }, { 488 input: "select /* straight_join on */ 1 from t1 straight_join t2 on a = b", 489 }, { 490 input: "select /* left join */ 1 from t1 left join t2 on a = b", 491 }, { 492 input: "select /* left join */ 1 from t1 left join t2 using (a)", 493 }, { 494 input: "select /* left outer join */ 1 from t1 left outer join t2 on a = b", 495 output: "select /* left outer join */ 1 from t1 left join t2 on a = b", 496 }, { 497 input: "select /* left outer join */ 1 from t1 left outer join t2 using (a)", 498 output: "select /* left outer join */ 1 from t1 left join t2 using (a)", 499 }, { 500 input: "select /* right join */ 1 from t1 right join t2 on a = b", 501 }, { 502 input: "select /* right join */ 1 from t1 right join t2 using (a)", 503 }, { 504 input: "select /* right outer join */ 1 from t1 right outer join t2 on a = b", 505 output: "select /* right outer join */ 1 from t1 right join t2 on a = b", 506 }, { 507 input: "select /* right outer join */ 1 from t1 right outer join t2 using (a)", 508 output: "select /* right outer join */ 1 from t1 right join t2 using (a)", 509 }, { 510 input: "select /* natural join */ 1 from t1 natural join t2", 511 }, { 512 input: "select /* natural left join */ 1 from t1 natural left join t2", 513 }, { 514 input: "select /* natural left outer join */ 1 from t1 natural left join t2", 515 output: "select /* natural left outer join */ 1 from t1 natural left join t2", 516 }, { 517 input: "select /* natural right join */ 1 from t1 natural right join t2", 518 }, { 519 input: "select /* natural right outer join */ 1 from t1 natural right join t2", 520 output: "select /* natural right outer join */ 1 from t1 natural right join t2", 521 }, { 522 input: "select /* join on */ 1 from t1 join t2 on a = b", 523 }, { 524 input: "select /* join using */ 1 from t1 join t2 using (a)", 525 }, { 526 input: "select /* join using (a, b, c) */ 1 from t1 join t2 using (a, b, c)", 527 }, { 528 input: "select /* s.t */ 1 from s.t", 529 }, { 530 input: "select /* keyword schema & table name */ 1 from `By`.`bY`", 531 }, { 532 input: "select /* select in from */ 1 from (select 1 from t) as a", 533 }, { 534 input: "select /* select in from with no as */ 1 from (select 1 from t) a", 535 output: "select /* select in from with no as */ 1 from (select 1 from t) as a", 536 }, { 537 input: "select /* where */ 1 from t where a = b", 538 }, { 539 input: "select /* and */ 1 from t where a = b and a = c", 540 }, { 541 input: "select /* && */ 1 from t where a = b && a = c", 542 output: "select /* && */ 1 from t where a = b and a = c", 543 }, { 544 input: "select /* or */ 1 from t where a = b or a = c", 545 }, { 546 input: "select /* || */ 1 from t where a = b || a = c", 547 output: "select /* || */ 1 from t where a = b or a = c", 548 }, { 549 input: "select /* not */ 1 from t where not a = b", 550 }, { 551 input: "select /* ! */ 1 from t where a = !1", 552 }, { 553 input: "select /* bool is */ 1 from t where a = b is null", 554 }, { 555 input: "select /* bool is not */ 1 from t where a = b is not false", 556 }, { 557 input: "select /* true */ 1 from t where true", 558 }, { 559 input: "select /* false */ 1 from t where false", 560 }, { 561 input: "select /* false on left */ 1 from t where false = 0", 562 }, { 563 input: "select /* exists */ 1 from t where exists (select 1 from t)", 564 }, { 565 input: "select /* (boolean) */ 1 from t where not (a = b)", 566 output: "select /* (boolean) */ 1 from t where not a = b", 567 }, { 568 input: "select /* in value list */ 1 from t where a in (b, c)", 569 }, { 570 input: "select /* in select */ 1 from t where a in (select 1 from t)", 571 }, { 572 input: "select /* not in */ 1 from t where a not in (b, c)", 573 }, { 574 input: "select /* like */ 1 from t where a like b", 575 }, { 576 input: "select /* like escape */ 1 from t where a like b escape '!'", 577 }, { 578 input: "select /* not like */ 1 from t where a not like b", 579 }, { 580 input: "select /* not like escape */ 1 from t where a not like b escape '$'", 581 }, { 582 input: "select /* regexp */ 1 from t where a regexp b", 583 }, { 584 input: "select /* not regexp */ 1 from t where a not regexp b", 585 }, { 586 input: "select /* rlike */ 1 from t where a rlike b", 587 output: "select /* rlike */ 1 from t where a regexp b", 588 }, { 589 input: "select /* not rlike */ 1 from t where a not rlike b", 590 output: "select /* not rlike */ 1 from t where a not regexp b", 591 }, { 592 input: "select /* between */ 1 from t where a between b and c", 593 }, { 594 input: "select /* not between */ 1 from t where a not between b and c", 595 }, { 596 input: "select /* is null */ 1 from t where a is null", 597 }, { 598 input: "select /* is not null */ 1 from t where a is not null", 599 }, { 600 input: "select /* is true */ 1 from t where a is true", 601 }, { 602 input: "select /* is not true */ 1 from t where a is not true", 603 }, { 604 input: "select /* is false */ 1 from t where a is false", 605 }, { 606 input: "select /* is not false */ 1 from t where a is not false", 607 }, { 608 input: "select /* < */ 1 from t where a < b", 609 }, { 610 input: "select /* <= */ 1 from t where a <= b", 611 }, { 612 input: "select /* >= */ 1 from t where a >= b", 613 }, { 614 input: "select /* > */ 1 from t where a > b", 615 }, { 616 input: "select /* != */ 1 from t where a != b", 617 }, { 618 input: "select /* <> */ 1 from t where a <> b", 619 output: "select /* <> */ 1 from t where a != b", 620 }, { 621 input: "select /* <=> */ 1 from t where a <=> b", 622 }, { 623 input: "select /* != */ 1 from t where a != b", 624 }, { 625 input: "select /* single value expre list */ 1 from t where a in (b)", 626 }, { 627 input: "select /* select as a value expression */ 1 from t where a = (select a from t)", 628 }, { 629 input: "select /* parenthesised value */ 1 from t where a = (b)", 630 output: "select /* parenthesised value */ 1 from t where a = b", 631 }, { 632 input: "select /* over-parenthesize */ ((1)) from t where ((a)) in (((1))) and ((a, b)) in ((((1, 1))), ((2, 2)))", 633 output: "select /* over-parenthesize */ 1 from t where a in (1) and (a, b) in ((1, 1), (2, 2))", 634 }, { 635 input: "select /* dot-parenthesize */ (a.b) from t where (b.c) = 2", 636 output: "select /* dot-parenthesize */ a.b from t where b.c = 2", 637 }, { 638 input: "select /* & */ 1 from t where a = b & c", 639 }, { 640 input: "select /* & */ 1 from t where a = b & c", 641 }, { 642 input: "select /* | */ 1 from t where a = b | c", 643 }, { 644 input: "select /* ^ */ 1 from t where a = b ^ c", 645 }, { 646 input: "select /* + */ 1 from t where a = b + c", 647 }, { 648 input: "select /* - */ 1 from t where a = b - c", 649 }, { 650 input: "select /* * */ 1 from t where a = b * c", 651 }, { 652 input: "select /* / */ 1 from t where a = b / c", 653 }, { 654 input: "select /* % */ 1 from t where a = b % c", 655 }, { 656 input: "select /* div */ 1 from t where a = b div c", 657 }, { 658 input: "select /* MOD */ 1 from t where a = b MOD c", 659 output: "select /* MOD */ 1 from t where a = b % c", 660 }, { 661 input: "select /* << */ 1 from t where a = b << c", 662 }, { 663 input: "select /* >> */ 1 from t where a = b >> c", 664 }, { 665 input: "select /* % no space */ 1 from t where a = b%c", 666 output: "select /* % no space */ 1 from t where a = b % c", 667 }, { 668 input: "select /* u+ */ 1 from t where a = +b", 669 output: "select /* u+ */ 1 from t where a = b", 670 }, { 671 input: "select /* u- */ 1 from t where a = -b", 672 }, { 673 input: "select /* u~ */ 1 from t where a = ~b", 674 }, { 675 input: "select /* -> */ a.b -> 'ab' from t", 676 }, { 677 input: "select /* -> */ a.b ->> 'ab' from t", 678 }, { 679 input: "select /* empty function */ 1 from t where a = b()", 680 }, { 681 input: "select /* function with 1 param */ 1 from t where a = b(c)", 682 }, { 683 input: "select /* function with many params */ 1 from t where a = b(c, d)", 684 }, { 685 input: "select /* function with distinct */ count(distinct a) from t", 686 }, { 687 input: "select count(distinctrow(1)) from (select (1) from dual union all select 1 from dual) a", 688 output: "select count(distinct 1) from (select 1 from dual union all select 1 from dual) as a", 689 }, { 690 input: "select /* if as func */ 1 from t where a = if(b)", 691 }, { 692 input: "select /* current_timestamp */ current_timestamp() from t", 693 }, { 694 input: "select /* current_timestamp as func */ current_timestamp() from t", 695 }, { 696 input: "select /* current_timestamp with fsp */ current_timestamp(3) from t", 697 }, { 698 input: "select /* current_date */ current_date() from t", 699 }, { 700 input: "select /* current_date as func */ current_date() from t", 701 }, { 702 input: "select /* current_time */ current_time() from t", 703 }, { 704 input: "select /* current_time as func */ current_time() from t", 705 }, { 706 input: "select /* current_time with fsp */ current_time(1) from t", 707 }, { 708 input: "select /* utc_timestamp */ utc_timestamp() from t", 709 }, { 710 input: "select /* utc_timestamp as func */ utc_timestamp() from t", 711 }, { 712 input: "select /* utc_timestamp with fsp */ utc_timestamp(0) from t", 713 }, { 714 input: "select /* utc_time */ utc_time() from t", 715 }, { 716 input: "select /* utc_time as func */ utc_time() from t", 717 }, { 718 input: "select /* utc_time with fsp */ utc_time(4) from t", 719 }, { 720 input: "select /* utc_date */ utc_date() from t", 721 }, { 722 input: "select /* utc_date as func */ utc_date() from t", 723 }, { 724 input: "select /* localtime */ localtime() from t", 725 }, { 726 input: "select /* localtime as func */ localtime() from t", 727 }, { 728 input: "select /* localtime with fsp */ localtime(5) from t", 729 }, { 730 input: "select /* localtimestamp */ localtimestamp() from t", 731 }, { 732 input: "select /* localtimestamp as func */ localtimestamp() from t", 733 }, { 734 input: "select /* localtimestamp with fsp */ localtimestamp(7) from t", 735 }, { 736 input: "select /* mod as func */ a from tab where mod(b, 2) = 0", 737 }, { 738 input: "select /* database as func no param */ database() from t", 739 }, { 740 input: "select /* database as func 1 param */ database(1) from t", 741 }, { 742 input: "select /* a */ a from t", 743 }, { 744 input: "select /* a.b */ a.b from t", 745 }, { 746 input: "select /* a.b.c */ a.b.c from t", 747 }, { 748 input: "select /* keyword a.b */ `By`.`bY` from t", 749 }, { 750 input: "select /* string */ 'a' from t", 751 }, { 752 input: "select /* double quoted string */ \"a\" from t", 753 output: "select /* double quoted string */ 'a' from t", 754 }, { 755 input: "select /* quote quote in string */ 'a''a' from t", 756 output: "select /* quote quote in string */ 'a\\'a' from t", 757 }, { 758 input: "select /* double quote quote in string */ \"a\"\"a\" from t", 759 output: "select /* double quote quote in string */ 'a\\\"a' from t", 760 }, { 761 input: "select /* quote in double quoted string */ \"a'a\" from t", 762 output: "select /* quote in double quoted string */ 'a\\'a' from t", 763 }, { 764 input: "select /* backslash quote in string */ 'a\\'a' from t", 765 }, { 766 input: "select /* literal backslash in string */ 'a\\\\na' from t", 767 }, { 768 input: "select /* all escapes */ '\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\' from t", 769 }, { 770 input: "select /* non-escape */ '\\x' from t", 771 output: "select /* non-escape */ 'x' from t", 772 }, { 773 input: "select /* unescaped backslash */ '\\n' from t", 774 }, { 775 input: "select /* value argument */ :a from t", 776 }, { 777 input: "select /* value argument with digit */ :a1 from t", 778 }, { 779 input: "select /* value argument with dot */ :a.b from t", 780 }, { 781 input: "select /* positional argument */ ? from t", 782 output: "select /* positional argument */ :v1 from t", 783 }, { 784 input: "select /* multiple positional arguments */ ?, ? from t", 785 output: "select /* multiple positional arguments */ :v1, :v2 from t", 786 }, { 787 input: "select /* list arg */ * from t where a in ::list", 788 }, { 789 input: "select /* list arg not in */ * from t where a not in ::list", 790 }, { 791 input: "select /* null */ null from t", 792 }, { 793 input: "select /* octal */ 010 from t", 794 }, { 795 input: "select /* hex */ x'f0A1' from t", 796 output: "select /* hex */ X'f0A1' from t", 797 }, { 798 input: "select /* hex caps */ X'F0a1' from t", 799 }, { 800 input: "select /* bit literal */ b'0101' from t", 801 output: "select /* bit literal */ B'0101' from t", 802 }, { 803 input: "select /* bit literal caps */ B'010011011010' from t", 804 }, { 805 input: "select /* 0x */ 0xf0 from t", 806 }, { 807 input: "select /* float */ 0.1 from t", 808 }, { 809 input: "select /* group by */ 1 from t group by a", 810 }, { 811 input: "select /* having */ 1 from t having a = b", 812 }, { 813 input: "select /* simple order by */ 1 from t order by a", 814 output: "select /* simple order by */ 1 from t order by a asc", 815 }, { 816 input: "select * from t where id = ((select a from t1 union select b from t2) order by a limit 1)", 817 output: "select * from t where id = (select a from t1 union select b from t2 order by a asc limit 1)", 818 }, { 819 input: "select /* order by asc */ 1 from t order by a asc", 820 }, { 821 input: "select /* order by desc */ 1 from t order by a desc", 822 }, { 823 input: "select /* order by null */ 1 from t order by null", 824 }, { 825 input: "select /* limit a */ 1 from t limit a", 826 }, { 827 input: "select /* limit a,b */ 1 from t limit a, b", 828 }, { 829 input: "select /* binary unary */ a- -b from t", 830 output: "select /* binary unary */ a - -b from t", 831 }, { 832 input: "select /* - - */ - -b from t", 833 output: "select /* - - */ - -b from t", 834 }, { 835 input: "select /* binary binary */ binary binary b from t", 836 output: "select /* binary binary */ convert(convert(b, binary), binary) from t", 837 }, { 838 input: "select /* binary ~ */ binary ~b from t", 839 output: "select /* binary ~ */ convert(~b, binary) from t", 840 }, { 841 input: "select /* ~ binary */ ~ binary b from t", 842 output: "select /* ~ binary */ ~convert(b, binary) from t", 843 }, { 844 input: "select /* interval */ adddate('2008-01-02', interval 31 day) from t", 845 }, { 846 input: "select /* interval keyword */ adddate('2008-01-02', interval 1 year) from t", 847 }, { 848 input: "select /* TIMESTAMPADD */ TIMESTAMPADD(MINUTE, 1, '2008-01-04') from t", 849 output: "select /* TIMESTAMPADD */ timestampadd(MINUTE, 1, '2008-01-04') from t", 850 }, { 851 input: "select /* TIMESTAMPDIFF */ TIMESTAMPDIFF(MINUTE, '2008-01-02', '2008-01-04') from t", 852 output: "select /* TIMESTAMPDIFF */ timestampdiff(MINUTE, '2008-01-02', '2008-01-04') from t", 853 }, { 854 input: "select DATE_ADD(MIN(FROM_UNIXTIME(1673444922)),interval -DAYOFWEEK(MIN(FROM_UNIXTIME(1673444922)))+1 DAY)", 855 output: "select DATE_ADD(min(FROM_UNIXTIME(1673444922)), interval (-DAYOFWEEK(min(FROM_UNIXTIME(1673444922))) + 1) DAY) from dual", 856 }, { 857 input: "select '2020-01-01' + interval month(DATE_SUB(FROM_UNIXTIME(1234), interval 1 month))-1 month", 858 output: "select '2020-01-01' + interval (month(DATE_SUB(FROM_UNIXTIME(1234), interval 1 month)) - 1) month from dual", 859 }, { 860 input: "select /* dual */ 1 from dual", 861 }, { 862 input: "select /* Dual */ 1 from Dual", 863 output: "select /* Dual */ 1 from dual", 864 }, { 865 input: "select /* DUAL */ 1 from Dual", 866 output: "select /* DUAL */ 1 from dual", 867 }, { 868 input: "select /* column as bool in where */ a from t where b", 869 }, { 870 input: "select /* OR of columns in where */ * from t where a or b", 871 }, { 872 input: "select /* OR of mixed columns in where */ * from t where a = 5 or b and c is not null", 873 }, { 874 input: "select /* OR in select columns */ (a or b) from t where c = 5", 875 output: "select /* OR in select columns */ a or b from t where c = 5", 876 }, { 877 input: "select /* XOR of columns in where */ * from t where a xor b", 878 }, { 879 input: "select /* XOR of mixed columns in where */ * from t where a = 5 xor b and c is not null", 880 }, { 881 input: "select /* XOR in select columns */ (a xor b) from t where c = 5", 882 output: "select /* XOR in select columns */ a xor b from t where c = 5", 883 }, { 884 input: "select /* XOR in select columns */ * from t where (1 xor c1 > 0)", 885 output: "select /* XOR in select columns */ * from t where 1 xor c1 > 0", 886 }, { 887 input: "select /* bool as select value */ a, true from t", 888 }, { 889 input: "select /* bool column in ON clause */ * from t join s on t.id = s.id and s.foo where t.bar", 890 }, { 891 input: "select /* bool in order by */ * from t order by a is null or b asc", 892 }, { 893 input: "select /* string in case statement */ if(max(case a when 'foo' then 1 else 0 end) = 1, 'foo', 'bar') as foobar from t", 894 }, { 895 input: "/*!show databases*/", 896 output: "show databases", 897 }, { 898 input: "select /*!40101 * from*/ t", 899 output: "select * from t", 900 }, { 901 input: "select /*! * from*/ t", 902 output: "select * from t", 903 }, { 904 input: "select /*!* from*/ t", 905 output: "select * from t", 906 }, { 907 input: "select /*!401011 from*/ t", 908 output: "select 1 from t", 909 }, { 910 input: "select /* dual */ 1 from dual", 911 }, { 912 input: "select * from (select 'tables') tables", 913 output: "select * from (select 'tables' from dual) as `tables`", 914 }, { 915 input: "insert /* simple */ into a values (1)", 916 }, { 917 input: "insert /* a.b */ into a.b values (1)", 918 }, { 919 input: "insert /* multi-value */ into a values (1, 2)", 920 }, { 921 input: "insert /* multi-value list */ into a values (1, 2), (3, 4)", 922 }, { 923 input: "insert /* no values */ into a values ()", 924 }, { 925 input: "insert /* set */ into a set a = 1, b = 2", 926 output: "insert /* set */ into a(a, b) values (1, 2)", 927 }, { 928 input: "insert /* set default */ into a set a = default, b = 2", 929 output: "insert /* set default */ into a(a, b) values (default, 2)", 930 }, { 931 input: "insert /* value expression list */ into a values (a + 1, 2 * 3)", 932 }, { 933 input: "insert /* default */ into a values (default, 2 * 3)", 934 }, { 935 input: "insert /* column list */ into a(a, b) values (1, 2)", 936 }, { 937 input: "insert into a(a, b) values (1, ifnull(null, default(b)))", 938 }, { 939 input: "insert /* qualified column list */ into a(a, b) values (1, 2)", 940 }, { 941 input: "insert /* qualified columns */ into t (t.a, t.b) values (1, 2)", 942 output: "insert /* qualified columns */ into t(a, b) values (1, 2)", 943 }, { 944 input: "insert /* select */ into a select b, c from d", 945 }, { 946 input: "insert /* it accepts columns with keyword action */ into a(action, b) values (1, 2)", 947 output: "insert /* it accepts columns with keyword action */ into a(`action`, b) values (1, 2)", 948 }, { 949 input: "insert /* no cols & paren select */ into a (select * from t)", 950 output: "insert /* no cols & paren select */ into a select * from t", 951 }, { 952 input: "insert /* cols & paren select */ into a(a, b, c) (select * from t)", 953 output: "insert /* cols & paren select */ into a(a, b, c) select * from t", 954 }, { 955 input: "insert /* cols & union with paren select */ into a(b, c) (select d, e from f) union (select g from h)", 956 output: "insert /* cols & union with paren select */ into a(b, c) select d, e from f union select g from h", 957 }, { 958 input: "insert /* on duplicate */ into a values (1, 2) on duplicate key update b = func(a), c = d", 959 }, { 960 input: "insert /* bool in insert value */ into a values (1, true, false)", 961 }, { 962 input: "insert /* bool in on duplicate */ into a values (1, 2) on duplicate key update b = false, c = d", 963 }, { 964 input: "insert /* bool in on duplicate */ into a values (1, 2, 3) on duplicate key update b = values(b), c = d", 965 }, { 966 input: "insert /* bool in on duplicate */ into a values (1, 2, 3) on duplicate key update b = values(a.b), c = d", 967 }, { 968 input: "insert /* bool expression on duplicate */ into a values (1, 2) on duplicate key update b = func(a), c = a > d", 969 }, { 970 input: "insert into `user`(username, `status`) values ('Chuck', default(`status`))", 971 }, { 972 input: "insert into user(format, tree, vitess) values ('Chuck', 42, 'Barry')", 973 output: "insert into `user`(`format`, `tree`, `vitess`) values ('Chuck', 42, 'Barry')", 974 }, { 975 input: "insert into customer() values ()", 976 }, { 977 input: "update /* simple */ a set b = 3", 978 }, { 979 input: "update /* a.b */ a.b set b = 3", 980 }, { 981 input: "update /* list */ a set b = 3, c = 4", 982 }, { 983 input: "update /* expression */ a set b = 3 + 4", 984 }, { 985 input: "update /* where */ a set b = 3 where a = b", 986 }, { 987 input: "update /* order */ a set b = 3 order by c desc", 988 }, { 989 input: "update /* limit */ a set b = 3 limit c", 990 }, { 991 input: "update /* bool in update */ a set b = true", 992 }, { 993 input: "update /* bool expr in update */ a set b = 5 > 2", 994 }, { 995 input: "update /* bool in update where */ a set b = 5 where c", 996 }, { 997 input: "update /* table qualifier */ a set a.b = 3", 998 }, { 999 input: "update /* table qualifier */ a set t.a.b = 3", 1000 }, { 1001 input: "update /* table alias */ tt aa set aa.cc = 3", 1002 output: "update /* table alias */ tt as aa set aa.cc = 3", 1003 }, { 1004 input: "update (select id from foo) subqalias set id = 4", 1005 output: "update (select id from foo) as subqalias set id = 4", 1006 }, { 1007 input: "update foo f, bar b set f.id = b.id where b.name = 'test'", 1008 output: "update foo as f, bar as b set f.id = b.id where b.`name` = 'test'", 1009 }, { 1010 input: "update foo f join bar b on f.name = b.name set f.id = b.id where b.name = 'test'", 1011 output: "update foo as f join bar as b on f.`name` = b.`name` set f.id = b.id where b.`name` = 'test'", 1012 }, { 1013 input: "update /* ignore */ ignore a set b = 3", 1014 }, { 1015 input: "delete /* simple */ from a", 1016 }, { 1017 input: "delete /* a.b */ from a.b", 1018 }, { 1019 input: "delete /* where */ from a where a = b", 1020 }, { 1021 input: "delete /* order */ from a order by b desc", 1022 }, { 1023 input: "delete /* limit */ from a limit b", 1024 }, { 1025 input: "delete /* alias where */ t.* from a as t where t.id = 2", 1026 output: "delete /* alias where */ t from a as t where t.id = 2", 1027 }, { 1028 input: "delete t.* from t, t1", 1029 output: "delete t from t, t1", 1030 }, { 1031 input: "delete a from a join b on a.id = b.id where b.name = 'test'", 1032 output: "delete a from a join b on a.id = b.id where b.`name` = 'test'", 1033 }, { 1034 input: "delete a, b from a, b where a.id = b.id and b.name = 'test'", 1035 output: "delete a, b from a, b where a.id = b.id and b.`name` = 'test'", 1036 }, { 1037 input: "delete /* simple */ ignore from a", 1038 }, { 1039 input: "delete ignore from a", 1040 }, { 1041 input: "delete /* limit */ ignore from a", 1042 }, { 1043 input: "delete from a1, a2 using t1 as a1 inner join t2 as a2 where a1.id=a2.id", 1044 output: "delete a1, a2 from t1 as a1 join t2 as a2 where a1.id = a2.id", 1045 }, { 1046 input: "set /* simple */ a = 3", 1047 output: "set /* simple */ @@a = 3", 1048 }, { 1049 input: "set #simple\n b = 4", 1050 output: "set #simple\n @@b = 4", 1051 }, { 1052 input: "set character_set_results = utf8", 1053 output: "set @@character_set_results = utf8", 1054 }, { 1055 input: "set @@session.autocommit = true", 1056 output: "set @@autocommit = true", 1057 }, { 1058 input: "set @@session.`autocommit` = true", 1059 output: "set @@autocommit = true", 1060 }, { 1061 input: "set @@session.autocommit = ON", 1062 output: "set @@autocommit = 'on'", 1063 }, { 1064 input: "set @@session.autocommit= OFF", 1065 output: "set @@autocommit = 'off'", 1066 }, { 1067 input: "set autocommit = on", 1068 output: "set @@autocommit = 'on'", 1069 }, { 1070 input: "set autocommit = off", 1071 output: "set @@autocommit = 'off'", 1072 }, { 1073 input: "set names utf8 collate foo", 1074 output: "set names 'utf8'", 1075 }, { 1076 input: "set names utf8 collate 'foo'", 1077 output: "set names 'utf8'", 1078 }, { 1079 input: "set character set utf8", 1080 output: "set charset 'utf8'", 1081 }, { 1082 input: "set character set 'utf8'", 1083 output: "set charset 'utf8'", 1084 }, { 1085 input: "set s = 1--4", 1086 output: "set @@s = 1 - -4", 1087 }, { 1088 input: "set character set \"utf8\"", 1089 output: "set charset 'utf8'", 1090 }, { 1091 input: "set charset default", 1092 output: "set charset default", 1093 }, { 1094 input: "set session wait_timeout = 3600", 1095 output: "set @@wait_timeout = 3600", 1096 }, { 1097 input: "set session wait_timeout = 3600, session autocommit = off", 1098 output: "set @@wait_timeout = 3600, @@autocommit = 'off'", 1099 }, { 1100 input: "set session wait_timeout = 3600, @@global.autocommit = off", 1101 output: "set @@wait_timeout = 3600, @@global.autocommit = 'off'", 1102 }, { 1103 input: "set local wait_timeout = 3600", 1104 output: "set @@wait_timeout = 3600", 1105 }, { 1106 input: "set @@local.wait_timeout = 3600", 1107 output: "set @@wait_timeout = 3600", 1108 }, { 1109 input: "set /* list */ a = 3, b = 4", 1110 output: "set /* list */ @@a = 3, @@b = 4", 1111 }, { 1112 input: "set /* mixed list */ a = 3, names 'utf8', charset 'ascii', b = 4", 1113 output: "set /* mixed list */ @@a = 3, names 'utf8', charset 'ascii', @@b = 4", 1114 }, { 1115 input: "set session transaction isolation level repeatable read", 1116 output: "set @@session.transaction_isolation = 'repeatable-read'", 1117 }, { 1118 input: "set transaction isolation level repeatable read", 1119 output: "set @@transaction_isolation = 'repeatable-read'", 1120 }, { 1121 input: "set global transaction isolation level repeatable read", 1122 output: "set @@global.transaction_isolation = 'repeatable-read'", 1123 }, { 1124 input: "set transaction isolation level repeatable read", 1125 output: "set @@transaction_isolation = 'repeatable-read'", 1126 }, { 1127 input: "set transaction isolation level read committed", 1128 output: "set @@transaction_isolation = 'read-committed'", 1129 }, { 1130 input: "set transaction isolation level read uncommitted", 1131 output: "set @@transaction_isolation = 'read-uncommitted'", 1132 }, { 1133 input: "set transaction isolation level serializable", 1134 output: "set @@transaction_isolation = 'serializable'", 1135 }, { 1136 input: "set transaction read write", 1137 output: "set @@transaction_read_only = 'off'", 1138 }, { 1139 input: "set transaction read only", 1140 output: "set @@transaction_read_only = 'on'", 1141 }, { 1142 input: "set session transaction read only, isolation level serializable", 1143 output: "set @@session.transaction_read_only = 'on', @@session.transaction_isolation = 'serializable'", 1144 }, { 1145 input: "set tx_read_only = 1", 1146 output: "set @@tx_read_only = 1", 1147 }, { 1148 input: "set tx_read_only = 0", 1149 output: "set @@tx_read_only = 0", 1150 }, { 1151 input: "set transaction_read_only = 1", 1152 output: "set @@session.transaction_read_only = 1", 1153 }, { 1154 input: "set transaction_read_only = 0", 1155 output: "set @@session.transaction_read_only = 0", 1156 }, { 1157 input: "set @@transaction_read_only = 1", 1158 }, { 1159 input: "set @@transaction_isolation = 'read-committed'", 1160 }, { 1161 input: "set tx_isolation = 'repeatable read'", 1162 output: "set @@tx_isolation = 'repeatable read'", 1163 }, { 1164 input: "set tx_isolation = 'read committed'", 1165 output: "set @@tx_isolation = 'read committed'", 1166 }, { 1167 input: "set tx_isolation = 'read uncommitted'", 1168 output: "set @@tx_isolation = 'read uncommitted'", 1169 }, { 1170 input: "set tx_isolation = 'serializable'", 1171 output: "set @@tx_isolation = 'serializable'", 1172 }, { 1173 input: "set sql_safe_updates = 0", 1174 output: "set @@sql_safe_updates = 0", 1175 }, { 1176 input: "set sql_safe_updates = 1", 1177 output: "set @@sql_safe_updates = 1", 1178 }, { 1179 input: "set @variable = 42", 1180 }, { 1181 input: "set @period.variable = 42", 1182 output: "set @`period.variable` = 42", 1183 }, { 1184 input: "set S= +++-++-+(4+1)", 1185 output: "set @@S = - -(4 + 1)", 1186 }, { 1187 input: "set S= +- - - - -(4+1)", 1188 output: "set @@S = - - - - -(4 + 1)", 1189 }, { 1190 input: "alter table a add foo int references b (a) on delete restrict first", 1191 output: "alter table a add column foo int references b (a) on delete restrict first", 1192 }, { 1193 input: "alter table a lock default, lock = none, lock shared, lock exclusive", 1194 output: "alter table a lock default, lock none, lock shared, lock exclusive", 1195 }, { 1196 input: "alter table a alter x set default NULL, alter column x2 set default 's', alter x3 drop default", 1197 output: "alter table a alter column x set default null, alter column x2 set default 's', alter column x3 drop default", 1198 }, { 1199 input: "alter table a alter column x set visible, alter column x2 set invisible", 1200 }, { 1201 input: "alter table a alter index x visible, alter index x2 invisible", 1202 }, { 1203 input: "alter table a add spatial key foo (column1)", 1204 }, { 1205 input: "alter table a add fulltext key foo (column1), order by a, b, c", 1206 }, { 1207 input: "alter table a add unique key foo (column1)", 1208 }, { 1209 input: "alter /*vt+ strategy=online */ table a add unique key foo (column1)", 1210 }, { 1211 input: "alter table a change column s foo int default 1 after x", 1212 }, { 1213 input: "alter table a modify column foo int default 1 first", 1214 }, { 1215 input: "alter table a rename column foo to bar", 1216 }, { 1217 input: "alter table a add foo varchar(255) generated always as (concat(bar, ' ', baz)) stored", 1218 output: "alter table a add column foo varchar(255) as (concat(bar, ' ', baz)) stored", 1219 }, { 1220 input: "alter table a add foo varchar(255) generated always as (concat(bar, ' ', baz))", 1221 output: "alter table a add column foo varchar(255) as (concat(bar, ' ', baz)) virtual", 1222 }, { 1223 input: "alter table a add foo varchar(255) generated always as (concat(bar, ' ', baz)) null", 1224 output: "alter table a add column foo varchar(255) as (concat(bar, ' ', baz)) virtual null", 1225 }, { 1226 input: "alter table a add foo varchar(255) generated always as (concat(bar, ' ', baz)) not null", 1227 output: "alter table a add column foo varchar(255) as (concat(bar, ' ', baz)) virtual not null", 1228 }, { 1229 input: "alter table a change column s foo varchar(255) generated always as (concat(bar, ' ', baz)) stored", 1230 output: "alter table a change column s foo varchar(255) as (concat(bar, ' ', baz)) stored", 1231 }, { 1232 input: "alter table a modify column foo varchar(255) generated always as (concat(bar, ' ', baz))", 1233 output: "alter table a modify column foo varchar(255) as (concat(bar, ' ', baz)) virtual", 1234 }, { 1235 input: "alter table a character set utf32 collate = 'utf'", 1236 output: "alter table a charset utf32 collate utf", 1237 }, { 1238 input: "alter table a convert to character set utf32", 1239 }, { 1240 input: "alter table `By` add column foo int, algorithm = default", 1241 }, { 1242 input: "alter table `By` add column foo int, algorithm = copy", 1243 }, { 1244 input: "alter table `By` add column foo int, algorithm = inplace", 1245 }, { 1246 input: "alter table `By` add column foo int, algorithm = INPLACE", 1247 }, { 1248 input: "alter table `By` add column foo int, algorithm = instant", 1249 }, { 1250 input: "alter table a rename b", 1251 }, { 1252 input: "alter table `By` rename `bY`", 1253 }, { 1254 input: "alter table a rename to b", 1255 output: "alter table a rename b", 1256 }, { 1257 input: "alter table a rename as b", 1258 output: "alter table a rename b", 1259 }, { 1260 input: "alter table a rename index foo to bar, with validation", 1261 }, { 1262 input: "alter table a rename key foo to bar", 1263 output: "alter table a rename index foo to bar", 1264 }, { 1265 input: "alter table e auto_increment 20", 1266 }, { 1267 input: "alter table e character set = 'ascii'", 1268 output: "alter table e charset ascii", 1269 }, { 1270 input: "alter table e enable keys, discard tablespace, force", 1271 }, { 1272 input: "alter table e default character set = 'ascii'", 1273 output: "alter table e charset ascii", 1274 }, { 1275 input: "alter table e comment 'hello' remove partitioning", 1276 }, { 1277 input: "alter table a reorganize partition b into (partition c values less than (?), partition d values less than (maxvalue))", 1278 output: "alter table a reorganize partition b into (partition c values less than (:v1), partition d values less than maxvalue)", 1279 }, { 1280 input: "alter table a algorithm = default, lock none, add partition (partition d values less than maxvalue)", 1281 }, { 1282 input: "alter table a discard partition all tablespace", 1283 }, { 1284 input: "alter table a import partition a, b, v tablespace", 1285 }, { 1286 input: "alter table a truncate partition a, b, v", 1287 }, { 1288 input: "alter table a coalesce partition 7", 1289 }, { 1290 input: "alter table a exchange partition a with table t without validation", 1291 }, { 1292 input: "alter table a analyze partition all", 1293 }, { 1294 input: "alter table a analyze partition a, v", 1295 }, { 1296 input: "alter table a check partition all", 1297 }, { 1298 input: "alter table a check partition a, v", 1299 }, { 1300 input: "alter table a optimize partition all", 1301 }, { 1302 input: "alter table a optimize partition a, v", 1303 }, { 1304 input: "alter table a rebuild partition all", 1305 }, { 1306 input: "alter table a rebuild partition a, v", 1307 }, { 1308 input: "alter table a repair partition all", 1309 }, { 1310 input: "alter table a repair partition a, v", 1311 }, { 1312 input: "alter table a remove partitioning", 1313 }, { 1314 input: "alter table a upgrade partitioning", 1315 }, { 1316 input: "alter table t2 add primary key `zzz` (id)", 1317 output: "alter table t2 add primary key (id)", 1318 }, { 1319 input: "alter table a \npartition by hash (id) partitions 4", 1320 }, { 1321 input: "alter table a \npartition by range (id)\n(partition p0 values less than (10),\n partition p1 values less than maxvalue)", 1322 }, { 1323 input: "create database a garbage values", 1324 output: "create database a", 1325 partialDDL: true, 1326 }, { 1327 input: "alter table `Post With Space` drop foreign key `Post With Space_ibfk_1`", 1328 }, { 1329 input: "alter table a add column (id int, id2 char(23))", 1330 }, { 1331 input: "alter table a add index idx (id)", 1332 }, { 1333 input: "alter table a add fulltext index idx (id)", 1334 }, { 1335 input: "alter table a add spatial index idx (id)", 1336 }, { 1337 input: "alter table a add fulltext index idx (id)", 1338 }, { 1339 input: "alter table a add foreign key (id) references f (id)", 1340 }, { 1341 input: "alter table a add foreign key the_idx(id) references f (id)", 1342 }, { 1343 input: "alter table a add primary key (id)", 1344 }, { 1345 input: "alter table a add constraint b primary key (id)", 1346 }, { 1347 input: "alter table a add constraint b primary key (id)", 1348 }, { 1349 input: "alter table a add constraint b unique key (id)", 1350 }, { 1351 input: "alter table t add column iii int signed not null", 1352 output: "alter table t add column iii int not null", 1353 }, { 1354 input: "alter table t add column iii int unsigned not null", 1355 }, { 1356 input: "alter table a add constraint b unique c (id)", 1357 output: "alter table a add constraint b unique key c (id)", 1358 }, { 1359 input: "alter table a add constraint check (id)", 1360 output: "alter table a add check (id)", 1361 }, { 1362 input: "alter table a add constraint c check (id)", 1363 }, { 1364 input: "alter table a add id int", 1365 output: "alter table a add column id int", 1366 }, { 1367 input: "alter table a add column id int first", 1368 }, { 1369 input: "alter table a add column id int after id2", 1370 }, { 1371 input: "alter table a drop column id", 1372 }, { 1373 input: "alter table a drop partition p2712, p123", 1374 }, { 1375 input: "alter table a drop index idx", 1376 output: "alter table a drop key idx", 1377 }, { 1378 input: "alter table a add check (ch_1) not enforced", 1379 }, { 1380 input: "alter table a alter check ch_1 enforced", 1381 }, { 1382 input: "alter table a alter check ch_1 not enforced", 1383 }, { 1384 input: "alter table a drop check ch_1", 1385 }, { 1386 input: "alter table a drop constraint ch_1", 1387 output: "alter table a drop check ch_1", 1388 }, { 1389 input: "alter table a drop foreign key kx", 1390 }, { 1391 input: "alter table a drop primary key", 1392 }, { 1393 input: "alter table a drop id", 1394 output: "alter table a drop column id", 1395 }, { 1396 input: "ALTER TABLE `product115s` CHANGE `part_number` `part_number` varchar(255) DEFAULT '0' NOT NULL", 1397 output: "alter table product115s change column part_number part_number varchar(255) not null default '0'", 1398 }, { 1399 input: "ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5)", 1400 output: "alter table distributors add constraint zipchk check (char_length(zipcode) = 5)", 1401 }, { 1402 input: "alter database character set geostd8", 1403 }, { 1404 input: "alter database d character set geostd8", 1405 }, { 1406 input: "alter database d default collate 'utf8_bin'", 1407 }, { 1408 input: "alter database default collate 'utf8_bin'", 1409 }, { 1410 input: "alter database d upgrade data directory name", 1411 }, { 1412 input: "alter database d collate = 'utf8_bin'", 1413 output: "alter database d collate 'utf8_bin'", 1414 }, { 1415 input: "alter schema d default character set = geostd8", 1416 output: "alter database d default character set geostd8", 1417 }, { 1418 input: "alter schema d character set = geostd8", 1419 output: "alter database d character set geostd8", 1420 }, { 1421 input: "alter schema d default collate = 'utf8_bin'", 1422 output: "alter database d default collate 'utf8_bin'", 1423 }, { 1424 input: "alter schema d collate = 'utf8_bin' character set = geostd8 character set = geostd8", 1425 output: "alter database d collate 'utf8_bin' character set geostd8 character set geostd8", 1426 }, { 1427 input: "create table a", 1428 partialDDL: true, 1429 }, { 1430 input: "CREATE TABLE a", 1431 output: "create table a", 1432 partialDDL: true, 1433 }, { 1434 input: "create table `a`", 1435 output: "create table a", 1436 partialDDL: true, 1437 }, { 1438 input: "create table function_default (x varchar(25) default (trim(' check ')))", 1439 output: "create table function_default (\n\tx varchar(25) default (trim(' check '))\n)", 1440 }, { 1441 input: "create table function_default (x varchar(25) default (((trim(' check ')))))", 1442 output: "create table function_default (\n\tx varchar(25) default (trim(' check '))\n)", 1443 }, { 1444 input: "create table function_default3 (x bool DEFAULT (true AND false));", 1445 output: "create table function_default3 (\n\tx bool default (true and false)\n)", 1446 }, { 1447 input: "create table function_default (x bool DEFAULT true);", 1448 output: "create table function_default (\n\tx bool default true\n)", 1449 }, { 1450 input: "create table a (\n\t`a` int\n)", 1451 output: "create table a (\n\ta int\n)", 1452 }, { 1453 input: "create table `by` (\n\t`by` char\n)", 1454 }, { 1455 input: "create table test (\n\t__year year(4)\n)", 1456 }, { 1457 input: "create table a (\n\ta int not null\n)", 1458 }, { 1459 input: "create /*vt+ strategy=online */ table a (\n\ta int not null\n)", 1460 }, { 1461 input: "create table a (\n\ta int not null default 0\n)", 1462 }, { 1463 input: "create table a (\n\ta float not null default -1\n)", 1464 output: "create table a (\n\ta float not null default -1\n)", 1465 }, { 1466 input: "create table a (\n\ta float not null default -2.1\n)", 1467 output: "create table a (\n\ta float not null default -2.1\n)", 1468 }, { 1469 input: "create table a (\n\ta float(24) not null default -1\n)", 1470 output: "create table a (\n\ta float(24) not null default -1\n)", 1471 }, { 1472 input: "create table a (\n\ta float(24,10) not null default -1\n)", 1473 output: "create table a (\n\ta float(24,10) not null default -1\n)", 1474 }, { 1475 input: "create table a (\n\ta float4 not null default -1\n)", 1476 output: "create table a (\n\ta float4 not null default -1\n)", 1477 }, { 1478 input: "create table a (\n\ta float8 not null default -1\n)", 1479 output: "create table a (\n\ta float8 not null default -1\n)", 1480 }, { 1481 input: "create table a (a int not null default 0, primary key(a))", 1482 output: "create table a (\n\ta int not null default 0,\n\tprimary key (a)\n)", 1483 }, { 1484 input: "create table a (`a column` int)", 1485 output: "create table a (\n\t`a column` int\n)", 1486 }, { 1487 input: "create table a (\n\ta varchar(32) not null default ''\n)", 1488 }, { 1489 input: "create table if not exists a (\n\t`a` int\n)", 1490 output: "create table if not exists a (\n\ta int\n)", 1491 }, { 1492 input: "create table a ignore me this is garbage", 1493 output: "create table a", 1494 partialDDL: true, 1495 }, { 1496 input: "create table a (a int, b char, c garbage)", 1497 output: "create table a", 1498 partialDDL: true, 1499 }, { 1500 input: "create table a (b1 bool not null primary key, b2 boolean not null)", 1501 output: "create table a (\n\tb1 bool not null primary key,\n\tb2 boolean not null\n)", 1502 }, { 1503 input: "create table a (b1 bool NOT NULL PRIMARY KEY, b2 boolean not null references b (a) on delete restrict, KEY b2_idx(b))", 1504 output: "create table a (\n\tb1 bool not null primary key,\n\tb2 boolean not null references b (a) on delete restrict,\n\tKEY b2_idx (b)\n)", 1505 }, { 1506 input: "create temporary table a (\n\tid bigint\n)", 1507 }, { 1508 input: "CREATE TABLE pkai (id INT PRIMARY KEY AUTO_INCREMENT);", 1509 output: "create table pkai (\n\tid INT auto_increment primary key\n)", 1510 }, { 1511 input: "CREATE TABLE aipk (id INT AUTO_INCREMENT PRIMARY KEY)", 1512 output: "create table aipk (\n\tid INT auto_increment primary key\n)", 1513 }, { 1514 // This test case is added because MySQL supports this behaviour. 1515 // It allows the user to specify null and not null multiple times. 1516 // The last value specified is used. 1517 input: "create table foo (f timestamp null not null , g timestamp not null null)", 1518 output: "create table foo (\n\tf timestamp not null,\n\tg timestamp null\n)", 1519 }, { 1520 // Tests unicode character § 1521 input: "create table invalid_enum_value_name (\n\there_be_enum enum('$§!') default null\n)", 1522 }, { 1523 input: "create table t (id int) partition by hash (id) partitions 3", 1524 output: "create table t (\n\tid int\n)\npartition by hash (id) partitions 3", 1525 }, { 1526 input: "create table t (hired date) partition by linear hash (year(hired)) partitions 4", 1527 output: "create table t (\n\thired date\n)\npartition by linear hash (year(hired)) partitions 4", 1528 }, { 1529 input: "create table t (id int) partition by key (id) partitions 2", 1530 output: "create table t (\n\tid int\n)\npartition by key (id) partitions 2", 1531 }, { 1532 input: "create table t (id int, primary key(id)) partition by key () partitions 2", 1533 output: "create table t (\n\tid int,\n\tprimary key (id)\n)\npartition by key () partitions 2", 1534 }, { 1535 input: "create table t (id int) partition by key algorithm = 1 (id)", 1536 output: "create table t (\n\tid int\n)\npartition by key algorithm = 1 (id)", 1537 }, { 1538 input: "create table t (id int not null) partition by linear key (id) partitions 5", 1539 output: "create table t (\n\tid int not null\n)\npartition by linear key (id) partitions 5", 1540 }, { 1541 input: "create table t (id int) partition by list (id) (partition p0 values in (1, 4, 7))", 1542 output: "create table t (\n\tid int\n)\npartition by list (id)\n(partition p0 values in (1, 4, 7))", 1543 }, { 1544 input: "create table t (renewal date) partition by range columns (renewal) (partition p0 values less than ('2021-08-27'))", 1545 output: "create table t (\n\trenewal date\n)\npartition by range columns (renewal)\n(partition p0 values less than ('2021-08-27'))", 1546 }, { 1547 input: "create table t (pur date) partition by range (year(pur)) subpartition by hash (to_days(pur)) subpartitions 2 (partition p0 values less than (2015), partition p2 values less than (2018))", 1548 output: "create table t (\n\tpur date\n)\npartition by range (year(pur)) subpartition by hash (to_days(pur)) subpartitions 2\n(partition p0 values less than (2015),\n partition p2 values less than (2018))", 1549 }, { 1550 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1551 input: "alter vschema create vindex hash_vdx using `hash`", 1552 ignoreNormalizerTest: true, 1553 }, { 1554 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1555 input: "alter vschema create vindex keyspace.hash_vdx using `hash`", 1556 ignoreNormalizerTest: true, 1557 }, { 1558 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1559 input: "alter vschema create vindex lookup_vdx using lookup with owner=user, table=name_user_idx, from=name, to=user_id", 1560 ignoreNormalizerTest: true, 1561 }, { 1562 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1563 input: "alter vschema create vindex xyz_vdx using xyz with param1=hello, param2='world', param3=123", 1564 ignoreNormalizerTest: true, 1565 }, { 1566 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1567 input: "alter vschema drop vindex hash_vdx", 1568 ignoreNormalizerTest: true, 1569 }, { 1570 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1571 input: "alter vschema drop vindex ks.hash_vdx", 1572 ignoreNormalizerTest: true, 1573 }, { 1574 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1575 input: "alter vschema add table a", 1576 ignoreNormalizerTest: true, 1577 }, { 1578 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1579 input: "alter vschema add table ks.a", 1580 ignoreNormalizerTest: true, 1581 }, { 1582 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1583 input: "alter vschema add sequence a_seq", 1584 ignoreNormalizerTest: true, 1585 }, { 1586 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1587 input: "alter vschema add sequence ks.a_seq", 1588 ignoreNormalizerTest: true, 1589 }, { 1590 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1591 input: "alter vschema on a add auto_increment id using a_seq", 1592 ignoreNormalizerTest: true, 1593 }, { 1594 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1595 input: "alter vschema on ks.a add auto_increment id using a_seq", 1596 ignoreNormalizerTest: true, 1597 }, { 1598 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1599 input: "alter vschema drop table a", 1600 ignoreNormalizerTest: true, 1601 }, { 1602 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1603 input: "alter vschema drop table ks.a", 1604 ignoreNormalizerTest: true, 1605 }, { 1606 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1607 input: "alter vschema on a add vindex `hash` (id)", 1608 ignoreNormalizerTest: true, 1609 }, { 1610 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1611 input: "alter vschema on ks.a add vindex `hash` (id)", 1612 ignoreNormalizerTest: true, 1613 }, { 1614 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1615 input: "alter vschema on a add vindex `hash` (`id`)", 1616 output: "alter vschema on a add vindex `hash` (id)", 1617 ignoreNormalizerTest: true, 1618 }, { 1619 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1620 input: "alter vschema on `ks`.a add vindex `hash` (`id`)", 1621 output: "alter vschema on ks.a add vindex `hash` (id)", 1622 ignoreNormalizerTest: true, 1623 }, { 1624 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1625 input: "alter vschema on a add vindex hash (id) using `hash`", 1626 output: "alter vschema on a add vindex `hash` (id) using `hash`", 1627 ignoreNormalizerTest: true, 1628 }, { 1629 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1630 input: "alter vschema on a add vindex `add` (`add`)", 1631 ignoreNormalizerTest: true, 1632 }, { 1633 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1634 input: "alter vschema on a add vindex `hash` (id) using `hash`", 1635 ignoreNormalizerTest: true, 1636 }, { 1637 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1638 input: "alter vschema on a add vindex hash (id) using `hash`", 1639 output: "alter vschema on a add vindex `hash` (id) using `hash`", 1640 ignoreNormalizerTest: true, 1641 }, { 1642 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1643 input: "alter vschema on user add vindex name_lookup_vdx (name) using lookup_hash with owner=user, table=name_user_idx, from=name, to=user_id", 1644 output: "alter vschema on `user` add vindex name_lookup_vdx (`name`) using lookup_hash with owner=user, table=name_user_idx, from=name, to=user_id", 1645 ignoreNormalizerTest: true, 1646 }, { 1647 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1648 input: "alter vschema on user2 add vindex name_lastname_lookup_vdx (name,lastname) using lookup with owner=`user`, table=`name_lastname_keyspace_id_map`, from=`name,lastname`, to=`keyspace_id`", 1649 output: "alter vschema on user2 add vindex name_lastname_lookup_vdx (`name`, lastname) using lookup with owner=user, table=name_lastname_keyspace_id_map, from=name,lastname, to=keyspace_id", 1650 ignoreNormalizerTest: true, 1651 }, { 1652 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1653 input: "alter vschema on a drop vindex `hash`", 1654 ignoreNormalizerTest: true, 1655 }, { 1656 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1657 input: "alter vschema on ks.a drop vindex `hash`", 1658 ignoreNormalizerTest: true, 1659 }, { 1660 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1661 input: "alter vschema on a drop vindex `hash`", 1662 output: "alter vschema on a drop vindex `hash`", 1663 ignoreNormalizerTest: true, 1664 }, { 1665 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1666 input: "alter vschema on a drop vindex hash", 1667 output: "alter vschema on a drop vindex `hash`", 1668 ignoreNormalizerTest: true, 1669 }, { 1670 // Alter Vschema does not reach the vttablets, so we don't need to run the normalizer test 1671 input: "alter vschema on a drop vindex `add`", 1672 output: "alter vschema on a drop vindex `add`", 1673 ignoreNormalizerTest: true, 1674 }, { 1675 input: "create index a on b (col1)", 1676 output: "alter table b add index a (col1)", 1677 }, { 1678 input: "create unique index a on b (col1)", 1679 output: "alter table b add unique index a (col1)", 1680 }, { 1681 input: "create unique index a using foo on b (col1 desc)", 1682 output: "alter table b add unique index a (col1 desc) using foo", 1683 }, { 1684 input: "create fulltext index a on b (col1) with parser a", 1685 output: "alter table b add fulltext index a (col1) with parser a", 1686 }, { 1687 input: "create spatial index a on b (col1)", 1688 output: "alter table b add spatial index a (col1)", 1689 }, { 1690 input: "create fulltext index a on b (col1) key_block_size=12 with parser a comment 'string' algorithm inplace lock none", 1691 output: "alter table b add fulltext index a (col1) key_block_size 12 with parser a comment 'string', algorithm = inplace, lock none", 1692 }, { 1693 input: "create index a on b ((col1 + col2), (col1*col2))", 1694 output: "alter table b add index a ((col1 + col2), (col1 * col2))", 1695 }, { 1696 input: "create fulltext index b using btree on A (col1 desc, col2) algorithm = inplace lock = none", 1697 output: "alter table A add fulltext index b (col1 desc, col2) using btree, algorithm = inplace, lock none", 1698 }, { 1699 input: "create algorithm = merge sql security definer view a as select * from e", 1700 }, { 1701 input: "create view ks.a as select * from e", 1702 }, { 1703 input: "create algorithm = merge sql security definer view a (b,c,d) as select * from e", 1704 output: "create algorithm = merge sql security definer view a(b, c, d) as select * from e", 1705 }, { 1706 input: "create algorithm = merge sql security definer view a (b,c,d) as select * from e with cascaded check option", 1707 output: "create algorithm = merge sql security definer view a(b, c, d) as select * from e with cascaded check option", 1708 }, { 1709 input: "create algorithm = temptable definer = a@b.c.d view a(b,c,d) as select * from e with local check option", 1710 output: "create algorithm = temptable definer = a@`b.c.d` view a(b, c, d) as select * from e with local check option", 1711 }, { 1712 input: "create algorithm = temptable definer = a@b view a(b,c,d) as select * from e with local check option", 1713 output: "create algorithm = temptable definer = a@b view a(b, c, d) as select * from e with local check option", 1714 }, { 1715 input: "create algorithm = temptable definer = 'create'@b view a(b,c,d) as select * from e with local check option", 1716 output: "create algorithm = temptable definer = 'create'@b view a(b, c, d) as select * from e with local check option", 1717 }, { 1718 input: "create algorithm = temptable definer = a@'create' view a(b,c,d) as select * from e with local check option", 1719 output: "create algorithm = temptable definer = a@'create' view a(b, c, d) as select * from e with local check option", 1720 }, { 1721 input: "create algorithm = temptable definer = 'a' view a(b,c,d) as select * from e with local check option", 1722 output: "create algorithm = temptable definer = 'a' view a(b, c, d) as select * from e with local check option", 1723 }, { 1724 input: "create algorithm = temptable definer = 'select'@'create' view a(b,c,d) as select * from e with local check option", 1725 output: "create algorithm = temptable definer = 'select'@'create' view a(b, c, d) as select * from e with local check option", 1726 }, { 1727 input: "create algorithm = temptable definer = `create`@b view a(b,c,d) as select * from e with local check option", 1728 output: "create algorithm = temptable definer = `create`@b view a(b, c, d) as select * from e with local check option", 1729 }, { 1730 input: "create algorithm = temptable definer = a@`create` view a(b,c,d) as select * from e with local check option", 1731 output: "create algorithm = temptable definer = a@`create` view a(b, c, d) as select * from e with local check option", 1732 }, { 1733 input: "create algorithm = temptable definer = `select`@`create` view a(b,c,d) as select * from e with local check option", 1734 output: "create algorithm = temptable definer = `select`@`create` view a(b, c, d) as select * from e with local check option", 1735 }, { 1736 input: "create or replace algorithm = temptable definer = a@b.c.d sql security definer view a(b,c,d) as select * from e with local check option", 1737 output: "create or replace algorithm = temptable definer = a@`b.c.d` sql security definer view a(b, c, d) as select * from e with local check option", 1738 }, { 1739 input: "create algorithm = undefined definer = `msandbox`@`localhost` sql security definer view `v3` as select `t`.`id` as `id` from `t`", 1740 output: "create algorithm = undefined definer = msandbox@localhost sql security definer view v3 as select t.id as id from t", 1741 }, { 1742 input: "create definer = 'sa'@b.c.d view a(b,c,d) as select * from e", 1743 output: "create definer = 'sa'@`b.c.d` view a(b, c, d) as select * from e", 1744 }, { 1745 input: "create /*vt+ strategy=online */ or replace view v as select a, b, c from t", 1746 }, { 1747 input: "alter view a as select * from t", 1748 }, { 1749 input: "alter /*vt+ strategy=online */ view a as select * from t", 1750 }, { 1751 input: "alter algorithm = merge definer = m@`172.0.1.01` sql security definer view a as select * from t with local check option", 1752 }, { 1753 input: "rename table a to b", 1754 output: "rename table a to b", 1755 }, { 1756 input: "rename table x.a to b, b to c", 1757 output: "rename table x.a to b, b to c", 1758 }, { 1759 input: "drop view a,B,c", 1760 output: "drop view a, b, c", 1761 }, { 1762 input: "drop /*vt+ strategy=online */ view if exists v", 1763 }, { 1764 input: "drop table a", 1765 }, { 1766 input: "drop /*vt+ strategy=online */ table if exists a", 1767 }, { 1768 input: "drop /*vt+ strategy=online */ table a", 1769 }, { 1770 input: "drop table a, b", 1771 output: "drop table a, b", 1772 }, { 1773 input: "drop table if exists a,b restrict", 1774 output: "drop table if exists a, b", 1775 }, { 1776 input: "drop temporary table if exists a, b", 1777 }, { 1778 input: "drop view if exists a cascade", 1779 output: "drop view if exists a", 1780 }, { 1781 input: "drop index b on a lock = none algorithm default", 1782 output: "alter table a drop key b, lock none, algorithm = default", 1783 }, { 1784 input: "drop index `PRIMARY` on a lock none", 1785 output: "alter table a drop primary key, lock none", 1786 }, { 1787 input: "analyze table a", 1788 output: "otherread", 1789 }, { 1790 input: "flush tables", 1791 }, { 1792 input: "flush tables with read lock", 1793 }, { 1794 input: "flush tables a, c.v, b", 1795 }, { 1796 input: "flush local tables a, c.v, b with read lock", 1797 }, { 1798 input: "flush tables a, c.v, b for export", 1799 }, { 1800 input: "flush local binary logs, engine logs, error logs, general logs, hosts, logs, privileges, optimizer_costs", 1801 }, { 1802 input: "flush no_write_to_binlog slow logs, status, user_resources, relay logs, relay logs for channel s", 1803 output: "flush local slow logs, status, user_resources, relay logs, relay logs for channel s", 1804 }, { 1805 input: "show binary logs", 1806 output: "show binary logs", 1807 }, { 1808 input: "show binlog events", 1809 output: "show binlog", 1810 }, { 1811 input: "show character set", 1812 output: "show charset", 1813 }, { 1814 input: "show character set like '%foo'", 1815 output: "show charset like '%foo'", 1816 }, { 1817 input: "show charset", 1818 output: "show charset", 1819 }, { 1820 input: "show charset like '%foo'", 1821 output: "show charset like '%foo'", 1822 }, { 1823 input: "show charset where 'charset' = 'utf8'", 1824 output: "show charset where 'charset' = 'utf8'", 1825 }, { 1826 input: "show charset where 'charset' = '%foo'", 1827 output: "show charset where 'charset' = '%foo'", 1828 }, { 1829 input: "show collation", 1830 output: "show collation", 1831 }, { 1832 input: "show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'", 1833 output: "show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'", 1834 }, { 1835 input: "show create database d", 1836 }, { 1837 input: "show create event e", 1838 }, { 1839 input: "show create function f", 1840 }, { 1841 input: "show create procedure p", 1842 }, { 1843 input: "show create table t", 1844 }, { 1845 input: "show create trigger t", 1846 }, { 1847 input: "show create user u", 1848 output: "show create user", 1849 }, { 1850 input: "show create view v", 1851 }, { 1852 input: "show databases", 1853 output: "show databases", 1854 }, { 1855 input: "show databases like '%'", 1856 output: "show databases like '%'", 1857 }, { 1858 input: "show schemas", 1859 output: "show databases", 1860 }, { 1861 input: "show schemas like '%'", 1862 output: "show databases like '%'", 1863 }, { 1864 input: "show engine INNODB", 1865 output: "show engine", 1866 }, { 1867 input: "show engines", 1868 }, { 1869 input: "show storage engines", 1870 output: "show storage", 1871 }, { 1872 input: "show errors", 1873 }, { 1874 input: "show events", 1875 }, { 1876 input: "show function code func", 1877 }, { 1878 input: "show function status", 1879 }, { 1880 input: "show grants for 'root@localhost'", 1881 output: "show grants", 1882 }, { 1883 input: "show index from t", 1884 output: "show indexes from t", 1885 }, { 1886 input: "show indexes from t", 1887 }, { 1888 input: "show keys from t", 1889 output: "show indexes from t", 1890 }, { 1891 input: "show master status", 1892 output: "show master", 1893 }, { 1894 input: "show open tables", 1895 }, { 1896 input: "show plugins", 1897 output: "show plugins", 1898 }, { 1899 input: "show privileges", 1900 output: "show privileges", 1901 }, { 1902 input: "show procedure code p", 1903 }, { 1904 input: "show procedure status", 1905 }, { 1906 input: "show processlist", 1907 output: "show processlist", 1908 }, { 1909 input: "show full processlist", 1910 output: "show processlist", 1911 }, { 1912 input: "show profile cpu for query 1", 1913 output: "show profile", 1914 }, { 1915 input: "show profiles", 1916 output: "show profiles", 1917 }, { 1918 input: "show relaylog events", 1919 output: "show relaylog", 1920 }, { 1921 input: "show slave hosts", 1922 output: "show slave", 1923 }, { 1924 input: "show slave status", 1925 output: "show slave", 1926 }, { 1927 input: "show status", 1928 output: "show status", 1929 }, { 1930 input: "show global status", 1931 output: "show global status", 1932 }, { 1933 input: "show session status", 1934 output: "show status", 1935 }, { 1936 input: "show table status", 1937 }, { 1938 input: "show table status from dbname", 1939 }, { 1940 input: "show table status in dbname", 1941 output: "show table status from dbname", 1942 }, { 1943 input: "show table status in dbname LIKE '%' ", 1944 output: "show table status from dbname like '%'", 1945 }, { 1946 input: "show table status from dbname Where col=42 ", 1947 output: "show table status from dbname where col = 42", 1948 }, { 1949 input: "show tables", 1950 }, { 1951 input: "show tables like '%keyspace%'", 1952 }, { 1953 input: "show tables where 1 = 0", 1954 }, { 1955 input: "show tables from a", 1956 }, { 1957 input: "show tables from a where 1 = 0", 1958 }, { 1959 input: "show tables from a like '%keyspace%'", 1960 }, { 1961 input: "show full tables", 1962 }, { 1963 input: "show full tables from a", 1964 }, { 1965 input: "show full tables in a", 1966 output: "show full tables from a", 1967 }, { 1968 input: "show full tables from a like '%keyspace%'", 1969 }, { 1970 input: "show full tables from a where 1 = 0", 1971 }, { 1972 input: "show full tables like '%keyspace%'", 1973 }, { 1974 input: "show full tables where 1 = 0", 1975 }, { 1976 input: "show full columns in a in b like '%'", 1977 output: "show full columns from a from b like '%'", 1978 }, { 1979 input: "show full columns from messages from test_keyspace like '%'", 1980 }, { 1981 input: "show full fields from a like '%'", 1982 output: "show full columns from a like '%'", 1983 }, { 1984 input: "show fields from a where 1 = 1", 1985 output: "show columns from a where 1 = 1", 1986 }, { 1987 input: "show triggers", 1988 output: "show triggers", 1989 }, { 1990 input: "show variables", 1991 output: "show variables", 1992 }, { 1993 input: "show global variables", 1994 output: "show global variables", 1995 }, { 1996 input: "show session variables", 1997 output: "show variables", 1998 }, { 1999 input: "show global vgtid_executed", 2000 }, { 2001 input: "show global vgtid_executed from ks", 2002 }, { 2003 input: "show global gtid_executed", 2004 }, { 2005 input: "show global gtid_executed from ks", 2006 }, { 2007 input: "show vitess_keyspaces", 2008 output: "show keyspaces", 2009 }, { 2010 input: "show vitess_keyspaces like '%'", 2011 output: "show keyspaces like '%'", 2012 }, { 2013 input: "show vitess_metadata variables", 2014 }, { 2015 input: "show vitess_replication_status", 2016 }, { 2017 input: "show vitess_replication_status like '%'", 2018 }, { 2019 input: "show vitess_shards", 2020 }, { 2021 input: "show vitess_shards like '%'", 2022 }, { 2023 input: "show vitess_tablets", 2024 }, { 2025 input: "show vitess_tablets like '%'", 2026 }, { 2027 input: "show vitess_tablets where hostname = 'some-tablet'", 2028 }, { 2029 input: "show vitess_targets", 2030 }, { 2031 input: "show vschema tables", 2032 }, { 2033 input: "show vschema vindexes", 2034 }, { 2035 input: "show vschema vindexes from t", 2036 }, { 2037 input: "show vschema vindexes on t", 2038 output: "show vschema vindexes from t", 2039 }, { 2040 input: "show vitess_migrations", 2041 }, { 2042 input: "show vitess_migrations from ks", 2043 }, { 2044 input: "show vitess_migrations from ks where col = 42", 2045 }, { 2046 input: `show vitess_migrations from ks like '%pattern'`, 2047 }, { 2048 input: "show vitess_migrations like '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", 2049 }, { 2050 input: "show vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' logs", 2051 }, { 2052 input: "revert vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", 2053 }, { 2054 input: "revert /*vt+ uuid=123 */ vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", 2055 }, { 2056 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' retry", 2057 }, { 2058 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' cleanup", 2059 }, { 2060 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' launch", 2061 }, { 2062 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' launch vitess_shards '-40'", 2063 }, { 2064 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' launch vitess_shards '-40,40-80'", 2065 }, { 2066 input: "alter vitess_migration launch all", 2067 }, { 2068 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' complete", 2069 }, { 2070 input: "alter vitess_migration complete all", 2071 }, { 2072 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' cancel", 2073 }, { 2074 input: "alter vitess_migration cancel all", 2075 }, { 2076 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' throttle", 2077 }, { 2078 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' throttle expire '1h'", 2079 }, { 2080 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' throttle ratio 0.7", 2081 }, { 2082 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' throttle expire '1h' ratio 0.7", 2083 }, { 2084 input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' unthrottle", 2085 }, { 2086 input: "alter vitess_migration throttle all", 2087 }, { 2088 input: "alter vitess_migration unthrottle all", 2089 }, { 2090 input: "alter vitess_migration throttle all expire '1h'", 2091 }, { 2092 input: "alter vitess_migration throttle all ratio 0.7", 2093 }, { 2094 input: "alter vitess_migration throttle all expire '1h' ratio 0.7", 2095 }, { 2096 input: "show vitess_throttled_apps", 2097 }, { 2098 input: "show vitess_throttler status", 2099 }, { 2100 input: "show warnings", 2101 }, { 2102 input: "select warnings from t", 2103 output: "select `warnings` from t", 2104 }, { 2105 input: "show foobar", 2106 output: "show foobar", 2107 }, { 2108 input: "show foobar like select * from table where syntax is 'ignored'", 2109 output: "show foobar", 2110 }, { 2111 input: "use db", 2112 output: "use db", 2113 }, { 2114 input: "use duplicate", 2115 output: "use `duplicate`", 2116 }, { 2117 input: "use `ks:-80@master`", 2118 output: "use `ks:-80@master`", 2119 }, { 2120 input: "use `ks:-80@primary`", 2121 output: "use `ks:-80@primary`", 2122 }, { 2123 input: "use @replica", 2124 output: "use `@replica`", 2125 }, { 2126 input: "use ks@replica", 2127 output: "use `ks@replica`", 2128 }, { 2129 input: "describe select * from t", 2130 output: "explain select * from t", 2131 }, { 2132 input: "describe /*vt+ execute_dml_queries */ select * from t", 2133 output: "explain /*vt+ execute_dml_queries */ select * from t", 2134 }, { 2135 input: "desc select * from t", 2136 output: "explain select * from t", 2137 }, { 2138 input: "desc foobar", 2139 output: "explain foobar", 2140 }, { 2141 input: "explain t1", 2142 }, { 2143 input: "explain t1 col", 2144 }, { 2145 input: "explain t1 '%col%'", 2146 }, { 2147 input: "explain select * from t", 2148 }, { 2149 input: "explain format = traditional select * from t", 2150 }, { 2151 input: "vexplain queries select * from t", 2152 }, { 2153 input: "vexplain all select * from t", 2154 }, { 2155 input: "vexplain plan select * from t", 2156 }, { 2157 input: "vexplain select * from t", 2158 output: "vexplain plan select * from t", 2159 }, { 2160 input: "explain analyze select * from t", 2161 }, { 2162 input: "explain format = tree select * from t", 2163 }, { 2164 input: "explain format = json select * from t", 2165 }, { 2166 input: "explain format = vtexplain select * from t", 2167 }, { 2168 input: "explain format = vitess select * from t", 2169 }, { 2170 input: "describe format = vitess select * from t", 2171 output: "explain format = vitess select * from t", 2172 }, { 2173 input: "describe format = vtexplain select * from t", 2174 output: "explain format = vtexplain select * from t", 2175 }, { 2176 input: "explain delete from t", 2177 }, { 2178 input: "explain insert into t(col1, col2) values (1, 2)", 2179 }, { 2180 input: "explain update t set col = 2", 2181 }, { 2182 input: "truncate table foo", 2183 output: "truncate table foo", 2184 }, { 2185 input: "truncate foo", 2186 output: "truncate table foo", 2187 }, { 2188 input: "repair foo", 2189 output: "otheradmin", 2190 }, { 2191 input: "optimize foo", 2192 output: "otheradmin", 2193 }, { 2194 input: "lock tables foo read", 2195 output: "lock tables foo read", 2196 }, { 2197 input: "lock tables foo write", 2198 output: "lock tables foo write", 2199 }, { 2200 input: "lock tables foo read local", 2201 output: "lock tables foo read local", 2202 }, { 2203 input: "lock tables foo low_priority write", 2204 output: "lock tables foo low_priority write", 2205 }, { 2206 input: "unlock tables", 2207 output: "unlock tables", 2208 }, { 2209 input: "select /* EQ true */ 1 from t where a = true", 2210 }, { 2211 input: "select /* EQ false */ 1 from t where a = false", 2212 }, { 2213 input: "select /* NE true */ 1 from t where a != true", 2214 }, { 2215 input: "select /* NE false */ 1 from t where a != false", 2216 }, { 2217 input: "select /* LT true */ 1 from t where a < true", 2218 }, { 2219 input: "select /* LT false */ 1 from t where a < false", 2220 }, { 2221 input: "select /* GT true */ 1 from t where a > true", 2222 }, { 2223 input: "select /* GT false */ 1 from t where a > false", 2224 }, { 2225 input: "select /* LE true */ 1 from t where a <= true", 2226 }, { 2227 input: "select /* LE false */ 1 from t where a <= false", 2228 }, { 2229 input: "select /* GE true */ 1 from t where a >= true", 2230 }, { 2231 input: "select /* GE false */ 1 from t where a >= false", 2232 }, { 2233 input: "select * from t order by a collate utf8_general_ci", 2234 output: "select * from t order by a collate utf8_general_ci asc", 2235 }, { 2236 input: "select k collate latin1_german2_ci as k1 from t1 order by k1 asc", 2237 }, { 2238 input: "select * from t group by a collate utf8_general_ci", 2239 }, { 2240 input: "select MAX(k collate latin1_german2_ci) from t1", 2241 output: "select max(k collate latin1_german2_ci) from t1", 2242 }, { 2243 input: "select distinct k collate latin1_german2_ci from t1", 2244 }, { 2245 input: "select * from t1 where 'Müller' collate latin1_german2_ci = k", 2246 }, { 2247 input: "select * from t1 where k like 'Müller' collate latin1_german2_ci", 2248 }, { 2249 input: "select k from t1 group by k having k = 'Müller' collate latin1_german2_ci", 2250 }, { 2251 input: "select k from t1 join t2 order by a collate latin1_german2_ci asc, b collate latin1_german2_ci asc", 2252 }, { 2253 input: "select k collate 'latin1_german2_ci' as k1 from t1 order by k1 asc", 2254 output: "select k collate latin1_german2_ci as k1 from t1 order by k1 asc", 2255 }, { 2256 input: "select /* drop trailing semicolon */ 1 from dual;", 2257 output: "select /* drop trailing semicolon */ 1 from dual", 2258 }, { 2259 input: "select /* cache directive */ sql_no_cache 'foo' from t", 2260 }, { 2261 input: "select distinct sql_no_cache 'foo' from t", 2262 }, { 2263 input: "select sql_no_cache distinct 'foo' from t", 2264 output: "select distinct sql_no_cache 'foo' from t", 2265 }, { 2266 input: "select sql_no_cache straight_join distinct 'foo' from t", 2267 output: "select distinct sql_no_cache straight_join 'foo' from t", 2268 }, { 2269 input: "select straight_join distinct sql_no_cache 'foo' from t", 2270 output: "select distinct sql_no_cache straight_join 'foo' from t", 2271 }, { 2272 input: "select sql_calc_found_rows 'foo' from t", 2273 output: "select sql_calc_found_rows 'foo' from t", 2274 }, { 2275 input: "select binary 'a' = 'A' from t", 2276 output: "select convert('a', binary) = 'A' from t", 2277 }, { 2278 input: "select 1 from t where foo = _binary 'bar'", 2279 }, { 2280 input: "select 1 from t where foo = _utf8 'bar' and bar = _latin1 'sjösjuk'", 2281 }, { 2282 input: "select 1 from t where foo = _binary'bar'", 2283 output: "select 1 from t where foo = _binary 'bar'", 2284 }, { 2285 input: "select 1 from t where foo = _utf8mb4 'bar'", 2286 }, { 2287 input: "select 1 from t where foo = _utf8mb4'bar'", 2288 output: "select 1 from t where foo = _utf8mb4 'bar'", 2289 }, { 2290 input: "select 1 from t where foo = _utf8mb3 'bar'", 2291 output: "select 1 from t where foo = _utf8 'bar'", 2292 }, { 2293 input: "select 1 from t where foo = _utf8mb3'bar'", 2294 output: "select 1 from t where foo = _utf8 'bar'", 2295 }, { 2296 input: "select match(a) against ('foo') from t", 2297 }, { 2298 input: "select match(a1, a2) against ('foo' in natural language mode with query expansion) from t", 2299 }, { 2300 input: "select database()", 2301 output: "select database() from dual", 2302 }, { 2303 input: "select schema()", 2304 output: "select schema() from dual", 2305 }, { 2306 input: "select title from video as v where match(v.title, v.tag) against ('DEMO' in boolean mode)", 2307 }, { 2308 input: "SELECT id FROM blog_posts USE INDEX (PRIMARY) WHERE id = 10", 2309 output: "select id from blog_posts use index (`PRIMARY`) where id = 10", 2310 }, { 2311 input: "select name, group_concat(score) from t group by name", 2312 output: "select `name`, group_concat(score) from t group by `name`", 2313 }, { 2314 input: "select name, group_concat(distinct id, score order by id desc separator ':') from t group by name", 2315 output: "select `name`, group_concat(distinct id, score order by id desc separator ':') from t group by `name`", 2316 }, { 2317 input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by name", 2318 output: "select `name`, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by `name`", 2319 }, { 2320 input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by name", 2321 output: "select `name`, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by `name`", 2322 }, { 2323 input: "select * from t partition (p0)", 2324 }, { 2325 input: "select * from t partition (p0, p1)", 2326 }, { 2327 input: "select e.id, s.city from employees as e join stores partition (p1) as s on e.store_id = s.id", 2328 }, { 2329 input: "select truncate(120.3333, 2) from dual", 2330 }, { 2331 input: "update t partition (p0) set a = 1", 2332 }, { 2333 input: "insert into t partition (p0) values (1, 'asdf')", 2334 }, { 2335 input: "insert into t1 select * from t2 partition (p0)", 2336 }, { 2337 input: "replace into t partition (p0) values (1, 'asdf')", 2338 }, { 2339 input: "delete from t partition (p0) where a = 1", 2340 }, { 2341 input: "stream * from t", 2342 }, { 2343 input: "stream /* comment */ * from t", 2344 }, { 2345 input: "vstream * from t", 2346 }, { 2347 input: "begin", 2348 }, { 2349 input: "begin;", 2350 output: "begin", 2351 }, { 2352 input: "start transaction", 2353 output: "begin", 2354 }, { 2355 input: "start transaction with consistent snapshot", 2356 }, { 2357 input: "start transaction read write", 2358 }, { 2359 input: "start transaction read only", 2360 }, { 2361 input: "start transaction read only, with consistent snapshot", 2362 }, { 2363 input: "commit", 2364 }, { 2365 input: "rollback", 2366 }, { 2367 input: "create database /* simple */ test_db", 2368 }, { 2369 input: "create schema test_db", 2370 output: "create database test_db", 2371 }, { 2372 input: "create database /* simple */ if not exists test_db", 2373 }, { 2374 input: "create schema if not exists test_db", 2375 output: "create database if not exists test_db", 2376 }, { 2377 input: "create database test_db default collate 'utf8mb4_general_ci' collate utf8mb4_general_ci", 2378 }, { 2379 input: "create database test_db character set geostd8", 2380 }, { 2381 input: "alter table corder zzzz zzzz zzzz", 2382 output: "alter table corder", 2383 partialDDL: true, 2384 }, { 2385 input: "create database test_db character set * unparsable", 2386 output: "create database test_db", 2387 partialDDL: true, 2388 }, { 2389 input: "CREATE DATABASE IF NOT EXISTS `mysql` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ENCRYPTION='N';", 2390 output: "create database if not exists mysql default character set utf8mb4 collate utf8mb4_0900_ai_ci encryption 'N'", 2391 }, { 2392 input: "drop /* simple */ database test_db", 2393 }, { 2394 input: "drop schema test_db", 2395 output: "drop database test_db", 2396 }, { 2397 input: "drop /* simple */ database if exists test_db", 2398 }, { 2399 input: "delete a.*, b.* from tbl_a a, tbl_b b where a.id = b.id and b.name = 'test'", 2400 output: "delete a, b from tbl_a as a, tbl_b as b where a.id = b.id and b.`name` = 'test'", 2401 }, { 2402 input: "select distinctrow a.* from (select (1) from dual union all select 1 from dual) a", 2403 output: "select distinct a.* from (select 1 from dual union all select 1 from dual) as a", 2404 }, { 2405 input: "select `weird function name`() from t", 2406 }, { 2407 input: "select all* from t", 2408 output: "select * from t", 2409 }, { 2410 input: "select distinct* from t", 2411 output: "select distinct * from t", 2412 }, { 2413 input: "select status() from t", // should not escape function names that are keywords 2414 }, { 2415 input: "select * from `weird table name`", 2416 }, { 2417 input: "SHOW FULL TABLES FROM `jiradb` LIKE 'AO_E8B6CC_ISSUE_MAPPING'", 2418 output: "show full tables from jiradb like 'AO_E8B6CC_ISSUE_MAPPING'", 2419 }, { 2420 input: "SHOW FULL COLUMNS FROM AO_E8B6CC_ISSUE_MAPPING FROM jiradb LIKE '%'", 2421 output: "show full columns from AO_E8B6CC_ISSUE_MAPPING from jiradb like '%'", 2422 }, { 2423 input: "SHOW KEYS FROM `AO_E8B6CC_ISSUE_MAPPING` FROM `jiradb`", 2424 output: "show indexes from AO_E8B6CC_ISSUE_MAPPING from jiradb", 2425 }, { 2426 input: "SHOW CREATE TABLE `jiradb`.`AO_E8B6CC_ISSUE_MAPPING`", 2427 output: "show create table jiradb.AO_E8B6CC_ISSUE_MAPPING", 2428 }, { 2429 input: "SHOW INDEX FROM `AO_E8B6CC_ISSUE_MAPPING` FROM `jiradb`", 2430 output: "show indexes from AO_E8B6CC_ISSUE_MAPPING from jiradb", 2431 }, { 2432 input: "SHOW FULL TABLES FROM `jiradb` LIKE '%'", 2433 output: "show full tables from jiradb like '%'", 2434 }, { 2435 input: "SHOW EXTENDED INDEX FROM `AO_E8B6CC_PROJECT_MAPPING` FROM `jiradb`", 2436 output: "show indexes from AO_E8B6CC_PROJECT_MAPPING from jiradb", 2437 }, { 2438 input: "SHOW EXTENDED KEYS FROM `AO_E8B6CC_ISSUE_MAPPING` FROM `jiradb`", 2439 output: "show indexes from AO_E8B6CC_ISSUE_MAPPING from jiradb", 2440 }, { 2441 input: "SHOW CREATE TABLE `jiradb`.`AO_E8B6CC_ISSUE_MAPPING`", 2442 output: "show create table jiradb.AO_E8B6CC_ISSUE_MAPPING", 2443 }, { 2444 input: "create table t1 ( check (c1 <> c2), c1 int check (c1 > 10), c2 int constraint c2_positive check (c2 > 0), c3 int check (c3 < 100), constraint c1_nonzero check (c1 <> 0), check (c1 > c3))", 2445 output: "create table t1 (\n" + 2446 "\tc1 int,\n" + 2447 "\tc2 int,\n" + 2448 "\tc3 int,\n" + 2449 "\tcheck (c1 != c2),\n" + 2450 "\tcheck (c1 > 10),\n" + 2451 "\tconstraint c2_positive check (c2 > 0),\n" + 2452 "\tcheck (c3 < 100),\n" + 2453 "\tconstraint c1_nonzero check (c1 != 0),\n" + 2454 "\tcheck (c1 > c3)\n)", 2455 }, { 2456 input: "SHOW INDEXES FROM `AO_E8B6CC_ISSUE_MAPPING` FROM `jiradb`", 2457 output: "show indexes from AO_E8B6CC_ISSUE_MAPPING from jiradb", 2458 }, { 2459 input: "SHOW FULL TABLES FROM `jiradb` LIKE '%'", 2460 output: "show full tables from jiradb like '%'", 2461 }, { 2462 input: "SHOW EXTENDED INDEXES FROM `AO_E8B6CC_PROJECT_MAPPING` FROM `jiradb`", 2463 output: "show indexes from AO_E8B6CC_PROJECT_MAPPING from jiradb", 2464 }, { 2465 input: "SHOW EXTENDED INDEXES IN `AO_E8B6CC_PROJECT_MAPPING` IN `jiradb`", 2466 output: "show indexes from AO_E8B6CC_PROJECT_MAPPING from jiradb", 2467 }, { 2468 input: "do 1", 2469 output: "otheradmin", 2470 }, { 2471 input: "do funcCall(), 2 = 1, 3 + 1", 2472 output: "otheradmin", 2473 }, { 2474 input: "savepoint a", 2475 }, { 2476 input: "savepoint `@@@;a`", 2477 }, { 2478 input: "rollback to a", 2479 }, { 2480 input: "rollback to `@@@;a`", 2481 }, { 2482 input: "rollback work to a", 2483 output: "rollback to a", 2484 }, { 2485 input: "rollback to savepoint a", 2486 output: "rollback to a", 2487 }, { 2488 input: "rollback work to savepoint a", 2489 output: "rollback to a", 2490 }, { 2491 input: "release savepoint a", 2492 }, { 2493 input: "release savepoint `@@@;a`", 2494 }, { 2495 input: "call proc()", 2496 }, { 2497 input: "call qualified.proc()", 2498 }, { 2499 input: "call proc(1, 'foo')", 2500 }, { 2501 input: "call proc(@param)", 2502 }, { 2503 input: "PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'", 2504 output: "prepare stmt1 from 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'", 2505 }, { 2506 input: "PREPARE stmt2 FROM @s", 2507 output: "prepare stmt2 from @s", 2508 }, { 2509 input: "PREPARE /* comment */ stmt2 FROM @s", 2510 output: "prepare /* comment */ stmt2 from @s", 2511 }, { 2512 input: "EXECUTE stmt1", 2513 output: "execute stmt1", 2514 }, { 2515 input: "EXECUTE /* comment */ stmt1", 2516 output: "execute /* comment */ stmt1", 2517 }, { 2518 input: "EXECUTE stmt1 USING @a", 2519 output: "execute stmt1 using @a", 2520 }, { 2521 input: "EXECUTE stmt1 USING @a, @b", 2522 output: "execute stmt1 using @a, @b", 2523 }, { 2524 input: "DEALLOCATE PREPARE stmt1", 2525 output: "deallocate prepare stmt1", 2526 }, { 2527 input: "DROP PREPARE stmt1", 2528 output: "drop prepare stmt1", 2529 }, { 2530 input: "DROP /* comment */ PREPARE stmt1", 2531 output: "drop /* comment */ prepare stmt1", 2532 }, { 2533 input: `SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}')`, 2534 output: `select json_pretty('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, 2535 }, { 2536 input: `SELECT JSON_PRETTY(N'{"a":"10","b":"15","x":"25"}')`, 2537 output: `select json_pretty(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, 2538 /*We need to ignore this test because, after the normalizer, we change the produced NChar 2539 string into an introducer expression, so the vttablet will never see a NChar string */ 2540 ignoreNormalizerTest: true, 2541 }, { 2542 input: "SELECT jcol, JSON_PRETTY(jcol) from jtable", 2543 output: "select jcol, json_pretty(jcol) from jtable", 2544 }, { 2545 input: "SELECT JSON_PRETTY(@j)", 2546 output: "select json_pretty(@j) from dual", 2547 }, { 2548 input: "SELECT jcol, JSON_STORAGE_SIZE(jcol) AS Size FROM jtable", 2549 output: "select jcol, json_storage_size(jcol) as Size from jtable", 2550 }, { 2551 input: `SELECT jcol, JSON_STORAGE_SIZE(N'{"a":"10","b":"15","x":"25"}') AS Size FROM jtable`, 2552 output: `select jcol, json_storage_size(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') as Size from jtable`, 2553 /*We need to ignore this test because, after the normalizer, we change the produced NChar 2554 string into an introducer expression, so the vttablet will never see a NChar string */ 2555 ignoreNormalizerTest: true, 2556 }, { 2557 input: `SELECT JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A, JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B, JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D`, 2558 output: `select json_storage_size('[100, \"sakila\", [1, 3, 5], 425.05]') as A, json_storage_size('{\"a\": 1000, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') as B, json_storage_size('{\"a\": 1000, \"b\": \"wxyz\", \"c\": \"[1, 3, 5, 7]\"}') as C, json_storage_size('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') as D from dual`, 2559 }, { 2560 input: "SELECT JSON_STORAGE_SIZE(@j)", 2561 output: "select json_storage_size(@j) from dual", 2562 }, { 2563 input: "SELECT JSON_STORAGE_FREE(jcol) FROM jtable", 2564 output: "select json_storage_free(jcol) from jtable", 2565 }, { 2566 input: `SELECT JSON_STORAGE_FREE('{"a":"10","b":"15","x":"25"}')`, 2567 output: `select json_storage_free('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, 2568 }, { 2569 input: `SELECT JSON_STORAGE_FREE(N'{"a":"10","b":"15","x":"25"}')`, 2570 output: `select json_storage_free(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, 2571 /*We need to ignore this test because, after the normalizer, we change the produced NChar 2572 string into an introducer expression, so the vttablet will never see a NChar string */ 2573 ignoreNormalizerTest: true, 2574 }, { 2575 input: "SELECT JSON_STORAGE_FREE(@j)", 2576 output: "select json_storage_free(@j) from dual", 2577 }, { 2578 input: "SELECT LTRIM('abc')", 2579 output: "select ltrim('abc') from dual", 2580 }, { 2581 input: "SELECT RTRIM('abc')", 2582 output: "select rtrim('abc') from dual", 2583 }, { 2584 input: "SELECT TRIM(' abc ')", 2585 output: "select trim(' abc ') from dual", 2586 }, { 2587 input: "SELECT TRIM('aa' FROM 'aabccaaa')", 2588 output: "select trim('aa' from 'aabccaaa') from dual", 2589 }, { 2590 input: "SELECT TRIM(LEADING FROM 'aabccaaa')", 2591 output: "select trim(leading from 'aabccaaa') from dual", 2592 }, { 2593 input: "SELECT TRIM(TRAILING FROM 'abca')", 2594 output: "select trim(trailing from 'abca') from dual", 2595 }, { 2596 input: "SELECT TRIM(BOTH FROM 'abc')", 2597 output: "select trim(both from 'abc') from dual", 2598 }, { 2599 input: "SELECT TRIM(LEADING 'a' FROM 'abc')", 2600 output: "select trim(leading 'a' from 'abc') from dual", 2601 }, { 2602 input: "SELECT TRIM(TRAILING 'a' FROM 'abc')", 2603 output: "select trim(trailing 'a' from 'abc') from dual", 2604 }, { 2605 input: "SELECT TRIM(BOTH 'a' FROM 'abc')", 2606 output: "select trim(both 'a' from 'abc') from dual", 2607 }, { 2608 input: `SELECT * FROM JSON_TABLE('[ {"c1": null} ]','$[*]' COLUMNS( c1 INT PATH '$.c1' ERROR ON ERROR )) as jt`, 2609 output: `select * from json_table('[ {\"c1\": null} ]', '$[*]' columns( 2610 c1 INT path '$.c1' error on error 2611 ) 2612 ) as jt`, 2613 }, { 2614 input: `SELECT * FROM JSON_TABLE( '[{"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}]', '$[*]' COLUMNS(a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'), NESTED PATH '$.b[*]' COLUMNS (b2 INT PATH '$'))) AS jt`, 2615 output: `select * from json_table('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' columns( 2616 a INT path '$.a' , 2617 nested path '$.b[*]' columns( 2618 b1 INT path '$' 2619 ), 2620 nested path '$.b[*]' columns( 2621 b2 INT path '$' 2622 ) 2623 ) 2624 ) as jt`, 2625 }, { 2626 input: `SELECT * FROM JSON_TABLE('[ {"c1": null} ]','$[*]' COLUMNS( c1 INT PATH '$.c1' ERROR ON ERROR )) as jt`, 2627 output: `select * from json_table('[ {\"c1\": null} ]', '$[*]' columns( 2628 c1 INT path '$.c1' error on error 2629 ) 2630 ) as jt`, 2631 }, { 2632 input: `SELECT * FROM JSON_TABLE('[{"a":"3"},{"a":2},{"b":1},{"a":0},{"a":[1,2]}]', "$[*]" COLUMNS(rowid FOR ORDINALITY, ac VARCHAR(100) PATH "$.a" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR, aj JSON PATH "$.a" DEFAULT '{"x": 333}' ON EMPTY, bx INT EXISTS PATH "$.b" ) ) AS tt`, 2633 output: `select * from json_table('[{\"a\":\"3\"},{\"a\":2},{\"b\":1},{\"a\":0},{\"a\":[1,2]}]', '$[*]' columns( 2634 rowid for ordinality, 2635 ac VARCHAR(100) path '$.a' default '111' on empty default '999' on error , 2636 aj JSON path '$.a' default '{\"x\": 333}' on empty , 2637 bx INT exists path '$.b' 2638 ) 2639 ) as tt`, 2640 }, { 2641 input: `SELECT * FROM JSON_TABLE( '[ {"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]', '$[*]' COLUMNS( a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$') ) ) AS jt WHERE b IS NOT NULL`, 2642 output: `select * from json_table('[ {\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}, {\"a\":3}]', '$[*]' columns( 2643 a INT path '$.a' , 2644 nested path '$.b[*]' columns( 2645 b INT path '$' 2646 ) 2647 ) 2648 ) as jt where b is not null`, 2649 }, { 2650 input: `SELECT * FROM JSON_TABLE( '[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', "$[1]" COLUMNS( xval VARCHAR(100) PATH "$.x", yval VARCHAR(100) PATH "$.y" ) ) AS jt1`, 2651 output: `select * from json_table('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', '$[1]' columns( 2652 xval VARCHAR(100) path '$.x' , 2653 yval VARCHAR(100) path '$.y' 2654 ) 2655 ) as jt1`, 2656 }, { 2657 input: `SELECT * FROM JSON_TABLE( '[{"a": "a_val","b": [{"c": "c_val", "l": [1,2]}]},{"a": "a_val", "b": [{"c": "c_val","l": [11]}, {"c": "c_val", "l": [22]}]}]', '$[*]' COLUMNS( top_ord FOR ORDINALITY, apath VARCHAR(10) PATH '$.a', NESTED PATH '$.b[*]' COLUMNS ( bpath VARCHAR(10) PATH '$.c', ord FOR ORDINALITY, NESTED PATH '$.l[*]' COLUMNS (lpath varchar(10) PATH '$') ) )) as jt`, 2658 output: `select * from json_table('[{\"a\": \"a_val\",\"b\": [{\"c\": \"c_val\", \"l\": [1,2]}]},{\"a\": \"a_val\", \"b\": [{\"c\": \"c_val\",\"l\": [11]}, {\"c\": \"c_val\", \"l\": [22]}]}]', '$[*]' columns( 2659 top_ord for ordinality, 2660 apath VARCHAR(10) path '$.a' , 2661 nested path '$.b[*]' columns( 2662 bpath VARCHAR(10) path '$.c' , 2663 ord for ordinality, 2664 nested path '$.l[*]' columns( 2665 lpath varchar(10) path '$' 2666 ) 2667 ) 2668 ) 2669 ) as jt`, 2670 }, { 2671 input: `SELECT * FROM JSON_TABLE('[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', "$[1]" COLUMNS( xval VARCHAR(100) PATH "$.x", yval VARCHAR(100) PATH "$.y")) AS jt1;`, 2672 output: `select * from json_table('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', '$[1]' columns( 2673 xval VARCHAR(100) path '$.x' , 2674 yval VARCHAR(100) path '$.y' 2675 ) 2676 ) as jt1`, 2677 }, { 2678 input: "SELECT JSON_ARRAY()", 2679 output: "select json_array() from dual", 2680 }, { 2681 input: "SELECT JSON_ARRAY(1)", 2682 output: "select json_array(1) from dual", 2683 }, { 2684 input: "SELECT JSON_ARRAY('abc')", 2685 output: "select json_array('abc') from dual", 2686 }, { 2687 input: "SELECT JSON_ARRAY(BIN(11))", 2688 output: "select json_array(BIN(11)) from dual", 2689 }, { 2690 input: `SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME());`, 2691 output: `select json_array(1, 'abc', null, true, CURTIME()) from dual`, 2692 }, { 2693 input: "SELECT JSON_OBJECT(1,2)", 2694 output: "select json_object(1, 2) from dual", 2695 }, { 2696 input: "SELECT JSON_OBJECT(1,'abc')", 2697 output: "select json_object(1, 'abc') from dual", 2698 }, { 2699 input: "SELECT JSON_OBJECT('abc',1)", 2700 output: "select json_object('abc', 1) from dual", 2701 }, { 2702 input: "SELECT JSON_OBJECT(BIN(1),2)", 2703 output: "select json_object(BIN(1), 2) from dual", 2704 }, { 2705 input: "SELECT JSON_OBJECT(BIN(1),2,'abc',ASCII(4))", 2706 output: "select json_object(BIN(1), 2, 'abc', ASCII(4)) from dual", 2707 }, { 2708 input: "SELECT JSON_QUOTE(BIN(11))", 2709 output: "select json_quote(BIN(11)) from dual", 2710 }, { 2711 input: `SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"')`, 2712 output: `select json_quote('null'), json_quote('\"null\"') from dual`, 2713 }, { 2714 input: "select t1.a, dt.a from t1, lateral (select t1.a+t2.a as a from t2) dt", 2715 output: "select t1.a, dt.a from t1, lateral (select t1.a + t2.a as a from t2) as dt", 2716 }, { 2717 input: "select b from v1 vq1, lateral (select count(*) from v1 vq2 having vq1.b = 3) dt", 2718 output: "select b from v1 as vq1, lateral (select count(*) from v1 as vq2 having vq1.b = 3) as dt", 2719 }, { 2720 input: `SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"')`, 2721 output: `select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, 2722 }, { 2723 input: `SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', @a)`, 2724 output: `select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', @a) from dual`, 2725 }, { 2726 input: `SELECT JSON_SCHEMA_VALID(@b, BIN(1))`, 2727 output: `select json_schema_valid(@b, BIN(1)) from dual`, 2728 }, { 2729 input: `SELECT JSON_SCHEMA_VALID(N'{"type":"string","pattern":"("}', '"abc"')`, 2730 output: `select json_schema_valid(N'{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, 2731 /*We need to ignore this test because, after the normalizer, we change the produced NChar 2732 string into an introducer expression, so the vttablet will never see a NChar string */ 2733 ignoreNormalizerTest: true, 2734 }, { 2735 input: `SELECT JSON_SCHEMA_VALIDATION_REPORT('{"type":"string","pattern":"("}', '"abc"')`, 2736 output: `select json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, 2737 }, { 2738 input: `SELECT JSON_SCHEMA_VALIDATION_REPORT('{"type":"string","pattern":"("}', @a)`, 2739 output: `select json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', @a) from dual`, 2740 }, { 2741 input: `SELECT JSON_SCHEMA_VALIDATION_REPORT(@b, BIN(1))`, 2742 output: `select json_schema_validation_report(@b, BIN(1)) from dual`, 2743 }, { 2744 input: `SELECT JSON_SCHEMA_VALIDATION_REPORT(N'{"type":"string","pattern":"("}', '"abc"')`, 2745 output: `select json_schema_validation_report(N'{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, 2746 /*We need to ignore this test because, after the normalizer, we change the produced NChar 2747 string into an introducer expression, so the vttablet will never see a NChar string */ 2748 ignoreNormalizerTest: true, 2749 }, { 2750 input: `SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1')`, 2751 output: `select json_contains('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '1') from dual`, 2752 }, { 2753 input: "SELECT JSON_CONTAINS(@j, @j2)", 2754 output: "select json_contains(@j, @j2) from dual", 2755 }, { 2756 input: "SELECT JSON_CONTAINS(@j, @j2,'$.a', @j)", 2757 output: "select json_contains(@j, @j2, '$.a', @j) from dual", 2758 }, { 2759 input: "SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e')", 2760 output: "select json_contains_path(@j, 'one', '$.a', '$.e') from dual", 2761 }, { 2762 input: `SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a', '$.e')`, 2763 output: `select json_contains_path('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'one', '$.a', '$.e') from dual`, 2764 }, { 2765 input: "SELECT JSON_CONTAINS_PATH(@j, TRIM('one'), '$.a', '$.e')", 2766 output: "select json_contains_path(@j, trim('one'), '$.a', '$.e') from dual", 2767 }, { 2768 input: "SELECT JSON_CONTAINS_PATH(@j, @k, '$.a', @i)", 2769 output: "select json_contains_path(@j, @k, '$.a', @i) from dual", 2770 }, { 2771 input: "SELECT JSON_EXTRACT(@j, '$.a')", 2772 output: "select json_extract(@j, '$.a') from dual", 2773 }, { 2774 input: `SELECT c, JSON_EXTRACT(c, "$.id"), g FROM jemp WHERE JSON_EXTRACT(c, "$.id") > 1 ORDER BY JSON_EXTRACT(c, "$.name")`, 2775 output: "select c, json_extract(c, '$.id'), g from jemp where json_extract(c, '$.id') > 1 order by json_extract(c, '$.name') asc", 2776 }, { 2777 input: `SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a', @j)`, 2778 output: `select json_extract('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a', @j) from dual`, 2779 }, { 2780 input: "SELECT JSON_EXTRACT(@k, TRIM('abc'))", 2781 output: `select json_extract(@k, trim('abc')) from dual`, 2782 }, { 2783 input: `SELECT JSON_KEYS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, 2784 output: `select json_keys('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, 2785 }, { 2786 input: `SELECT JSON_KEYS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}')`, 2787 output: `select json_keys('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}') from dual`, 2788 }, { 2789 input: `SELECT JSON_OVERLAPS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, 2790 output: `select json_overlaps('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, 2791 }, { 2792 input: "SELECT JSON_OVERLAPS(@j, @k)", 2793 output: "select json_overlaps(@j, @k) from dual", 2794 }, { 2795 input: "SELECT JSON_OVERLAPS(@j, BIN(1))", 2796 output: "select json_overlaps(@j, BIN(1)) from dual", 2797 }, { 2798 input: "SELECT JSON_SEARCH(@j, 'one', 'abc')", 2799 output: "select json_search(@j, 'one', 'abc') from dual", 2800 }, { 2801 input: `SELECT JSON_SEARCH('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', @j, BIN(2))`, 2802 output: `select json_search('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', @j, BIN(2)) from dual`, 2803 }, { 2804 input: `SELECT JSON_SEARCH('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'all', '10', NULL)`, 2805 output: `select json_search('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'all', '10', null) from dual`, 2806 }, { 2807 input: "SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]')", 2808 output: "select json_search(@j, 'all', '%b%', '', '$[3]') from dual", 2809 }, { 2810 input: "SELECT JSON_SEARCH(@j, 'all', '%b%', 'a', '$[3]')", 2811 output: "select json_search(@j, 'all', '%b%', 'a', '$[3]') from dual", 2812 }, { 2813 input: `SELECT JSON_VALUE('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, 2814 output: `select json_value('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, 2815 }, { 2816 input: `SELECT JSON_VALUE(@j, @k)`, 2817 output: `select json_value(@j, @k) from dual`, 2818 }, { 2819 input: `select json_value(@j, @k RETURNING FLOAT) from dual`, 2820 output: `select json_value(@j, @k returning FLOAT) from dual`, 2821 }, { 2822 input: `select json_value(@j, @k RETURNING DECIMAL(4,2)) from dual`, 2823 output: `select json_value(@j, @k returning DECIMAL(4, 2)) from dual`, 2824 }, { 2825 input: `SELECT JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname' returning char(49) Charset utf8mb4 error on error)`, 2826 output: `select json_value('{\"fname\": \"Joe\", \"lname\": \"Palmer\"}', '$.fname' returning char(49) character set utf8mb4 error on error) from dual`, 2827 }, { 2828 input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON EMPTY) `, 2829 output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on empty) from dual`, 2830 }, { 2831 input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON ERROR) `, 2832 output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on error) from dual`, 2833 }, { 2834 input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON EMPTY ERROR ON ERROR) `, 2835 output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on empty error on error) from dual`, 2836 }, { 2837 input: `select json_value(@j, @k RETURNING FLOAT NULL ON EMPTY ERROR ON ERROR) from dual`, 2838 output: `select json_value(@j, @k returning FLOAT null on empty error on error) from dual`, 2839 }, { 2840 input: `SELECT 17 MEMBER OF ('[23, "abc", 17, "ab", 10]')`, 2841 output: `select 17 member of ('[23, \"abc\", 17, \"ab\", 10]') from dual`, 2842 }, { 2843 input: "SELECT @j MEMBER OF (@k)", 2844 output: "select @j member of (@k) from dual", 2845 }, { 2846 input: `SELECT 17 MEMBER OF('[23, "abc", "17", "ab", 10]'), "17" MEMBER OF('[23, "abc", 17, "ab", 10]')`, 2847 output: `select 17 member of ('[23, \"abc\", \"17\", \"ab\", 10]'), '17' member of ('[23, \"abc\", 17, \"ab\", 10]') from dual`, 2848 }, { 2849 input: `SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true')`, 2850 output: `select json_depth('{}'), json_depth('[]'), json_depth('true') from dual`, 2851 }, { 2852 input: `SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}')`, 2853 output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}') from dual`, 2854 }, { 2855 input: `SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');`, 2856 output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}', '$.b') from dual`, 2857 }, { 2858 input: `SELECT JSON_LENGTH('{\"a\": 1, \"b\": {\"c\": 30}}', @j);`, 2859 output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}', @j) from dual`, 2860 }, { 2861 input: `SELECT jcol, JSON_LENGTH(jcol)`, 2862 output: `select jcol, json_length(jcol) from dual`, 2863 }, { 2864 input: "SELECT JSON_TYPE(@j)", 2865 output: "select json_type(@j) from dual", 2866 }, { 2867 input: `SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]'))`, 2868 output: `select json_type(json_extract(@j, '$.a[0]')) from dual`, 2869 }, { 2870 input: `SELECT JSON_VALID('{\"a\": 1}')`, 2871 output: `select json_valid('{\"a\": 1}') from dual`, 2872 }, { 2873 input: "SELECT JSON_VALID(@j)", 2874 output: "select json_valid(@j) from dual", 2875 }, { 2876 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, 2877 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, 2878 }, { 2879 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, 2880 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, 2881 }, { 2882 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, 2883 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, 2884 }, { 2885 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', @j, 1)`, 2886 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, 2887 }, { 2888 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, 2889 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, 2890 }, { 2891 input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', @j, @k)`, 2892 output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, 2893 }, { 2894 input: "SELECT JSON_ARRAY_APPEND(@i,@j,@k)", 2895 output: `select json_array_append(@i, @j, @k) from dual`, 2896 }, { 2897 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, 2898 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, 2899 }, { 2900 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, 2901 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, 2902 }, { 2903 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, 2904 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, 2905 }, { 2906 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', @j, 1)`, 2907 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, 2908 }, { 2909 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, 2910 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, 2911 }, { 2912 input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', @j, @k)`, 2913 output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, 2914 }, { 2915 input: "SELECT JSON_ARRAY_INSERT(@i,@j,@k)", 2916 output: "select json_array_insert(@i, @j, @k) from dual", 2917 }, { 2918 input: "SELECT JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y')", 2919 output: "select json_array_insert(@j, '$[0]', 'x', '$[2][1]', 'y') from dual", 2920 }, { 2921 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, 2922 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, 2923 }, { 2924 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, 2925 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, 2926 }, { 2927 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, 2928 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, 2929 }, { 2930 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', @j, 1)`, 2931 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, 2932 }, { 2933 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, 2934 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, 2935 }, { 2936 input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', @j, @k)`, 2937 output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, 2938 }, { 2939 input: "SELECT JSON_INSERT(@i,@j,@k)", 2940 output: "select json_insert(@i, @j, @k) from dual", 2941 }, { 2942 input: "SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]')", 2943 output: "select json_insert(@j, '$.a', 10, '$.c', '[true, false]') from dual", 2944 }, { 2945 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, 2946 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, 2947 }, { 2948 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, 2949 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, 2950 }, { 2951 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, 2952 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, 2953 }, { 2954 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', @j, 1)`, 2955 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, 2956 }, { 2957 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, 2958 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, 2959 }, { 2960 input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', @j, @k)`, 2961 output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, 2962 }, { 2963 input: "SELECT JSON_REPLACE(@i,@j,@k)", 2964 output: "select json_replace(@i, @j, @k) from dual", 2965 }, { 2966 input: "SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]')", 2967 output: "select json_replace(@j, '$.a', 10, '$.c', '[true, false]') from dual", 2968 }, { 2969 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, 2970 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, 2971 }, { 2972 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, 2973 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, 2974 }, { 2975 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, 2976 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, 2977 }, { 2978 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', @j, 1)`, 2979 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, 2980 }, { 2981 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, 2982 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, 2983 }, { 2984 input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', @j, @k)`, 2985 output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, 2986 }, { 2987 input: "SELECT JSON_SET(@i,@j,@k)", 2988 output: "select json_set(@i, @j, @k) from dual", 2989 }, { 2990 input: "SELECT JSON_SET(@j, '$.a', 10, '$.c', '[true, false]')", 2991 output: "select json_set(@j, '$.a', 10, '$.c', '[true, false]') from dual", 2992 }, { 2993 input: "SELECT JSON_MERGE('[1, 2]', '[true, false]')", 2994 output: "select json_merge('[1, 2]', '[true, false]') from dual", 2995 }, { 2996 input: "SELECT JSON_MERGE('[1, 2]', '[true, false]', 'hello')", 2997 output: "select json_merge('[1, 2]', '[true, false]', 'hello') from dual", 2998 }, { 2999 input: "SELECT JSON_MERGE('[1, 2]', @i)", 3000 output: "select json_merge('[1, 2]', @i) from dual", 3001 }, { 3002 input: "SELECT JSON_MERGE(@i, @j)", 3003 output: "select json_merge(@i, @j) from dual", 3004 }, { 3005 input: "SELECT JSON_MERGE(@i, @j, @k)", 3006 output: "select json_merge(@i, @j, @k) from dual", 3007 }, { 3008 input: "SELECT JSON_MERGE(@i, '[true, false]')", 3009 output: "select json_merge(@i, '[true, false]') from dual", 3010 }, { 3011 input: `SELECT JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}')`, 3012 output: `select json_merge_patch('{\"name\": \"x\"}', '{\"id\": 47}') from dual`, 3013 }, { 3014 input: `SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }');`, 3015 output: `select json_merge_patch('{ \"a\": 1, \"b\":2 }', '{ \"a\": 3, \"c\":4 }', '{ \"a\": 5, \"d\":6 }') from dual`, 3016 }, { 3017 input: "SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]', 'hello')", 3018 output: "select json_merge_patch('[1, 2]', '[true, false]', 'hello') from dual", 3019 }, { 3020 input: "SELECT JSON_MERGE_PATCH('[1, 2]', @i)", 3021 output: "select json_merge_patch('[1, 2]', @i) from dual", 3022 }, { 3023 input: "SELECT JSON_MERGE_PATCH(@i, @j)", 3024 output: "select json_merge_patch(@i, @j) from dual", 3025 }, { 3026 input: "SELECT JSON_MERGE_PATCH(@i, '[true, false]')", 3027 output: "select json_merge_patch(@i, '[true, false]') from dual", 3028 }, { 3029 input: `SELECT JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}')`, 3030 output: `select json_merge_preserve('{\"name\": \"x\"}', '{\"id\": 47}') from dual`, 3031 }, { 3032 input: `SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }');`, 3033 output: `select json_merge_preserve('{ \"a\": 1, \"b\":2 }', '{ \"a\": 3, \"c\":4 }', '{ \"a\": 5, \"d\":6 }') from dual`, 3034 }, { 3035 input: "SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]', 'hello')", 3036 output: "select json_merge_preserve('[1, 2]', '[true, false]', 'hello') from dual", 3037 }, { 3038 input: "SELECT JSON_MERGE_PRESERVE('[1, 2]', @i)", 3039 output: "select json_merge_preserve('[1, 2]', @i) from dual", 3040 }, { 3041 input: "SELECT JSON_MERGE_PRESERVE(@i, @j)", 3042 output: "select json_merge_preserve(@i, @j) from dual", 3043 }, { 3044 input: "SELECT JSON_MERGE_PRESERVE(@i, '[true, false]')", 3045 output: "select json_merge_preserve(@i, '[true, false]') from dual", 3046 }, { 3047 input: "SELECT JSON_REMOVE(@i, '$[1]')", 3048 output: "select json_remove(@i, '$[1]') from dual", 3049 }, { 3050 input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', '$[1]')`, 3051 output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', '$[1]') from dual`, 3052 }, { 3053 input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', @i)`, 3054 output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', @i) from dual`, 3055 }, { 3056 input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', @i, @j, '$[0]', '$[1]','$[2]')`, 3057 output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', @i, @j, '$[0]', '$[1]', '$[2]') from dual`, 3058 }, { 3059 input: "SELECT JSON_UNQUOTE('abc')", 3060 output: "select json_unquote('abc') from dual", 3061 }, { 3062 input: `SELECT JSON_UNQUOTE('\"\\\\t\\\\u0032\"')`, 3063 output: `select json_unquote('\"\\\\t\\\\u0032\"') from dual`, 3064 }, { 3065 input: "SELECT JSON_UNQUOTE(@j)", 3066 output: "select json_unquote(@j) from dual", 3067 }, { 3068 input: "CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) (SUBPARTITION s0,SUBPARTITION s1),PARTITION p1 VALUES LESS THAN (2000),PARTITION p2 VALUES LESS THAN MAXVALUE (SUBPARTITION s2,SUBPARTITION s3));", 3069 output: "create table ts (\n\tid INT,\n\tpurchased DATE\n)\npartition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased))\n(partition p0 values less than (1990) (subpartition s0, subpartition s1),\n partition p1 values less than (2000),\n partition p2 values less than maxvalue (subpartition s2, subpartition `s3`))", 3070 }, { 3071 input: "SELECT REGEXP_INSTR('dog cat dog', 'dog')", 3072 output: "select regexp_instr('dog cat dog', 'dog') from dual", 3073 }, { 3074 input: "SELECT REGEXP_INSTR('aa aaa aaaa aaaa aaaa aaaa', 'a{4}',1)", 3075 output: "select regexp_instr('aa aaa aaaa aaaa aaaa aaaa', 'a{4}', 1) from dual", 3076 }, { 3077 input: "SELECT REGEXP_INSTR('aa aaa aaaa aaaa aaaa aaaa', 'a{4}',1,TRIM('2'))", 3078 output: "select regexp_instr('aa aaa aaaa aaaa aaaa aaaa', 'a{4}', 1, trim('2')) from dual", 3079 }, { 3080 input: "SELECT REGEXP_INSTR('aa aaa aaaa aaaa aaaa aaaa', 'a{4}',1,TRIM('2'),0)", 3081 output: "select regexp_instr('aa aaa aaaa aaaa aaaa aaaa', 'a{4}', 1, trim('2'), 0) from dual", 3082 }, { 3083 input: "SELECT REGEXP_INSTR('aa aaa aaaa aaaa aaaa aaaa', 'a{4}',1,TRIM('2'),0, 'c')", 3084 output: "select regexp_instr('aa aaa aaaa aaaa aaaa aaaa', 'a{4}', 1, trim('2'), 0, 'c') from dual", 3085 }, { 3086 input: "SELECT REGEXP_LIKE('dog cat dog', 'dog')", 3087 output: "select regexp_like('dog cat dog', 'dog') from dual", 3088 }, { 3089 input: "SELECT NOT REGEXP_LIKE('dog cat dog', 'dog')", 3090 output: "select not regexp_like('dog cat dog', 'dog') from dual", 3091 }, { 3092 input: "SELECT REGEXP_LIKE('aa aaa aaaa aaaa aaaa aaaa', 'a{4}',1)", 3093 output: "select regexp_like('aa aaa aaaa aaaa aaaa aaaa', 'a{4}', 1) from dual", 3094 }, { 3095 input: "SELECT REGEXP_REPLACE('a b c', 'b', 'X');", 3096 output: "select regexp_replace('a b c', 'b', 'X') from dual", 3097 }, { 3098 input: "SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1);", 3099 output: "select regexp_replace('abc def ghi', '[a-z]+', 'X', 1) from dual", 3100 }, { 3101 input: "SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3);", 3102 output: "select regexp_replace('abc def ghi', '[a-z]+', 'X', 1, 3) from dual", 3103 }, { 3104 input: "SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3, 'c');", 3105 output: "select regexp_replace('abc def ghi', '[a-z]+', 'X', 1, 3, 'c') from dual", 3106 }, { 3107 input: "SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+');", 3108 output: "select regexp_substr('abc def ghi', '[a-z]+') from dual", 3109 }, { 3110 input: "SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1);", 3111 output: "select regexp_substr('abc def ghi', '[a-z]+', 1) from dual", 3112 }, { 3113 input: "SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3);", 3114 output: "select regexp_substr('abc def ghi', '[a-z]+', 1, 3) from dual", 3115 }, { 3116 input: "SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3, TRIM(' n '));", 3117 output: "select regexp_substr('abc def ghi', '[a-z]+', 1, 3, trim(' n ')) from dual", 3118 }, { 3119 input: "SELECT 'Michael!' RLIKE '.*';", 3120 output: "select 'Michael!' regexp '.*' from dual", 3121 }, { 3122 input: "SELECT TRIM('Michael!') RLIKE @j", 3123 output: "select trim('Michael!') regexp @j from dual", 3124 }, { 3125 input: "SELECT INSERT('Quadratic', 3, 4, 'What')", 3126 output: "select insert('Quadratic', 3, 4, 'What') from dual", 3127 }, { 3128 input: "SELECT INTERVAL(1, 3, 4)", 3129 output: "select interval(1, 3, 4) from dual", 3130 }, { 3131 input: "SELECT POSITION('bar' IN 'foobarbar')", 3132 output: "select locate('bar', 'foobarbar') from dual", 3133 }, { 3134 input: "SELECT CHAR(77,121,83,81,'76' USING utf8mb4)", 3135 output: "select char(77, 121, 83, 81, '76' using utf8mb4) from dual", 3136 }, { 3137 input: "SELECT val, CUME_DIST() OVER w, ROW_NUMBER() OVER w, DENSE_RANK() OVER w, PERCENT_RANK() OVER w, RANK() OVER w AS 'cd' FROM numbers", 3138 output: "select val, cume_dist() over w, row_number() over w, dense_rank() over w, percent_rank() over w, rank() over w as cd from numbers", 3139 }, { 3140 input: "SELECT year, country, product, profit, CUME_DIST() OVER() AS total_profit FROM sales", 3141 output: "select `year`, country, product, profit, cume_dist() over () as total_profit from sales", 3142 }, { 3143 input: "SELECT val, CUME_DIST() OVER (ORDER BY val) AS 'cd' FROM numbers", 3144 output: "select val, cume_dist() over ( order by val asc) as cd from numbers", 3145 }, { 3146 input: "SELECT val, CUME_DIST() OVER (PARTITION BY z ORDER BY val, subject DESC ROWS CURRENT ROW) AS 'cd' FROM numbers", 3147 output: "select val, cume_dist() over ( partition by z order by val asc, subject desc rows current row) as cd from numbers", 3148 }, { 3149 input: "SELECT val, CUME_DIST() OVER (val PARTITION BY z, subject ORDER BY val, subject DESC ROWS CURRENT ROW) AS 'cd' FROM numbers", 3150 output: "select val, cume_dist() over ( val partition by z, subject order by val asc, subject desc rows current row) as cd from numbers", 3151 }, { 3152 input: "SELECT val, FIRST_VALUE(val) OVER w FROM numbers", 3153 output: "select val, first_value(val) over w from numbers", 3154 }, { 3155 input: "SELECT val, LAST_VALUE(val) IGNORE NULLS OVER w FROM numbers", 3156 output: "select val, last_value(val) ignore nulls over w from numbers", 3157 }, { 3158 input: "SELECT NTILE(1) OVER w, NTILE(0) OVER w FROM numbers", 3159 output: "select ntile(1) over w, ntile(0) over w from numbers", 3160 }, { 3161 input: "SELECT NTILE(NULL) OVER w FROM numbers", 3162 output: "select ntile(null) over w from numbers", 3163 }, { 3164 input: "SELECT NTILE(@val) OVER w FROM numbers", 3165 output: "select ntile(@val) over w from numbers", 3166 }, { 3167 input: "SELECT NTH_VALUE(@z,1) OVER w, NTH_VALUE('val',0) OVER w FROM numbers", 3168 output: "select nth_value(@z, 1) over w, nth_value('val', 0) over w from numbers", 3169 }, { 3170 input: "SELECT NTH_VALUE(val,NULL) FROM FIRST OVER w FROM numbers", 3171 output: "select nth_value(val, null) respect nulls over w from numbers", 3172 }, { 3173 input: "SELECT NTH_VALUE(val,NULL) RESPECT NULLS OVER w FROM numbers", 3174 output: "select nth_value(val, null) respect nulls over w from numbers", 3175 }, { 3176 input: "SELECT LAG(val) OVER w, LEAD(TRIM('abc')) OVER w FROM numbers", 3177 output: "select lag(val) over w, lead(trim('abc')) over w from numbers", 3178 }, { 3179 input: "SELECT LAG(val, 10) OVER w, LEAD('val', null) OVER w, LEAD(val, 1, ASCII(1)) OVER w FROM numbers", 3180 output: "select lag(val, 10) over w, lead('val', null) over w, lead(val, 1, ASCII(1)) over w from numbers", 3181 }, { 3182 input: "SELECT val, ROW_NUMBER() OVER (ORDER BY val) AS 'row_number' FROM numbers WINDOW w AS (ORDER BY val);", 3183 output: "select val, row_number() over ( order by val asc) as `row_number` from numbers window w AS ( order by val asc)", 3184 }, { 3185 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time ROWS UNBOUNDED PRECEDING);", 3186 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc rows unbounded preceding)", 3187 }, { 3188 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time RANGE 10 PRECEDING);", 3189 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc range 10 preceding)", 3190 }, { 3191 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time ROWS INTERVAL 5 DAY PRECEDING);", 3192 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc rows interval 5 DAY preceding)", 3193 }, { 3194 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time RANGE 5 FOLLOWING);", 3195 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc range 5 following)", 3196 }, { 3197 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time ROWS INTERVAL '2:30' MINUTE_SECOND FOLLOWING);", 3198 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc rows interval '2:30' MINUTE_SECOND following)", 3199 }, { 3200 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time ASC RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING);", 3201 output: "select `time`, subject, val, first_value(val) over w as `first`, last_value(val) over w as `last`, nth_value(val, 2) over w as `second`, nth_value(val, 4) over w as fourth from observations window w AS ( partition by subject order by `time` asc range between 10 preceding and 10 following)", 3202 }, { 3203 input: "SELECT ExtractValue('<a><b/></a>', '/a/b')", 3204 output: "select extractvalue('<a><b/></a>', '/a/b') from dual", 3205 }, { 3206 input: "SELECT @i, ExtractValue(@xml, '//b[$@i]')", 3207 output: "select @i, extractvalue(@xml, '//b[$@i]') from dual", 3208 }, { 3209 input: "SELECT ExtractValue(TRIM('<a><c/></a>'), 'count(/a/b)')", 3210 output: "select extractvalue(trim('<a><c/></a>'), 'count(/a/b)') from dual", 3211 }, { 3212 input: "SELECT UpdateXML(@xml, '//b:c', '<g:h>555</g:h>')", 3213 output: "select updatexml(@xml, '//b:c', '<g:h>555</g:h>') from dual", 3214 }, { 3215 input: "SELECT UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5", 3216 output: "select updatexml('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') as val5 from dual", 3217 }, { 3218 input: "select get_lock('a', 10), is_free_lock('b'), is_used_lock('c'), release_all_locks(), release_lock('d') from dual", 3219 }, { 3220 input: "select /* function with distinct */ count(a) from t", 3221 }, { 3222 input: "select /* function with distinct */ count(a) 'total col' from t", 3223 output: "select /* function with distinct */ count(a) as `total col` from t", 3224 }, { 3225 input: "select /* function with distinct */ count(distinct a) from t", 3226 }, { 3227 input: "select /* function with distinct */ count(distinct(a)) from t", 3228 output: "select /* function with distinct */ count(distinct a) from t", 3229 }, { 3230 input: "select /* function with distinct */ count(*) from t", 3231 }, { 3232 input: "select avg(a) from products", 3233 }, { 3234 input: "select avg(distinct(a)) from products", 3235 output: "select avg(distinct a) from products", 3236 }, { 3237 input: "select avg(a) 'Avg Price' from products", 3238 output: "select avg(a) as `Avg Price` from products", 3239 }, { 3240 input: "select format(avg(distinct a), 2) from products", 3241 }, { 3242 input: "select max(a) from products", 3243 }, { 3244 input: "select min(a) from products", 3245 }, { 3246 input: "select sum(a) from products", 3247 }, { 3248 input: "select sum(distinct(a)) from products", 3249 output: "select sum(distinct a) from products", 3250 }, { 3251 input: "select sum(distinct a) from products", 3252 }, { 3253 input: "select sum(a) 'sum Price' from products", 3254 output: "select sum(a) as `sum Price` from products", 3255 }, { 3256 input: "select sum(a * b) from products", 3257 }, { 3258 input: "select bit_and(a) from products", 3259 }, { 3260 input: "select bit_or(a) from products", 3261 }, { 3262 input: "select bit_xor(a) from products", 3263 }, { 3264 input: "select std(a) from products", 3265 }, { 3266 input: "select stddev(a) from products", 3267 }, { 3268 input: "select stddev_pop(a) from products", 3269 }, { 3270 input: "select stddev_samp(a) from products", 3271 }, { 3272 input: "select var_pop(a) from products", 3273 }, { 3274 input: "select var_samp(a) from products", 3275 }, { 3276 input: "select variance(a) from products", 3277 }, { 3278 input: "SELECT FORMAT_BYTES(512), FORMAT_BYTES(18446644073709551615), FORMAT_BYTES(@j), FORMAT_BYTES('asd'), FORMAT_BYTES(TRIM('str'))", 3279 output: "select format_bytes(512), format_bytes(18446644073709551615), format_bytes(@j), format_bytes('asd'), format_bytes(trim('str')) from dual", 3280 }, { 3281 input: "SELECT FORMAT_PICO_TIME(512), FORMAT_PICO_TIME(18446644073709551615), FORMAT_PICO_TIME(@j), FORMAT_PICO_TIME('asd'), FORMAT_PICO_TIME(TRIM('str'))", 3282 output: "select format_pico_time(512), format_pico_time(18446644073709551615), format_pico_time(@j), format_pico_time('asd'), format_pico_time(trim('str')) from dual", 3283 }, { 3284 input: "SELECT PS_CURRENT_THREAD_ID()", 3285 output: "select ps_current_thread_id() from dual", 3286 }, { 3287 input: "SELECT PS_THREAD_ID(512), PS_THREAD_ID(18446644073709551615), PS_THREAD_ID(@j), PS_THREAD_ID('asd'), PS_THREAD_ID(TRIM('str'))", 3288 output: "select ps_thread_id(512), ps_thread_id(18446644073709551615), ps_thread_id(@j), ps_thread_id('asd'), ps_thread_id(trim('str')) from dual", 3289 }, { 3290 input: "SELECT GTID_SUBSET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23','3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')", 3291 output: "select gtid_subset('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') from dual", 3292 }, { 3293 input: "SELECT GTID_SUBSET(@j,TRIM('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'))", 3294 output: "select gtid_subset(@j, trim('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')) from dual", 3295 }, { 3296 input: "SELECT GTID_SUBTRACT('3E11FA47-71CA-11E1-9E33-C80AA9429562:23','3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')", 3297 output: "select gtid_subtract('3E11FA47-71CA-11E1-9E33-C80AA9429562:23', '3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57') from dual", 3298 }, { 3299 input: "SELECT GTID_SUBTRACT(@j,TRIM('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'))", 3300 output: "select gtid_subtract(@j, trim('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57')) from dual", 3301 }, { 3302 input: "SELECT WAIT_FOR_EXECUTED_GTID_SET('3E11FA47-71CA-11E1-9E33-C80AA9429562:23')", 3303 output: "select wait_for_executed_gtid_set('3E11FA47-71CA-11E1-9E33-C80AA9429562:23') from dual", 3304 }, { 3305 input: "SELECT WAIT_FOR_EXECUTED_GTID_SET(TRIM('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), @j)", 3306 output: "select wait_for_executed_gtid_set(trim('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), @j) from dual", 3307 }, { 3308 input: "SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('3E11FA47-71CA-11E1-9E33-C80AA9429562:23')", 3309 output: "select wait_until_sql_thread_after_gtids('3E11FA47-71CA-11E1-9E33-C80AA9429562:23') from dual", 3310 }, { 3311 input: "SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(TRIM('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), @j)", 3312 output: "select wait_until_sql_thread_after_gtids(trim('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), @j) from dual", 3313 }, { 3314 input: "SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(TRIM('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), 10, @i)", 3315 output: "select wait_until_sql_thread_after_gtids(trim('3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57'), 10, @i) from dual", 3316 }, { 3317 // Offset as part of expressions 3318 input: "select a, b from c where :1 + :2 = :302 and sum(:34) < :24", 3319 }, { 3320 input: "select * from (((select 1))) as tbl", 3321 output: "select * from (select 1 from dual) as tbl", 3322 }, { 3323 input: `select * from t1 where col1 like 'ks\%' and col2 = 'ks\%' and col1 like 'ks%' and col2 = 'ks%'`, 3324 output: `select * from t1 where col1 like 'ks\%' and col2 = 'ks\%' and col1 like 'ks%' and col2 = 'ks%'`, 3325 }, { 3326 input: `select * from t1 where col1 like 'ks\_' and col2 = 'ks\_' and col1 like 'ks_' and col2 = 'ks_'`, 3327 output: `select * from t1 where col1 like 'ks\_' and col2 = 'ks\_' and col1 like 'ks_' and col2 = 'ks_'`, 3328 }} 3329 ) 3330 3331 func TestValid(t *testing.T) { 3332 for _, tcase := range validSQL { 3333 t.Run(tcase.input, func(t *testing.T) { 3334 if tcase.output == "" { 3335 tcase.output = tcase.input 3336 } 3337 tree, err := Parse(tcase.input) 3338 require.NoError(t, err, tcase.input) 3339 out := String(tree) 3340 assert.Equal(t, tcase.output, out) 3341 3342 // Some statements currently only have 5.7 specifications. 3343 // For mysql 8.0 syntax, the query is not entirely parsed. 3344 // Add more structs as we go on adding full parsing support for DDL constructs for 5.7 syntax. 3345 switch x := tree.(type) { 3346 case DBDDLStatement: 3347 assert.Equal(t, !tcase.partialDDL, x.IsFullyParsed()) 3348 case DDLStatement: 3349 assert.Equal(t, !tcase.partialDDL, x.IsFullyParsed()) 3350 } 3351 // This test just exercises the tree walking functionality. 3352 // There's no way automated way to verify that a node calls 3353 // all its children. But we can examine code coverage and 3354 // ensure that all walkSubtree functions were called. 3355 _ = Walk(func(node SQLNode) (bool, error) { 3356 return true, nil 3357 }, tree) 3358 }) 3359 } 3360 } 3361 3362 // Ensure there is no corruption from using a pooled yyParserImpl in Parse. 3363 func TestParallelValid(t *testing.T) { 3364 parallelism := 100 3365 numIters := 1000 3366 3367 wg := sync.WaitGroup{} 3368 wg.Add(parallelism) 3369 for i := 0; i < parallelism; i++ { 3370 go func() { 3371 defer wg.Done() 3372 for j := 0; j < numIters; j++ { 3373 tcase := validSQL[rand.Intn(len(validSQL))] 3374 if tcase.output == "" { 3375 tcase.output = tcase.input 3376 } 3377 tree, err := Parse(tcase.input) 3378 if err != nil { 3379 t.Errorf("Parse(%q) err: %v, want nil", tcase.input, err) 3380 continue 3381 } 3382 out := String(tree) 3383 if out != tcase.output { 3384 t.Errorf("Parse(%q) = %q, want: %q", tcase.input, out, tcase.output) 3385 } 3386 } 3387 }() 3388 } 3389 wg.Wait() 3390 } 3391 3392 func TestInvalid(t *testing.T) { 3393 invalidSQL := []struct { 3394 input string 3395 err string 3396 }{{ 3397 input: "select a, b from (select * from tbl) sort by a", 3398 err: "syntax error", 3399 }, { 3400 input: "/*!*/", 3401 err: "Query was empty", 3402 }, { 3403 input: "select /* union with limit on lhs */ 1 from t limit 1 union select 1 from t", 3404 err: "syntax error at position 60 near 'union'", 3405 }, { 3406 input: "(select * from t limit 100 into outfile s3 'out_file_name') union (select * from t2)", 3407 err: "syntax error", 3408 }, { 3409 input: "select * from (select * from t into outfile s3 'inner_outfile') as t2 into outfile s3 'out_file_name'", 3410 err: "syntax error at position 36 near 'into'", 3411 }, { 3412 input: "select a from x order by y union select a from c", 3413 err: "syntax error", 3414 }, { 3415 input: "select `name`, numbers from (select * from users) as x()", 3416 err: "syntax error at position 57", 3417 }, { 3418 input: "select next 2 values from seq union select next value from seq", 3419 err: "syntax error at position 36 near 'union'", 3420 }, { 3421 input: "select next 2 values from user where id = 1", 3422 err: "syntax error at position 37 near 'where'", 3423 }, { 3424 input: "select next 2 values from seq, seq", 3425 err: "syntax error at position 31", 3426 }, { 3427 input: "select 1, next value from seq", 3428 err: "syntax error", 3429 }, { 3430 input: "SELECT jcol, JSON_PRETTY(jcol, jcol) from jtable", 3431 err: "syntax error at position 31", 3432 }, { 3433 input: "SELECT JSON_ARRAY(1,)", 3434 err: "syntax error at position 22", 3435 }, { 3436 input: "SELECT JSON_OBJECT(1)", 3437 err: "syntax error at position 22", 3438 }, { 3439 input: "SELECT JSON_OBJECT(1,2,)", 3440 err: "syntax error at position 25", 3441 }, { 3442 input: "SELECT JSON_OBJECT(1,)", 3443 err: "syntax error at position 23", 3444 }, { 3445 input: "SELECT JSON_QUOTE()", 3446 err: "syntax error at position 20", 3447 }, { 3448 input: "select from t1, lateral (with qn as (select t1.a) select (select max(a) from qn)) as dt", 3449 err: "syntax error at position 12 near 'from'", 3450 }, { 3451 input: `SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}')`, 3452 err: `syntax error at position 60`, 3453 }, { 3454 input: `SELECT JSON_SCHEMA_VALIDATION_REPORT('{"type":"string","pattern":"("}')`, 3455 err: `syntax error at position 72`, 3456 }, { 3457 input: "SELECT JSON_CONTAINS(@j, @j2, )", 3458 err: "syntax error at position 32", 3459 }, { 3460 input: "SELECT JSON_CONTAINS_PATH(@j, @j2)", 3461 err: "syntax error at position 35", 3462 }, { 3463 input: "SELECT JSON_EXTRACT(@k)", 3464 err: "syntax error at position 24", 3465 }, { 3466 input: `SELECT JSON_KEYS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}',)`, 3467 err: `syntax error at position 61`, 3468 }, { 3469 input: "SELECT JSON_ARRAY_APPEND('{ \"a\": 1, \"b\": [2, 3]}')", 3470 err: "syntax error at position 51", 3471 }, { 3472 input: "SELECT JSON_ARRAY_APPEND('{ \"a\": 1, \"b\": [2, 3]}','$[1]',)", 3473 err: "syntax error at position 59", 3474 }, { 3475 input: "SELECT JSON_ARRAY_INSERT('{ \"a\": 1, \"b\": [2, 3]}')", 3476 err: "syntax error at position 51", 3477 }, { 3478 input: "SELECT JSON_ARRAY_INSERT('{ \"a\": 1, \"b\": [2, 3]}','$[1]',)", 3479 err: "syntax error at position 59", 3480 }, { 3481 input: "SELECT JSON_INSERT('{ \"a\": 1, \"b\": [2, 3]}')", 3482 err: "syntax error at position 45", 3483 }, { 3484 input: "SELECT JSON_INSERT('{ \"a\": 1, \"b\": [2, 3]}','$[1]',)", 3485 err: "syntax error at position 53", 3486 }, { 3487 input: "SELECT JSON_REPLACE('{ \"a\": 1, \"b\": [2, 3]}')", 3488 err: "syntax error at position 46", 3489 }, { 3490 input: "SELECT JSON_REPLACE('{ \"a\": 1, \"b\": [2, 3]}','$[1]',)", 3491 err: "syntax error at position 54", 3492 }, { 3493 input: "SELECT JSON_SET('{ \"a\": 1, \"b\": [2, 3]}')", 3494 err: "syntax error at position 42", 3495 }, { 3496 input: "SELECT JSON_SET('{ \"a\": 1, \"b\": [2, 3]}','$[1]',)", 3497 err: "syntax error at position 50", 3498 }, { 3499 input: "SELECT JSON_MERGE('[1, 2]')", 3500 err: "syntax error at position 28", 3501 }, { 3502 input: "SELECT JSON_MERGE_PATCH('[1, 2]')", 3503 err: "syntax error at position 34", 3504 }, { 3505 input: "SELECT JSON_MERGE_PRESERVE('[1, 2]')", 3506 err: "syntax error at position 37", 3507 }, { 3508 input: "SELECT JSON_REMOVE('[\"a\", [\"b\", \"c\"], \"d\"]')", 3509 err: "syntax error at position 45", 3510 }, { 3511 input: "SELECT NTILE('val') OVER w FROM numbers", 3512 err: "syntax error at position 19 near 'val'", 3513 }, { 3514 input: "SELECT NTILE(-10) OVER w FROM numbers", 3515 err: "syntax error at position 15", 3516 }, { 3517 input: "SELECT NTH_VALUE(val,) OVER w FROM numbers", 3518 err: "syntax error at position 23", 3519 }, { 3520 input: "SELECT NTH_VALUE(TRIM('abc'),-10) OVER w FROM numbers", 3521 err: "syntax error at position 31", 3522 }, { 3523 input: "SELECT LAG(val, ) OVER w", 3524 err: "syntax error at position 18", 3525 }, { 3526 input: "SELECT LAG(val, 10, ) OVER w", 3527 err: "syntax error at position 23", 3528 }, { 3529 input: "SELECT time, subject, val, FIRST_VALUE(val) OVER w AS 'first', LAST_VALUE(val) OVER w AS 'last', NTH_VALUE(val, 2) OVER w AS 'second', NTH_VALUE(val, 4) OVER w AS 'fourth' FROM observations WINDOW w AS (PARTITION BY subject ORDER BY time ROWS -10 FOLLOWING);", 3530 err: "syntax error at position 246", 3531 }, { 3532 input: "SELECT BIT_AND(DISTINCT a) FROM products", 3533 err: "syntax error at position 24 near 'DISTINCT'", 3534 }, { 3535 input: "SELECT BIT_OR(DISTINCT a) FROM products", 3536 err: "syntax error at position 23 near 'DISTINCT'", 3537 }, { 3538 input: "SELECT BIT_XOR(DISTINCT a) FROM products", 3539 err: "syntax error at position 24 near 'DISTINCT'", 3540 }, { 3541 input: "SELECT STD(DISTINCT a) FROM products", 3542 err: "syntax error at position 20 near 'DISTINCT'", 3543 }, { 3544 input: "SELECT STDDEV(DISTINCT a) FROM products", 3545 err: "syntax error at position 23 near 'DISTINCT'", 3546 }, { 3547 input: "SELECT STDDEV_POP(DISTINCT a) FROM products", 3548 err: "syntax error at position 27 near 'DISTINCT'", 3549 }, { 3550 input: "SELECT STDDEV_SAMP(DISTINCT a) FROM products", 3551 err: "syntax error at position 28 near 'DISTINCT'", 3552 }, { 3553 input: "SELECT VAR_POP(DISTINCT a) FROM products", 3554 err: "syntax error at position 24 near 'DISTINCT'", 3555 }, { 3556 input: "SELECT VAR_SAMP(DISTINCT a) FROM products", 3557 err: "syntax error at position 25 near 'DISTINCT'", 3558 }, { 3559 input: "SELECT VARIANCE(DISTINCT a) FROM products", 3560 err: "syntax error at position 25 near 'DISTINCT'", 3561 }, { 3562 input: "SELECT COUNT(DISTINCT *) FROM user", 3563 err: "syntax error at position 24", 3564 }, { 3565 input: "SELECT x'018' FROM user", 3566 err: "syntax error at position 14", 3567 }, { 3568 input: "SELECT b'012' FROM user", 3569 err: "syntax error at position 12", 3570 }, { 3571 input: "SELECT 0b2 FROM user", 3572 err: "syntax error at position 11", 3573 }, 3574 } 3575 3576 for _, tcase := range invalidSQL { 3577 t.Run(tcase.input, func(t *testing.T) { 3578 _, err := Parse(tcase.input) 3579 require.Error(t, err) 3580 require.Contains(t, err.Error(), tcase.err) 3581 }) 3582 } 3583 } 3584 3585 func TestIntroducers(t *testing.T) { 3586 validSQL := []struct { 3587 input string 3588 output string 3589 }{{ 3590 input: "select _armscii8 'x'", 3591 output: "select _armscii8 'x' from dual", 3592 }, { 3593 input: "select _ascii 'x'", 3594 output: "select _ascii 'x' from dual", 3595 }, { 3596 input: "select _big5 'x'", 3597 output: "select _big5 'x' from dual", 3598 }, { 3599 input: "select _binary 'x'", 3600 output: "select _binary 'x' from dual", 3601 }, { 3602 input: "select _cp1250 'x'", 3603 output: "select _cp1250 'x' from dual", 3604 }, { 3605 input: "select _cp1251 'x'", 3606 output: "select _cp1251 'x' from dual", 3607 }, { 3608 input: "select _cp1256 'x'", 3609 output: "select _cp1256 'x' from dual", 3610 }, { 3611 input: "select _cp1257 'x'", 3612 output: "select _cp1257 'x' from dual", 3613 }, { 3614 input: "select _cp850 'x'", 3615 output: "select _cp850 'x' from dual", 3616 }, { 3617 input: "select _cp852 'x'", 3618 output: "select _cp852 'x' from dual", 3619 }, { 3620 input: "select _cp866 'x'", 3621 output: "select _cp866 'x' from dual", 3622 }, { 3623 input: "select _cp932 'x'", 3624 output: "select _cp932 'x' from dual", 3625 }, { 3626 input: "select _dec8 'x'", 3627 output: "select _dec8 'x' from dual", 3628 }, { 3629 input: "select _eucjpms 'x'", 3630 output: "select _eucjpms 'x' from dual", 3631 }, { 3632 input: "select _euckr 'x'", 3633 output: "select _euckr 'x' from dual", 3634 }, { 3635 input: "select _gb18030 'x'", 3636 output: "select _gb18030 'x' from dual", 3637 }, { 3638 input: "select _gb2312 'x'", 3639 output: "select _gb2312 'x' from dual", 3640 }, { 3641 input: "select _gbk 'x'", 3642 output: "select _gbk 'x' from dual", 3643 }, { 3644 input: "select _geostd8 'x'", 3645 output: "select _geostd8 'x' from dual", 3646 }, { 3647 input: "select _greek 'x'", 3648 output: "select _greek 'x' from dual", 3649 }, { 3650 input: "select _hebrew 'x'", 3651 output: "select _hebrew 'x' from dual", 3652 }, { 3653 input: "select _hp8 'x'", 3654 output: "select _hp8 'x' from dual", 3655 }, { 3656 input: "select _keybcs2 'x'", 3657 output: "select _keybcs2 'x' from dual", 3658 }, { 3659 input: "select _koi8r 'x'", 3660 output: "select _koi8r 'x' from dual", 3661 }, { 3662 input: "select _koi8u 'x'", 3663 output: "select _koi8u 'x' from dual", 3664 }, { 3665 input: "select _latin1 'x'", 3666 output: "select _latin1 'x' from dual", 3667 }, { 3668 input: "select _latin2 'x'", 3669 output: "select _latin2 'x' from dual", 3670 }, { 3671 input: "select _latin5 'x'", 3672 output: "select _latin5 'x' from dual", 3673 }, { 3674 input: "select _latin7 'x'", 3675 output: "select _latin7 'x' from dual", 3676 }, { 3677 input: "select _macce 'x'", 3678 output: "select _macce 'x' from dual", 3679 }, { 3680 input: "select _macroman 'x'", 3681 output: "select _macroman 'x' from dual", 3682 }, { 3683 input: "select _sjis 'x'", 3684 output: "select _sjis 'x' from dual", 3685 }, { 3686 input: "select _swe7 'x'", 3687 output: "select _swe7 'x' from dual", 3688 }, { 3689 input: "select _tis620 'x'", 3690 output: "select _tis620 'x' from dual", 3691 }, { 3692 input: "select _ucs2 'x'", 3693 output: "select _ucs2 'x' from dual", 3694 }, { 3695 input: "select _ujis 'x'", 3696 output: "select _ujis 'x' from dual", 3697 }, { 3698 input: "select _utf16 'x'", 3699 output: "select _utf16 'x' from dual", 3700 }, { 3701 input: "select _utf16le 'x'", 3702 output: "select _utf16le 'x' from dual", 3703 }, { 3704 input: "select _utf32 'x'", 3705 output: "select _utf32 'x' from dual", 3706 }, { 3707 input: "select _utf8 'x'", 3708 output: "select _utf8 'x' from dual", 3709 }, { 3710 input: "select _utf8mb4 'x'", 3711 output: "select _utf8mb4 'x' from dual", 3712 }, { 3713 input: "select _utf8mb3 'x'", 3714 output: "select _utf8 'x' from dual", 3715 }} 3716 for _, tcase := range validSQL { 3717 t.Run(tcase.input, func(t *testing.T) { 3718 if tcase.output == "" { 3719 tcase.output = tcase.input 3720 } 3721 tree, err := Parse(tcase.input) 3722 assert.NoError(t, err) 3723 out := String(tree) 3724 assert.Equal(t, tcase.output, out) 3725 }) 3726 } 3727 } 3728 3729 func TestCaseSensitivity(t *testing.T) { 3730 validSQL := []struct { 3731 input string 3732 output string 3733 }{{ 3734 input: "create table A (\n\t`B` int\n)", 3735 output: "create table A (\n\tB int\n)", 3736 }, { 3737 input: "create index b on A (col1 desc)", 3738 output: "alter table A add index b (col1 desc)", 3739 }, { 3740 input: "alter table A foo", 3741 output: "alter table A", 3742 }, { 3743 input: "alter table A convert unparsable", 3744 output: "alter table A", 3745 }, { 3746 // View names get lower-cased. 3747 input: "alter view A as select * from t", 3748 output: "alter view a as select * from t", 3749 }, { 3750 input: "alter table A rename to B", 3751 output: "alter table A rename B", 3752 }, { 3753 input: "alter table `A r` rename to `B r`", 3754 output: "alter table `A r` rename `B r`", 3755 }, { 3756 input: "rename table A to B", 3757 }, { 3758 input: "drop table B", 3759 output: "drop table B", 3760 }, { 3761 input: "drop table if exists B", 3762 output: "drop table if exists B", 3763 }, { 3764 input: "drop index b on A", 3765 output: "alter table A drop key b", 3766 }, { 3767 input: "select a from B", 3768 }, { 3769 input: "select A as B from C", 3770 }, { 3771 input: "select B.* from c", 3772 }, { 3773 input: "select B.A from c", 3774 }, { 3775 input: "select * from B as C", 3776 }, { 3777 input: "select * from A.B", 3778 }, { 3779 input: "update A set b = 1", 3780 }, { 3781 input: "update A.B set b = 1", 3782 }, { 3783 input: "select A() from b", 3784 }, { 3785 input: "select A(B, C) from b", 3786 }, { 3787 // IF is an exception. It's always lower-cased. 3788 input: "select IF(B, C) from b", 3789 output: "select if(B, C) from b", 3790 }, { 3791 input: "select * from b use index (A)", 3792 }, { 3793 input: "insert into A(A, B) values (1, 2)", 3794 }, { 3795 input: "CREATE TABLE A (\n\t`A` int\n)", 3796 output: "create table A (\n\tA int\n)", 3797 }, { 3798 input: "create view A as select * from b", 3799 output: "create view a as select * from b", 3800 }, { 3801 input: "drop view A", 3802 output: "drop view a", 3803 }, { 3804 input: "drop view if exists A", 3805 output: "drop view if exists a", 3806 }, { 3807 input: "select /* lock in SHARE MODE */ 1 from t lock in SHARE MODE", 3808 output: "select /* lock in SHARE MODE */ 1 from t lock in share mode", 3809 }, { 3810 input: "select next VALUE from t", 3811 output: "select next 1 values from t", 3812 }, { 3813 input: "select /* use */ 1 from t1 use index (A) where b = 1", 3814 }} 3815 for _, tcase := range validSQL { 3816 if tcase.output == "" { 3817 tcase.output = tcase.input 3818 } 3819 tree, err := Parse(tcase.input) 3820 if err != nil { 3821 t.Errorf("input: %s, err: %v", tcase.input, err) 3822 continue 3823 } 3824 out := String(tree) 3825 if out != tcase.output { 3826 t.Errorf("out: %s, want %s", out, tcase.output) 3827 } 3828 } 3829 } 3830 3831 func TestKeywords(t *testing.T) { 3832 validSQL := []struct { 3833 input string 3834 output string 3835 }{{ 3836 input: "select current_timestamp", 3837 output: "select current_timestamp() from dual", 3838 }, { 3839 input: "update t set a = current_timestamp()", 3840 }, { 3841 input: "update t set a = current_timestamp(5)", 3842 }, { 3843 input: "select a, current_date from t", 3844 output: "select a, current_date() from t", 3845 }, { 3846 input: "insert into t(a, b) values (current_date, current_date())", 3847 output: "insert into t(a, b) values (current_date(), current_date())", 3848 }, { 3849 input: "select * from t where a > utc_timestmp()", 3850 }, { 3851 input: "select * from t where a > utc_timestamp(4)", 3852 }, { 3853 input: "update t set b = utc_timestamp + 5", 3854 output: "update t set b = utc_timestamp() + 5", 3855 }, { 3856 input: "select utc_time, utc_date, utc_time(6)", 3857 output: "select utc_time(), utc_date(), utc_time(6) from dual", 3858 }, { 3859 input: "select 1 from dual where localtime > utc_time", 3860 output: "select 1 from dual where localtime() > utc_time()", 3861 }, { 3862 input: "select 1 from dual where localtime(2) > utc_time(1)", 3863 output: "select 1 from dual where localtime(2) > utc_time(1)", 3864 }, { 3865 input: "update t set a = localtimestamp(), b = utc_timestamp", 3866 output: "update t set a = localtimestamp(), b = utc_timestamp()", 3867 }, { 3868 input: "update t set a = localtimestamp(10), b = utc_timestamp(13)", 3869 output: "update t set a = localtimestamp(10), b = utc_timestamp(13)", 3870 }, { 3871 input: "insert into t(a) values (unix_timestamp)", 3872 }, { 3873 input: "select replace(a, 'foo', 'bar') from t", 3874 }, { 3875 input: "update t set a = replace('1234', '2', '1')", 3876 }, { 3877 input: "insert into t(a, b) values ('foo', 'bar') on duplicate key update a = replace(hex('foo'), 'f', 'b')", 3878 }, { 3879 input: "update t set a = left('1234', 3)", 3880 }, { 3881 input: "select left(a, 5) from t", 3882 }, { 3883 input: "update t set d = adddate(date('2003-12-31 01:02:03'), interval 5 days)", 3884 }, { 3885 input: "insert into t(a, b) values (left('foo', 1), 'b')", 3886 }, { 3887 input: "insert /* qualified function */ into t(a, b) values (test.PI(), 'b')", 3888 }, { 3889 input: "select /* keyword in qualified id */ * from t join z on t.key = z.key", 3890 output: "select /* keyword in qualified id */ * from t join z on t.`key` = z.`key`", 3891 }, { 3892 input: "select /* non-reserved keywords as unqualified cols */ date, view, offset from t", 3893 output: "select /* non-reserved keywords as unqualified cols */ `date`, `view`, `offset` from t", 3894 }, { 3895 input: "select /* share and mode as cols */ share, mode from t where share = 'foo'", 3896 output: "select /* share and mode as cols */ `share`, `mode` from t where `share` = 'foo'", 3897 }, { 3898 input: "select status from t", 3899 output: "select `status` from t", 3900 }, { 3901 input: "select Status from t", 3902 output: "select `Status` from t", 3903 }, { 3904 input: "select variables from t", 3905 output: "select `variables` from t", 3906 }, { 3907 input: "select Variables from t", 3908 output: "select `Variables` from t", 3909 }, { 3910 input: "select current_user, current_user() from dual", 3911 output: "select current_user(), current_user() from dual", 3912 }} 3913 3914 for _, tcase := range validSQL { 3915 if tcase.output == "" { 3916 tcase.output = tcase.input 3917 } 3918 tree, err := Parse(tcase.input) 3919 if err != nil { 3920 t.Errorf("input: %s, err: %v", tcase.input, err) 3921 continue 3922 } 3923 out := String(tree) 3924 if out != tcase.output { 3925 t.Errorf("out: %s, want %s", out, tcase.output) 3926 } 3927 } 3928 } 3929 3930 func TestConvert(t *testing.T) { 3931 validSQL := []struct { 3932 input string 3933 output string 3934 }{{ 3935 input: "select cast('abc' as date) from t", 3936 }, { 3937 input: "select convert('abc', binary(4)) from t", 3938 }, { 3939 input: "select convert('abc', binary) from t", 3940 }, { 3941 input: "select convert('abc', char character set binary) from t", 3942 }, { 3943 input: "select convert('abc', char(4) ascii) from t", 3944 output: "select convert('abc', char(4) character set latin1) from t", 3945 }, { 3946 input: "select convert('abc', char(4) ascii binary) from t", 3947 output: "select convert('abc', char(4) character set latin1 binary) from t", 3948 }, { 3949 input: "select convert('abc', char unicode) from t", 3950 output: "select convert('abc', char character set ucs2) from t", 3951 }, { 3952 input: "select convert('abc', char(4)) from t", 3953 }, { 3954 input: "select convert('abc', char) from t", 3955 }, { 3956 input: "select convert('abc', nchar(4)) from t", 3957 }, { 3958 input: "select convert('abc', nchar) from t", 3959 }, { 3960 input: "select convert('abc', signed) from t", 3961 }, { 3962 input: "select convert('abc', signed integer) from t", 3963 output: "select convert('abc', signed) from t", 3964 }, { 3965 input: "select convert('abc', unsigned) from t", 3966 }, { 3967 input: "select convert('abc', unsigned integer) from t", 3968 output: "select convert('abc', unsigned) from t", 3969 }, { 3970 input: "select convert('abc', decimal(3, 4)) from t", 3971 }, { 3972 input: "select convert('abc', decimal(4)) from t", 3973 }, { 3974 input: "select convert('abc', decimal) from t", 3975 }, { 3976 input: "select convert('abc', date) from t", 3977 }, { 3978 input: "select convert('abc', time(4)) from t", 3979 }, { 3980 input: "select convert('abc', time) from t", 3981 }, { 3982 input: "select convert('abc', datetime(9)) from t", 3983 }, { 3984 input: "select convert('abc', datetime) from t", 3985 }, { 3986 input: "select convert('abc', json) from t", 3987 }, { 3988 input: "select cast(json_keys(c) as char(64) array) from t", 3989 }} 3990 3991 for _, tcase := range validSQL { 3992 if tcase.output == "" { 3993 tcase.output = tcase.input 3994 } 3995 tree, err := Parse(tcase.input) 3996 if err != nil { 3997 t.Errorf("input: %s, err: %v", tcase.input, err) 3998 continue 3999 } 4000 out := String(tree) 4001 if out != tcase.output { 4002 t.Errorf("out: %s, want %s", out, tcase.output) 4003 } 4004 } 4005 4006 invalidSQL := []struct { 4007 input string 4008 output string 4009 }{{ 4010 input: "select convert('abc' as date) from t", 4011 output: "syntax error at position 24 near 'as'", 4012 }, { 4013 input: "select convert from t", 4014 output: "syntax error at position 20 near 'from'", 4015 }, { 4016 input: "select cast('foo', decimal) from t", 4017 output: "syntax error at position 19", 4018 }, { 4019 input: "select convert('abc', datetime(4+9)) from t", 4020 output: "syntax error at position 34", 4021 }, { 4022 input: "select convert('abc', decimal(4+9)) from t", 4023 output: "syntax error at position 33", 4024 }, { 4025 input: "set transaction isolation level 12345", 4026 output: "syntax error at position 38 near '12345'", 4027 }, { 4028 input: "@", 4029 output: "syntax error at position 2", 4030 }, { 4031 input: "@@", 4032 output: "syntax error at position 3", 4033 }, { 4034 input: "select A(distinct B, C) from b", 4035 output: "syntax error at position 18 near 'distinct'", 4036 }} 4037 4038 for _, tcase := range invalidSQL { 4039 _, err := Parse(tcase.input) 4040 if err == nil || err.Error() != tcase.output { 4041 t.Errorf("%s: %v, want %s", tcase.input, err, tcase.output) 4042 } 4043 } 4044 } 4045 4046 func TestSelectInto(t *testing.T) { 4047 validSQL := []struct { 4048 input string 4049 output string 4050 }{{ 4051 input: "select * from t order by name limit 100 into outfile s3 'out_file_name'", 4052 output: "select * from t order by `name` asc limit 100 into outfile s3 'out_file_name'", 4053 }, { 4054 input: `select * from TestPerson into outfile s3 's3://test-bucket/export_import/export/users.csv' fields terminated by ',' enclosed by '\"' escaped by '\\' overwrite on`, 4055 }, { 4056 input: "select * from t into dumpfile 'out_file_name'", 4057 }, { 4058 input: "select * from t into outfile 'out_file_name' character set binary fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\\n'", 4059 }, { 4060 input: "select * from t into outfile s3 'out_file_name' character set binary format csv header fields terminated by 'term' optionally enclosed by 'c' escaped by 'e' lines starting by 'a' terminated by '\\n' manifest on overwrite off", 4061 }, { 4062 input: "select * from t into outfile s3 'out_file_name' character set binary lines terminated by '\\n' starting by 'a' manifest on overwrite off", 4063 }, { 4064 input: "select * from (select * from t union select * from t2) as t3 where t3.name in (select col from t4) into outfile s3 'out_file_name'", 4065 output: "select * from (select * from t union select * from t2) as t3 where t3.`name` in (select col from t4) into outfile s3 'out_file_name'", 4066 }, { 4067 input: `select * from TestPerson into outfile s3 's3://test-bucket/export_import/export/users.csv' character set 'utf8' overwrite on`, 4068 }, { 4069 input: `select * from t1 into outfile '/tmp/foo.csv' fields escaped by '\\' terminated by '\n'`, 4070 }, { 4071 input: `select * from t1 into outfile '/tmp/foo.csv' fields escaped by 'c' terminated by '\n' enclosed by '\t'`, 4072 }, { 4073 input: `alter vschema create vindex my_vdx using hash`, 4074 output: "alter vschema create vindex my_vdx using `hash`", 4075 }} 4076 4077 for _, tcase := range validSQL { 4078 t.Run(tcase.input, func(t *testing.T) { 4079 if tcase.output == "" { 4080 tcase.output = tcase.input 4081 } 4082 tree, err := Parse(tcase.input) 4083 require.NoError(t, err) 4084 out := String(tree) 4085 assert.Equal(t, tcase.output, out) 4086 }) 4087 } 4088 4089 invalidSQL := []struct { 4090 input string 4091 output string 4092 }{{ 4093 input: "select convert('abc' as date) from t", 4094 output: "syntax error at position 24 near 'as'", 4095 }, { 4096 input: "set transaction isolation level 12345", 4097 output: "syntax error at position 38 near '12345'", 4098 }} 4099 4100 for _, tcase := range invalidSQL { 4101 _, err := Parse(tcase.input) 4102 if err == nil || err.Error() != tcase.output { 4103 t.Errorf("%s: %v, want %s", tcase.input, err, tcase.output) 4104 } 4105 } 4106 } 4107 4108 func TestPositionedErr(t *testing.T) { 4109 invalidSQL := []struct { 4110 input string 4111 output PositionedErr 4112 }{{ 4113 input: "select convert('abc' as date) from t", 4114 output: PositionedErr{"syntax error", 24, "as"}, 4115 }, { 4116 input: "select convert from t", 4117 output: PositionedErr{"syntax error", 20, "from"}, 4118 }, { 4119 input: "select cast('foo', decimal) from t", 4120 output: PositionedErr{"syntax error", 19, ""}, 4121 }, { 4122 input: "select convert('abc', datetime(4+9)) from t", 4123 output: PositionedErr{"syntax error", 34, ""}, 4124 }, { 4125 input: "select convert('abc', decimal(4+9)) from t", 4126 output: PositionedErr{"syntax error", 33, ""}, 4127 }, { 4128 input: "set transaction isolation level 12345", 4129 output: PositionedErr{"syntax error", 38, "12345"}, 4130 }, { 4131 input: "select * from a left join b", 4132 output: PositionedErr{"syntax error", 28, ""}, 4133 }, { 4134 input: "select a from (select * from tbl)", 4135 output: PositionedErr{"syntax error", 34, ""}, 4136 }} 4137 4138 for _, tcase := range invalidSQL { 4139 tkn := NewStringTokenizer(tcase.input) 4140 _, err := ParseNext(tkn) 4141 4142 if posErr, ok := err.(PositionedErr); !ok { 4143 t.Errorf("%s: %v expected PositionedErr, got (%T) %v", tcase.input, err, err, tcase.output) 4144 } else if posErr.Pos != tcase.output.Pos || posErr.Near != tcase.output.Near || err.Error() != tcase.output.Error() { 4145 t.Errorf("%s: %v, want: %v", tcase.input, err, tcase.output) 4146 } 4147 } 4148 } 4149 4150 func TestSubStr(t *testing.T) { 4151 4152 validSQL := []struct { 4153 input string 4154 output string 4155 }{{ 4156 input: `select substr('foobar', 1) from t`, 4157 }, { 4158 input: "select substr(a, 1, 6) from t", 4159 }, { 4160 input: "select substring(a, 1) from t", 4161 output: "select substr(a, 1) from t", 4162 }, { 4163 input: "select substring(a, 1, 6) from t", 4164 output: "select substr(a, 1, 6) from t", 4165 }, { 4166 input: "select substr(a from 1 for 6) from t", 4167 output: "select substr(a, 1, 6) from t", 4168 }, { 4169 input: "select substring(a from 1 for 6) from t", 4170 output: "select substr(a, 1, 6) from t", 4171 }, { 4172 input: `select substr("foo" from 1 for 2) from t`, 4173 output: `select substr('foo', 1, 2) from t`, 4174 }, { 4175 input: `select substring("foo", 1, 2) from t`, 4176 output: `select substr('foo', 1, 2) from t`, 4177 }, { 4178 input: `select substr(substr("foo" from 1 for 2), 1, 2) from t`, 4179 output: `select substr(substr('foo', 1, 2), 1, 2) from t`, 4180 }, { 4181 input: `select substr(substring("foo", 1, 2), 3, 4) from t`, 4182 output: `select substr(substr('foo', 1, 2), 3, 4) from t`, 4183 }, { 4184 input: `select substring(substr("foo", 1), 2) from t`, 4185 output: `select substr(substr('foo', 1), 2) from t`, 4186 }} 4187 4188 for _, tcase := range validSQL { 4189 if tcase.output == "" { 4190 tcase.output = tcase.input 4191 } 4192 tree, err := Parse(tcase.input) 4193 if err != nil { 4194 t.Errorf("input: %s, err: %v", tcase.input, err) 4195 continue 4196 } 4197 out := String(tree) 4198 if out != tcase.output { 4199 t.Errorf("out: %s, want %s", out, tcase.output) 4200 } 4201 } 4202 } 4203 4204 func TestLoadData(t *testing.T) { 4205 validSQL := []string{ 4206 "load data from s3 'x.txt'", 4207 "load data from s3 manifest 'x.txt'", 4208 "load data from s3 file 'x.txt'", 4209 "load data infile 'x.txt' into table 'c'", 4210 "load data from s3 'x.txt' into table x"} 4211 4212 for _, tcase := range validSQL { 4213 _, err := Parse(tcase) 4214 require.NoError(t, err) 4215 } 4216 } 4217 4218 func TestCreateTable(t *testing.T) { 4219 createTableQueries := []struct { 4220 input, output string 4221 }{{ 4222 // test all the data types and options 4223 input: `create table t ( 4224 col_bit bit, 4225 col_tinyint tinyint auto_increment, 4226 col_tinyint3 tinyint(3) unsigned, 4227 col_smallint smallint, 4228 col_smallint4 smallint(4) zerofill, 4229 col_mediumint mediumint, 4230 col_mediumint5 mediumint(5) unsigned not null, 4231 col_int int, 4232 col_int10 int(10) not null, 4233 col_integer integer comment 'this is an integer', 4234 col_bigint bigint, 4235 col_bigint10 bigint(10) zerofill not null default 10, 4236 col_real real, 4237 col_real2 real(1,2) not null default 1.23, 4238 col_double double, 4239 col_double2 double(3,4) not null default 1.23, 4240 col_float float, 4241 col_float2 float(3,4) not null default 1.23, 4242 col_decimal decimal, 4243 col_decimal2 decimal(2), 4244 col_decimal3 decimal(2,3), 4245 col_numeric numeric, 4246 col_numeric2 numeric(2), 4247 col_numeric3 numeric(2,3), 4248 col_date date, 4249 col_time time, 4250 col_timestamp timestamp, 4251 col_datetime datetime, 4252 col_year year, 4253 col_char char, 4254 col_char2 char(2), 4255 col_char3 char(3) character set ascii, 4256 col_char4 char(4) character set ascii collate ascii_bin, 4257 col_varchar varchar, 4258 col_varchar2 varchar(2), 4259 col_varchar3 varchar(3) character set ascii, 4260 col_varchar4 varchar(4) character set ascii collate ascii_bin, 4261 col_binary binary, 4262 col_varbinary varbinary(10), 4263 col_tinyblob tinyblob, 4264 col_blob blob, 4265 col_mediumblob mediumblob, 4266 col_longblob longblob, 4267 col_tinytext tinytext, 4268 col_text text, 4269 col_mediumtext mediumtext, 4270 col_longtext longtext, 4271 col_text text character set ascii collate ascii_bin, 4272 col_json json, 4273 col_enum enum('a', 'b', 'c', 'd'), 4274 col_enum2 enum('a', 'b', 'c', 'd') character set ascii, 4275 col_enum3 enum('a', 'b', 'c', 'd') collate ascii_bin, 4276 col_enum4 enum('a', 'b', 'c', 'd') character set ascii collate ascii_bin, 4277 col_set set('a', 'b', 'c', 'd'), 4278 col_set2 set('a', 'b', 'c', 'd') character set ascii, 4279 col_set3 set('a', 'b', 'c', 'd') collate ascii_bin, 4280 col_set4 set('a', 'b', 'c', 'd') character set ascii collate ascii_bin, 4281 col_geometry1 geometry, 4282 col_geometry2 geometry not null, 4283 col_point1 point, 4284 col_point2 point not null, 4285 col_linestring1 linestring, 4286 col_linestring2 linestring not null, 4287 col_polygon1 polygon, 4288 col_polygon2 polygon not null, 4289 col_geometrycollection1 geometrycollection, 4290 col_geometrycollection2 geometrycollection not null, 4291 col_multipoint1 multipoint, 4292 col_multipoint2 multipoint not null, 4293 col_multilinestring1 multilinestring, 4294 col_multilinestring2 multilinestring not null, 4295 col_multipolygon1 multipolygon, 4296 col_multipolygon2 multipolygon not null 4297 )`, 4298 }, 4299 // test null columns 4300 { 4301 input: `create table foo ( 4302 id int primary key, 4303 a varchar(255) null, 4304 b varchar(255) null default 'foo', 4305 c timestamp null default current_timestamp() 4306 )`, 4307 }, 4308 // test defining indexes separately 4309 { 4310 input: `create table t ( 4311 id int auto_increment, 4312 username varchar, 4313 email varchar, 4314 full_name varchar, 4315 geom point not null, 4316 status_nonkeyword varchar, 4317 primary key (id), 4318 spatial key geom (geom), 4319 fulltext key fts (full_name), 4320 unique key by_username (username), 4321 unique key by_username2 (username), 4322 unique index by_username3 (username), 4323 index by_status (status_nonkeyword), 4324 key by_full_name (full_name) 4325 )`, 4326 }, 4327 // test defining index visibility 4328 { 4329 input: `create table t ( 4330 id int auto_increment, 4331 username varchar, 4332 unique key by_username (username) visible, 4333 unique key by_username2 (username) invisible, 4334 unique index by_username3 (username) 4335 )`, 4336 }, 4337 // test adding engine attributes 4338 { 4339 input: `create table t ( 4340 id int auto_increment, 4341 username varchar, 4342 unique key by_username (username) engine_attribute '{}' secondary_engine_attribute '{}', 4343 unique index by_username3 (username) 4344 )`, 4345 }, 4346 // test defining SRID 4347 { 4348 input: `create table t ( 4349 p point srid 0, 4350 g geometry not null srid 4326 4351 )`, 4352 }, 4353 // test defining column visibility 4354 { 4355 input: `create table t ( 4356 id int auto_increment, 4357 username varchar invisible, 4358 login varchar visible 4359 )`, 4360 }, 4361 // test adding column engine attributes 4362 { 4363 input: `create table t ( 4364 id int auto_increment, 4365 username varchar engine_attribute '{}' secondary_engine_attribute '{}' 4366 )`, 4367 }, 4368 // test adding column format 4369 { 4370 input: `create table t ( 4371 id int auto_increment, 4372 username varchar column_format dynamic 4373 )`, 4374 }, 4375 // test that indexes support USING <id> 4376 { 4377 input: `create table t ( 4378 id int auto_increment, 4379 username varchar, 4380 email varchar, 4381 full_name varchar, 4382 status_nonkeyword varchar, 4383 primary key (id) using BTREE, 4384 unique key by_username (username) using HASH, 4385 unique key by_username2 (username) using OTHER, 4386 unique index by_username3 (username) using XYZ, 4387 index by_status (status_nonkeyword) using PDQ, 4388 key by_full_name (full_name) using OTHER 4389 )`, 4390 }, 4391 // test other index options 4392 { 4393 input: `create table t ( 4394 id int auto_increment, 4395 username varchar, 4396 email varchar, 4397 primary key (id) comment 'hi', 4398 unique key by_username (username) key_block_size 8, 4399 unique index by_username4 (username) comment 'hi' using BTREE, 4400 unique index by_username4 (username) using BTREE key_block_size 4 comment 'hi' 4401 )`, 4402 }, 4403 { 4404 input: `create table t1 ( 4405 first_name varchar(10), 4406 last_name varchar(10), 4407 full_name varchar(255) character set utf8mb4 collate utf8mb4_0900_ai_ci as (concat(first_name, ' ', last_name)) virtual, 4408 middle_name varchar(255) character set utf8mb4 collate utf8mb4_0900_ai_ci default '' collate utf8mb4_bin 4409 )`, 4410 output: `create table t1 ( 4411 first_name varchar(10), 4412 last_name varchar(10), 4413 full_name varchar(255) character set utf8mb4 collate utf8mb4_0900_ai_ci as (concat(first_name, ' ', last_name)) virtual, 4414 middle_name varchar(255) character set utf8mb4 collate utf8mb4_bin default '' 4415 )`, 4416 }, 4417 { 4418 input: "create table t1 (`idb` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci GENERATED ALWAYS AS (json_unquote(json_extract(`jsonobj`,_utf8mb4'$._id'))) STORED NOT NULL)", 4419 output: `create table t1 ( 4420 idb varchar(36) character set utf8mb4 collate utf8mb4_0900_ai_ci as (json_unquote(json_extract(jsonobj, _utf8mb4 '$._id'))) stored not null 4421 )`, 4422 }, 4423 { 4424 input: "create table t2 (\n\tid int not null,\n\textra tinyint(1) as (id = 1) stored,\n\tPRIMARY KEY (id)\n)", 4425 }, 4426 // multi-column indexes 4427 { 4428 input: `create table t ( 4429 id int auto_increment, 4430 username varchar, 4431 email varchar, 4432 full_name varchar, 4433 a int, 4434 b int, 4435 c int, 4436 primary key (id, username), 4437 unique key by_abc (a, b, c), 4438 unique key (a, b, c), 4439 key by_email (email(10), username) 4440 )`, 4441 }, 4442 // geometrycollection & geomcollection alias 4443 { 4444 input: `create table t ( 4445 id int auto_increment, 4446 col_geometrycollection1 geometrycollection, 4447 col_geometrycollection2 geometrycollection not null, 4448 col_geometrycollection3 geomcollection, 4449 col_geometrycollection4 geomcollection not null, 4450 primary key (id) 4451 )`, 4452 }, 4453 // foreign keys 4454 { 4455 input: `create table t ( 4456 id int auto_increment, 4457 username varchar, 4458 k int, 4459 Z int, 4460 newCol int references t2 (a), 4461 newCol int references t2 (a) on delete restrict, 4462 newCol int references t2 (a) on delete no action, 4463 newCol int references t2 (a) on delete cascade on update set default, 4464 newCol int references t2 (a) on delete set default on update set null, 4465 newCol int references t2 (a) on delete set null on update restrict, 4466 newCol int references t2 (a) on update set default on delete cascade, 4467 newCol int references t2 (a) on update set null on delete set default, 4468 newCol int references t2 (a) on update restrict on delete set null, 4469 newCol int references t2 (a) match full on delete cascade on update set default, 4470 newCol int references t2 (a) match partial on delete set default on update set null, 4471 newCol int references t2 (a) match simple on delete set null on update restrict, 4472 newCol int references t2 (a) on update no action, 4473 newCol int references t2 (a) on update cascade, 4474 primary key (id, username), 4475 key by_email (email(10), username), 4476 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b), 4477 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete restrict, 4478 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete no action, 4479 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete cascade on update set default, 4480 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set default on update set null, 4481 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set null on update restrict, 4482 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update set default on delete cascade , 4483 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update set null on delete set default, 4484 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update restrict on delete set null, 4485 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match full on delete cascade on update set default, 4486 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match partial on delete set default on update set null, 4487 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match simple on delete set null on update restrict, 4488 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update no action, 4489 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update cascade 4490 )`, 4491 output: `create table t ( 4492 id int auto_increment, 4493 username varchar, 4494 k int, 4495 Z int, 4496 newCol int references t2 (a), 4497 newCol int references t2 (a) on delete restrict, 4498 newCol int references t2 (a) on delete no action, 4499 newCol int references t2 (a) on delete cascade on update set default, 4500 newCol int references t2 (a) on delete set default on update set null, 4501 newCol int references t2 (a) on delete set null on update restrict, 4502 newCol int references t2 (a) on delete cascade on update set default, 4503 newCol int references t2 (a) on delete set default on update set null, 4504 newCol int references t2 (a) on delete set null on update restrict, 4505 newCol int references t2 (a) match full on delete cascade on update set default, 4506 newCol int references t2 (a) match partial on delete set default on update set null, 4507 newCol int references t2 (a) match simple on delete set null on update restrict, 4508 newCol int references t2 (a) on update no action, 4509 newCol int references t2 (a) on update cascade, 4510 primary key (id, username), 4511 key by_email (email(10), username), 4512 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b), 4513 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete restrict, 4514 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete no action, 4515 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete cascade on update set default, 4516 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set default on update set null, 4517 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set null on update restrict, 4518 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete cascade on update set default, 4519 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set default on update set null, 4520 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on delete set null on update restrict, 4521 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match full on delete cascade on update set default, 4522 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match partial on delete set default on update set null, 4523 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) match simple on delete set null on update restrict, 4524 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update no action, 4525 constraint second_ibfk_1 foreign key (k, j) references t2 (a, b) on update cascade 4526 )`, 4527 }, 4528 // constraint name with spaces 4529 { 4530 input: `create table ` + "`" + `Post With Space` + "`" + ` ( 4531 id int(11) not null auto_increment, 4532 user_id int(11) not null, 4533 primary key (id), 4534 unique key post_user_unique (user_id), 4535 constraint ` + "`" + `Post With Space_ibfk_1` + "`" + ` foreign key (user_id) references ` + "`" + `User` + "`" + ` (id) 4536 ) ENGINE Innodb`, 4537 }, 4538 // table options 4539 { 4540 input: `create table t ( 4541 id int auto_increment 4542 ) engine InnoDB, 4543 auto_increment 123, 4544 autoextend_size 16, 4545 avg_row_length 1, 4546 charset utf8mb4, 4547 charset latin1, 4548 checksum 0, 4549 collate binary, 4550 collate ascii_bin, 4551 comment 'this is a comment', 4552 compression 'zlib', 4553 connection 'connect_string', 4554 data directory 'absolute path to directory', 4555 delay_key_write 1, 4556 encryption 'n', 4557 engine_attribute '{}', 4558 index directory 'absolute path to directory', 4559 insert_method no, 4560 key_block_size 1024, 4561 max_rows 100, 4562 min_rows 10, 4563 pack_keys 0, 4564 password 'sekret', 4565 row_format default, 4566 secondary_engine_attribute '{}', 4567 stats_auto_recalc default, 4568 stats_persistent 0, 4569 stats_sample_pages 1, 4570 tablespace tablespace_name storage disk, 4571 union (a, b, c), 4572 tablespace tablespace_name`, 4573 }, 4574 // boolean columns 4575 { 4576 input: `create table t ( 4577 bi bigint not null primary key, 4578 b1 bool not null, 4579 b2 boolean 4580 )`, 4581 }, 4582 { 4583 // test key_block_size 4584 input: `create table t ( 4585 id int auto_increment, 4586 username varchar, 4587 unique key by_username (username) key_block_size 8, 4588 unique key by_username2 (username) key_block_size=8, 4589 unique by_username3 (username) key_block_size = 4 4590 )`, 4591 output: `create table t ( 4592 id int auto_increment, 4593 username varchar, 4594 unique key by_username (username) key_block_size 8, 4595 unique key by_username2 (username) key_block_size 8, 4596 unique key by_username3 (username) key_block_size 4 4597 )`, 4598 }, { 4599 // test defaults 4600 input: `create table t ( 4601 i1 int default 1, 4602 i2 int default null, 4603 f1 float default 1.23, 4604 s1 varchar default 'c', 4605 s2 varchar default 'this is a string', 4606 s3 varchar default null, 4607 s4 timestamp default current_timestamp, 4608 s41 timestamp default now, 4609 s5 bit(1) default B'0' 4610 )`, 4611 output: `create table t ( 4612 i1 int default 1, 4613 i2 int default null, 4614 f1 float default 1.23, 4615 s1 varchar default 'c', 4616 s2 varchar default 'this is a string', 4617 ` + "`" + `s3` + "`" + ` varchar default null, 4618 s4 timestamp default current_timestamp(), 4619 s41 timestamp default now(), 4620 s5 bit(1) default B'0' 4621 )`, 4622 }, { 4623 // test non_reserved word in column name 4624 input: `create table t ( 4625 repair int 4626 )`, 4627 output: `create table t ( 4628 ` + "`" + `repair` + "`" + ` int 4629 )`, 4630 }, { 4631 // test key field options 4632 input: `create table t ( 4633 id int auto_increment primary key, 4634 username varchar unique key, 4635 email varchar unique, 4636 full_name varchar key, 4637 time1 timestamp on update current_timestamp, 4638 time2 timestamp default current_timestamp on update current_timestamp 4639 )`, 4640 output: `create table t ( 4641 id int auto_increment primary key, 4642 username varchar unique key, 4643 email varchar unique, 4644 full_name varchar key, 4645 time1 timestamp on update current_timestamp(), 4646 time2 timestamp default current_timestamp() on update current_timestamp() 4647 )`, 4648 }, { 4649 // test current_timestamp with and without () 4650 input: `create table t ( 4651 time1 timestamp default current_timestamp, 4652 time2 timestamp default current_timestamp(), 4653 time3 timestamp default current_timestamp on update current_timestamp, 4654 time4 timestamp default current_timestamp() on update current_timestamp(), 4655 time5 timestamp(3) default current_timestamp(3) on update current_timestamp(3) 4656 )`, 4657 output: `create table t ( 4658 time1 timestamp default current_timestamp(), 4659 time2 timestamp default current_timestamp(), 4660 time3 timestamp default current_timestamp() on update current_timestamp(), 4661 time4 timestamp default current_timestamp() on update current_timestamp(), 4662 time5 timestamp(3) default current_timestamp(3) on update current_timestamp(3) 4663 )`, 4664 }, { 4665 // test now with and without () 4666 input: `create table t ( 4667 time1 timestamp default now, 4668 time2 timestamp default now(), 4669 time3 timestamp default (now()), 4670 time4 timestamp default now on update now, 4671 time5 timestamp default now() on update now(), 4672 time6 timestamp(3) default now(3) on update now(3) 4673 )`, 4674 output: `create table t ( 4675 time1 timestamp default now(), 4676 time2 timestamp default now(), 4677 time3 timestamp default now(), 4678 time4 timestamp default now() on update now(), 4679 time5 timestamp default now() on update now(), 4680 time6 timestamp(3) default now(3) on update now(3) 4681 )`, 4682 }, { 4683 // test localtime with and without () 4684 input: `create table t ( 4685 time1 timestamp default localtime, 4686 time2 timestamp default localtime(), 4687 time3 timestamp default localtime on update localtime, 4688 time4 timestamp default localtime() on update localtime(), 4689 time5 timestamp(6) default localtime(6) on update localtime(6) 4690 )`, 4691 output: `create table t ( 4692 time1 timestamp default localtime(), 4693 time2 timestamp default localtime(), 4694 time3 timestamp default localtime() on update localtime(), 4695 time4 timestamp default localtime() on update localtime(), 4696 time5 timestamp(6) default localtime(6) on update localtime(6) 4697 )`, 4698 }, { 4699 // test localtimestamp with and without () 4700 input: `create table t ( 4701 time1 timestamp default localtimestamp, 4702 time2 timestamp default localtimestamp(), 4703 time3 timestamp default localtimestamp on update localtimestamp, 4704 time4 timestamp default localtimestamp() on update localtimestamp(), 4705 time5 timestamp(1) default localtimestamp(1) on update localtimestamp(1) 4706 )`, 4707 output: `create table t ( 4708 time1 timestamp default localtimestamp(), 4709 time2 timestamp default localtimestamp(), 4710 time3 timestamp default localtimestamp() on update localtimestamp(), 4711 time4 timestamp default localtimestamp() on update localtimestamp(), 4712 time5 timestamp(1) default localtimestamp(1) on update localtimestamp(1) 4713 )`, 4714 }, { 4715 input: `create table t1 ( 4716 first_name varchar(10), 4717 last_name varchar(10), 4718 full_name varchar(255) as (concat(first_name, ' ', last_name)) 4719 )`, output: `create table t1 ( 4720 first_name varchar(10), 4721 last_name varchar(10), 4722 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual 4723 )`, 4724 }, { 4725 input: `create table t1 (id int, gnrtd int as (id+2) virtual)`, 4726 output: `create table t1 ( 4727 id int, 4728 gnrtd int as (id + 2) virtual 4729 )`, 4730 }, { 4731 input: `create table t1 (first_name varchar(10), last_name varchar(10), 4732 full_name varchar(255) generated always as (concat(first_name, ' ', last_name)))`, 4733 output: `create table t1 ( 4734 first_name varchar(10), 4735 last_name varchar(10), 4736 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual 4737 )`, 4738 }, { 4739 input: `create table t1 (first_name varchar(10), last_name varchar(10), 4740 full_name varchar(255) generated always as (concat(first_name, ' ', last_name)) not null )`, 4741 output: `create table t1 ( 4742 first_name varchar(10), 4743 last_name varchar(10), 4744 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual not null 4745 )`, 4746 }, { 4747 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) null)`, 4748 output: `create table t1 ( 4749 first_name varchar(10), 4750 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual null 4751 )`, 4752 }, { 4753 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) unique)`, 4754 output: `create table t1 ( 4755 first_name varchar(10), 4756 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual unique 4757 )`, 4758 }, { 4759 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) unique key)`, 4760 output: `create table t1 ( 4761 first_name varchar(10), 4762 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual unique key 4763 )`, 4764 }, { 4765 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) key)`, 4766 output: `create table t1 ( 4767 first_name varchar(10), 4768 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual key 4769 )`, 4770 }, { 4771 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) primary key)`, 4772 output: `create table t1 ( 4773 first_name varchar(10), 4774 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual primary key 4775 )`, 4776 }, { 4777 input: `create table t1 (first_name varchar(10), full_name varchar(255) as (concat(first_name, ' ', last_name)) comment 'hello world')`, 4778 output: `create table t1 ( 4779 first_name varchar(10), 4780 full_name varchar(255) as (concat(first_name, ' ', last_name)) virtual comment 'hello world' 4781 )`, 4782 }, { 4783 input: `create table non_reserved_keyword (id int(11)) ENGINE = MEMORY`, 4784 output: `create table non_reserved_keyword ( 4785 id int(11) 4786 ) ENGINE MEMORY`, 4787 }, { 4788 input: `create table non_reserved_keyword (id int(11)) ENGINE = MEDIUMTEXT`, 4789 output: `create table non_reserved_keyword ( 4790 id int(11) 4791 ) ENGINE MEDIUMTEXT`, 4792 }, { 4793 input: `create table t1 (id int(11)) ENGINE = FOOBAR`, 4794 output: `create table t1 ( 4795 id int(11) 4796 ) ENGINE FOOBAR`, 4797 }, 4798 // partitions 4799 { 4800 input: ` 4801 CREATE TABLE employees ( 4802 id INT NOT NULL, 4803 fname VARCHAR(30), 4804 lname VARCHAR(30), 4805 hired DATE NOT NULL DEFAULT '1970-01-01', 4806 separated DATE NOT NULL DEFAULT '9999-12-31', 4807 job_code INT NOT NULL, 4808 store_id INT NOT NULL 4809 ) 4810 PARTITION BY RANGE (store_id) ( 4811 PARTITION p0 VALUES LESS THAN (6), 4812 PARTITION p1 VALUES LESS THAN (11), 4813 PARTITION p2 VALUES LESS THAN (16), 4814 PARTITION p3 VALUES LESS THAN (21) 4815 )`, 4816 output: `create table employees ( 4817 id INT not null, 4818 fname VARCHAR(30), 4819 lname VARCHAR(30), 4820 hired DATE not null default '1970-01-01', 4821 separated DATE not null default '9999-12-31', 4822 job_code INT not null, 4823 store_id INT not null 4824 ) 4825 partition by range (store_id) 4826 (partition p0 values less than (6), 4827 partition p1 values less than (11), 4828 partition p2 values less than (16), 4829 partition p3 values less than (21))`, 4830 }, 4831 { 4832 input: `CREATE TABLE employees ( 4833 id INT NOT NULL, 4834 fname VARCHAR(30), 4835 lname VARCHAR(30), 4836 hired DATE NOT NULL DEFAULT '1970-01-01', 4837 separated DATE NOT NULL DEFAULT '9999-12-31', 4838 job_code INT NOT NULL, 4839 store_id INT NOT NULL 4840 ) 4841 PARTITION BY RANGE (store_id) ( 4842 PARTITION p0 VALUES LESS THAN (6), 4843 PARTITION p1 VALUES LESS THAN (11), 4844 PARTITION p2 VALUES LESS THAN (16), 4845 PARTITION p3 VALUES LESS THAN MAXVALUE 4846 )`, 4847 output: `create table employees ( 4848 id INT not null, 4849 fname VARCHAR(30), 4850 lname VARCHAR(30), 4851 hired DATE not null default '1970-01-01', 4852 separated DATE not null default '9999-12-31', 4853 job_code INT not null, 4854 store_id INT not null 4855 ) 4856 partition by range (store_id) 4857 (partition p0 values less than (6), 4858 partition p1 values less than (11), 4859 partition p2 values less than (16), 4860 partition p3 values less than maxvalue)`, 4861 }, 4862 { 4863 input: `CREATE TABLE employees ( 4864 id INT NOT NULL, 4865 fname VARCHAR(30), 4866 lname VARCHAR(30), 4867 hired DATE NOT NULL DEFAULT '1970-01-01', 4868 separated DATE NOT NULL DEFAULT '9999-12-31', 4869 job_code INT NOT NULL, 4870 store_id INT NOT NULL 4871 ) 4872 PARTITION BY RANGE (job_code) ( 4873 PARTITION p0 VALUES LESS THAN (100), 4874 PARTITION p1 VALUES LESS THAN (1000), 4875 PARTITION p2 VALUES LESS THAN (10000) 4876 )`, 4877 output: `create table employees ( 4878 id INT not null, 4879 fname VARCHAR(30), 4880 lname VARCHAR(30), 4881 hired DATE not null default '1970-01-01', 4882 separated DATE not null default '9999-12-31', 4883 job_code INT not null, 4884 store_id INT not null 4885 ) 4886 partition by range (job_code) 4887 (partition p0 values less than (100), 4888 partition p1 values less than (1000), 4889 partition p2 values less than (10000))`, 4890 }, 4891 { 4892 input: `CREATE TABLE employees ( 4893 id INT NOT NULL, 4894 fname VARCHAR(30), 4895 lname VARCHAR(30), 4896 hired DATE NOT NULL DEFAULT '1970-01-01', 4897 separated DATE NOT NULL DEFAULT '9999-12-31', 4898 job_code INT, 4899 store_id INT 4900 ) 4901 PARTITION BY RANGE ( YEAR(separated) ) ( 4902 PARTITION p0 VALUES LESS THAN (1991), 4903 PARTITION p1 VALUES LESS THAN (1996), 4904 PARTITION p2 VALUES LESS THAN (2001), 4905 PARTITION p3 VALUES LESS THAN MAXVALUE 4906 )`, 4907 output: `create table employees ( 4908 id INT not null, 4909 fname VARCHAR(30), 4910 lname VARCHAR(30), 4911 hired DATE not null default '1970-01-01', 4912 separated DATE not null default '9999-12-31', 4913 job_code INT, 4914 store_id INT 4915 ) 4916 partition by range (YEAR(separated)) 4917 (partition p0 values less than (1991), 4918 partition p1 values less than (1996), 4919 partition p2 values less than (2001), 4920 partition p3 values less than maxvalue)`, 4921 }, 4922 { 4923 input: `CREATE TABLE quarterly_report_status ( 4924 report_id INT NOT NULL, 4925 report_status VARCHAR(20) NOT NULL, 4926 report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 4927 ) 4928 PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( 4929 PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ), 4930 PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ), 4931 PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ), 4932 PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ), 4933 PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ), 4934 PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ), 4935 PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ), 4936 PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ), 4937 PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ), 4938 PARTITION p9 VALUES LESS THAN (MAXVALUE) 4939 )`, 4940 output: `create table quarterly_report_status ( 4941 report_id INT not null, 4942 report_status VARCHAR(20) not null, 4943 report_updated TIMESTAMP not null default current_timestamp() on update current_timestamp() 4944 ) 4945 partition by range (UNIX_TIMESTAMP(report_updated)) 4946 (partition p0 values less than (UNIX_TIMESTAMP('2008-01-01 00:00:00')), 4947 partition p1 values less than (UNIX_TIMESTAMP('2008-04-01 00:00:00')), 4948 partition p2 values less than (UNIX_TIMESTAMP('2008-07-01 00:00:00')), 4949 partition p3 values less than (UNIX_TIMESTAMP('2008-10-01 00:00:00')), 4950 partition p4 values less than (UNIX_TIMESTAMP('2009-01-01 00:00:00')), 4951 partition p5 values less than (UNIX_TIMESTAMP('2009-04-01 00:00:00')), 4952 partition p6 values less than (UNIX_TIMESTAMP('2009-07-01 00:00:00')), 4953 partition p7 values less than (UNIX_TIMESTAMP('2009-10-01 00:00:00')), 4954 partition p8 values less than (UNIX_TIMESTAMP('2010-01-01 00:00:00')), 4955 partition p9 values less than maxvalue)`, 4956 }, 4957 { 4958 input: `CREATE TABLE quarterly_report_status ( 4959 report_id INT NOT NULL, 4960 report_status VARCHAR(20) NOT NULL, 4961 report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 4962 ) 4963 PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( 4964 PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ), 4965 PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ), 4966 PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ), 4967 PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ), 4968 PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ), 4969 PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ), 4970 PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ), 4971 PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ), 4972 PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ), 4973 PARTITION p9 VALUES LESS THAN (MAXVALUE) 4974 )`, 4975 output: `create table quarterly_report_status ( 4976 report_id INT not null, 4977 report_status VARCHAR(20) not null, 4978 report_updated TIMESTAMP not null default current_timestamp() on update current_timestamp() 4979 ) 4980 partition by range (UNIX_TIMESTAMP(report_updated)) 4981 (partition p0 values less than (UNIX_TIMESTAMP('2008-01-01 00:00:00')), 4982 partition p1 values less than (UNIX_TIMESTAMP('2008-04-01 00:00:00')), 4983 partition p2 values less than (UNIX_TIMESTAMP('2008-07-01 00:00:00')), 4984 partition p3 values less than (UNIX_TIMESTAMP('2008-10-01 00:00:00')), 4985 partition p4 values less than (UNIX_TIMESTAMP('2009-01-01 00:00:00')), 4986 partition p5 values less than (UNIX_TIMESTAMP('2009-04-01 00:00:00')), 4987 partition p6 values less than (UNIX_TIMESTAMP('2009-07-01 00:00:00')), 4988 partition p7 values less than (UNIX_TIMESTAMP('2009-10-01 00:00:00')), 4989 partition p8 values less than (UNIX_TIMESTAMP('2010-01-01 00:00:00')), 4990 partition p9 values less than maxvalue)`, 4991 }, 4992 { 4993 input: `CREATE TABLE members ( 4994 firstname VARCHAR(25) NOT NULL, 4995 lastname VARCHAR(25) NOT NULL, 4996 username VARCHAR(16) NOT NULL, 4997 email VARCHAR(35), 4998 joined DATE NOT NULL 4999 ) 5000 PARTITION BY RANGE COLUMNS(joined) ( 5001 PARTITION p0 VALUES LESS THAN ('1960-01-01'), 5002 PARTITION p1 VALUES LESS THAN ('1970-01-01'), 5003 PARTITION p2 VALUES LESS THAN ('1980-01-01'), 5004 PARTITION p3 VALUES LESS THAN ('1990-01-01'), 5005 PARTITION p4 VALUES LESS THAN MAXVALUE 5006 )`, 5007 output: `create table members ( 5008 firstname VARCHAR(25) not null, 5009 lastname VARCHAR(25) not null, 5010 username VARCHAR(16) not null, 5011 email VARCHAR(35), 5012 joined DATE not null 5013 ) 5014 partition by range columns (joined) 5015 (partition p0 values less than ('1960-01-01'), 5016 partition p1 values less than ('1970-01-01'), 5017 partition p2 values less than ('1980-01-01'), 5018 partition p3 values less than ('1990-01-01'), 5019 partition p4 values less than maxvalue)`, 5020 }, 5021 { 5022 input: `CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE) 5023 ENGINE=INNODB 5024 PARTITION BY HASH( MONTH(tr_date) ) 5025 PARTITIONS 6`, 5026 output: `create table ti ( 5027 id INT, 5028 amount DECIMAL(7,2), 5029 tr_date DATE 5030 ) ENGINE INNODB 5031 partition by hash (MONTH(tr_date)) partitions 6`, 5032 }, 5033 { 5034 input: `CREATE TABLE members ( 5035 firstname VARCHAR(25) NOT NULL, 5036 lastname VARCHAR(25) NOT NULL, 5037 username VARCHAR(16) NOT NULL, 5038 email VARCHAR(35), 5039 joined DATE NOT NULL 5040 ) 5041 PARTITION BY KEY(joined) 5042 PARTITIONS 6`, 5043 output: `create table members ( 5044 firstname VARCHAR(25) not null, 5045 lastname VARCHAR(25) not null, 5046 username VARCHAR(16) not null, 5047 email VARCHAR(35), 5048 joined DATE not null 5049 ) 5050 partition by key (joined) partitions 6`, 5051 }, 5052 { 5053 input: `CREATE TABLE t2 (val INT) 5054 PARTITION BY LIST(val)( 5055 PARTITION mypart VALUES IN (1,3,5), 5056 PARTITION MyPart VALUES IN (2,4,6) 5057 )`, 5058 output: `create table t2 ( 5059 val INT 5060 ) 5061 partition by list (val) 5062 (partition mypart values in (1, 3, 5), 5063 partition MyPart values in (2, 4, 6))`, 5064 }, 5065 { 5066 input: `CREATE TABLE t2 (val INT) 5067 PARTITION BY LIST(val)( 5068 PARTITION mypart VALUES IN (1,3,5) STORAGE ENGINE = FOOBAR, 5069 PARTITION MyPart VALUES IN (2,4,6) 5070 )`, 5071 output: `create table t2 ( 5072 val INT 5073 ) 5074 partition by list (val) 5075 (partition mypart values in (1, 3, 5) storage engine FOOBAR, 5076 partition MyPart values in (2, 4, 6))`, 5077 }, 5078 { 5079 input: `CREATE TABLE t2 (val INT) 5080 PARTITION BY LIST(val)( 5081 PARTITION mypart VALUES IN (1,3,5) ENGINE = FOOBAR, 5082 PARTITION MyPart VALUES IN (2,4,6) 5083 )`, 5084 output: `create table t2 ( 5085 val INT 5086 ) 5087 partition by list (val) 5088 (partition mypart values in (1, 3, 5) engine FOOBAR, 5089 partition MyPart values in (2, 4, 6))`, 5090 }, 5091 { 5092 input: `CREATE TABLE t2 (val INT) 5093 PARTITION BY LIST(val)( 5094 PARTITION mypart VALUES IN (1,3,5) STORAGE ENGINE FOOBAR, 5095 PARTITION MyPart VALUES IN (2,4,6) 5096 )`, 5097 output: `create table t2 ( 5098 val INT 5099 ) 5100 partition by list (val) 5101 (partition mypart values in (1, 3, 5) storage engine FOOBAR, 5102 partition MyPart values in (2, 4, 6))`, 5103 }, 5104 { 5105 input: `CREATE TABLE t2 (val INT) 5106 PARTITION BY LIST(val)( 5107 PARTITION mypart VALUES IN (1,3,5) STORAGE ENGINE FOOBAR COMMENT = 'test', 5108 PARTITION MyPart VALUES IN (2,4,6) comment 'test2' 5109 )`, 5110 output: `create table t2 ( 5111 val INT 5112 ) 5113 partition by list (val) 5114 (partition mypart values in (1, 3, 5) storage engine FOOBAR comment 'test', 5115 partition MyPart values in (2, 4, 6) comment 'test2')`, 5116 }, 5117 { 5118 input: `CREATE TABLE t2 (val INT) 5119 PARTITION BY LIST(val)( 5120 PARTITION mypart VALUES IN (1,3,5) STORAGE ENGINE FOOBAR DATA DIRECTORY = 'test', 5121 PARTITION MyPart VALUES IN (2,4,6) DATA DIRECTORY 'test2' 5122 )`, 5123 output: `create table t2 ( 5124 val INT 5125 ) 5126 partition by list (val) 5127 (partition mypart values in (1, 3, 5) storage engine FOOBAR data directory 'test', 5128 partition MyPart values in (2, 4, 6) data directory 'test2')`, 5129 }, 5130 { 5131 input: `CREATE TABLE t2 (val INT) 5132 PARTITION BY LIST(val)( 5133 PARTITION mypart VALUES IN (1,3,5) INDEX DIRECTORY = 'test', 5134 PARTITION MyPart VALUES IN (2,4,6) INDEX DIRECTORY 'test2' 5135 )`, 5136 output: `create table t2 ( 5137 val INT 5138 ) 5139 partition by list (val) 5140 (partition mypart values in (1, 3, 5) index directory 'test', 5141 partition MyPart values in (2, 4, 6) index directory 'test2')`, 5142 }, 5143 { 5144 input: `create table t1 (id int primary key) partition by list (id) (partition p1 values in(11,21), partition p2 values in (12,22))`, 5145 output: `create table t1 ( 5146 id int primary key 5147 ) 5148 partition by list (id) 5149 (partition p1 values in (11, 21), 5150 partition p2 values in (12, 22))`, 5151 }, 5152 { 5153 input: `CREATE TABLE t2 (val INT) 5154 PARTITION BY LIST(val)( 5155 PARTITION mypart VALUES IN (1,3,5) COMMENT = 'before' STORAGE ENGINE FOOBAR DATA DIRECTORY = 'test', 5156 PARTITION MyPart VALUES IN (2,4,6) DATA DIRECTORY 'test2' 5157 )`, 5158 output: `create table t2 ( 5159 val INT 5160 ) 5161 partition by list (val) 5162 (partition mypart values in (1, 3, 5) storage engine FOOBAR comment 'before' data directory 'test', 5163 partition MyPart values in (2, 4, 6) data directory 'test2')`, 5164 }, 5165 { 5166 input: `CREATE TABLE t2 (val INT) 5167 PARTITION BY LIST(val)( 5168 PARTITION mypart VALUES IN (1,3,5) MAX_ROWS = 4, 5169 PARTITION MyPart VALUES IN (2,4,6) MAX_ROWS 10 5170 )`, 5171 output: `create table t2 ( 5172 val INT 5173 ) 5174 partition by list (val) 5175 (partition mypart values in (1, 3, 5) max_rows 4, 5176 partition MyPart values in (2, 4, 6) max_rows 10)`, 5177 }, 5178 { 5179 input: `CREATE TABLE t2 (val INT) 5180 PARTITION BY LIST(val)( 5181 PARTITION mypart VALUES IN (1,3,5) MIN_ROWS = 4, 5182 PARTITION MyPart VALUES IN (2,4,6) MIN_ROWS 10 5183 )`, 5184 output: `create table t2 ( 5185 val INT 5186 ) 5187 partition by list (val) 5188 (partition mypart values in (1, 3, 5) min_rows 4, 5189 partition MyPart values in (2, 4, 6) min_rows 10)`, 5190 }, 5191 { 5192 input: `CREATE TABLE t2 (val INT) 5193 PARTITION BY LIST(val)( 5194 PARTITION mypart VALUES IN (1,3,5) TABLESPACE = innodb_system, 5195 PARTITION MyPart VALUES IN (2,4,6) TABLESPACE innodb_system 5196 )`, 5197 output: `create table t2 ( 5198 val INT 5199 ) 5200 partition by list (val) 5201 (partition mypart values in (1, 3, 5) tablespace innodb_system, 5202 partition MyPart values in (2, 4, 6) tablespace innodb_system)`, 5203 }, 5204 { 5205 // index with an expression 5206 input: `create table t ( 5207 id int auto_increment, 5208 username varchar(64), 5209 nickname varchar(64), 5210 email varchar(64), 5211 primary key (id), 5212 key email_idx (email, (if(username = '', nickname, username))) 5213 )`, 5214 }, 5215 { 5216 input: `create table entries ( 5217 uid varchar(53) character set utf8mb4 collate utf8mb4_bin not null, 5218 namespace varchar(254) character set utf8mb4 collate utf8mb4_bin not null, 5219 place varchar(254) character set utf8mb4 collate utf8mb4_bin not null, 5220 creationTimestamp timestamp null default current_timestamp(), 5221 updatedTimestamp timestamp null default current_timestamp() on update current_timestamp(), 5222 labels json default null, 5223 spec json default null, 5224 salaryInfo json default null, 5225 PRIMARY KEY (namespace, uid), 5226 UNIQUE KEY namespaced_name (namespace, place), 5227 UNIQUE KEY unique_uid (uid), 5228 KEY entries_spec_updatedAt ((json_value(spec, _utf8mb4 '$.updatedAt'))) 5229 ) ENGINE InnoDB, 5230 CHARSET utf8mb4, 5231 COLLATE utf8mb4_bin`, 5232 }, 5233 { 5234 input: `CREATE TABLE t1( 5235 j JSON, 5236 INDEX i1 ( (JSON_VALUE(j, '$.id' RETURNING UNSIGNED)) ) 5237 )`, 5238 output: `create table t1 ( 5239 j JSON, 5240 INDEX i1 ((json_value(j, '$.id' returning UNSIGNED))) 5241 )`, 5242 }, { 5243 input: `CREATE TABLE entries ( 5244 uid varchar(53) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, 5245 namespace varchar(254) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, 5246 employee varchar(254) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, 5247 creationTimestamp timestamp NULL DEFAULT CURRENT_TIMESTAMP, 5248 updatedTimestamp timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 5249 labels json DEFAULT NULL, 5250 spec json DEFAULT NULL, 5251 salaryInfo json DEFAULT NULL, 5252 PRIMARY KEY (namespace,uid), 5253 UNIQUE KEY namespaced_employee (namespace,employee), 5254 UNIQUE KEY unique_uid (uid), 5255 KEY entries_spec_updatedAt ((json_value(spec, _utf8mb4'$.updatedAt' returning datetime))) 5256 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin`, 5257 output: `create table entries ( 5258 uid varchar(53) character set utf8mb4 collate utf8mb4_bin not null, 5259 namespace varchar(254) character set utf8mb4 collate utf8mb4_bin not null, 5260 employee varchar(254) character set utf8mb4 collate utf8mb4_bin not null, 5261 creationTimestamp timestamp null default current_timestamp(), 5262 updatedTimestamp timestamp null default current_timestamp() on update current_timestamp(), 5263 labels json default null, 5264 spec json default null, 5265 salaryInfo json default null, 5266 PRIMARY KEY (namespace, uid), 5267 UNIQUE KEY namespaced_employee (namespace, employee), 5268 UNIQUE KEY unique_uid (uid), 5269 KEY entries_spec_updatedAt ((json_value(spec, _utf8mb4 '$.updatedAt' returning datetime))) 5270 ) ENGINE InnoDB, 5271 CHARSET utf8mb4, 5272 COLLATE utf8mb4_bin`, 5273 }, { 5274 // Subpartitions 5275 input: `CREATE TABLE ts (id INT, purchased DATE) 5276 PARTITION BY RANGE( YEAR(purchased) ) 5277 SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( 5278 PARTITION p0 VALUES LESS THAN (1990) ( 5279 SUBPARTITION s0, 5280 SUBPARTITION s1 5281 ), 5282 PARTITION p1 VALUES LESS THAN (2000) ( 5283 SUBPARTITION s2, 5284 SUBPARTITION s31 5285 ), 5286 PARTITION p2 VALUES LESS THAN MAXVALUE ( 5287 SUBPARTITION s4, 5288 SUBPARTITION s5 5289 ) 5290 )`, 5291 output: `create table ts ( 5292 id INT, 5293 purchased DATE 5294 ) 5295 partition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased)) 5296 (partition p0 values less than (1990) (subpartition s0, subpartition s1), 5297 partition p1 values less than (2000) (subpartition s2, subpartition s31), 5298 partition p2 values less than maxvalue (subpartition s4, subpartition s5))`, 5299 }, 5300 { 5301 input: `CREATE TABLE ts (id INT, purchased DATE) 5302 PARTITION BY RANGE( YEAR(purchased) ) 5303 SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( 5304 PARTITION p0 VALUES LESS THAN (1990) ( 5305 SUBPARTITION s0 STORAGE Engine = 'innodb' data directory = '/data', 5306 SUBPARTITION s1 COMMENT = 'this is s1' index directory = '/index' 5307 ), 5308 PARTITION p1 VALUES LESS THAN (2000) ( 5309 SUBPARTITION s2 MAx_rows = 4, 5310 SUBPARTITION s31 min_rows = 5 tablespace = t2 5311 ), 5312 PARTITION p2 VALUES LESS THAN MAXVALUE ( 5313 SUBPARTITION s4, 5314 SUBPARTITION s5 5315 ) 5316 )`, 5317 output: `create table ts ( 5318 id INT, 5319 purchased DATE 5320 ) 5321 partition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased)) 5322 (partition p0 values less than (1990) (subpartition s0 storage engine innodb data directory '/data', subpartition s1 comment 'this is s1' index directory '/index'), 5323 partition p1 values less than (2000) (subpartition s2 max_rows 4, subpartition s31 min_rows 5 tablespace t2), 5324 partition p2 values less than maxvalue (subpartition s4, subpartition s5))`, 5325 }, 5326 { 5327 input: "create table t (i bigint) charset ascii", 5328 output: "create table t (\n\ti bigint\n) charset ascii", 5329 }, 5330 { 5331 input: "create table t (i1 char ascii, i2 char character set ascii, i3 char binary, i4 char unicode binary, i5 char binary unicode, i6 char ascii binary, i7 char binary ascii, i8 char byte, i9 char character set latin1 binary)", 5332 output: "create table t (\n\ti1 char character set latin1,\n\ti2 char character set ascii,\n\ti3 char binary,\n\ti4 char character set ucs2 binary,\n\ti5 char character set ucs2 binary,\n\ti6 char character set latin1 binary,\n\ti7 char character set latin1 binary,\n\ti8 binary,\n\ti9 char character set latin1 binary\n)", 5333 }, 5334 { 5335 input: "create table t (id int, info JSON, INDEX zips((CAST(info->'$.field' AS unsigned ARRAY))))", 5336 output: "create table t (\n\tid int,\n\tinfo JSON,\n\tINDEX zips ((cast(info -> '$.field' as unsigned array)))\n)", 5337 }, 5338 } 5339 for _, test := range createTableQueries { 5340 sql := strings.TrimSpace(test.input) 5341 t.Run(sql, func(t *testing.T) { 5342 tree, err := ParseStrictDDL(sql) 5343 require.NoError(t, err) 5344 got := String(tree) 5345 expected := test.output 5346 if expected == "" { 5347 expected = sql 5348 } 5349 require.Equal(t, expected, got) 5350 }) 5351 } 5352 } 5353 5354 func TestOne(t *testing.T) { 5355 testOne := struct { 5356 input, output string 5357 }{ 5358 input: "", 5359 output: "", 5360 } 5361 if testOne.input == "" { 5362 return 5363 } 5364 sql := strings.TrimSpace(testOne.input) 5365 tree, err := Parse(sql) 5366 require.NoError(t, err) 5367 got := String(tree) 5368 expected := testOne.output 5369 if expected == "" { 5370 expected = sql 5371 } 5372 require.Equal(t, expected, got) 5373 } 5374 5375 func TestCreateTableLike(t *testing.T) { 5376 normal := "create table a like b" 5377 testCases := []struct { 5378 input string 5379 output string 5380 }{ 5381 { 5382 "create table a like b", 5383 normal, 5384 }, 5385 { 5386 "create table a (like b)", 5387 normal, 5388 }, 5389 { 5390 "create table ks.a like unsharded_ks.b", 5391 "create table ks.a like unsharded_ks.b", 5392 }, 5393 } 5394 for _, tcase := range testCases { 5395 tree, err := ParseStrictDDL(tcase.input) 5396 if err != nil { 5397 t.Errorf("input: %s, err: %v", tcase.input, err) 5398 continue 5399 } 5400 assert.True(t, tree.(*CreateTable).FullyParsed) 5401 if got, want := String(tree.(*CreateTable)), tcase.output; got != want { 5402 t.Errorf("Parse(%s):\n%s, want\n%s", tcase.input, got, want) 5403 } 5404 } 5405 } 5406 5407 func TestCreateTableEscaped(t *testing.T) { 5408 testCases := []struct { 5409 input string 5410 output string 5411 }{{ 5412 input: "create table `a`(`id` int, primary key(`id`))", 5413 output: "create table a (\n" + 5414 "\tid int,\n" + 5415 "\tprimary key (id)\n" + 5416 ")", 5417 }, { 5418 input: "create table `insert`(`update` int, primary key(`delete`))", 5419 output: "create table `insert` (\n" + 5420 "\t`update` int,\n" + 5421 "\tprimary key (`delete`)\n" + 5422 ")", 5423 }} 5424 for _, tcase := range testCases { 5425 tree, err := ParseStrictDDL(tcase.input) 5426 if err != nil { 5427 t.Errorf("input: %s, err: %v", tcase.input, err) 5428 continue 5429 } 5430 if got, want := String(tree.(*CreateTable)), tcase.output; got != want { 5431 t.Errorf("Parse(%s):\n%s, want\n%s", tcase.input, got, want) 5432 } 5433 } 5434 } 5435 5436 var ( 5437 invalidSQL = []struct { 5438 input string 5439 output string 5440 excludeMulti bool // Don't use in the ParseNext multi-statement parsing tests. 5441 }{{ 5442 input: "select : from t", 5443 output: "syntax error at position 9 near ':'", 5444 }, { 5445 input: "execute stmt using 1;", 5446 output: "syntax error at position 21 near '1'", 5447 }, { 5448 input: "PREPARE stmt FROM a;", 5449 output: "syntax error at position 20 near 'a'", 5450 }, { 5451 input: "PREPARE stmt FROM @@a;", 5452 output: "syntax error at position 22 near 'a'", 5453 }, { 5454 input: "select x'78 from t", 5455 output: "syntax error at position 12 near '78'", 5456 }, { 5457 input: "select x'777' from t", 5458 output: "syntax error at position 14 near '777'", 5459 }, { 5460 input: "select * from t where :1f = 2", 5461 output: "syntax error at position 26 near 'f'", 5462 }, { 5463 input: "select * from t where :. = 2", 5464 output: "syntax error at position 24 near ':'", 5465 }, { 5466 input: "select * from t where ::1 = 2", 5467 output: "syntax error at position 25 near '::'", 5468 }, { 5469 input: "select * from t where ::. = 2", 5470 output: "syntax error at position 25 near '::'", 5471 }, { 5472 input: "update a set c = values(1)", 5473 output: "syntax error at position 26 near '1'", 5474 }, { 5475 input: "select(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5476 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5477 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5478 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5479 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5480 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5481 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5482 "(F(F(F(F(F(F(F(F(F(F(F(F(", 5483 output: "max nesting level reached at position 406", 5484 }, { 5485 input: "select(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5486 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5487 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5488 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5489 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5490 "(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(" + 5491 "F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F(F" + 5492 "(F(F(F(F(F(F(F(F(F(F(F(", 5493 output: "syntax error at position 404", 5494 }, { 5495 // This construct is considered invalid due to a grammar conflict. 5496 input: "insert into a select * from b join c on duplicate key update d=e", 5497 output: "syntax error at position 54 near 'key'", 5498 }, { 5499 input: "select * from a left join b", 5500 output: "syntax error at position 28", 5501 }, { 5502 input: "select * from a natural join b on c = d", 5503 output: "syntax error at position 34 near 'on'", 5504 }, { 5505 input: "select * from a natural join b using (c)", 5506 output: "syntax error at position 37 near 'using'", 5507 }, { 5508 input: "select next id from a", 5509 output: "expecting value after next at position 15 near 'id'", 5510 }, { 5511 input: "select next 1+1 values from a", 5512 output: "syntax error at position 15", 5513 }, { 5514 input: "insert into a values (select * from b)", 5515 output: "syntax error at position 29 near 'select'", 5516 }, { 5517 input: "select database", 5518 output: "syntax error at position 16", 5519 }, { 5520 input: "select mod from t", 5521 output: "syntax error at position 16 near 'from'", 5522 }, { 5523 input: "select 1 from t where div 5", 5524 output: "syntax error at position 26 near 'div'", 5525 }, { 5526 input: "select 1 from t where binary", 5527 output: "syntax error at position 29", 5528 }, { 5529 input: "select match(a1, a2) against ('foo' in boolean mode with query expansion) from t", 5530 output: "syntax error at position 57 near 'with'", 5531 }, { 5532 input: "select /* reserved keyword as unqualified column */ * from t where key = 'test'", 5533 output: "syntax error at position 71 near 'key'", 5534 }, { 5535 input: "select /* vitess-reserved keyword as unqualified column */ * from t where escape = 'test'", 5536 output: "syntax error at position 81 near 'escape'", 5537 }, { 5538 input: "select /* straight_join using */ 1 from t1 straight_join t2 using (a)", 5539 output: "syntax error at position 66 near 'using'", 5540 }, { 5541 input: "select 'aa", 5542 output: "syntax error at position 11 near 'aa'", 5543 excludeMulti: true, 5544 }, { 5545 input: "select 'aa\\", 5546 output: "syntax error at position 12 near 'aa'", 5547 excludeMulti: true, 5548 }, { 5549 input: "select /* aa", 5550 output: "syntax error at position 13 near '/* aa'", 5551 excludeMulti: true, 5552 }, { 5553 // This is a valid MySQL query but does not yet work with Vitess. 5554 // The problem is that the tokenizer takes .3 as a single token which causes parsing error 5555 // We should instead be using . as a separate token and then 3t2 as an identifier. 5556 // This highlights another problem, the tokenization has to be aware of the context of parsing! 5557 // Since in an alternate query like `select .3e3t`, we should use .3e3 as a single token FLOAT and then t as ID. 5558 input: "create table 2t.3t2 (c1 bigint not null, c2 text, primary key(c1))", 5559 output: "syntax error at position 18 near '.3'", 5560 excludeMulti: true, 5561 }, { 5562 input: "execute stmt1 using a, @b", 5563 output: "syntax error at position 22 near 'a'", 5564 }, { 5565 input: "create index @a on b (col1)", 5566 output: "syntax error at position 16 near 'a'", 5567 }, { 5568 input: "create database test_db default collate @a", 5569 output: "syntax error at position 43 near 'a'", 5570 }, { 5571 input: "create database test_db default charset @a", 5572 output: "syntax error at position 43 near 'a'", 5573 }, { 5574 input: "create database test_db default encryption @a", 5575 output: "syntax error at position 46 near 'a'", 5576 }} 5577 ) 5578 5579 func TestErrors(t *testing.T) { 5580 for _, tcase := range invalidSQL { 5581 t.Run(tcase.input, func(t *testing.T) { 5582 _, err := ParseStrictDDL(tcase.input) 5583 require.Error(t, err, tcase.output) 5584 require.Equal(t, tcase.output, err.Error()) 5585 }) 5586 } 5587 } 5588 5589 // TestSkipToEnd tests that the skip to end functionality 5590 // does not skip past a ';'. If any tokens exist after that, Parse 5591 // should return an error. 5592 func TestSkipToEnd(t *testing.T) { 5593 testcases := []struct { 5594 input string 5595 output string 5596 }{{ 5597 // This is the case where the partial ddl will be reset 5598 // because of a premature ';'. 5599 input: "create table a(id; select * from t", 5600 output: "syntax error at position 19", 5601 }, { 5602 // Partial DDL should get reset for valid DDLs also. 5603 input: "create table a(id int); select * from t", 5604 output: "syntax error at position 31 near 'select'", 5605 }, { 5606 // Partial DDL does not get reset here. But we allow the 5607 // DDL only if there are no new tokens after skipping to end. 5608 input: "create table a bb cc; select * from t", 5609 output: "extra characters encountered after end of DDL: 'select'", 5610 }, { 5611 // Test that we don't step at ';' inside strings. 5612 input: "create table a bb 'a;'; select * from t", 5613 output: "extra characters encountered after end of DDL: 'select'", 5614 }} 5615 for _, tcase := range testcases { 5616 _, err := Parse(tcase.input) 5617 if err == nil || err.Error() != tcase.output { 5618 t.Errorf("%s: %v, want %s", tcase.input, err, tcase.output) 5619 } 5620 } 5621 } 5622 5623 func loadQueries(t testing.TB, filename string) (queries []string) { 5624 file, err := os.Open(path.Join("testdata", filename)) 5625 require.NoError(t, err) 5626 defer file.Close() 5627 5628 var read io.Reader 5629 if strings.HasSuffix(filename, ".gz") { 5630 gzread, err := gzip.NewReader(file) 5631 if err != nil { 5632 t.Fatal(err) 5633 } 5634 defer gzread.Close() 5635 read = gzread 5636 } else { 5637 read = file 5638 } 5639 5640 scanner := bufio.NewScanner(read) 5641 for scanner.Scan() { 5642 queries = append(queries, scanner.Text()) 5643 } 5644 return queries 5645 } 5646 5647 func TestParseDjangoQueries(t *testing.T) { 5648 for _, query := range loadQueries(t, "django_queries.txt") { 5649 _, err := Parse(query) 5650 if err != nil { 5651 t.Errorf("failed to parse %q: %v", query, err) 5652 } 5653 } 5654 } 5655 5656 func TestParseLobstersQueries(t *testing.T) { 5657 for _, query := range loadQueries(t, "lobsters.sql.gz") { 5658 _, err := Parse(query) 5659 if err != nil { 5660 t.Errorf("failed to parse %q: %v", query, err) 5661 } 5662 } 5663 } 5664 5665 func TestParseVersionedComments(t *testing.T) { 5666 testcases := []struct { 5667 input string 5668 mysqlVersion string 5669 output string 5670 }{ 5671 { 5672 input: `CREATE TABLE table1 (id int) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 /*!50900 PARTITION BY RANGE (id) (PARTITION x VALUES LESS THAN (5) ENGINE = InnoDB, PARTITION t VALUES LESS THAN (20) ENGINE = InnoDB) */`, 5673 mysqlVersion: "50401", 5674 output: `create table table1 ( 5675 id int 5676 ) ENGINE InnoDB, 5677 CHARSET utf8mb4`, 5678 }, { 5679 input: `CREATE TABLE table1 (id int) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 /*!50900 PARTITION BY RANGE (id) (PARTITION x VALUES LESS THAN (5) ENGINE = InnoDB, PARTITION t VALUES LESS THAN (20) ENGINE = InnoDB) */`, 5680 mysqlVersion: "80001", 5681 output: `create table table1 ( 5682 id int 5683 ) ENGINE InnoDB, 5684 CHARSET utf8mb4 5685 partition by range (id) 5686 (partition x values less than (5) engine InnoDB, 5687 partition t values less than (20) engine InnoDB)`, 5688 }, 5689 } 5690 5691 for _, testcase := range testcases { 5692 t.Run(testcase.input+":"+testcase.mysqlVersion, func(t *testing.T) { 5693 oldMySQLVersion := mySQLParserVersion 5694 defer func() { mySQLParserVersion = oldMySQLVersion }() 5695 mySQLParserVersion = testcase.mysqlVersion 5696 tree, err := Parse(testcase.input) 5697 require.NoError(t, err, testcase.input) 5698 out := String(tree) 5699 require.Equal(t, testcase.output, out) 5700 }) 5701 } 5702 } 5703 5704 func BenchmarkParseTraces(b *testing.B) { 5705 for _, trace := range []string{"django_queries.txt", "lobsters.sql.gz"} { 5706 b.Run(trace, func(b *testing.B) { 5707 queries := loadQueries(b, trace) 5708 if len(queries) > 10000 { 5709 queries = queries[:10000] 5710 } 5711 b.ResetTimer() 5712 b.ReportAllocs() 5713 5714 for i := 0; i < b.N; i++ { 5715 for _, query := range queries { 5716 _, err := Parse(query) 5717 if err != nil { 5718 b.Fatal(err) 5719 } 5720 } 5721 } 5722 }) 5723 } 5724 5725 } 5726 5727 func BenchmarkParseStress(b *testing.B) { 5728 const ( 5729 sql1 = "select 'abcd', 20, 30.0, eid from a where 1=eid and name='3'" 5730 sql2 = "select aaaa, bbb, ccc, ddd, eeee, ffff, gggg, hhhh, iiii from tttt, ttt1, ttt3 where aaaa = bbbb and bbbb = cccc and dddd+1 = eeee group by fff, gggg having hhhh = iiii and iiii = jjjj order by kkkk, llll limit 3, 4" 5731 ) 5732 5733 for i, sql := range []string{sql1, sql2} { 5734 b.Run(fmt.Sprintf("sql%d", i), func(b *testing.B) { 5735 var buf bytes.Buffer 5736 buf.WriteString(sql) 5737 querySQL := buf.String() 5738 b.ReportAllocs() 5739 b.ResetTimer() 5740 5741 for i := 0; i < b.N; i++ { 5742 _, err := Parse(querySQL) 5743 if err != nil { 5744 b.Fatal(err) 5745 } 5746 } 5747 }) 5748 } 5749 } 5750 5751 func BenchmarkParse3(b *testing.B) { 5752 largeQueryBenchmark := func(b *testing.B, escape bool) { 5753 b.Helper() 5754 5755 // benchQuerySize is the approximate size of the query. 5756 benchQuerySize := 1000000 5757 5758 // Size of value is 1/10 size of query. Then we add 5759 // 10 such values to the where clause. 5760 var baseval bytes.Buffer 5761 for i := 0; i < benchQuerySize/100; i++ { 5762 // Add an escape character: This will force the upcoming 5763 // tokenizer improvement to still create a copy of the string. 5764 // Then we can see if avoiding the copy will be worth it. 5765 if escape { 5766 baseval.WriteString("\\'123456789") 5767 } else { 5768 baseval.WriteString("123456789") 5769 } 5770 } 5771 5772 var buf bytes.Buffer 5773 buf.WriteString("select a from t1 where v = 1") 5774 for i := 0; i < 10; i++ { 5775 fmt.Fprintf(&buf, " and v%d = \"%d%s\"", i, i, baseval.String()) 5776 } 5777 benchQuery := buf.String() 5778 b.ResetTimer() 5779 b.ReportAllocs() 5780 5781 for i := 0; i < b.N; i++ { 5782 if _, err := Parse(benchQuery); err != nil { 5783 b.Fatal(err) 5784 } 5785 } 5786 } 5787 5788 b.Run("normal", func(b *testing.B) { 5789 largeQueryBenchmark(b, false) 5790 }) 5791 5792 b.Run("escaped", func(b *testing.B) { 5793 largeQueryBenchmark(b, true) 5794 }) 5795 } 5796 5797 func TestValidUnionCases(t *testing.T) { 5798 testFile(t, "union_cases.txt", makeTestOutput(t)) 5799 } 5800 5801 func TestValidSelectCases(t *testing.T) { 5802 testFile(t, "select_cases.txt", makeTestOutput(t)) 5803 } 5804 5805 func makeTestOutput(t *testing.T) string { 5806 testOutputTempDir := utils.MakeTestOutput(t, "testdata", "parse_test") 5807 5808 t.Cleanup(func() { 5809 if !t.Failed() { 5810 _ = os.RemoveAll(testOutputTempDir) 5811 } else { 5812 t.Logf("Errors found. If the output is correct, run `cp %s/* testdata/` to update test expectations", testOutputTempDir) 5813 } 5814 }) 5815 5816 return testOutputTempDir 5817 } 5818 5819 type testCase struct { 5820 file string 5821 lineno int 5822 input string 5823 output string 5824 errStr string 5825 comments string 5826 } 5827 5828 func escapeNewLines(in string) string { 5829 return strings.ReplaceAll(in, "\n", "\\n") 5830 } 5831 5832 func testFile(t *testing.T, filename, tempDir string) { 5833 t.Run(filename, func(t *testing.T) { 5834 fail := false 5835 expected := strings.Builder{} 5836 for tcase := range iterateExecFile(filename) { 5837 t.Run(fmt.Sprintf("%d : %s", tcase.lineno, tcase.input), func(t *testing.T) { 5838 if tcase.output == "" && tcase.errStr == "" { 5839 tcase.output = tcase.input 5840 } 5841 expected.WriteString(fmt.Sprintf("%sINPUT\n%s\nEND\n", tcase.comments, escapeNewLines(tcase.input))) 5842 tree, err := Parse(tcase.input) 5843 if tcase.errStr != "" { 5844 errPresent := "" 5845 if err != nil { 5846 errPresent = err.Error() 5847 } 5848 expected.WriteString(fmt.Sprintf("ERROR\n%s\nEND\n", escapeNewLines(errPresent))) 5849 if err == nil || tcase.errStr != err.Error() { 5850 fail = true 5851 t.Errorf("File: %s, Line: %d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.errStr, errPresent), tcase.errStr, errPresent) 5852 } 5853 } else { 5854 if err != nil { 5855 expected.WriteString(fmt.Sprintf("ERROR\n%s\nEND\n", escapeNewLines(err.Error()))) 5856 fail = true 5857 t.Errorf("File: %s:%d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.errStr, err.Error()), tcase.errStr, err.Error()) 5858 } else { 5859 out := String(tree) 5860 expected.WriteString(fmt.Sprintf("OUTPUT\n%s\nEND\n", escapeNewLines(out))) 5861 if tcase.output != out { 5862 fail = true 5863 t.Errorf("Parsing failed. \nExpected/Got:\n%s\n%s", tcase.output, out) 5864 } 5865 } 5866 } 5867 }) 5868 } 5869 5870 if fail && tempDir != "" { 5871 gotFile := fmt.Sprintf("%s/%s", tempDir, filename) 5872 _ = os.WriteFile(gotFile, []byte(strings.TrimSpace(expected.String())+"\n"), 0644) 5873 fmt.Println(fmt.Sprintf("Errors found in parse tests. If the output is correct, run `cp %s/* testdata/` to update test expectations", tempDir)) // nolint 5874 } 5875 }) 5876 } 5877 5878 func iterateExecFile(name string) (testCaseIterator chan testCase) { 5879 name = locateFile(name) 5880 fd, err := os.OpenFile(name, os.O_RDONLY, 0) 5881 if err != nil { 5882 panic(fmt.Sprintf("Could not open file %s", name)) 5883 } 5884 5885 testCaseIterator = make(chan testCase) 5886 var comments string 5887 go func() { 5888 defer close(testCaseIterator) 5889 5890 r := bufio.NewReader(fd) 5891 lineno := 0 5892 var output string 5893 var returnTypeNumber int 5894 var input string 5895 for { 5896 input, lineno, _ = parsePartial(r, []string{"INPUT"}, lineno, name) 5897 if input == "" && lineno == 0 { 5898 break 5899 } 5900 output, lineno, returnTypeNumber = parsePartial(r, []string{"OUTPUT", "ERROR"}, lineno, name) 5901 var errStr string 5902 if returnTypeNumber == 1 { 5903 errStr = output 5904 output = "" 5905 } 5906 testCaseIterator <- testCase{ 5907 file: name, 5908 lineno: lineno, 5909 input: input, 5910 comments: comments, 5911 output: output, 5912 errStr: errStr, 5913 } 5914 comments = "" 5915 } 5916 }() 5917 return testCaseIterator 5918 } 5919 5920 func parsePartial(r *bufio.Reader, readType []string, lineno int, fileName string) (string, int, int) { 5921 returnTypeNumber := -1 5922 for { 5923 binput, err := r.ReadBytes('\n') 5924 if err != nil { 5925 if err != io.EOF { 5926 panic(fmt.Errorf("error reading file %s: line %d: %s", fileName, lineno, err.Error())) 5927 } 5928 return "", 0, 0 5929 } 5930 lineno++ 5931 input := string(binput) 5932 input = strings.TrimSpace(input) 5933 if input == "" || input == "\n" { 5934 continue 5935 } 5936 for i, str := range readType { 5937 if input == str { 5938 returnTypeNumber = i 5939 break 5940 } 5941 } 5942 if returnTypeNumber != -1 { 5943 break 5944 } 5945 panic(fmt.Errorf("error reading file %s: line %d: %s - Expected keyword", fileName, lineno, err.Error())) 5946 } 5947 input := "" 5948 for { 5949 l, err := r.ReadBytes('\n') 5950 lineno++ 5951 if err != nil { 5952 panic(fmt.Sprintf("error reading file %s line# %d: %s", fileName, lineno, err.Error())) 5953 } 5954 str := strings.TrimSpace(string(l)) 5955 if str == "END" { 5956 break 5957 } 5958 if input == "" { 5959 input += str 5960 } else { 5961 input += str + "\n" 5962 } 5963 } 5964 return input, lineno, returnTypeNumber 5965 } 5966 5967 func locateFile(name string) string { 5968 return "testdata/" + name 5969 }