github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/update_queries.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package queries 16 17 import ( 18 "time" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 "github.com/dolthub/go-mysql-server/sql/plan" 22 "github.com/dolthub/go-mysql-server/sql/types" 23 24 "github.com/dolthub/vitess/go/mysql" 25 ) 26 27 var UpdateTests = []WriteQueryTest{ 28 { 29 WriteQuery: "UPDATE mytable SET s = 'updated';", 30 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 31 SelectQuery: "SELECT * FROM mytable;", 32 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}}, 33 }, 34 { 35 WriteQuery: "UPDATE mytable SET S = 'updated';", 36 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 37 SelectQuery: "SELECT * FROM mytable;", 38 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}}, 39 }, 40 { 41 WriteQuery: "UPDATE mytable SET s = 'updated' WHERE i > 9999;", 42 ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}}, 43 SelectQuery: "SELECT * FROM mytable;", 44 ExpectedSelect: []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}}, 45 }, 46 { 47 WriteQuery: "UPDATE mytable SET s = 'updated' WHERE i = 1;", 48 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 49 SelectQuery: "SELECT * FROM mytable;", 50 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "second row"}, {int64(3), "third row"}}, 51 }, 52 { 53 WriteQuery: "UPDATE mytable SET s = 'updated' WHERE i <> 9999;", 54 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 55 SelectQuery: "SELECT * FROM mytable;", 56 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}}, 57 }, 58 { 59 WriteQuery: "UPDATE floattable SET f32 = f32 + f32, f64 = f32 * f64 WHERE i = 2;", 60 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 61 SelectQuery: "SELECT * FROM floattable WHERE i = 2;", 62 ExpectedSelect: []sql.Row{{int64(2), float32(3.0), float64(4.5)}}, 63 }, 64 { 65 WriteQuery: "UPDATE floattable SET f32 = 5, f32 = 4 WHERE i = 1;", 66 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 67 SelectQuery: "SELECT f32 FROM floattable WHERE i = 1;", 68 ExpectedSelect: []sql.Row{{float32(4.0)}}, 69 }, 70 { 71 WriteQuery: "UPDATE mytable SET s = 'first row' WHERE i = 1;", 72 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}}, 73 SelectQuery: "SELECT * FROM mytable;", 74 ExpectedSelect: []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}}, 75 }, 76 { 77 WriteQuery: "UPDATE niltable SET b = NULL WHERE f IS NULL;", 78 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 2)}}, 79 SelectQuery: "SELECT i,b FROM niltable WHERE f IS NULL;", 80 ExpectedSelect: []sql.Row{{int64(1), nil}, {int64(2), nil}, {int64(3), nil}}, 81 }, 82 { 83 WriteQuery: "UPDATE mytable SET s = 'updated' ORDER BY i ASC LIMIT 2;", 84 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 85 SelectQuery: "SELECT * FROM mytable;", 86 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "third row"}}, 87 }, 88 { 89 WriteQuery: "UPDATE mytable SET s = 'updated' ORDER BY i DESC LIMIT 2;", 90 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 91 SelectQuery: "SELECT * FROM mytable;", 92 ExpectedSelect: []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "updated"}}, 93 }, 94 { 95 WriteQuery: "UPDATE mytable SET s = 'updated' ORDER BY i LIMIT 1 OFFSET 1;", 96 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 97 SelectQuery: "SELECT * FROM mytable;", 98 ExpectedSelect: []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "third row"}}, 99 }, 100 { 101 WriteQuery: "UPDATE mytable SET s = 'updated';", 102 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 103 SelectQuery: "SELECT * FROM mytable;", 104 ExpectedSelect: []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}}, 105 }, 106 { 107 WriteQuery: "UPDATE mytable SET s = _binary 'updated' WHERE i = 3;", 108 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 109 SelectQuery: "SELECT * FROM mytable;", 110 ExpectedSelect: []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "updated"}}, 111 }, 112 { 113 WriteQuery: "UPDATE typestable SET ti = '2020-03-06 00:00:00';", 114 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 115 SelectQuery: "SELECT * FROM typestable;", 116 ExpectedSelect: []sql.Row{{ 117 int64(1), 118 int8(2), 119 int16(3), 120 int32(4), 121 int64(5), 122 uint8(6), 123 uint16(7), 124 uint32(8), 125 uint64(9), 126 float32(10), 127 float64(11), 128 sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")), 129 sql.MustConvert(types.Date.Convert("2019-12-31")), 130 "fourteen", 131 0, 132 nil, 133 nil, 134 "", ""}}, 135 }, 136 { 137 WriteQuery: "UPDATE typestable SET ti = '2020-03-06 00:00:00', da = '2020-03-06';", 138 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 139 SelectQuery: "SELECT * FROM typestable;", 140 ExpectedSelect: []sql.Row{{ 141 int64(1), 142 int8(2), 143 int16(3), 144 int32(4), 145 int64(5), 146 uint8(6), 147 uint16(7), 148 uint32(8), 149 uint64(9), 150 float32(10), 151 float64(11), 152 sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")), 153 sql.MustConvert(types.Date.Convert("2020-03-06")), 154 "fourteen", 155 0, 156 nil, 157 nil, 158 "", ""}}, 159 }, 160 { 161 SkipServerEngine: true, // datetime returned is non-zero over the wire 162 WriteQuery: "UPDATE typestable SET da = '0000-00-00', ti = '0000-00-00 00:00:00';", 163 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 164 SelectQuery: "SELECT * FROM typestable;", 165 ExpectedSelect: []sql.Row{{ 166 int64(1), 167 int8(2), 168 int16(3), 169 int32(4), 170 int64(5), 171 uint8(6), 172 uint16(7), 173 uint32(8), 174 uint64(9), 175 float32(10), 176 float64(11), 177 types.Timestamp.Zero(), 178 types.Date.Zero(), 179 "fourteen", 180 0, 181 nil, 182 nil, 183 "", ""}}, 184 }, 185 { 186 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1`, 187 ExpectedWriteResult: []sql.Row{{newUpdateResult(4, 4)}}, 188 SelectQuery: "SELECT * FROM two_pk;", 189 ExpectedSelect: []sql.Row{ 190 sql.NewRow(0, 0, 1, 1, 2, 3, 4), 191 sql.NewRow(0, 1, 11, 11, 12, 13, 14), 192 sql.NewRow(1, 0, 21, 21, 22, 23, 24), 193 sql.NewRow(1, 1, 31, 31, 32, 33, 34), 194 }, 195 }, 196 { 197 WriteQuery: "UPDATE mytable INNER JOIN one_pk ON mytable.i = one_pk.c5 SET mytable.i = mytable.i * 10", 198 ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}}, 199 SelectQuery: "SELECT * FROM mytable", 200 ExpectedSelect: []sql.Row{ 201 sql.NewRow(int64(1), "first row"), 202 sql.NewRow(int64(2), "second row"), 203 sql.NewRow(int64(3), "third row"), 204 }, 205 }, 206 { 207 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1 WHERE one_pk.c5 < 10`, 208 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 209 SelectQuery: "SELECT * FROM two_pk;", 210 ExpectedSelect: []sql.Row{ 211 sql.NewRow(0, 0, 1, 1, 2, 3, 4), 212 sql.NewRow(0, 1, 11, 11, 12, 13, 14), 213 sql.NewRow(1, 0, 20, 21, 22, 23, 24), 214 sql.NewRow(1, 1, 30, 31, 32, 33, 34), 215 }, 216 }, 217 { 218 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN othertable on othertable.i2 = two_pk.pk2 SET one_pk.c1 = one_pk.c1 + 1`, 219 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 220 SelectQuery: "SELECT * FROM one_pk;", 221 ExpectedSelect: []sql.Row{ 222 sql.NewRow(0, 1, 1, 2, 3, 4), 223 sql.NewRow(1, 11, 11, 12, 13, 14), 224 sql.NewRow(2, 20, 21, 22, 23, 24), 225 sql.NewRow(3, 30, 31, 32, 33, 34), 226 }, 227 }, 228 { 229 WriteQuery: `UPDATE one_pk INNER JOIN (SELECT * FROM two_pk order by pk1, pk2) as t2 on one_pk.pk = t2.pk1 SET one_pk.c1 = t2.c1 + 1 where one_pk.pk < 1`, 230 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 231 SelectQuery: "SELECT * FROM one_pk where pk < 1", 232 ExpectedSelect: []sql.Row{ 233 sql.NewRow(0, 1, 1, 2, 3, 4), 234 }, 235 }, 236 { 237 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1`, 238 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 239 SelectQuery: "SELECT * FROM one_pk;", 240 ExpectedSelect: []sql.Row{ 241 sql.NewRow(0, 1, 1, 2, 3, 4), 242 sql.NewRow(1, 11, 11, 12, 13, 14), 243 sql.NewRow(2, 20, 21, 22, 23, 24), 244 sql.NewRow(3, 30, 31, 32, 33, 34), 245 }, 246 }, 247 { 248 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, one_pk.c2 = one_pk.c2 + 1 ORDER BY one_pk.pk`, 249 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 250 SelectQuery: "SELECT * FROM one_pk;", 251 ExpectedSelect: []sql.Row{ 252 sql.NewRow(0, 1, 2, 2, 3, 4), 253 sql.NewRow(1, 11, 12, 12, 13, 14), 254 sql.NewRow(2, 20, 21, 22, 23, 24), 255 sql.NewRow(3, 30, 31, 32, 33, 34), 256 }, 257 }, 258 { 259 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`, 260 ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}}, // TODO: Should be matched = 6 261 SelectQuery: "SELECT * FROM two_pk;", 262 ExpectedSelect: []sql.Row{ 263 sql.NewRow(0, 0, 2, 1, 2, 3, 4), 264 sql.NewRow(0, 1, 12, 11, 12, 13, 14), 265 sql.NewRow(1, 0, 22, 21, 22, 23, 24), 266 sql.NewRow(1, 1, 32, 31, 32, 33, 34), 267 }, 268 }, 269 { 270 WriteQuery: `update mytable h join mytable on h.i = mytable.i and h.s <> mytable.s set h.i = mytable.i+1;`, 271 ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}}, 272 SelectQuery: "select * from mytable", 273 ExpectedSelect: []sql.Row{{1, "first row"}, {2, "second row"}, {3, "third row"}}, 274 }, 275 { 276 WriteQuery: `UPDATE othertable CROSS JOIN tabletest set othertable.i2 = othertable.i2 * 10`, // cross join 277 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 278 SelectQuery: "SELECT * FROM othertable order by i2", 279 ExpectedSelect: []sql.Row{ 280 sql.NewRow("third", 10), 281 sql.NewRow("second", 20), 282 sql.NewRow("first", 30), 283 }, 284 }, 285 { 286 WriteQuery: `UPDATE tabletest cross join tabletest as t2 set tabletest.i = tabletest.i * 10`, // cross join 287 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 288 SelectQuery: "SELECT * FROM tabletest order by i", 289 ExpectedSelect: []sql.Row{ 290 sql.NewRow(10, "first row"), 291 sql.NewRow(20, "second row"), 292 sql.NewRow(30, "third row"), 293 }, 294 }, 295 { 296 WriteQuery: `UPDATE othertable cross join tabletest set tabletest.i = tabletest.i * 10`, // cross join 297 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 298 SelectQuery: "SELECT * FROM tabletest order by i", 299 ExpectedSelect: []sql.Row{ 300 sql.NewRow(10, "first row"), 301 sql.NewRow(20, "second row"), 302 sql.NewRow(30, "third row"), 303 }, 304 }, 305 { 306 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN two_pk a1 on one_pk.pk = two_pk.pk2 SET two_pk.c1 = two_pk.c1 + 1`, // cross join 307 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 308 SelectQuery: "SELECT * FROM two_pk order by pk1 ASC, pk2 ASC;", 309 ExpectedSelect: []sql.Row{ 310 sql.NewRow(0, 0, 1, 1, 2, 3, 4), 311 sql.NewRow(0, 1, 10, 11, 12, 13, 14), 312 sql.NewRow(1, 0, 20, 21, 22, 23, 24), 313 sql.NewRow(1, 1, 31, 31, 32, 33, 34), 314 }, 315 }, 316 { 317 WriteQuery: `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // cross join 318 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 319 SelectQuery: "SELECT * FROM othertable order by i2", 320 ExpectedSelect: []sql.Row{ 321 sql.NewRow("third", 1), 322 sql.NewRow("second", 2), 323 sql.NewRow("fourth", 3), 324 }, 325 }, 326 { 327 WriteQuery: `UPDATE tabletest cross join tabletest as t2 set t2.i = t2.i * 10`, // cross join 328 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 329 SelectQuery: "SELECT * FROM tabletest order by i", 330 ExpectedSelect: []sql.Row{ 331 sql.NewRow(10, "first row"), 332 sql.NewRow(20, "second row"), 333 sql.NewRow(30, "third row"), 334 }, 335 }, 336 { 337 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // left join 338 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 339 SelectQuery: "SELECT * FROM othertable order by i2", 340 ExpectedSelect: []sql.Row{ 341 sql.NewRow("fourth", 1), 342 sql.NewRow("fourth", 2), 343 sql.NewRow("fourth", 3), 344 }, 345 }, 346 { 347 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET tabletest.s = 'fourth row', tabletest.i = tabletest.i + 1`, // left join 348 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 349 SelectQuery: "SELECT * FROM tabletest order by i", 350 ExpectedSelect: []sql.Row{ 351 sql.NewRow(1, "first row"), 352 sql.NewRow(2, "second row"), 353 sql.NewRow(4, "fourth row"), 354 }, 355 }, 356 { 357 WriteQuery: `UPDATE othertable LEFT JOIN tabletest t3 on othertable.i2=3 and t3.i=3 SET t3.s = 'fourth row', t3.i = t3.i + 1`, // left join 358 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 359 SelectQuery: "SELECT * FROM tabletest order by i", 360 ExpectedSelect: []sql.Row{ 361 sql.NewRow(1, "first row"), 362 sql.NewRow(2, "second row"), 363 sql.NewRow(4, "fourth row"), 364 }, 365 }, 366 { 367 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1`, // left join 368 ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}}, 369 SelectQuery: "SELECT * FROM one_pk order by pk", 370 ExpectedSelect: []sql.Row{ 371 sql.NewRow(0, 0, 1, 2, 3, 4), 372 sql.NewRow(1, 11, 11, 12, 13, 14), 373 sql.NewRow(2, 21, 21, 22, 23, 24), 374 sql.NewRow(3, 31, 31, 32, 33, 34), 375 }, 376 }, 377 { 378 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1 where one_pk.pk > 4`, // left join 379 ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}}, 380 SelectQuery: "SELECT * FROM one_pk order by pk", 381 ExpectedSelect: []sql.Row{ 382 sql.NewRow(0, 0, 1, 2, 3, 4), 383 sql.NewRow(1, 10, 11, 12, 13, 14), 384 sql.NewRow(2, 20, 21, 22, 23, 24), 385 sql.NewRow(3, 30, 31, 32, 33, 34), 386 }, 387 }, 388 { 389 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET one_pk.c1 = one_pk.c1 + 1`, // left join 390 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 391 SelectQuery: "SELECT * FROM one_pk order by pk", 392 ExpectedSelect: []sql.Row{ 393 sql.NewRow(0, 0, 1, 2, 3, 4), 394 sql.NewRow(1, 11, 11, 12, 13, 14), 395 sql.NewRow(2, 20, 21, 22, 23, 24), 396 sql.NewRow(3, 30, 31, 32, 33, 34), 397 }, 398 }, 399 { 400 WriteQuery: `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, // right join 401 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 402 SelectQuery: "SELECT * FROM othertable order by i2", 403 ExpectedSelect: []sql.Row{ 404 sql.NewRow("third", 1), 405 sql.NewRow("second", 2), 406 sql.NewRow("fourth", 3), 407 }, 408 }, 409 { 410 WriteQuery: `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.i2 = othertable.i2 + 1`, // right join 411 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 412 SelectQuery: "SELECT * FROM othertable order by i2", 413 ExpectedSelect: []sql.Row{ 414 sql.NewRow("third", 1), 415 sql.NewRow("second", 2), 416 sql.NewRow("first", 4), 417 }, 418 }, 419 { 420 WriteQuery: `UPDATE othertable LEFT JOIN tabletest on othertable.i2=tabletest.i RIGHT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET tabletest.s = 'updated';`, // right join 421 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 422 SelectQuery: "SELECT * FROM tabletest order by i", 423 ExpectedSelect: []sql.Row{ 424 sql.NewRow(1, "updated"), 425 sql.NewRow(2, "second row"), 426 sql.NewRow(3, "third row"), 427 }, 428 }, 429 { 430 WriteQuery: "with t (n) as (select (1) from dual) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)", 431 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 432 SelectQuery: "select * from mytable order by i", 433 ExpectedSelect: []sql.Row{ 434 sql.NewRow(1, "updated 1"), 435 sql.NewRow(2, "second row"), 436 sql.NewRow(3, "third row"), 437 }, 438 }, 439 { 440 WriteQuery: "with recursive t (n) as (select (1) from dual union all select n + 1 from t where n < 2) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)", 441 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 442 SelectQuery: "select * from mytable order by i", 443 ExpectedSelect: []sql.Row{ 444 sql.NewRow(1, "updated 1"), 445 sql.NewRow(2, "updated 2"), 446 sql.NewRow(3, "third row"), 447 }, 448 }, 449 } 450 451 var SpatialUpdateTests = []WriteQueryTest{ 452 { 453 WriteQuery: "UPDATE point_table SET p = point(123.456,789);", 454 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 455 SelectQuery: "SELECT * FROM point_table;", 456 ExpectedSelect: []sql.Row{{int64(5), types.Point{X: 123.456, Y: 789}}}, 457 }, 458 { 459 WriteQuery: "UPDATE line_table SET l = linestring(point(1.2,3.4),point(5.6,7.8));", 460 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 461 SelectQuery: "SELECT * FROM line_table;", 462 ExpectedSelect: []sql.Row{{int64(0), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}, {int64(1), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}}, 463 }, 464 { 465 WriteQuery: "UPDATE polygon_table SET p = polygon(linestring(point(1,1),point(1,-1),point(-1,-1),point(-1,1),point(1,1)));", 466 ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}}, 467 SelectQuery: "SELECT * FROM polygon_table;", 468 ExpectedSelect: []sql.Row{ 469 {int64(0), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}}, 470 {int64(1), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}}, 471 }, 472 }, 473 } 474 475 // These tests return the correct select query answer but the wrong write result. 476 var SkippedUpdateTests = []WriteQueryTest{ 477 { 478 WriteQuery: `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`, 479 ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}}, // TODO: Should be matched = 6 480 SelectQuery: "SELECT * FROM two_pk;", 481 ExpectedSelect: []sql.Row{ 482 sql.NewRow(0, 0, 2, 1, 2, 3, 4), 483 sql.NewRow(0, 1, 12, 11, 12, 13, 14), 484 sql.NewRow(1, 0, 22, 21, 22, 23, 24), 485 sql.NewRow(1, 1, 32, 31, 32, 33, 34), 486 }, 487 }, 488 { 489 WriteQuery: `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`, 490 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}}, 491 SelectQuery: "SELECT * FROM othertable;", 492 ExpectedSelect: []sql.Row{ 493 sql.NewRow("third", 1), 494 sql.NewRow("second", 2), 495 sql.NewRow("fourth", 3), 496 }, 497 }, 498 } 499 500 func newUpdateResult(matched, updated int) types.OkResult { 501 return types.OkResult{ 502 RowsAffected: uint64(updated), 503 Info: plan.UpdateInfo{matched, updated, 0}, 504 } 505 } 506 507 var GenericUpdateErrorTests = []GenericErrorQueryTest{ 508 { 509 Name: "invalid table", 510 Query: "UPDATE doesnotexist SET i = 0;", 511 }, 512 { 513 Name: "missing binding", 514 Query: "UPDATE mytable SET i = ?;", 515 }, 516 { 517 Name: "wrong number of columns", 518 Query: `UPDATE mytable SET i = ("one", "two");`, 519 }, 520 { 521 Name: "type mismatch: string -> int", 522 Query: `UPDATE mytable SET i = "one"`, 523 }, 524 { 525 Name: "type mismatch: string -> float", 526 Query: `UPDATE floattable SET f64 = "one"`, 527 }, 528 { 529 Name: "type mismatch: string -> uint", 530 Query: `UPDATE typestable SET f64 = "one"`, 531 }, 532 { 533 Name: "invalid column set", 534 Query: "UPDATE mytable SET z = 0;", 535 }, 536 { 537 Name: "invalid column set value", 538 Query: "UPDATE mytable SET i = z;", 539 }, 540 { 541 Name: "invalid column where", 542 Query: "UPDATE mytable SET s = 'hi' WHERE z = 1;", 543 }, 544 { 545 Name: "invalid column order by", 546 Query: "UPDATE mytable SET s = 'hi' ORDER BY z;", 547 }, 548 { 549 Name: "negative limit", 550 Query: "UPDATE mytable SET s = 'hi' LIMIT -1;", 551 }, 552 { 553 Name: "negative offset", 554 Query: "UPDATE mytable SET s = 'hi' LIMIT 1 OFFSET -1;", 555 }, 556 { 557 Name: "set null on non-nullable", 558 Query: "UPDATE mytable SET s = NULL;", 559 }, 560 { 561 Name: "targets join", 562 Query: "UPDATE mytable one, mytable two SET s = NULL;", 563 }, 564 { 565 Name: "targets subquery alias", 566 Query: "UPDATE (SELECT * FROM mytable) mytable SET s = NULL;", 567 }, 568 } 569 570 var UpdateIgnoreTests = []WriteQueryTest{ 571 { 572 WriteQuery: "UPDATE IGNORE mytable SET i = 2 where i = 1", 573 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}}, 574 SelectQuery: "SELECT * FROM mytable order by i", 575 ExpectedSelect: []sql.Row{ 576 sql.NewRow(1, "first row"), 577 sql.NewRow(2, "second row"), 578 sql.NewRow(3, "third row"), 579 }, 580 }, 581 { 582 WriteQuery: "UPDATE IGNORE mytable SET i = i+1 where i = 1", 583 ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}}, 584 SelectQuery: "SELECT * FROM mytable order by i", 585 ExpectedSelect: []sql.Row{ 586 sql.NewRow(1, "first row"), 587 sql.NewRow(2, "second row"), 588 sql.NewRow(3, "third row"), 589 }, 590 }, 591 } 592 593 var UpdateIgnoreScripts = []ScriptTest{ 594 { 595 Name: "UPDATE IGNORE with primary keys and indexes", 596 SetUpScript: []string{ 597 "CREATE TABLE pkTable(pk int, val int, primary key(pk, val))", 598 "CREATE TABLE idxTable(pk int primary key, val int UNIQUE)", 599 "INSERT INTO pkTable VALUES (1, 1), (2, 2), (3, 3)", 600 "INSERT INTO idxTable VALUES (1, 1), (2, 2), (3, 3)", 601 }, 602 Assertions: []ScriptTestAssertion{ 603 { 604 Query: "UPDATE IGNORE pkTable set pk = pk + 1, val = val + 1", 605 Expected: []sql.Row{{newUpdateResult(3, 1)}}, 606 ExpectedWarning: mysql.ERDupEntry, 607 }, 608 { 609 Query: "SELECT * FROM pkTable order by pk", 610 Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}}, 611 }, 612 { 613 Query: "UPDATE IGNORE idxTable set val = val + 1", 614 Expected: []sql.Row{{newUpdateResult(3, 1)}}, 615 ExpectedWarning: mysql.ERDupEntry, 616 }, 617 { 618 Query: "SELECT * FROM idxTable order by pk", 619 Expected: []sql.Row{{1, 1}, {2, 2}, {3, 4}}, 620 }, 621 { 622 Query: "UPDATE IGNORE pkTable set val = val + 1 where pk = 2", 623 Expected: []sql.Row{{newUpdateResult(1, 1)}}, 624 }, 625 { 626 Query: "SELECT * FROM pkTable order by pk", 627 Expected: []sql.Row{{1, 1}, {2, 3}, {4, 4}}, 628 }, 629 { 630 Query: "UPDATE IGNORE pkTable SET pk = NULL", 631 Expected: []sql.Row{{newUpdateResult(3, 3)}}, 632 ExpectedWarning: mysql.ERBadNullError, 633 }, 634 { 635 Query: "SELECT * FROM pkTable order by pk", 636 Expected: []sql.Row{{0, 1}, {0, 3}, {0, 4}}, 637 }, 638 { 639 Query: "UPDATE IGNORE pkTable SET val = NULL", 640 Expected: []sql.Row{{newUpdateResult(3, 1)}}, 641 }, 642 { 643 Query: "SELECT * FROM pkTable order by pk", 644 Expected: []sql.Row{{0, 0}, {0, 3}, {0, 4}}, 645 }, 646 { 647 Query: "UPDATE IGNORE idxTable set pk = pk + 1, val = val + 1", // two bad updates 648 Expected: []sql.Row{{newUpdateResult(3, 1)}}, 649 ExpectedWarning: mysql.ERDupEntry, 650 }, 651 { 652 Query: "SELECT * FROM idxTable order by pk", 653 Expected: []sql.Row{{1, 1}, {2, 2}, {4, 5}}, 654 }, 655 }, 656 }, 657 { 658 Name: "UPDATE IGNORE with type conversions", 659 SetUpScript: []string{ 660 "CREATE TABLE t1 (pk int primary key, v1 int, v2 int)", 661 "INSERT INTO t1 VALUES (1, 1, 1)", 662 }, 663 Assertions: []ScriptTestAssertion{ 664 { 665 Query: "UPDATE IGNORE t1 SET v1 = 'dsddads'", 666 Expected: []sql.Row{{newUpdateResult(1, 1)}}, 667 ExpectedWarning: mysql.ERTruncatedWrongValueForField, 668 }, 669 { 670 Query: "SELECT * FROM t1", 671 Expected: []sql.Row{{1, 0, 1}}, 672 }, 673 { 674 Query: "UPDATE IGNORE t1 SET pk = 'dasda', v2 = 'dsddads'", 675 Expected: []sql.Row{{newUpdateResult(1, 1)}}, 676 ExpectedWarning: mysql.ERTruncatedWrongValueForField, 677 }, 678 { 679 Query: "SELECT * FROM t1", 680 Expected: []sql.Row{{0, 0, 0}}, 681 }, 682 }, 683 }, 684 { 685 Name: "UPDATE IGNORE with foreign keys", 686 SetUpScript: []string{ 687 "CREATE TABLE colors ( id INT NOT NULL, color VARCHAR(32) NOT NULL, PRIMARY KEY (id), INDEX color_index(color));", 688 "CREATE TABLE objects (id INT NOT NULL, name VARCHAR(64) NOT NULL,color VARCHAR(32), PRIMARY KEY(id),FOREIGN KEY (color) REFERENCES colors(color))", 689 "INSERT INTO colors (id,color) VALUES (1,'red'),(2,'green'),(3,'blue'),(4,'purple')", 690 "INSERT INTO objects (id,name,color) VALUES (1,'truck','red'),(2,'ball','green'),(3,'shoe','blue')", 691 }, 692 Assertions: []ScriptTestAssertion{ 693 { 694 Query: "UPDATE IGNORE objects SET color = 'orange' where id = 2", 695 Expected: []sql.Row{{newUpdateResult(1, 0)}}, 696 ExpectedWarning: mysql.ErNoReferencedRow2, 697 }, 698 { 699 Query: "SELECT * FROM objects ORDER BY id", 700 Expected: []sql.Row{{1, "truck", "red"}, {2, "ball", "green"}, {3, "shoe", "blue"}}, 701 }, 702 }, 703 }, 704 { 705 Name: "UPDATE IGNORE with check constraints", 706 SetUpScript: []string{ 707 "CREATE TABLE checksTable(pk int primary key)", 708 "ALTER TABLE checksTable ADD CONSTRAINT mycx CHECK (pk < 5)", 709 "INSERT INTO checksTable VALUES (1),(2),(3),(4)", 710 }, 711 Assertions: []ScriptTestAssertion{ 712 { 713 Query: "UPDATE IGNORE checksTable SET pk = pk + 1 where pk = 4", 714 Expected: []sql.Row{{newUpdateResult(1, 0)}}, 715 ExpectedWarning: mysql.ERUnknownError, 716 }, 717 { 718 Query: "SELECT * from checksTable ORDER BY pk", 719 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 720 }, 721 }, 722 }, 723 } 724 725 var UpdateErrorTests = []QueryErrorTest{ 726 { 727 Query: `UPDATE keyless INNER JOIN one_pk on keyless.c0 = one_pk.pk SET keyless.c0 = keyless.c0 + 1`, 728 ExpectedErr: sql.ErrUnsupportedFeature, 729 }, 730 { 731 Query: `UPDATE people set height_inches = null where height_inches < 100`, 732 ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull, 733 }, 734 { 735 Query: `UPDATE people SET height_inches = IF(SUM(height_inches) % 2 = 0, 42, height_inches)`, 736 ExpectedErr: sql.ErrAggregationUnsupported, 737 }, 738 { 739 Query: `UPDATE people SET height_inches = IF(SUM(*) % 2 = 0, 42, height_inches)`, 740 ExpectedErr: sql.ErrStarUnsupported, 741 }, 742 { 743 Query: `UPDATE people SET height_inches = IF(ROW_NUMBER() OVER() % 2 = 0, 42, height_inches)`, 744 ExpectedErr: sql.ErrWindowUnsupported, 745 }, 746 } 747 748 var UpdateErrorScripts = []ScriptTest{ 749 { 750 Name: "try updating string that is too long", 751 SetUpScript: []string{ 752 "create table bad (s varchar(9))", 753 "insert into bad values ('good')", 754 }, 755 Query: "update bad set s = '1234567890'", 756 ExpectedErr: types.ErrLengthBeyondLimit, 757 }, 758 } 759 760 var ZeroTime = time.Date(0000, time.January, 1, 0, 0, 0, 0, time.UTC) 761 var Jan1Noon = time.Date(2000, time.January, 1, 12, 0, 0, 0, time.UTC) 762 var Dec15_1_30 = time.Date(2023, time.December, 15, 1, 30, 0, 0, time.UTC) 763 var Oct2Midnight = time.Date(2020, time.October, 2, 0, 0, 0, 0, time.UTC) 764 var OnUpdateExprScripts = []ScriptTest{ 765 { 766 Name: "error cases", 767 SetUpScript: []string{ 768 "create table t (i int, ts timestamp);", 769 }, 770 Assertions: []ScriptTestAssertion{ 771 { 772 Query: "create table tt (i int, j int on update (5))", 773 ExpectedErrStr: "syntax error at position 42 near 'update'", 774 }, 775 { 776 Query: "create table tt (i int, j int on update current_timestamp)", 777 ExpectedErr: sql.ErrInvalidOnUpdate, 778 }, 779 { 780 Query: "create table tt (i int, d date on update current_timestamp)", 781 ExpectedErr: sql.ErrInvalidOnUpdate, 782 }, 783 { 784 Query: "create table tt (i int, ts timestamp on update now(1))", 785 ExpectedErr: sql.ErrInvalidOnUpdate, 786 }, 787 { 788 Query: "create table tt (i int, ts timestamp on update current_timestamp(1))", 789 ExpectedErr: sql.ErrInvalidOnUpdate, 790 }, 791 { 792 Query: "create table tt (i int, ts timestamp on update current_timestamp(100))", 793 ExpectedErr: sql.ErrInvalidOnUpdate, 794 }, 795 { 796 Query: "create table tt (i int, ts timestamp on update localtime(1))", 797 ExpectedErr: sql.ErrInvalidOnUpdate, 798 }, 799 { 800 Query: "create table tt (i int, ts timestamp on update localtimestamp(1))", 801 ExpectedErr: sql.ErrInvalidOnUpdate, 802 }, 803 { 804 Query: "alter table t modify column ts timestamp on update (5)", 805 ExpectedErrStr: "syntax error at position 53 near 'update'", 806 }, 807 { 808 Query: "alter table t modify column t int on update current_timestamp", 809 ExpectedErr: sql.ErrInvalidOnUpdate, 810 }, 811 { 812 Query: "alter table t modify column t date on update current_timestamp", 813 ExpectedErr: sql.ErrInvalidOnUpdate, 814 }, 815 { 816 Query: "select current_timestamp(i) from t", 817 ExpectedErrStr: "syntax error at position 27 near 'i'", 818 }, 819 }, 820 }, 821 { 822 Name: "basic case", 823 SetUpScript: []string{ 824 "create table t (i int, ts timestamp default 0 on update current_timestamp);", 825 "insert into t(i) values (1), (2), (3);", 826 }, 827 Assertions: []ScriptTestAssertion{ 828 { 829 Query: "show create table t", 830 Expected: []sql.Row{ 831 {"t", "CREATE TABLE `t` (\n" + 832 " `i` int,\n" + 833 " `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP\n" + 834 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 835 }, 836 }, 837 { 838 SkipResultCheckOnServerEngine: true, 839 Query: "select * from t order by i;", 840 Expected: []sql.Row{ 841 {1, ZeroTime}, 842 {2, ZeroTime}, 843 {3, ZeroTime}, 844 }, 845 }, 846 { 847 Query: "update t set i = 10 where i = 1;", 848 Expected: []sql.Row{ 849 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 850 }, 851 }, 852 { 853 SkipResultCheckOnServerEngine: true, 854 Query: "select * from t order by i;", 855 Expected: []sql.Row{ 856 {2, ZeroTime}, 857 {3, ZeroTime}, 858 {10, Dec15_1_30}, 859 }, 860 }, 861 { 862 Query: "update t set i = 100", 863 Expected: []sql.Row{ 864 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 865 }, 866 }, 867 { 868 Query: "select * from t order by i;", 869 Expected: []sql.Row{ 870 {100, Dec15_1_30}, 871 {100, Dec15_1_30}, 872 {100, Dec15_1_30}, 873 }, 874 }, 875 { 876 // updating timestamp itself blocks on update 877 Query: "update t set ts = timestamp('2020-10-2')", 878 Expected: []sql.Row{ 879 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 880 }, 881 }, 882 { 883 Query: "select * from t;", 884 Expected: []sql.Row{ 885 {100, Oct2Midnight}, 886 {100, Oct2Midnight}, 887 {100, Oct2Midnight}, 888 }, 889 }, 890 }, 891 }, 892 { 893 Name: "default time is current time", 894 SetUpScript: []string{ 895 "create table t (i int, ts timestamp default current_timestamp on update current_timestamp);", 896 "insert into t(i) values (1), (2), (3);", 897 }, 898 Assertions: []ScriptTestAssertion{ 899 { 900 Query: "show create table t", 901 Expected: []sql.Row{ 902 {"t", "CREATE TABLE `t` (\n" + 903 " `i` int,\n" + 904 " `ts` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n" + 905 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 906 }, 907 }, 908 { 909 Query: "select * from t order by i;", 910 Expected: []sql.Row{ 911 {1, Jan1Noon}, 912 {2, Jan1Noon}, 913 {3, Jan1Noon}, 914 }, 915 }, 916 { 917 Query: "update t set i = 10 where i = 1;", 918 Expected: []sql.Row{ 919 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 920 }, 921 }, 922 { 923 Query: "select * from t order by i;", 924 Expected: []sql.Row{ 925 {2, Jan1Noon}, 926 {3, Jan1Noon}, 927 {10, Dec15_1_30}, 928 }, 929 }, 930 { 931 Query: "update t set i = 100", 932 Expected: []sql.Row{ 933 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 934 }, 935 }, 936 { 937 Query: "select * from t order by i;", 938 Expected: []sql.Row{ 939 {100, Dec15_1_30}, 940 {100, Dec15_1_30}, 941 {100, Dec15_1_30}, 942 }, 943 }, 944 { 945 // updating timestamp itself blocks on update 946 Query: "update t set ts = timestamp('2020-10-2')", 947 Expected: []sql.Row{ 948 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 949 }, 950 }, 951 { 952 Query: "select * from t;", 953 Expected: []sql.Row{ 954 {100, Oct2Midnight}, 955 {100, Oct2Midnight}, 956 {100, Oct2Midnight}, 957 }, 958 }, 959 }, 960 }, 961 { 962 Name: "alter table", 963 SetUpScript: []string{ 964 "create table t (i int, ts timestamp);", 965 "insert into t(i) values (1), (2), (3);", 966 }, 967 Assertions: []ScriptTestAssertion{ 968 { 969 Query: "show create table t", 970 Expected: []sql.Row{ 971 {"t", "CREATE TABLE `t` (\n" + 972 " `i` int,\n" + 973 " `ts` timestamp\n" + 974 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 975 }, 976 }, 977 { 978 Query: "alter table t modify column ts timestamp default 0 on update current_timestamp;", 979 Expected: []sql.Row{ 980 {types.NewOkResult(0)}, 981 }, 982 }, 983 { 984 Query: "show create table t", 985 Expected: []sql.Row{ 986 {"t", "CREATE TABLE `t` (\n" + 987 " `i` int,\n" + 988 " `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP\n" + 989 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 990 }, 991 }, 992 { 993 Query: "select * from t order by i;", 994 Expected: []sql.Row{ 995 {1, nil}, 996 {2, nil}, 997 {3, nil}, 998 }, 999 }, 1000 { 1001 Query: "update t set i = 10 where i = 1;", 1002 Expected: []sql.Row{ 1003 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1004 }, 1005 }, 1006 { 1007 Query: "select * from t order by i;", 1008 Expected: []sql.Row{ 1009 {2, nil}, 1010 {3, nil}, 1011 {10, Dec15_1_30}, 1012 }, 1013 }, 1014 { 1015 Query: "update t set i = 100", 1016 Expected: []sql.Row{ 1017 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 1018 }, 1019 }, 1020 { 1021 Query: "select * from t order by i;", 1022 Expected: []sql.Row{ 1023 {100, Dec15_1_30}, 1024 {100, Dec15_1_30}, 1025 {100, Dec15_1_30}, 1026 }, 1027 }, 1028 { 1029 Query: "update t set ts = timestamp('2020-10-2')", 1030 Expected: []sql.Row{ 1031 {types.OkResult{RowsAffected: 3, Info: plan.UpdateInfo{Matched: 3, Updated: 3}}}, 1032 }, 1033 }, 1034 { 1035 Query: "select * from t;", 1036 Expected: []sql.Row{ 1037 {100, Oct2Midnight}, 1038 {100, Oct2Midnight}, 1039 {100, Oct2Midnight}, 1040 }, 1041 }, 1042 }, 1043 }, 1044 { 1045 Name: "multiple columns case", 1046 SetUpScript: []string{ 1047 "create table t (i int primary key, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);", 1048 "insert into t(i) values (1), (2), (3);", 1049 }, 1050 Assertions: []ScriptTestAssertion{ 1051 { 1052 Query: "show create table t", 1053 Expected: []sql.Row{ 1054 {"t", "CREATE TABLE `t` (\n" + 1055 " `i` int NOT NULL,\n" + 1056 " `ts` timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,\n" + 1057 " `dt` datetime DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,\n" + 1058 " PRIMARY KEY (`i`)\n" + 1059 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1060 }, 1061 }, 1062 { 1063 SkipResultCheckOnServerEngine: true, 1064 Query: "select * from t order by i;", 1065 Expected: []sql.Row{ 1066 {1, ZeroTime, ZeroTime}, 1067 {2, ZeroTime, ZeroTime}, 1068 {3, ZeroTime, ZeroTime}, 1069 }, 1070 }, 1071 { 1072 Query: "update t set i = 10 where i = 1;", 1073 Expected: []sql.Row{ 1074 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1075 }, 1076 }, 1077 { 1078 SkipResultCheckOnServerEngine: true, 1079 Query: "select * from t order by i;", 1080 Expected: []sql.Row{ 1081 {2, ZeroTime, ZeroTime}, 1082 {3, ZeroTime, ZeroTime}, 1083 {10, Dec15_1_30, Dec15_1_30}, 1084 }, 1085 }, 1086 { 1087 Query: "update t set ts = timestamp('2020-10-2') where i = 2", 1088 Expected: []sql.Row{ 1089 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1090 }, 1091 }, 1092 { 1093 SkipResultCheckOnServerEngine: true, 1094 Query: "select * from t order by i;", 1095 Expected: []sql.Row{ 1096 {2, Oct2Midnight, Dec15_1_30}, 1097 {3, ZeroTime, ZeroTime}, 1098 {10, Dec15_1_30, Dec15_1_30}, 1099 }, 1100 }, 1101 }, 1102 }, 1103 { 1104 // before update triggers that update the timestamp column block the on update 1105 Name: "before update trigger", 1106 SetUpScript: []string{ 1107 "create table t (i int primary key, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);", 1108 "create trigger trig before update on t for each row set new.ts = timestamp('2020-10-2');", 1109 "insert into t(i) values (1), (2), (3);", 1110 }, 1111 Assertions: []ScriptTestAssertion{ 1112 { 1113 Query: "update t set i = 10 where i = 1;", 1114 Expected: []sql.Row{ 1115 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1116 }, 1117 }, 1118 { 1119 SkipResultCheckOnServerEngine: true, 1120 Query: "select * from t order by i;", 1121 Expected: []sql.Row{ 1122 {2, ZeroTime, ZeroTime}, 1123 {3, ZeroTime, ZeroTime}, 1124 {10, Oct2Midnight, Dec15_1_30}, 1125 }, 1126 }, 1127 }, 1128 }, 1129 { 1130 // update triggers that update other tables do not block on update 1131 Name: "after update trigger", 1132 SetUpScript: []string{ 1133 "create table a (i int primary key);", 1134 "create table b (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);", 1135 "create trigger trig after update on a for each row update b set i = i + 1;", 1136 "insert into a values (0);", 1137 "insert into b(i) values (0);", 1138 }, 1139 Assertions: []ScriptTestAssertion{ 1140 { 1141 SkipResultCheckOnServerEngine: true, 1142 Query: "select * from b order by i;", 1143 Expected: []sql.Row{ 1144 {0, ZeroTime, ZeroTime}, 1145 }, 1146 }, 1147 { 1148 Query: "update a set i = 10;", 1149 Expected: []sql.Row{ 1150 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1151 }, 1152 }, 1153 { 1154 Query: "select * from b order by i;", 1155 Expected: []sql.Row{ 1156 {1, Dec15_1_30, Dec15_1_30}, 1157 }, 1158 }, 1159 }, 1160 }, 1161 { 1162 Name: "insert triggers", 1163 SetUpScript: []string{ 1164 "create table t (i int primary key);", 1165 "create table a (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);", 1166 "create table b (i int, ts timestamp default 0 on update current_timestamp, dt datetime default 0 on update current_timestamp);", 1167 "create trigger trigA after insert on t for each row update a set i = i + 1;", 1168 "create trigger trigB before insert on t for each row update b set i = i + 1;", 1169 "insert into a(i) values (0);", 1170 "insert into b(i) values (0);", 1171 }, 1172 Assertions: []ScriptTestAssertion{ 1173 { 1174 Query: "insert into t values (1);", 1175 Expected: []sql.Row{ 1176 {types.OkResult{RowsAffected: 1}}, 1177 }, 1178 }, 1179 { 1180 Query: "select * from a order by i;", 1181 Expected: []sql.Row{ 1182 {1, Dec15_1_30, Dec15_1_30}, 1183 }, 1184 }, 1185 { 1186 Query: "select * from b order by i;", 1187 Expected: []sql.Row{ 1188 {1, Dec15_1_30, Dec15_1_30}, 1189 }, 1190 }, 1191 }, 1192 }, 1193 { 1194 // Foreign Key Cascade Update does NOT trigger on update on child table 1195 Name: "foreign key tests", 1196 SetUpScript: []string{ 1197 "create table parent (i int primary key);", 1198 "create table child (i int primary key, ts timestamp default 0 on update current_timestamp, foreign key (i) references parent(i) on update cascade);", 1199 "insert into parent values (1);", 1200 "insert into child(i) values (1);", 1201 }, 1202 Assertions: []ScriptTestAssertion{ 1203 { 1204 Query: "update parent set i = 10;", 1205 Expected: []sql.Row{ 1206 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1207 }, 1208 }, 1209 { 1210 SkipResultCheckOnServerEngine: true, 1211 Query: "select * from child;", 1212 Expected: []sql.Row{ 1213 {10, ZeroTime}, 1214 }, 1215 }, 1216 }, 1217 }, 1218 { 1219 Name: "stored procedure tests", 1220 SetUpScript: []string{ 1221 "create table t (i int, ts timestamp default 0 on update current_timestamp);", 1222 "insert into t(i) values (0);", 1223 "create procedure p() update t set i = i + 1;", 1224 }, 1225 Assertions: []ScriptTestAssertion{ 1226 { 1227 // call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver. 1228 SkipResultCheckOnServerEngine: true, 1229 Query: "call p();", 1230 Expected: []sql.Row{ 1231 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 1232 }, 1233 }, 1234 { 1235 Query: "select * from t;", 1236 Expected: []sql.Row{ 1237 {1, Dec15_1_30}, 1238 }, 1239 }, 1240 }, 1241 }, 1242 { 1243 Name: "now() synonyms", 1244 SetUpScript: []string{ 1245 "create table t (i int, ts timestamp);", 1246 }, 1247 Assertions: []ScriptTestAssertion{ 1248 { 1249 Query: "create table t1 (i int, ts timestamp on update now())", 1250 Expected: []sql.Row{ 1251 {types.NewOkResult(0)}, 1252 }, 1253 }, 1254 { 1255 Query: "show create table t1;", 1256 Expected: []sql.Row{ 1257 {"t1", "CREATE TABLE `t1` (\n" + 1258 " `i` int,\n" + 1259 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1260 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1261 }, 1262 }, 1263 { 1264 Query: "create table t2 (i int, ts timestamp on update now(0))", 1265 Expected: []sql.Row{ 1266 {types.NewOkResult(0)}, 1267 }, 1268 }, 1269 { 1270 Query: "show create table t2;", 1271 Expected: []sql.Row{ 1272 {"t2", "CREATE TABLE `t2` (\n" + 1273 " `i` int,\n" + 1274 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1275 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1276 }, 1277 }, 1278 { 1279 Query: "create table t3 (i int, ts timestamp on update localtime)", 1280 Expected: []sql.Row{ 1281 {types.NewOkResult(0)}, 1282 }, 1283 }, 1284 { 1285 Query: "show create table t3;", 1286 Expected: []sql.Row{ 1287 {"t3", "CREATE TABLE `t3` (\n" + 1288 " `i` int,\n" + 1289 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1290 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1291 }, 1292 }, 1293 { 1294 Query: "create table t4 (i int, ts timestamp on update localtime())", 1295 Expected: []sql.Row{ 1296 {types.NewOkResult(0)}, 1297 }, 1298 }, 1299 { 1300 Query: "show create table t4;", 1301 Expected: []sql.Row{ 1302 {"t4", "CREATE TABLE `t4` (\n" + 1303 " `i` int,\n" + 1304 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1305 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1306 }, 1307 }, 1308 { 1309 Query: "create table t5 (i int, ts timestamp on update localtime(0))", 1310 Expected: []sql.Row{ 1311 {types.NewOkResult(0)}, 1312 }, 1313 }, 1314 { 1315 Query: "show create table t5;", 1316 Expected: []sql.Row{ 1317 {"t5", "CREATE TABLE `t5` (\n" + 1318 " `i` int,\n" + 1319 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1320 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1321 }, 1322 }, 1323 { 1324 Query: "create table t6 (i int, ts timestamp on update localtimestamp)", 1325 Expected: []sql.Row{ 1326 {types.NewOkResult(0)}, 1327 }, 1328 }, 1329 { 1330 Query: "show create table t6;", 1331 Expected: []sql.Row{ 1332 {"t6", "CREATE TABLE `t6` (\n" + 1333 " `i` int,\n" + 1334 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1335 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1336 }, 1337 }, 1338 { 1339 Query: "create table t7 (i int, ts timestamp on update localtimestamp())", 1340 Expected: []sql.Row{ 1341 {types.NewOkResult(0)}, 1342 }, 1343 }, 1344 { 1345 Query: "show create table t7;", 1346 Expected: []sql.Row{ 1347 {"t7", "CREATE TABLE `t7` (\n" + 1348 " `i` int,\n" + 1349 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1350 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1351 }, 1352 }, 1353 { 1354 Query: "create table t8 (i int, ts timestamp on update localtimestamp(0))", 1355 Expected: []sql.Row{ 1356 {types.NewOkResult(0)}, 1357 }, 1358 }, 1359 { 1360 Query: "show create table t8;", 1361 Expected: []sql.Row{ 1362 {"t8", "CREATE TABLE `t8` (\n" + 1363 " `i` int,\n" + 1364 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1365 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1366 }, 1367 }, 1368 { 1369 Query: "alter table t modify column ts timestamp on update now()", 1370 Expected: []sql.Row{ 1371 {types.NewOkResult(0)}, 1372 }, 1373 }, 1374 { 1375 Query: "show create table t;", 1376 Expected: []sql.Row{ 1377 {"t", "CREATE TABLE `t` (\n" + 1378 " `i` int,\n" + 1379 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1380 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1381 }, 1382 }, 1383 { 1384 Query: "alter table t modify column ts timestamp on update now(0)", 1385 Expected: []sql.Row{ 1386 {types.NewOkResult(0)}, 1387 }, 1388 }, 1389 { 1390 Query: "show create table t;", 1391 Expected: []sql.Row{ 1392 {"t", "CREATE TABLE `t` (\n" + 1393 " `i` int,\n" + 1394 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1395 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1396 }, 1397 }, 1398 { 1399 Query: "alter table t modify column ts timestamp on update localtime", 1400 Expected: []sql.Row{ 1401 {types.NewOkResult(0)}, 1402 }, 1403 }, 1404 { 1405 Query: "show create table t;", 1406 Expected: []sql.Row{ 1407 {"t", "CREATE TABLE `t` (\n" + 1408 " `i` int,\n" + 1409 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1410 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1411 }, 1412 }, 1413 { 1414 Query: "alter table t modify column ts timestamp on update localtime()", 1415 Expected: []sql.Row{ 1416 {types.NewOkResult(0)}, 1417 }, 1418 }, 1419 { 1420 Query: "show create table t;", 1421 Expected: []sql.Row{ 1422 {"t", "CREATE TABLE `t` (\n" + 1423 " `i` int,\n" + 1424 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1425 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1426 }, 1427 }, 1428 { 1429 Query: "alter table t modify column ts timestamp on update localtime(0)", 1430 Expected: []sql.Row{ 1431 {types.NewOkResult(0)}, 1432 }, 1433 }, 1434 { 1435 Query: "show create table t;", 1436 Expected: []sql.Row{ 1437 {"t", "CREATE TABLE `t` (\n" + 1438 " `i` int,\n" + 1439 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1440 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1441 }, 1442 }, 1443 { 1444 Query: "alter table t modify column ts timestamp on update localtimestamp", 1445 Expected: []sql.Row{ 1446 {types.NewOkResult(0)}, 1447 }, 1448 }, 1449 { 1450 Query: "show create table t;", 1451 Expected: []sql.Row{ 1452 {"t", "CREATE TABLE `t` (\n" + 1453 " `i` int,\n" + 1454 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1455 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1456 }, 1457 }, 1458 { 1459 Query: "alter table t modify column ts timestamp on update localtimestamp()", 1460 Expected: []sql.Row{ 1461 {types.NewOkResult(0)}, 1462 }, 1463 }, 1464 { 1465 Query: "show create table t;", 1466 Expected: []sql.Row{ 1467 {"t", "CREATE TABLE `t` (\n" + 1468 " `i` int,\n" + 1469 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1470 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1471 }, 1472 }, 1473 { 1474 Query: "alter table t modify column ts timestamp on update localtimestamp(0)", 1475 Expected: []sql.Row{ 1476 {types.NewOkResult(0)}, 1477 }, 1478 }, 1479 { 1480 Query: "show create table t;", 1481 Expected: []sql.Row{ 1482 {"t", "CREATE TABLE `t` (\n" + 1483 " `i` int,\n" + 1484 " `ts` timestamp ON UPDATE CURRENT_TIMESTAMP\n" + 1485 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 1486 }, 1487 }, 1488 }, 1489 }, 1490 }