github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/trigger_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 25 var TriggerTests = []ScriptTest{ 26 // INSERT triggers 27 { 28 Name: "trigger before inserts, use updated reference to other table", 29 SetUpScript: []string{ 30 "create table a (i int primary key, j int)", 31 "create table b (x int primary key)", 32 "create trigger trig before insert on a for each row begin set new.j = (select coalesce(max(x),1) from b); update b set x = x + 1; end;", 33 "insert into b values (1)", 34 "insert into a values (1,0), (2,0), (3,0)", 35 }, 36 Assertions: []ScriptTestAssertion{ 37 { 38 Query: "select * from a order by i", 39 Expected: []sql.Row{ 40 {1, 1}, {2, 2}, {3, 3}, 41 }, 42 }, 43 { 44 Query: "select x from b", 45 Expected: []sql.Row{ 46 {4}, 47 }, 48 }, 49 { 50 Query: "insert into a values (4,0), (5,0)", 51 Expected: []sql.Row{ 52 {types.OkResult{RowsAffected: 2}}, 53 }, 54 }, 55 }, 56 }, 57 { 58 Name: "trigger before inserts, use count updated reference to other table", 59 SetUpScript: []string{ 60 "create table a (i int, j int)", 61 "create table b (x int)", 62 "create trigger trig before insert on a for each row begin set new.j = (select count(x) from b); insert into b values (new.i + new.j); end;", 63 "insert into a values (0,0), (0,0), (0,0)", 64 }, 65 Assertions: []ScriptTestAssertion{ 66 { 67 Query: "select * from a order by j", 68 Expected: []sql.Row{ 69 {0, 0}, {0, 1}, {0, 2}, 70 }, 71 }, 72 { 73 Query: "select x from b", 74 Expected: []sql.Row{ 75 {0}, {1}, {2}, 76 }, 77 }, 78 { 79 Query: "insert into a values (0,0), (0,0)", 80 Expected: []sql.Row{ 81 {types.OkResult{RowsAffected: 2}}, 82 }, 83 }, 84 }, 85 }, 86 { 87 Name: "trigger after insert, insert into other table", 88 SetUpScript: []string{ 89 "create table a (x int primary key)", 90 "create table b (y int primary key)", 91 "create trigger insert_into_b after insert on a for each row insert into b values (new.x + 1)", 92 "insert into a values (1), (3), (5)", 93 }, 94 Assertions: []ScriptTestAssertion{ 95 { 96 Query: "select x from a order by 1", 97 Expected: []sql.Row{ 98 {1}, {3}, {5}, 99 }, 100 }, 101 { 102 Query: "select y from b order by 1", 103 Expected: []sql.Row{ 104 {2}, {4}, {6}, 105 }, 106 }, 107 { 108 Query: "insert into a values (7), (9)", 109 Expected: []sql.Row{ 110 {types.OkResult{RowsAffected: 2}}, 111 }, 112 }, 113 }, 114 }, 115 { 116 Name: "trigger after insert, delete from other table", 117 SetUpScript: []string{ 118 "create table a (x int primary key)", 119 "create table b (y int primary key)", 120 "insert into b values (0), (2), (4), (6), (8)", 121 "create trigger insert_into_b after insert on a for each row delete from b where y = (new.x + 1)", 122 "insert into a values (1), (3), (5)", 123 }, 124 Assertions: []ScriptTestAssertion{ 125 { 126 Query: "select x from a order by 1", 127 Expected: []sql.Row{ 128 {1}, {3}, {5}, 129 }, 130 }, 131 { 132 Query: "select y from b order by 1", 133 Expected: []sql.Row{ 134 {0}, {8}, 135 }, 136 }, 137 { 138 Query: "insert into a values (7), (9)", 139 Expected: []sql.Row{ 140 {types.OkResult{RowsAffected: 2}}, 141 }, 142 }, 143 }, 144 }, 145 { 146 Name: "trigger after insert, update other table", 147 SetUpScript: []string{ 148 "create table a (x int primary key)", 149 "create table b (y int primary key)", 150 "insert into b values (0), (2), (4), (6), (8)", 151 "create trigger insert_into_b after insert on a for each row update b set y = new.x where y = new.x + 1", 152 "insert into a values (1), (3), (5)", 153 }, 154 Assertions: []ScriptTestAssertion{ 155 { 156 Query: "select x from a order by 1", 157 Expected: []sql.Row{ 158 {1}, {3}, {5}, 159 }, 160 }, 161 { 162 Query: "select y from b order by 1", 163 Expected: []sql.Row{ 164 {0}, {1}, {3}, {5}, {8}, 165 }, 166 }, 167 }, 168 }, 169 { 170 Name: "trigger before insert, insert into other table", 171 SetUpScript: []string{ 172 "create table a (x int primary key)", 173 "create table b (y int primary key)", 174 "create trigger insert_into_b before insert on a for each row insert into b values (new.x + 1)", 175 "insert into a values (1), (3), (5)", 176 }, 177 Assertions: []ScriptTestAssertion{ 178 { 179 Query: "select x from a order by 1", 180 Expected: []sql.Row{ 181 {1}, {3}, {5}, 182 }, 183 }, 184 { 185 Query: "select y from b order by 1", 186 Expected: []sql.Row{ 187 {2}, {4}, {6}, 188 }, 189 }, 190 { 191 Query: "insert into a values (7), (9)", 192 Expected: []sql.Row{ 193 {types.OkResult{RowsAffected: 2}}, 194 }, 195 }, 196 }, 197 }, 198 { 199 Name: "trigger before insert, insert into other table with different schema", 200 SetUpScript: []string{ 201 "create table a (x int primary key, y int)", 202 "create table b (z int primary key)", 203 "create trigger insert_into_b before insert on a for each row insert into b values (new.x + 1)", 204 "insert into a values (1,2), (3,4), (5,6)", 205 }, 206 Assertions: []ScriptTestAssertion{ 207 { 208 Query: "select x from a order by 1", 209 Expected: []sql.Row{ 210 {1}, {3}, {5}, 211 }, 212 }, 213 { 214 Query: "select z from b order by 1", 215 Expected: []sql.Row{ 216 {2}, {4}, {6}, 217 }, 218 }, 219 { 220 Query: "insert into a values (7,8), (9,10)", 221 Expected: []sql.Row{ 222 {types.OkResult{RowsAffected: 2}}, 223 }, 224 }, 225 }, 226 }, 227 { 228 Name: "trigger before insert, delete from other table", 229 SetUpScript: []string{ 230 "create table a (x int primary key)", 231 "create table b (y int primary key)", 232 "insert into b values (0), (2), (4), (6), (8)", 233 "create trigger insert_into_b before insert on a for each row delete from b where y = (new.x + 1)", 234 "insert into a values (1), (3), (5)", 235 }, 236 Assertions: []ScriptTestAssertion{ 237 { 238 Query: "select x from a order by 1", 239 Expected: []sql.Row{ 240 {1}, {3}, {5}, 241 }, 242 }, 243 { 244 Query: "select y from b order by 1", 245 Expected: []sql.Row{ 246 {0}, {8}, 247 }, 248 }, 249 { 250 Query: "insert into a values (7), (9)", 251 Expected: []sql.Row{ 252 {types.OkResult{RowsAffected: 2}}, 253 }, 254 }, 255 }, 256 }, 257 { 258 Name: "trigger before insert, update other table", 259 SetUpScript: []string{ 260 "create table a (x int primary key)", 261 "create table b (y int primary key)", 262 "insert into b values (0), (2), (4), (6), (8)", 263 "create trigger insert_into_b before insert on a for each row update b set y = new.x where y = new.x + 1", 264 "insert into a values (1), (3), (5)", 265 }, 266 Assertions: []ScriptTestAssertion{ 267 { 268 Query: "select x from a order by 1", 269 Expected: []sql.Row{ 270 {1}, {3}, {5}, 271 }, 272 }, 273 { 274 Query: "select y from b order by 1", 275 Expected: []sql.Row{ 276 {0}, {1}, {3}, {5}, {8}, 277 }, 278 }, 279 }, 280 }, 281 { 282 Name: "trigger before insert, updates references to 2 tables", 283 SetUpScript: []string{ 284 "create table a (i int, j int, k int)", 285 "create table b (x int)", 286 "create table c (y int)", 287 "insert into b values (0)", 288 "insert into c values (0)", 289 "create trigger trig before insert on a for each row begin set new.j = (select x from b); set new.k = (select y from c); update b set x = x + 1; update c set y = y + 2; end;", 290 "insert into a values (0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0)", 291 }, 292 Assertions: []ScriptTestAssertion{ 293 { 294 Query: "select * from a order by 1", 295 Expected: []sql.Row{ 296 {0, 0, 0}, {1, 1, 2}, {2, 2, 4}, {3, 3, 6}, {4, 4, 8}, 297 }, 298 }, 299 { 300 Query: "select x from b order by 1", 301 Expected: []sql.Row{ 302 {5}, 303 }, 304 }, 305 { 306 Query: "select y from c order by 1", 307 Expected: []sql.Row{ 308 {10}, 309 }, 310 }, 311 }, 312 }, 313 { 314 Name: "trigger before insert, alter inserted value", 315 SetUpScript: []string{ 316 "create table a (x int primary key)", 317 "create trigger insert_into_a before insert on a for each row set new.x = new.x + 1", 318 "insert into a values (1)", 319 }, 320 Query: "select x from a order by 1", 321 Expected: []sql.Row{ 322 {2}, 323 }, 324 }, 325 { 326 Name: "trigger before insert, alter inserted value, multiple columns", 327 SetUpScript: []string{ 328 "create table x (a int primary key, b int, c int)", 329 "create trigger insert_into_x before insert on x for each row set new.a = new.a + 1, new.b = new.c, new.c = 0", 330 "insert into x values (1, 10, 100)", 331 }, 332 Query: "select * from x order by 1", 333 Expected: []sql.Row{ 334 {2, 100, 0}, 335 }, 336 }, 337 { 338 Name: "trigger before insert, alter inserted value, multiple columns, system var", 339 SetUpScript: []string{ 340 "create table x (a int primary key, b int, c int)", 341 "set @@auto_increment_increment = 1", 342 "create trigger insert_into_x before insert on x for each row " + 343 "set new.a = new.a + 1, new.b = new.c, new.c = 0, @@auto_increment_increment = @@auto_increment_increment + 1", 344 "insert into x values (1, 10, 100), (2, 20, 200)", 345 }, 346 Query: "select *, @@auto_increment_increment from x order by 1", 347 Expected: []sql.Row{ 348 {2, 100, 0, 3}, 349 {3, 200, 0, 3}, 350 }, 351 }, 352 { 353 Name: "trigger before insert, alter inserted value, out of order insertion", 354 SetUpScript: []string{ 355 "create table a (x int primary key, y int)", 356 "create trigger a1 before insert on a for each row set new.x = new.x * 2, new.y = new.y * 3", 357 }, 358 Assertions: []ScriptTestAssertion{ 359 { 360 Query: "insert into a (y, x) values (5,7), (9,11)", 361 Expected: []sql.Row{ 362 {types.OkResult{RowsAffected: 2}}, 363 }, 364 }, 365 { 366 Query: "select x, y from a order by 1", 367 Expected: []sql.Row{ 368 {14, 15}, 369 {22, 27}, 370 }, 371 }, 372 }, 373 }, 374 { 375 Name: "trigger before insert, alter inserted value, incomplete insertion", 376 SetUpScript: []string{ 377 "create table a (x int primary key, y int, z int default 5)", 378 "create trigger a1 before insert on a for each row set new.x = new.x * 2, new.y = new.y * 3, new.z = new.z * 5", 379 }, 380 Assertions: []ScriptTestAssertion{ 381 { 382 Query: "insert into a (y, x) values (5,7), (9,11)", 383 Expected: []sql.Row{ 384 {types.OkResult{RowsAffected: 2}}, 385 }, 386 }, 387 { 388 Query: "select x, y, z from a order by 1", 389 Expected: []sql.Row{ 390 {14, 15, 25}, 391 {22, 27, 25}, 392 }, 393 }, 394 }, 395 }, 396 { 397 Name: "trigger before insert, begin block with multiple set statements", 398 SetUpScript: []string{ 399 "CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);", 400 "INSERT INTO test VALUES (0,2),(1,3)", 401 `CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 402 BEGIN 403 SET NEW.v1 = NEW.v1 * 11; 404 SET NEW.v1 = NEW.v1 * -10; 405 END;`, 406 "INSERT INTO test VALUES (2,4), (6,8);", 407 }, 408 Assertions: []ScriptTestAssertion{ 409 { 410 Query: "SELECT * FROM test ORDER BY 1", 411 Expected: []sql.Row{ 412 {0, 2}, {1, 3}, {2, -440}, {6, -880}, 413 }, 414 }, 415 }, 416 }, 417 { 418 Name: "trigger before insert, begin block with multiple set statements and inserts", 419 SetUpScript: []string{ 420 "CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);", 421 "CREATE TABLE test2(pk BIGINT PRIMARY KEY, v1 BIGINT);", 422 "CREATE TABLE test3(pk BIGINT PRIMARY KEY, v1 BIGINT);", 423 "INSERT INTO test VALUES (0,2),(1,3)", 424 `CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 425 BEGIN 426 SET NEW.v1 = NEW.v1 * 11; 427 insert into test2 values (new.pk * 3, new.v1); 428 SET NEW.v1 = NEW.v1 * -10; 429 insert into test3 values (new.pk * 5, new.v1); 430 set @var = 0; 431 END;`, 432 "INSERT INTO test VALUES (2,4), (6,8);", 433 }, 434 Assertions: []ScriptTestAssertion{ 435 { 436 Query: "SELECT * FROM test ORDER BY 1", 437 Expected: []sql.Row{ 438 {0, 2}, {1, 3}, {2, -440}, {6, -880}, 439 }, 440 }, 441 { 442 Query: "SELECT * FROM test2 ORDER BY 1", 443 Expected: []sql.Row{ 444 {6, 44}, {18, 88}, 445 }, 446 }, 447 { 448 Query: "SELECT * FROM test3 ORDER BY 1", 449 Expected: []sql.Row{ 450 {10, -440}, {30, -880}, 451 }, 452 }, 453 }, 454 }, 455 { 456 Name: "Create a trigger on a new database and verify that the trigger works when selected on another database", 457 SetUpScript: []string{ 458 "create table foo.a (x int primary key)", 459 "create table foo.b (y int primary key)", 460 "use foo", 461 "create trigger insert_into_b after insert on foo.a for each row insert into foo.b values (new.x + 1)", 462 "use mydb", 463 "insert into foo.a values (1), (3), (5)", 464 }, 465 Assertions: []ScriptTestAssertion{ 466 { 467 Query: "select x from foo.a order by 1", 468 Expected: []sql.Row{ 469 {1}, {3}, {5}, 470 }, 471 }, 472 { 473 Query: "select y from foo.b order by 1", 474 Expected: []sql.Row{ 475 {2}, {4}, {6}, 476 }, 477 }, 478 { 479 Query: "insert into foo.a values (7), (9)", 480 Expected: []sql.Row{ 481 {types.OkResult{RowsAffected: 2}}, 482 }, 483 }, 484 }, 485 }, 486 { 487 Name: "trigger with escaped chars", 488 SetUpScript: []string{ 489 "CREATE TABLE testInt(v1 BIGINT);", 490 "CREATE TABLE testStr(s1 VARCHAR(255), s2 VARCHAR(255), s3 VARCHAR(255));", 491 `CREATE TRIGGER tt BEFORE INSERT ON testInt FOR EACH ROW 492 BEGIN 493 insert into testStr values (CONCAT('joe''s:', NEW.v1), 494 CONCAT('jill\'s:', NEW.v1 + 1), 495 CONCAT("stan""s:", NEW.v1 + 2) 496 ); 497 END;`, 498 "INSERT INTO testInt VALUES (1);", 499 }, 500 Assertions: []ScriptTestAssertion{ 501 { 502 Query: "SELECT * FROM testStr", 503 Expected: []sql.Row{ 504 {"joe's:1", "jill's:2", "stan\"s:3"}, 505 }, 506 }, 507 }, 508 }, 509 510 // UPDATE triggers 511 { 512 Name: "trigger after update, insert into other table", 513 SetUpScript: []string{ 514 "create table a (x int primary key)", 515 "create table b (y int primary key)", 516 "insert into a values (1), (3), (5)", 517 "create trigger insert_into_b after update on a for each row insert into b values (old.x + new.x + 1)", 518 "update a set x = x + 1 where x in (1, 3)", 519 }, 520 Assertions: []ScriptTestAssertion{ 521 { 522 Query: "select x from a order by 1", 523 Expected: []sql.Row{ 524 {2}, {4}, {5}, 525 }, 526 }, 527 { 528 Query: "select y from b order by 1", 529 Expected: []sql.Row{ 530 {4}, {8}, 531 }, 532 }, 533 { 534 Query: "update a set x = x + 1 where x = 5", 535 Expected: []sql.Row{ 536 {types.OkResult{ 537 RowsAffected: 1, 538 Info: plan.UpdateInfo{ 539 Matched: 1, 540 Updated: 1, 541 }, 542 }}, 543 }, 544 }, 545 }, 546 }, 547 { 548 Name: "trigger after update, delete from other table", 549 SetUpScript: []string{ 550 "create table a (x int primary key)", 551 "create table b (y int primary key)", 552 "insert into a values (0), (2), (4), (6), (8)", 553 "insert into b values (1), (3), (5), (7), (9)", 554 "create trigger delete_from_b after update on a for each row delete from b where y = old.x + new.x", 555 "update a set x = x + 1 where x in (2,4)", 556 }, 557 Assertions: []ScriptTestAssertion{ 558 { 559 Query: "select x from a order by 1", 560 Expected: []sql.Row{ 561 {0}, {3}, {5}, {6}, {8}, 562 }, 563 }, 564 { 565 Query: "select y from b order by 1", 566 Expected: []sql.Row{ 567 {1}, {3}, {7}, 568 }, 569 }, 570 }, 571 }, 572 { 573 Name: "trigger after update, update other table", 574 SetUpScript: []string{ 575 "create table a (x int primary key)", 576 "create table b (y int primary key)", 577 "insert into a values (0), (2), (4), (6), (8)", 578 "insert into b values (0), (2), (4), (8)", 579 "create trigger update_b after update on a for each row update b set y = old.x + new.x + 1 where y = old.x", 580 "update a set x = x + 1 where x in (2, 4)", 581 }, 582 Assertions: []ScriptTestAssertion{ 583 { 584 Query: "select x from a order by 1", 585 Expected: []sql.Row{ 586 {0}, {3}, {5}, {6}, {8}, 587 }, 588 }, 589 { 590 Query: "select y from b order by 1", 591 Expected: []sql.Row{ 592 {0}, {6}, {8}, {10}, 593 }, 594 }, 595 }, 596 }, 597 { 598 Name: "trigger before update, insert into other table", 599 SetUpScript: []string{ 600 "create table a (x int primary key)", 601 "create table b (y int primary key)", 602 "insert into a values (1), (3), (5)", 603 "create trigger insert_into_b before update on a for each row insert into b values (old.x + new.x + 1)", 604 "update a set x = x + 1 where x in (1, 3)", 605 }, 606 Assertions: []ScriptTestAssertion{ 607 { 608 Query: "select x from a order by 1", 609 Expected: []sql.Row{ 610 {2}, {4}, {5}, 611 }, 612 }, 613 { 614 Query: "select y from b order by 1", 615 Expected: []sql.Row{ 616 {4}, {8}, 617 }, 618 }, 619 { 620 Query: "update a set x = x + 1 where x = 5", 621 Expected: []sql.Row{ 622 {types.OkResult{ 623 RowsAffected: 1, 624 Info: plan.UpdateInfo{ 625 Matched: 1, 626 Updated: 1, 627 }, 628 }}, 629 }, 630 }, 631 }, 632 }, 633 { 634 Name: "trigger before update, delete from other table", 635 SetUpScript: []string{ 636 "create table a (x int primary key)", 637 "create table b (y int primary key)", 638 "insert into a values (0), (2), (4), (6), (8)", 639 "insert into b values (1), (3), (5), (7), (9)", 640 "create trigger delete_from_b before update on a for each row delete from b where y = old.x + new.x", 641 "update a set x = x + 1 where x in (2,4)", 642 }, 643 Assertions: []ScriptTestAssertion{ 644 { 645 Query: "select x from a order by 1", 646 Expected: []sql.Row{ 647 {0}, {3}, {5}, {6}, {8}, 648 }, 649 }, 650 { 651 Query: "select y from b order by 1", 652 Expected: []sql.Row{ 653 {1}, {3}, {7}, 654 }, 655 }, 656 }, 657 }, 658 { 659 Name: "trigger before update, update other table", 660 SetUpScript: []string{ 661 "create table a (x int primary key)", 662 "create table b (y int primary key)", 663 "insert into a values (0), (2), (4), (6), (8)", 664 "insert into b values (0), (2), (4), (8)", 665 "create trigger update_b before update on a for each row update b set y = old.x + new.x + 1 where y = old.x", 666 "update a set x = x + 1 where x in (2, 4)", 667 }, 668 Assertions: []ScriptTestAssertion{ 669 { 670 Query: "select x from a order by 1", 671 Expected: []sql.Row{ 672 {0}, {3}, {5}, {6}, {8}, 673 }, 674 }, 675 { 676 Query: "select y from b order by 1", 677 Expected: []sql.Row{ 678 {0}, {6}, {8}, {10}, 679 }, 680 }, 681 }, 682 }, 683 { 684 Name: "trigger before update, set new value", 685 SetUpScript: []string{ 686 "create table a (x int primary key)", 687 "insert into a values (1), (10)", 688 "create trigger update_a before update on a for each row set new.x = new.x + old.x", 689 "update a set x = x + 1", 690 }, 691 Query: "select x from a order by 1", 692 Expected: []sql.Row{ 693 {3}, {21}, 694 }, 695 }, 696 { 697 Name: "trigger before update, set new value to old value", 698 SetUpScript: []string{ 699 "create table a (x int primary key)", 700 "insert into a values (1), (10)", 701 "create trigger no_step_on_snek before update on a for each row set new.x = old.x", 702 "update a set x = x + 1", 703 }, 704 Query: "select x from a order by 1", 705 Expected: []sql.Row{ 706 {1}, {10}, 707 }, 708 }, 709 { 710 Name: "trigger before update, set new values, multiple cols", 711 SetUpScript: []string{ 712 "create table a (x int primary key, y int)", 713 "insert into a values (1,3), (10,20)", 714 "create trigger update_a before update on a for each row set new.x = new.x + old.y, new.y = new.y + old.x", 715 "update a set x = x + 1, y = y + 1", 716 }, 717 Query: "select x, y from a order by 1", 718 Expected: []sql.Row{ 719 {5, 5}, 720 {31, 31}, 721 }, 722 }, 723 { 724 Name: "trigger before update, set new values, multiple cols (2)", 725 SetUpScript: []string{ 726 "create table a (x int primary key, y int)", 727 "insert into a values (1,3), (10,20)", 728 "create trigger update_a before update on a for each row set new.x = new.x + new.y, new.y = new.y + old.y", 729 "update a set x = x + 1, y = y + 1", 730 }, 731 Query: "select x, y from a order by 1", 732 Expected: []sql.Row{ 733 {6, 7}, 734 {32, 41}, 735 }, 736 }, 737 { 738 Name: "trigger before update, with indexed update", 739 SetUpScript: []string{ 740 "create table a (x int primary key, y int, unique key (y))", 741 "create table b (z int primary key)", 742 "insert into a values (1,3), (10,20)", 743 "create trigger insert_b before update on a for each row insert into b values (old.x * 10)", 744 "update a set x = x + 1 where y = 20", 745 }, 746 Assertions: []ScriptTestAssertion{ 747 { 748 Query: "select x, y from a order by 1", 749 Expected: []sql.Row{ 750 {1, 3}, 751 {11, 20}, 752 }, 753 }, 754 { 755 Query: "select z from b", 756 Expected: []sql.Row{ 757 {100}, 758 }, 759 }, 760 }, 761 }, 762 { 763 Name: "trigger before update, begin block with multiple set statements", 764 SetUpScript: []string{ 765 "CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);", 766 "INSERT INTO test VALUES (0,2),(1,3)", 767 "CREATE TRIGGER tt BEFORE UPDATE ON test FOR EACH ROW BEGIN SET NEW.v1 = (OLD.v1 * 2) + NEW.v1; SET NEW.v1 = NEW.v1 * -10; END;", 768 "UPDATE test SET v1 = v1 + 1;", 769 }, 770 Assertions: []ScriptTestAssertion{ 771 { 772 Query: "SELECT * FROM test ORDER BY 1", 773 Expected: []sql.Row{ 774 {0, -70}, {1, -100}, 775 }, 776 }, 777 }, 778 }, 779 { 780 Name: "trigger before update with set clause inside if statement with '!' operator", 781 SetUpScript: []string{ 782 "CREATE TABLE test (stat_id INT);", 783 "INSERT INTO test VALUES (-1), (1);", 784 }, 785 Assertions: []ScriptTestAssertion{ 786 { 787 Query: ` 788 CREATE TRIGGER before_test_stat_update BEFORE UPDATE ON test FOR EACH ROW 789 BEGIN 790 IF !(new.stat_id < 0) 791 THEN SET new.stat_id = new.stat_id * -1; 792 END IF; 793 END;`, 794 Expected: []sql.Row{{types.OkResult{}}}, 795 }, 796 { 797 Query: "update test set stat_id=2 where stat_id=1;", 798 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}}, 799 }, 800 { 801 Query: "select * from test order by stat_id;", 802 Expected: []sql.Row{{-2}, {-1}}, 803 }, 804 { 805 Query: "update test set stat_id=-2 where stat_id=-1;", 806 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}}, 807 }, 808 { 809 Query: "select * from test;", 810 Expected: []sql.Row{{-2}, {-2}}, 811 }, 812 }, 813 }, 814 { 815 Name: "trigger before update with set clause inside if statement with 'NOT'", 816 SetUpScript: []string{ 817 "CREATE TABLE test (stat_id INT);", 818 "INSERT INTO test VALUES (-1), (1);", 819 }, 820 Assertions: []ScriptTestAssertion{ 821 { 822 Query: ` 823 CREATE TRIGGER before_test_stat_update BEFORE UPDATE ON test FOR EACH ROW 824 BEGIN 825 IF NOT(new.stat_id < 0) 826 THEN SET new.stat_id = new.stat_id * -1; 827 END IF; 828 END;`, 829 Expected: []sql.Row{{types.OkResult{}}}, 830 }, 831 { 832 Query: "update test set stat_id=2 where stat_id=1;", 833 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}}, 834 }, 835 { 836 Query: "select * from test order by stat_id;", 837 Expected: []sql.Row{{-2}, {-1}}, 838 }, 839 { 840 Query: "update test set stat_id=-2 where stat_id=-1;", 841 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}}, 842 }, 843 { 844 Query: "select * from test;", 845 Expected: []sql.Row{{-2}, {-2}}, 846 }, 847 }, 848 }, 849 // DELETE triggers 850 { 851 Name: "trigger after delete, insert into other table", 852 SetUpScript: []string{ 853 "create table a (x int primary key)", 854 "create table b (y int primary key)", 855 "insert into a values (1), (3), (5)", 856 "create trigger insert_into_b after delete on a for each row insert into b values (old.x + 1)", 857 "delete from a where x in (1, 3)", 858 }, 859 Assertions: []ScriptTestAssertion{ 860 { 861 Query: "select x from a order by 1", 862 Expected: []sql.Row{ 863 {5}, 864 }, 865 }, 866 { 867 Query: "select y from b order by 1", 868 Expected: []sql.Row{ 869 {2}, {4}, 870 }, 871 }, 872 { 873 Query: "delete from a where x = 5", 874 Expected: []sql.Row{ 875 {types.OkResult{RowsAffected: 1}}, 876 }, 877 }, 878 }, 879 }, 880 { 881 Name: "trigger after delete, delete from other table", 882 SetUpScript: []string{ 883 "create table a (x int primary key)", 884 "create table b (y int primary key)", 885 "insert into a values (0), (2), (4), (6), (8)", 886 "insert into b values (0), (2), (4), (6), (8)", 887 "create trigger delete_from_b after delete on a for each row delete from b where y = old.x", 888 "delete from a where x in (2,4,6)", 889 }, 890 Assertions: []ScriptTestAssertion{ 891 { 892 Query: "select x from a order by 1", 893 Expected: []sql.Row{ 894 {0}, {8}, 895 }, 896 }, 897 { 898 Query: "select y from b order by 1", 899 Expected: []sql.Row{ 900 {0}, {8}, 901 }, 902 }, 903 }, 904 }, 905 { 906 Name: "trigger after delete, update other table", 907 SetUpScript: []string{ 908 "create table a (x int primary key)", 909 "create table b (y int primary key)", 910 "insert into a values (0), (2), (4), (6), (8)", 911 "insert into b values (0), (2), (4), (6), (8)", 912 "create trigger update_b after delete on a for each row update b set y = old.x + 1 where y = old.x", 913 "delete from a where x in (2,4,6)", 914 }, 915 Assertions: []ScriptTestAssertion{ 916 { 917 Query: "select x from a order by 1", 918 Expected: []sql.Row{ 919 {0}, {8}, 920 }, 921 }, 922 { 923 Query: "select y from b order by 1", 924 Expected: []sql.Row{ 925 {0}, {3}, {5}, {7}, {8}, 926 }, 927 }, 928 }, 929 }, 930 { 931 Name: "trigger before delete, insert into other table", 932 SetUpScript: []string{ 933 "create table a (x int primary key)", 934 "create table b (y int primary key)", 935 "insert into a values (0), (2), (4), (6), (8)", 936 "create trigger insert_into_b before delete on a for each row insert into b values (old.x + 1)", 937 "delete from a where x in (2, 4, 6)", 938 }, 939 Assertions: []ScriptTestAssertion{ 940 { 941 Query: "select x from a order by 1", 942 Expected: []sql.Row{ 943 {0}, {8}, 944 }, 945 }, 946 { 947 Query: "select y from b order by 1", 948 Expected: []sql.Row{ 949 {3}, {5}, {7}, 950 }, 951 }, 952 { 953 Query: "delete from a where x = 0", 954 Expected: []sql.Row{ 955 {types.OkResult{RowsAffected: 1}}, 956 }, 957 }, 958 }, 959 }, 960 { 961 Name: "trigger before delete, delete from other table", 962 SetUpScript: []string{ 963 "create table a (x int primary key)", 964 "create table b (y int primary key)", 965 "insert into a values (0), (2), (4), (6), (8)", 966 "insert into b values (1), (3), (5), (7), (9)", 967 "create trigger delete_from_b before delete on a for each row delete from b where y = (old.x + 1)", 968 "delete from a where x in (2, 4, 6)", 969 }, 970 Assertions: []ScriptTestAssertion{ 971 { 972 Query: "select x from a order by 1", 973 Expected: []sql.Row{ 974 {0}, {8}, 975 }, 976 }, 977 { 978 Query: "select y from b order by 1", 979 Expected: []sql.Row{ 980 {1}, {9}, 981 }, 982 }, 983 }, 984 }, 985 { 986 Name: "trigger before delete, update other table", 987 SetUpScript: []string{ 988 "create table a (x int primary key)", 989 "create table b (y int primary key)", 990 "insert into a values (0), (2), (4), (6), (8)", 991 "insert into b values (1), (3), (5), (7), (9)", 992 "create trigger update_b before delete on a for each row update b set y = old.x where y = old.x + 1", 993 "delete from a where x in (2, 4, 6)", 994 }, 995 Assertions: []ScriptTestAssertion{ 996 { 997 Query: "select x from a order by 1", 998 Expected: []sql.Row{ 999 {0}, {8}, 1000 }, 1001 }, 1002 { 1003 Query: "select y from b order by 1", 1004 Expected: []sql.Row{ 1005 {1}, {2}, {4}, {6}, {9}, 1006 }, 1007 }, 1008 }, 1009 }, 1010 { 1011 Name: "trigger before delete, delete with index", 1012 SetUpScript: []string{ 1013 "create table a (x int primary key, z int, unique key (z))", 1014 "create table b (y int primary key)", 1015 "insert into a values (0,1), (2,3), (4,5)", 1016 "create trigger insert_b before delete on a for each row insert into b values (old.x * 2)", 1017 "delete from a where z > 2", 1018 }, 1019 Assertions: []ScriptTestAssertion{ 1020 { 1021 Query: "select x from a order by 1", 1022 Expected: []sql.Row{ 1023 {0}, 1024 }, 1025 }, 1026 { 1027 Query: "select y from b order by 1", 1028 Expected: []sql.Row{ 1029 {4}, {8}, 1030 }, 1031 }, 1032 }, 1033 }, 1034 { 1035 Name: "trigger before delete, update other table", 1036 SetUpScript: []string{ 1037 "create table a (i int primary key, j int)", 1038 "insert into a values (0,1), (2,3), (4,5)", 1039 "create table b (x int)", 1040 "insert into b values (0)", 1041 "create trigger trig before delete on a for each row begin update b set x = x + old.j; end;", 1042 "delete from a where true", 1043 }, 1044 Assertions: []ScriptTestAssertion{ 1045 { 1046 Query: "select * from a order by 1", 1047 Expected: []sql.Row{}, 1048 }, 1049 { 1050 Query: "select x from b order by 1", 1051 Expected: []sql.Row{ 1052 {9}, 1053 }, 1054 }, 1055 }, 1056 }, 1057 { 1058 Name: "single trigger before single target table delete from join", 1059 SetUpScript: []string{ 1060 "create table a (i int primary key, j int)", 1061 "insert into a values (0,1), (2,3), (4,5)", 1062 "create table b (i int primary key)", 1063 "insert into b values (1), (3), (5)", 1064 "create table c (x int)", 1065 "insert into c values (0)", 1066 "create trigger trig before delete on a for each row begin update c set x = x + 1; end;", 1067 }, 1068 Assertions: []ScriptTestAssertion{ 1069 { 1070 Query: "delete a from a inner join b on a.j=b.i;", 1071 ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes", 1072 }, 1073 }, 1074 }, 1075 { 1076 Name: "multiple trigger before single target table delete from join", 1077 SetUpScript: []string{ 1078 "create table a (i int primary key, j int)", 1079 "insert into a values (0,1), (2,3), (4,5)", 1080 "create table b (i int primary key)", 1081 "insert into b values (1), (3), (5)", 1082 "create table c (x int)", 1083 "insert into c values (0)", 1084 "create trigger trig1 before delete on a for each row begin update c set x = x + 1; end;", 1085 "create trigger trig2 before delete on b for each row begin update c set x = x + 1; end;", 1086 }, 1087 Assertions: []ScriptTestAssertion{ 1088 { 1089 Query: "delete a from a inner join b on a.j=b.i where a.i >= 0;", 1090 ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes", 1091 }, 1092 }, 1093 }, 1094 { 1095 Name: "multiple trigger before multiple target table delete from join", 1096 SetUpScript: []string{ 1097 "create table a (i int primary key, j int)", 1098 "insert into a values (0,1), (2,3), (4,5)", 1099 "create table b (i int primary key)", 1100 "insert into b values (1), (3), (5)", 1101 "create table c (x int)", 1102 "insert into c values (0)", 1103 "create trigger trig1 before delete on a for each row begin update c set x = x + 1; end;", 1104 "create trigger trig2 before delete on b for each row begin update c set x = x + 1; end;", 1105 }, 1106 Assertions: []ScriptTestAssertion{ 1107 { 1108 Query: "delete a, b from a inner join b on a.j=b.i where a.i >= 0;", 1109 ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes", 1110 }, 1111 }, 1112 }, 1113 // Multiple triggers defined 1114 { 1115 Name: "triggers before and after insert", 1116 SetUpScript: []string{ 1117 "create table a (x int primary key)", 1118 "create table b (y int primary key)", 1119 "create trigger a1 before insert on a for each row insert into b values (NEW.x * 7)", 1120 "create trigger a2 after insert on a for each row insert into b values (New.x * 11)", 1121 }, 1122 Assertions: []ScriptTestAssertion{ 1123 { 1124 Query: "insert into a values (2), (3), (5)", 1125 Expected: []sql.Row{ 1126 {types.NewOkResult(3)}, 1127 }, 1128 }, 1129 { 1130 Query: "select x from a order by 1", 1131 Expected: []sql.Row{ 1132 {2}, {3}, {5}, 1133 }, 1134 }, 1135 { 1136 Query: "select y from b order by 1", 1137 Expected: []sql.Row{ 1138 {14}, {21}, {22}, {33}, {35}, {55}, 1139 }, 1140 }, 1141 }, 1142 }, 1143 { 1144 Name: "multiple triggers before insert", 1145 SetUpScript: []string{ 1146 "create table a (x int primary key)", 1147 "create trigger a1 before insert on a for each row set new.x = New.x + 1", 1148 "create trigger a2 before insert on a for each row set new.x = New.x * 2", 1149 "create trigger a3 before insert on a for each row set new.x = New.x - 5", 1150 }, 1151 Assertions: []ScriptTestAssertion{ 1152 { 1153 Query: "insert into a values (1), (3)", 1154 Expected: []sql.Row{ 1155 {types.NewOkResult(2)}, 1156 }, 1157 }, 1158 { 1159 Query: "select x from a order by 1", 1160 Expected: []sql.Row{ 1161 {-1}, {3}, 1162 }, 1163 }, 1164 }, 1165 }, 1166 { 1167 Name: "multiple triggers before insert, with precedes / follows", 1168 SetUpScript: []string{ 1169 "create table a (x int primary key)", 1170 "create trigger a1 before insert on a for each row set new.x = New.x + 1", 1171 "create trigger a2 before insert on a for each row precedes a1 set new.x = New.x * 2", 1172 "create trigger a3 before insert on a for each row precedes a2 set new.x = New.x - 5", 1173 "create trigger a4 before insert on a for each row follows a2 set new.x = New.x * 3", 1174 // order of execution should be: a3, a2, a4, a1 1175 }, 1176 Assertions: []ScriptTestAssertion{ 1177 { 1178 Query: "insert into a values (1), (3)", 1179 Expected: []sql.Row{ 1180 {types.NewOkResult(2)}, 1181 }, 1182 }, 1183 { 1184 Query: "select x from a order by 1", 1185 Expected: []sql.Row{ 1186 {-23}, {-11}, 1187 }, 1188 }, 1189 }, 1190 }, 1191 { 1192 Name: "triggers before and after update", 1193 SetUpScript: []string{ 1194 "create table a (x int primary key)", 1195 "create table b (y int primary key)", 1196 "create trigger a1 before update on a for each row insert into b values (old.x * 7)", 1197 "create trigger a2 after update on a for each row insert into b values (old.x * 11)", 1198 "insert into a values (2), (3), (5)", 1199 }, 1200 Assertions: []ScriptTestAssertion{ 1201 { 1202 Query: "update a set x = x * 2", 1203 Expected: []sql.Row{ 1204 {types.OkResult{ 1205 RowsAffected: 3, 1206 Info: plan.UpdateInfo{ 1207 Matched: 3, 1208 Updated: 3, 1209 }, 1210 }}, 1211 }, 1212 }, 1213 { 1214 Query: "select x from a order by 1", 1215 Expected: []sql.Row{ 1216 {4}, {6}, {10}, 1217 }, 1218 }, 1219 { 1220 Query: "select y from b order by 1", 1221 Expected: []sql.Row{ 1222 {14}, {21}, {22}, {33}, {35}, {55}, 1223 }, 1224 }, 1225 }, 1226 }, 1227 { 1228 Name: "multiple triggers before and after update", 1229 SetUpScript: []string{ 1230 "create table a (x int primary key)", 1231 "create table b (y int primary key)", 1232 "create trigger a1 before update on a for each row insert into b values (old.x * 7)", 1233 "create trigger a2 after update on a for each row insert into b values (old.x * 11)", 1234 "create trigger a3 before update on a for each row insert into b values (old.x * 13)", 1235 "create trigger a4 after update on a for each row insert into b values (old.x * 17)", 1236 "insert into a values (2), (3), (5)", 1237 }, 1238 Assertions: []ScriptTestAssertion{ 1239 { 1240 Query: "update a set x = x * 2", 1241 Expected: []sql.Row{ 1242 {types.OkResult{ 1243 RowsAffected: 3, 1244 Info: plan.UpdateInfo{ 1245 Matched: 3, 1246 Updated: 3, 1247 }, 1248 }}, 1249 }, 1250 }, 1251 { 1252 Query: "select x from a order by 1", 1253 Expected: []sql.Row{ 1254 {4}, {6}, {10}, 1255 }, 1256 }, 1257 { 1258 Query: "select y from b order by 1", 1259 Expected: []sql.Row{ 1260 {14}, {21}, {22}, {26}, {33}, {34}, {35}, {39}, {51}, {55}, {65}, {85}, 1261 }, 1262 }, 1263 }, 1264 }, 1265 { 1266 Name: "triggers before and after delete", 1267 SetUpScript: []string{ 1268 "create table a (x int primary key)", 1269 "create table b (y int primary key)", 1270 "create trigger a1 before delete on a for each row insert into b values (old.x * 7)", 1271 "create trigger a2 after delete on a for each row insert into b values (old.x * 11)", 1272 "insert into a values (2), (3), (5)", 1273 }, 1274 Assertions: []ScriptTestAssertion{ 1275 { 1276 Query: "delete from a", 1277 Expected: []sql.Row{ 1278 {types.NewOkResult(3)}, 1279 }, 1280 }, 1281 { 1282 Query: "select x from a order by 1", 1283 Expected: []sql.Row{}, 1284 }, 1285 { 1286 Query: "select y from b order by 1", 1287 Expected: []sql.Row{ 1288 {14}, {21}, {22}, {33}, {35}, {55}, 1289 }, 1290 }, 1291 }, 1292 }, 1293 { 1294 Name: "multiple triggers before and after delete", 1295 SetUpScript: []string{ 1296 "create table a (x int primary key)", 1297 "create table b (y int primary key)", 1298 "create trigger a1 before delete on a for each row insert into b values (old.x * 7)", 1299 "create trigger a2 after delete on a for each row insert into b values (old.x * 11)", 1300 "create trigger a3 before delete on a for each row insert into b values (old.x * 13)", 1301 "create trigger a4 after delete on a for each row insert into b values (old.x * 17)", 1302 "insert into a values (2), (3), (5)", 1303 }, 1304 Assertions: []ScriptTestAssertion{ 1305 { 1306 Query: "delete from a", 1307 Expected: []sql.Row{ 1308 {types.NewOkResult(3)}, 1309 }, 1310 }, 1311 { 1312 Query: "select x from a order by 1", 1313 Expected: []sql.Row{}, 1314 }, 1315 { 1316 Query: "select y from b order by 1", 1317 Expected: []sql.Row{ 1318 {14}, {21}, {22}, {26}, {33}, {34}, {35}, {39}, {51}, {55}, {65}, {85}, 1319 }, 1320 }, 1321 }, 1322 }, 1323 { 1324 Name: "multiple triggers before and after insert, with precedes / follows", 1325 SetUpScript: []string{ 1326 "create table a (x int primary key)", 1327 "create table b (y int primary key)", 1328 "insert into b values (1), (3)", 1329 "create trigger a1 before insert on a for each row set new.x = New.x + 1", 1330 "create trigger a2 before insert on a for each row precedes a1 set new.x = New.x * 2", 1331 "create trigger a3 before insert on a for each row precedes a2 set new.x = New.x - 5", 1332 "create trigger a4 before insert on a for each row follows a2 set new.x = New.x * 3", 1333 // order of execution should be: a3, a2, a4, a1 1334 "create trigger a5 after insert on a for each row update b set y = y + 1 order by y asc", 1335 "create trigger a6 after insert on a for each row precedes a5 update b set y = y * 2 order by y asc", 1336 "create trigger a7 after insert on a for each row precedes a6 update b set y = y - 5 order by y asc", 1337 "create trigger a8 after insert on a for each row follows a6 update b set y = y * 3 order by y asc", 1338 // order of execution should be: a7, a6, a8, a5 1339 }, 1340 Assertions: []ScriptTestAssertion{ 1341 { 1342 Query: "insert into a values (1), (3)", 1343 Expected: []sql.Row{ 1344 {types.NewOkResult(2)}, 1345 }, 1346 }, 1347 { 1348 Query: "select x from a order by 1", 1349 Expected: []sql.Row{ 1350 {-23}, {-11}, 1351 }, 1352 }, 1353 { 1354 Query: "select y from b order by 1", 1355 // This result is a bit counter-intutitive: it doesn't match the inserted row, because all 4 triggers run their 1356 // update statement twice on the rows in b, once for each row inserted into a 1357 Expected: []sql.Row{ 1358 {-167}, {-95}, 1359 }, 1360 }, 1361 }, 1362 }, 1363 { 1364 Name: "triggered update query which could project", 1365 SetUpScript: []string{ 1366 "create table trigger_on_update (id int primary key, first varchar(25), last varchar(25))", 1367 "create table is_dirty (id int primary key, is_dirty bool)", 1368 "insert into is_dirty values (1, false)", 1369 "insert into trigger_on_update values (1, 'george', 'smith')", 1370 `create trigger trigger_on_update_on_update before update on trigger_on_update for each row 1371 begin 1372 update is_dirty set is_dirty = true; 1373 end;`, 1374 }, 1375 Assertions: []ScriptTestAssertion{ 1376 { 1377 Query: "select id, is_dirty from is_dirty", 1378 Expected: []sql.Row{ 1379 {1, 0}, 1380 }, 1381 }, 1382 { 1383 Query: "update trigger_on_update set id = 1, first = 'george', last = 'smith' where id = 1", 1384 Expected: []sql.Row{ 1385 { 1386 types.OkResult{ 1387 RowsAffected: 0, 1388 Info: plan.UpdateInfo{ 1389 Matched: 1, 1390 Updated: 0, 1391 }, 1392 }, 1393 }, 1394 }, 1395 }, 1396 { 1397 Query: "select id, is_dirty from is_dirty", 1398 Expected: []sql.Row{ 1399 {1, 1}, 1400 }, 1401 }, 1402 }, 1403 }, 1404 // Trigger with subquery 1405 { 1406 Name: "trigger before insert with subquery expressions", 1407 SetUpScript: []string{ 1408 "create table rn (id int primary key, upstream_edge_id int, downstream_edge_id int)", 1409 "create table sn (id int primary key, target_id int, source_id int)", 1410 ` 1411 create trigger rn_on_insert before insert on rn 1412 for each row 1413 begin 1414 if 1415 (select target_id from sn where id = NEW.upstream_edge_id) <> (select source_id from sn where id = NEW.downstream_edge_id) 1416 then 1417 set @myvar = concat('bro', 'ken'); 1418 SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @myvar; 1419 end if; 1420 end;`, 1421 }, 1422 Assertions: []ScriptTestAssertion{ 1423 { 1424 Query: "insert into rn values (1,1,1)", 1425 }, 1426 { 1427 Query: "select id from rn", 1428 Expected: []sql.Row{{1}}, 1429 }, 1430 }, 1431 }, 1432 { 1433 Name: "trigger with signal and user var", 1434 SetUpScript: []string{ 1435 "create table t1 (id int primary key)", 1436 "create table t2 (id int primary key)", 1437 ` 1438 create trigger trigger1 before insert on t1 1439 for each row 1440 begin 1441 set @myvar = concat('bro', 'ken'); 1442 SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @myvar; 1443 end;`, 1444 }, 1445 Assertions: []ScriptTestAssertion{ 1446 { 1447 Query: "insert into t1 values (1)", 1448 ExpectedErrStr: "broken (errno 1644) (sqlstate 45000)", 1449 }, 1450 { 1451 Query: "select id from t1", 1452 Expected: []sql.Row{}, 1453 }, 1454 }, 1455 }, 1456 // Complex trigger scripts 1457 { 1458 Name: "trigger before insert, multiple triggers defined", 1459 SetUpScript: []string{ 1460 "create table a (x int primary key)", 1461 "create table b (y int primary key)", 1462 "create table c (z int primary key)", 1463 // Only one of these triggers should run for each table 1464 "create trigger a1 before insert on a for each row insert into b values (new.x * 2)", 1465 "create trigger a2 before update on a for each row insert into b values (new.x * 3)", 1466 "create trigger a3 before delete on a for each row insert into b values (old.x * 5)", 1467 "create trigger b1 before insert on b for each row insert into c values (new.y * 7)", 1468 "create trigger b2 before update on b for each row insert into c values (new.y * 11)", 1469 "create trigger b3 before delete on b for each row insert into c values (old.y * 13)", 1470 "insert into a values (1), (2), (3)", 1471 }, 1472 Assertions: []ScriptTestAssertion{ 1473 { 1474 Query: "select x from a order by 1", 1475 Expected: []sql.Row{ 1476 {1}, {2}, {3}, 1477 }, 1478 }, 1479 { 1480 Query: "select y from b order by 1", 1481 Expected: []sql.Row{ 1482 {2}, {4}, {6}, 1483 }, 1484 }, 1485 { 1486 Query: "select z from c order by 1", 1487 Expected: []sql.Row{ 1488 {14}, {28}, {42}, 1489 }, 1490 }, 1491 }, 1492 }, 1493 { 1494 Name: "trigger with signal", 1495 SetUpScript: []string{ 1496 "create table a (x int primary key)", 1497 "create table b (y int primary key)", 1498 "create table c (z int primary key)", 1499 "insert into c values (-1)", 1500 `create trigger trig_with_signal before insert on a for each row 1501 begin 1502 declare cond_name condition for sqlstate '45000'; 1503 if new.x = 5 then signal cond_name set message_text = 'trig err'; 1504 end if; 1505 insert into b values (new.x + 1); 1506 update c set z = new.x; 1507 end;`, 1508 }, 1509 Assertions: []ScriptTestAssertion{ 1510 { 1511 Query: "insert into a values (1), (3)", 1512 Expected: []sql.Row{ 1513 {types.OkResult{RowsAffected: 2}}, 1514 }, 1515 }, 1516 { 1517 Query: "insert into a values (5)", 1518 ExpectedErrStr: "trig err (errno 1644) (sqlstate 45000)", 1519 }, 1520 { 1521 Query: "select x from a order by 1", 1522 Expected: []sql.Row{ 1523 {1}, {3}, 1524 }, 1525 }, 1526 { 1527 Query: "select y from b order by 1", 1528 Expected: []sql.Row{ 1529 {2}, {4}, 1530 }, 1531 }, 1532 { 1533 Query: "select z from c order by 1", 1534 Expected: []sql.Row{ 1535 {3}, 1536 }, 1537 }, 1538 }, 1539 }, 1540 // SHOW CREATE TRIGGER scripts 1541 { 1542 Name: "show create triggers", 1543 SetUpScript: []string{ 1544 "create table a (x int primary key)", 1545 "create trigger a1 before insert on a for each row set new.x = new.x + 1", 1546 "create table b (y int primary key)", 1547 "create trigger b1 before insert on b for each row set new.y = new.y + 2", 1548 }, 1549 Assertions: []ScriptTestAssertion{ 1550 { 1551 Query: "show create trigger a1", 1552 Expected: []sql.Row{ 1553 { 1554 "a1", // Trigger 1555 "", // sql_mode 1556 "create trigger a1 before insert on a for each row set new.x = new.x + 1", // SQL Original Statement 1557 sql.Collation_Default.CharacterSet().String(), // character_set_client 1558 sql.Collation_Default.String(), // collation_connection 1559 sql.Collation_Default.String(), // Database Collation 1560 time.Unix(0, 0).UTC(), // Created 1561 }, 1562 }, 1563 }, 1564 { 1565 Query: "show create trigger b1", 1566 Expected: []sql.Row{ 1567 { 1568 "b1", // Trigger 1569 "", // sql_mode 1570 "create trigger b1 before insert on b for each row set new.y = new.y + 2", // SQL Original Statement 1571 sql.Collation_Default.CharacterSet().String(), // character_set_client 1572 sql.Collation_Default.String(), // collation_connection 1573 sql.Collation_Default.String(), // Database Collation 1574 time.Unix(0, 0).UTC(), // Created 1575 }, 1576 }, 1577 }, 1578 { 1579 Query: "show create trigger b2", 1580 ExpectedErr: sql.ErrTriggerDoesNotExist, 1581 }, 1582 }, 1583 }, 1584 // SHOW TRIGGERS scripts 1585 { 1586 Name: "show triggers", 1587 SetUpScript: []string{ 1588 "create table abb (x int primary key)", 1589 "create table acc (y int primary key)", 1590 "create trigger t1 before insert on abb for each row set new.x = new.x + 1", 1591 "create trigger t2 before insert on abb for each row set new.x = new.x + 2", 1592 "create trigger t3 after insert on acc for each row insert into abb values (new.y)", 1593 "create trigger t4 before update on acc for each row set new.y = old.y + 2", 1594 }, 1595 Assertions: []ScriptTestAssertion{ 1596 { 1597 Query: "show triggers", 1598 Expected: []sql.Row{ 1599 { 1600 "t1", // Trigger 1601 "INSERT", // Event 1602 "abb", // Table 1603 "set new.x = new.x + 1", // Statement 1604 "BEFORE", // Timing 1605 time.Unix(0, 0).UTC(), // Created 1606 "", // sql_mode 1607 "", // Definer 1608 sql.Collation_Default.CharacterSet().String(), // character_set_client 1609 sql.Collation_Default.String(), // collation_connection 1610 sql.Collation_Default.String(), // Database Collation 1611 }, 1612 { 1613 "t2", // Trigger 1614 "INSERT", // Event 1615 "abb", // Table 1616 "set new.x = new.x + 2", // Statement 1617 "BEFORE", // Timing 1618 time.Unix(0, 0).UTC(), // Created 1619 "", // sql_mode 1620 "", // Definer 1621 sql.Collation_Default.CharacterSet().String(), // character_set_client 1622 sql.Collation_Default.String(), // collation_connection 1623 sql.Collation_Default.String(), // Database Collation 1624 }, 1625 { 1626 "t3", // Trigger 1627 "INSERT", // Event 1628 "acc", // Table 1629 "insert into abb values (new.y)", // Statement 1630 "AFTER", // Timing 1631 time.Unix(0, 0).UTC(), // Created 1632 "", // sql_mode 1633 "", // Definer 1634 sql.Collation_Default.CharacterSet().String(), // character_set_client 1635 sql.Collation_Default.String(), // collation_connection 1636 sql.Collation_Default.String(), // Database Collation 1637 }, 1638 { 1639 "t4", // Trigger 1640 "UPDATE", // Event 1641 "acc", // Table 1642 "set new.y = old.y + 2", // Statement 1643 "BEFORE", // Timing 1644 time.Unix(0, 0).UTC(), // Created 1645 "", // sql_mode 1646 "", // Definer 1647 sql.Collation_Default.CharacterSet().String(), // character_set_client 1648 sql.Collation_Default.String(), // collation_connection 1649 sql.Collation_Default.String(), // Database Collation 1650 }, 1651 }, 1652 }, 1653 { 1654 Query: "show triggers from mydb", 1655 Expected: []sql.Row{ 1656 { 1657 "t1", // Trigger 1658 "INSERT", // Event 1659 "abb", // Table 1660 "set new.x = new.x + 1", // Statement 1661 "BEFORE", // Timing 1662 time.Unix(0, 0).UTC(), // Created 1663 "", // sql_mode 1664 "", // Definer 1665 sql.Collation_Default.CharacterSet().String(), // character_set_client 1666 sql.Collation_Default.String(), // collation_connection 1667 sql.Collation_Default.String(), // Database Collation 1668 }, 1669 { 1670 "t2", // Trigger 1671 "INSERT", // Event 1672 "abb", // Table 1673 "set new.x = new.x + 2", // Statement 1674 "BEFORE", // Timing 1675 time.Unix(0, 0).UTC(), // Created 1676 "", // sql_mode 1677 "", // Definer 1678 sql.Collation_Default.CharacterSet().String(), // character_set_client 1679 sql.Collation_Default.String(), // collation_connection 1680 sql.Collation_Default.String(), // Database Collation 1681 }, 1682 { 1683 "t3", // Trigger 1684 "INSERT", // Event 1685 "acc", // Table 1686 "insert into abb values (new.y)", // Statement 1687 "AFTER", // Timing 1688 time.Unix(0, 0).UTC(), // Created 1689 "", // sql_mode 1690 "", // Definer 1691 sql.Collation_Default.CharacterSet().String(), // character_set_client 1692 sql.Collation_Default.String(), // collation_connection 1693 sql.Collation_Default.String(), // Database Collation 1694 }, 1695 { 1696 "t4", // Trigger 1697 "UPDATE", // Event 1698 "acc", // Table 1699 "set new.y = old.y + 2", // Statement 1700 "BEFORE", // Timing 1701 time.Unix(0, 0).UTC(), // Created 1702 "", // sql_mode 1703 "", // Definer 1704 sql.Collation_Default.CharacterSet().String(), // character_set_client 1705 sql.Collation_Default.String(), // collation_connection 1706 sql.Collation_Default.String(), // Database Collation 1707 }, 1708 }, 1709 }, 1710 { 1711 Query: "show triggers like '%cc'", 1712 Expected: []sql.Row{ 1713 { 1714 "t3", // Trigger 1715 "INSERT", // Event 1716 "acc", // Table 1717 "insert into abb values (new.y)", // Statement 1718 "AFTER", // Timing 1719 time.Unix(0, 0).UTC(), // Created 1720 "", // sql_mode 1721 "", // Definer 1722 sql.Collation_Default.CharacterSet().String(), // character_set_client 1723 sql.Collation_Default.String(), // collation_connection 1724 sql.Collation_Default.String(), // Database Collation 1725 }, 1726 { 1727 "t4", // Trigger 1728 "UPDATE", // Event 1729 "acc", // Table 1730 "set new.y = old.y + 2", // Statement 1731 "BEFORE", // Timing 1732 time.Unix(0, 0).UTC(), // Created 1733 "", // sql_mode 1734 "", // Definer 1735 sql.Collation_Default.CharacterSet().String(), // character_set_client 1736 sql.Collation_Default.String(), // collation_connection 1737 sql.Collation_Default.String(), // Database Collation 1738 }, 1739 }, 1740 }, 1741 { 1742 Query: "show triggers where `event` = 'INSERT'", 1743 Expected: []sql.Row{ 1744 { 1745 "t1", // Trigger 1746 "INSERT", // Event 1747 "abb", // Table 1748 "set new.x = new.x + 1", // Statement 1749 "BEFORE", // Timing 1750 time.Unix(0, 0).UTC(), // Created 1751 "", // sql_mode 1752 "", // Definer 1753 sql.Collation_Default.CharacterSet().String(), // character_set_client 1754 sql.Collation_Default.String(), // collation_connection 1755 sql.Collation_Default.String(), // Database Collation 1756 }, 1757 { 1758 "t2", // Trigger 1759 "INSERT", // Event 1760 "abb", // Table 1761 "set new.x = new.x + 2", // Statement 1762 "BEFORE", // Timing 1763 time.Unix(0, 0).UTC(), // Created 1764 "", // sql_mode 1765 "", // Definer 1766 sql.Collation_Default.CharacterSet().String(), // character_set_client 1767 sql.Collation_Default.String(), // collation_connection 1768 sql.Collation_Default.String(), // Database Collation 1769 }, 1770 { 1771 "t3", // Trigger 1772 "INSERT", // Event 1773 "acc", // Table 1774 "insert into abb values (new.y)", // Statement 1775 "AFTER", // Timing 1776 time.Unix(0, 0).UTC(), // Created 1777 "", // sql_mode 1778 "", // Definer 1779 sql.Collation_Default.CharacterSet().String(), // character_set_client 1780 sql.Collation_Default.String(), // collation_connection 1781 sql.Collation_Default.String(), // Database Collation 1782 }, 1783 }, 1784 }, 1785 { 1786 Query: "show triggers where timing = 'AFTER'", 1787 Expected: []sql.Row{ 1788 { 1789 "t3", // Trigger 1790 "INSERT", // Event 1791 "acc", // Table 1792 "insert into abb values (new.y)", // Statement 1793 "AFTER", // Timing 1794 time.Unix(0, 0).UTC(), // Created 1795 "", // sql_mode 1796 "", // Definer 1797 sql.Collation_Default.CharacterSet().String(), // character_set_client 1798 sql.Collation_Default.String(), // collation_connection 1799 sql.Collation_Default.String(), // Database Collation 1800 }, 1801 }, 1802 }, 1803 { 1804 Query: "show triggers where timing = 'BEFORE' and `Table` like '%bb'", 1805 Expected: []sql.Row{ 1806 { 1807 "t1", // Trigger 1808 "INSERT", // Event 1809 "abb", // Table 1810 "set new.x = new.x + 1", // Statement 1811 "BEFORE", // Timing 1812 time.Unix(0, 0).UTC(), // Created 1813 "", // sql_mode 1814 "", // Definer 1815 sql.Collation_Default.CharacterSet().String(), // character_set_client 1816 sql.Collation_Default.String(), // collation_connection 1817 sql.Collation_Default.String(), // Database Collation 1818 }, 1819 { 1820 "t2", // Trigger 1821 "INSERT", // Event 1822 "abb", // Table 1823 "set new.x = new.x + 2", // Statement 1824 "BEFORE", // Timing 1825 time.Unix(0, 0).UTC(), // Created 1826 "", // sql_mode 1827 "", // Definer 1828 sql.Collation_Default.CharacterSet().String(), // character_set_client 1829 sql.Collation_Default.String(), // collation_connection 1830 sql.Collation_Default.String(), // Database Collation 1831 }, 1832 }, 1833 }, 1834 }, 1835 }, 1836 // DROP TRIGGER 1837 { 1838 Name: "drop trigger", 1839 SetUpScript: []string{ 1840 "create table a (x int primary key)", 1841 "create trigger t1 before insert on a for each row set new.x = new.x * 1", 1842 "create trigger t2 before insert on a for each row follows t1 set new.x = new.x * 2", 1843 "create trigger t3 before insert on a for each row set new.x = new.x * 3", 1844 "create trigger t4 before insert on a for each row precedes t3 set new.x = new.x * 5", 1845 }, 1846 Assertions: []ScriptTestAssertion{ 1847 { 1848 Query: "drop trigger t1", 1849 ExpectedErr: sql.ErrTriggerCannotBeDropped, 1850 }, 1851 { 1852 Query: "drop trigger t3", 1853 ExpectedErr: sql.ErrTriggerCannotBeDropped, 1854 }, 1855 { 1856 Query: "drop trigger t4", 1857 Expected: []sql.Row{{types.OkResult{}}}, 1858 }, 1859 { 1860 Query: "drop trigger t3", 1861 Expected: []sql.Row{{types.OkResult{}}}, 1862 }, 1863 { 1864 Query: "drop trigger if exists t5", 1865 Expected: []sql.Row{{types.OkResult{}}}, 1866 }, 1867 { 1868 Query: "drop trigger t5", 1869 ExpectedErr: sql.ErrTriggerDoesNotExist, 1870 }, 1871 { 1872 Query: "select trigger_name from information_schema.triggers order by 1", 1873 Expected: []sql.Row{ 1874 {"t1"}, 1875 {"t2"}, 1876 }, 1877 }, 1878 { 1879 Query: "drop trigger if exists t2", 1880 Expected: []sql.Row{{types.OkResult{}}}, 1881 }, 1882 { 1883 Query: "select trigger_name from information_schema.triggers order by 1", 1884 Expected: []sql.Row{ 1885 {"t1"}, 1886 }, 1887 }, 1888 }, 1889 }, 1890 // DROP TABLE referenced in triggers 1891 { 1892 Name: "drop table referenced in triggers", 1893 SetUpScript: []string{ 1894 "create table a (w int primary key)", 1895 "create table b (x int primary key)", 1896 "create table c (y int primary key)", 1897 "create table d (z int primary key)", 1898 "create trigger t1 before insert on a for each row set new.w = new.w", 1899 "create trigger t2 before insert on a for each row set new.w = new.w * 100", 1900 "create trigger t3 before insert on b for each row set new.x = new.x", 1901 "create trigger t4 before insert on b for each row set new.x = new.x * 100", 1902 "create trigger t5 before insert on c for each row set new.y = new.y", 1903 "create trigger t6 before insert on c for each row set new.y = new.y * 100", 1904 "create trigger t7 before insert on d for each row set new.z = new.z", 1905 "create trigger t8 before insert on d for each row set new.z = new.z * 100", 1906 }, 1907 Assertions: []ScriptTestAssertion{ 1908 { 1909 Query: "drop table a", 1910 Expected: []sql.Row{{types.NewOkResult(0)}}, 1911 }, 1912 { 1913 Query: "select trigger_name from information_schema.triggers order by 1", 1914 Expected: []sql.Row{ 1915 {"t3"}, 1916 {"t4"}, 1917 {"t5"}, 1918 {"t6"}, 1919 {"t7"}, 1920 {"t8"}, 1921 }, 1922 }, 1923 { 1924 Query: "drop table if exists b, d, e", 1925 Expected: []sql.Row{{types.NewOkResult(0)}}, 1926 }, 1927 { 1928 Query: "select trigger_name from information_schema.triggers order by 1", 1929 Expected: []sql.Row{ 1930 {"t5"}, 1931 {"t6"}, 1932 }, 1933 }, 1934 }, 1935 }, 1936 { 1937 Name: "drop table referenced in triggers with follows/precedes", 1938 SetUpScript: []string{ 1939 "create table a (x int primary key)", 1940 "create trigger t1 before insert on a for each row set new.x = new.x", 1941 "create trigger t2 before insert on a for each row follows t1 set new.x = new.x * 10", 1942 "create trigger t3 before insert on a for each row precedes t1 set new.x = new.x * 100", 1943 "create trigger t4 before insert on a for each row follows t3 set new.x = new.x * 1000", 1944 "create trigger t5 before insert on a for each row precedes t2 set new.x = new.x * 10000", 1945 "create trigger t6 before insert on a for each row follows t4 set new.x = new.x * 100000", 1946 "create trigger t7 before insert on a for each row precedes t1 set new.x = new.x * 1000000", 1947 "create trigger t8 before insert on a for each row follows t6 set new.x = new.x * 10000000", 1948 }, 1949 Assertions: []ScriptTestAssertion{ 1950 { 1951 Query: "drop table a", 1952 Expected: []sql.Row{{types.NewOkResult(0)}}, 1953 }, 1954 { 1955 Query: "show triggers", 1956 Expected: []sql.Row{}, 1957 }, 1958 }, 1959 }, 1960 { 1961 Name: "triggers with subquery expressions analyze", 1962 SetUpScript: []string{ 1963 "create table a (x int primary key)", 1964 "create trigger t1 before insert on a for each row begin if NEW.x in (select 2+2 from dual) then signal SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.'; end if; end;", 1965 }, 1966 Assertions: nil, 1967 }, 1968 { 1969 Name: "insert into common sequence table (https://github.com/dolthub/dolt/issues/2534)", 1970 SetUpScript: []string{ 1971 "create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);", 1972 "create table sequence_table (max_id integer PRIMARY KEY);", 1973 "create trigger update_position_id before insert on mytable for each row begin set new.id = (select coalesce(max(max_id),1) from sequence_table); update sequence_table set max_id = max_id + 1; end;", 1974 "insert into sequence_table values (1);", 1975 }, 1976 Assertions: []ScriptTestAssertion{ 1977 { 1978 Query: "insert into mytable () values ();", 1979 Expected: []sql.Row{{types.NewOkResult(1)}}, 1980 }, 1981 { 1982 Query: "insert into mytable (sometext) values ('hello');", 1983 Expected: []sql.Row{{types.NewOkResult(1)}}, 1984 }, 1985 { 1986 Query: "insert into mytable values (10, 'goodbye');", 1987 Expected: []sql.Row{{types.NewOkResult(1)}}, 1988 }, 1989 { 1990 Query: "select * from mytable order by id", 1991 Expected: []sql.Row{ 1992 {1, nil}, 1993 {2, "hello"}, 1994 {3, "goodbye"}, 1995 }, 1996 }, 1997 }, 1998 }, 1999 { 2000 Name: "insert into common sequence table workaround", 2001 SetUpScript: []string{ 2002 "create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);", 2003 "create table sequence_table (max_id integer PRIMARY KEY);", 2004 `create trigger update_position_id before insert on mytable for each row 2005 begin 2006 if @max_id is null then set @max_id = (select coalesce(max(max_id),1) from sequence_table); 2007 end if; 2008 set new.id = @max_id; 2009 set @max_id = @max_id + 1; 2010 update sequence_table set max_id = @max_id; 2011 end;`, 2012 "insert into sequence_table values (1);", 2013 }, 2014 Assertions: []ScriptTestAssertion{ 2015 { 2016 Query: "insert into mytable () values ();", 2017 Expected: []sql.Row{{types.NewOkResult(1)}}, 2018 }, 2019 { 2020 Query: "insert into mytable (sometext) values ('hello');", 2021 Expected: []sql.Row{{types.NewOkResult(1)}}, 2022 }, 2023 { 2024 Query: "insert into mytable values (10, 'goodbye');", 2025 Expected: []sql.Row{{types.NewOkResult(1)}}, 2026 }, 2027 { 2028 Query: "insert into mytable () values (), ();", 2029 Expected: []sql.Row{{types.NewOkResult(2)}}, 2030 }, 2031 { 2032 Query: "select * from mytable order by id", 2033 Expected: []sql.Row{ 2034 {1, nil}, 2035 {2, "hello"}, 2036 {3, "goodbye"}, 2037 {4, nil}, 2038 {5, nil}, 2039 }, 2040 }, 2041 }, 2042 }, 2043 { 2044 Name: "simple trigger with non-existent table in trigger body", 2045 SetUpScript: []string{ 2046 "create table a (x int primary key)", 2047 }, 2048 Assertions: []ScriptTestAssertion{ 2049 { 2050 Query: "create trigger insert_into_b after insert on a for each row insert into b values (new.x + 1)", 2051 Expected: []sql.Row{{types.OkResult{}}}, 2052 }, 2053 { 2054 Query: "insert into a values (1), (3), (5)", 2055 ExpectedErr: sql.ErrTableNotFound, 2056 }, 2057 { 2058 Query: "create table b (y int primary key)", 2059 Expected: []sql.Row{{types.OkResult{}}}, 2060 }, 2061 { 2062 Query: "insert into a values (1), (3), (5)", 2063 Expected: []sql.Row{ 2064 {types.OkResult{RowsAffected: 3}}, 2065 }, 2066 }, 2067 { 2068 Query: "select x from a order by 1", 2069 Expected: []sql.Row{ 2070 {1}, {3}, {5}, 2071 }, 2072 }, 2073 { 2074 Query: "select y from b order by 1", 2075 Expected: []sql.Row{ 2076 {2}, {4}, {6}, 2077 }, 2078 }, 2079 }, 2080 }, 2081 { 2082 Name: "insert, update, delete triggers with non-existent table in trigger body", 2083 SetUpScript: []string{ 2084 "CREATE TABLE film (film_id smallint unsigned NOT NULL AUTO_INCREMENT, title varchar(128) NOT NULL, description text, PRIMARY KEY (film_id))", 2085 "INSERT INTO `film` VALUES (1,'ACADEMY DINOSAUR','A Epic Drama in The Canadian Rockies'),(2,'ACE GOLDFINGER','An Astounding Epistle of a Database Administrator in Ancient China');", 2086 }, 2087 Assertions: []ScriptTestAssertion{ 2088 { 2089 Query: "CREATE TRIGGER ins_film AFTER INSERT ON film FOR EACH ROW BEGIN INSERT INTO film_text (film_id, title, description) VALUES (new.film_id, new.title, new.description); END;", 2090 Expected: []sql.Row{{types.OkResult{}}}, 2091 }, 2092 { 2093 Query: `CREATE TRIGGER upd_film AFTER UPDATE ON film FOR EACH ROW BEGIN 2094 IF (old.title != new.title) OR (old.description != new.description) OR (old.film_id != new.film_id) 2095 THEN 2096 UPDATE film_text 2097 SET title=new.title, 2098 description=new.description, 2099 film_id=new.film_id 2100 WHERE film_id=old.film_id; 2101 END IF; END;`, 2102 Expected: []sql.Row{{types.OkResult{}}}, 2103 }, 2104 { 2105 Query: "CREATE TRIGGER del_film AFTER DELETE ON film FOR EACH ROW BEGIN DELETE FROM film_text WHERE film_id = old.film_id; END;", 2106 Expected: []sql.Row{{types.OkResult{}}}, 2107 }, 2108 { 2109 Query: "INSERT INTO `film` VALUES (3,'ADAPTATION HOLES','An Astounding Reflection in A Baloon Factory'),(4,'AFFAIR PREJUDICE','A Fanciful Documentary in A Shark Tank')", 2110 ExpectedErr: sql.ErrTableNotFound, 2111 }, 2112 { 2113 Query: "UPDATE film SET title = 'THE ACADEMY DINOSAUR' WHERE title = 'ACADEMY DINOSAUR'", 2114 ExpectedErr: sql.ErrTableNotFound, 2115 }, 2116 { 2117 Query: "DELETE FROM film WHERE title = 'ACE GOLDFINGER'", 2118 ExpectedErr: sql.ErrTableNotFound, 2119 }, 2120 { 2121 Query: "CREATE TABLE film_text (film_id smallint NOT NULL, title varchar(255) NOT NULL, description text, PRIMARY KEY (film_id))", 2122 Expected: []sql.Row{{types.OkResult{}}}, 2123 }, 2124 { 2125 Query: "SELECT COUNT(*) FROM film", 2126 Expected: []sql.Row{{2}}, 2127 }, 2128 { 2129 Query: "INSERT INTO `film` VALUES (3,'ADAPTATION HOLES','An Astounding Reflection in A Baloon Factory'),(4,'AFFAIR PREJUDICE','A Fanciful Documentary in A Shark Tank')", 2130 Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 3}}}, 2131 }, 2132 { 2133 Query: "SELECT COUNT(*) FROM film", 2134 Expected: []sql.Row{{4}}, 2135 }, 2136 { 2137 Query: "SELECT COUNT(*) FROM film_text", 2138 Expected: []sql.Row{{2}}, 2139 }, 2140 { 2141 Query: "UPDATE film SET title = 'DIFFERENT MOVIE' WHERE title = 'ADAPTATION HOLES'", 2142 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 0, Info: plan.UpdateInfo{Matched: 1, Updated: 1, Warnings: 0}}}}, 2143 }, 2144 { 2145 Query: "SELECT COUNT(*) FROM film_text WHERE title = 'DIFFERENT MOVIE'", 2146 Expected: []sql.Row{{1}}, 2147 }, 2148 { 2149 Query: "DELETE FROM film WHERE title = 'DIFFERENT MOVIE'", 2150 Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}}, 2151 }, 2152 { 2153 Query: "SELECT COUNT(*) FROM film_text WHERE title = 'DIFFERENT MOVIE'", 2154 Expected: []sql.Row{{0}}, 2155 }, 2156 }, 2157 }, 2158 { 2159 Name: "non-existent procedure in trigger body", 2160 SetUpScript: []string{ 2161 "CREATE TABLE t0 (id INT PRIMARY KEY AUTO_INCREMENT, v1 INT, v2 TEXT);", 2162 "CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, v1 INT, v2 TEXT);", 2163 "INSERT INTO t0 VALUES (1, 2, 'abc'), (2, 3, 'def');", 2164 }, 2165 Assertions: []ScriptTestAssertion{ 2166 { 2167 Query: "SELECT * FROM t0;", 2168 Expected: []sql.Row{{1, 2, "abc"}, {2, 3, "def"}}, 2169 }, 2170 { 2171 Query: `CREATE PROCEDURE add_entry(i INT, s TEXT) BEGIN IF i > 50 THEN 2172 SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'too big number'; END IF; 2173 INSERT INTO t0 (v1, v2) VALUES (i, s); END;`, 2174 Expected: []sql.Row{{types.OkResult{}}}, 2175 }, 2176 { 2177 Query: "CREATE TRIGGER trig AFTER INSERT ON t0 FOR EACH ROW BEGIN CALL back_up(NEW.v1, NEW.v2); END;", 2178 Expected: []sql.Row{{types.OkResult{}}}, 2179 }, 2180 { 2181 Query: "INSERT INTO t0 (v1, v2) VALUES (5, 'ggg');", 2182 ExpectedErr: sql.ErrStoredProcedureDoesNotExist, 2183 }, 2184 { 2185 Query: "CREATE PROCEDURE back_up(num INT, msg TEXT) INSERT INTO t1 (v1, v2) VALUES (num*2, msg);", 2186 Expected: []sql.Row{{types.OkResult{}}}, 2187 }, 2188 { 2189 SkipResultCheckOnServerEngine: true, // call depends on stored procedure stmt for whether to use 'query' or 'exec' from go sql driver. 2190 Query: "CALL add_entry(4, 'aaa');", 2191 Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}}, 2192 }, 2193 { 2194 Query: "SELECT * FROM t0;", 2195 Expected: []sql.Row{{1, 2, "abc"}, {2, 3, "def"}, {3, 4, "aaa"}}, 2196 }, 2197 { 2198 Query: "SELECT * FROM t1;", 2199 Expected: []sql.Row{{1, 8, "aaa"}}, 2200 }, 2201 { 2202 Query: "CALL add_entry(54, 'bbb');", 2203 ExpectedErrStr: "too big number (errno 1644) (sqlstate 45000)", 2204 }, 2205 }, 2206 }, 2207 } 2208 2209 // RollbackTriggerTests are trigger tests that require rollback logic to work correctly 2210 var RollbackTriggerTests = []ScriptTest{ 2211 // Insert Queries that fail, test trigger reverts 2212 { 2213 Name: "trigger before insert, reverts insert when query fails", 2214 SetUpScript: []string{ 2215 "create table a (i int primary key)", 2216 "create table b (x int)", 2217 "create trigger trig before insert on a for each row insert into b values (new.i);", 2218 }, 2219 Assertions: []ScriptTestAssertion{ 2220 { 2221 Query: "insert into a values (1), (2)", 2222 Expected: []sql.Row{ 2223 {types.OkResult{RowsAffected: 2}}, 2224 }, 2225 }, 2226 { 2227 Query: "select x from b order by x", 2228 Expected: []sql.Row{ 2229 {1}, {2}, 2230 }, 2231 }, 2232 { 2233 Query: "insert into a values (1)", 2234 ExpectedErr: sql.ErrPrimaryKeyViolation, 2235 }, 2236 { 2237 Query: "select * from b", 2238 Expected: []sql.Row{ 2239 {1}, {2}, 2240 }, 2241 }, 2242 }, 2243 }, 2244 { 2245 Name: "trigger after insert, reverts insert when query fails", 2246 SetUpScript: []string{ 2247 "create table a (i int primary key)", 2248 "create table b (x int)", 2249 "create trigger trig after insert on a for each row insert into b values (new.i);", 2250 }, 2251 Assertions: []ScriptTestAssertion{ 2252 { 2253 Query: "insert into a values (1), (2)", 2254 Expected: []sql.Row{ 2255 {types.OkResult{RowsAffected: 2}}, 2256 }, 2257 }, 2258 { 2259 Query: "select x from b order by x", 2260 Expected: []sql.Row{ 2261 {1}, {2}, 2262 }, 2263 }, 2264 { 2265 Query: "insert into a values (1)", 2266 ExpectedErr: sql.ErrPrimaryKeyViolation, 2267 }, 2268 { 2269 Query: "select * from b", 2270 Expected: []sql.Row{ 2271 {1}, {2}, 2272 }, 2273 }, 2274 }, 2275 }, 2276 { 2277 Name: "trigger before insert, reverts update when query fails", 2278 SetUpScript: []string{ 2279 "create table a (i int primary key)", 2280 "create table b (x int)", 2281 "insert into b values (0)", 2282 "create trigger trig before insert on a for each row update b set x = x + 1;", 2283 }, 2284 Assertions: []ScriptTestAssertion{ 2285 { 2286 Query: "insert into a values (1), (2)", 2287 Expected: []sql.Row{ 2288 {types.OkResult{RowsAffected: 2}}, 2289 }, 2290 }, 2291 { 2292 Query: "select * from b", 2293 Expected: []sql.Row{ 2294 {2}, 2295 }, 2296 }, 2297 { 2298 Query: "insert into a values (1)", 2299 ExpectedErr: sql.ErrPrimaryKeyViolation, 2300 }, 2301 { 2302 Query: "select * from b", 2303 Expected: []sql.Row{ 2304 {2}, 2305 }, 2306 }, 2307 }, 2308 }, 2309 { 2310 Name: "trigger after insert, reverts update when query fails", 2311 SetUpScript: []string{ 2312 "create table a (i int primary key)", 2313 "create table b (x int)", 2314 "insert into b values (0)", 2315 "create trigger trig after insert on a for each row update b set x = x + 1;", 2316 }, 2317 Assertions: []ScriptTestAssertion{ 2318 { 2319 Query: "insert into a values (1), (2)", 2320 Expected: []sql.Row{ 2321 {types.OkResult{RowsAffected: 2}}, 2322 }, 2323 }, 2324 { 2325 Query: "select * from b", 2326 Expected: []sql.Row{ 2327 {2}, 2328 }, 2329 }, 2330 { 2331 Query: "insert into a values (1)", 2332 ExpectedErr: sql.ErrPrimaryKeyViolation, 2333 }, 2334 { 2335 Query: "select * from b", 2336 Expected: []sql.Row{ 2337 {2}, 2338 }, 2339 }, 2340 }, 2341 }, 2342 { 2343 Name: "trigger before insert, reverts delete when query fails", 2344 SetUpScript: []string{ 2345 "create table a (i int primary key)", 2346 "create table b (x int)", 2347 "insert into a values (1)", 2348 "insert into b values (1), (2)", 2349 "create trigger trig before insert on a for each row delete from b where x = new.i;", 2350 }, 2351 Assertions: []ScriptTestAssertion{ 2352 { 2353 Query: "insert into a values (2)", 2354 Expected: []sql.Row{ 2355 {types.OkResult{RowsAffected: 1}}, 2356 }, 2357 }, 2358 { 2359 Query: "select x from b order by x", 2360 Expected: []sql.Row{ 2361 {1}, 2362 }, 2363 }, 2364 { 2365 Query: "insert into a values (1)", 2366 ExpectedErr: sql.ErrPrimaryKeyViolation, 2367 }, 2368 { 2369 Query: "select * from b", 2370 Expected: []sql.Row{ 2371 {1}, 2372 }, 2373 }, 2374 }, 2375 }, 2376 { 2377 Name: "trigger after insert, reverts delete when query fails", 2378 SetUpScript: []string{ 2379 "create table a (i int primary key)", 2380 "create table b (x int)", 2381 "insert into a values (1)", 2382 "insert into b values (1), (2)", 2383 "create trigger trig after insert on a for each row delete from b where x = new.i;", 2384 }, 2385 Assertions: []ScriptTestAssertion{ 2386 { 2387 Query: "insert into a values (2)", 2388 Expected: []sql.Row{ 2389 {types.OkResult{RowsAffected: 1}}, 2390 }, 2391 }, 2392 { 2393 Query: "select x from b order by x", 2394 Expected: []sql.Row{ 2395 {1}, 2396 }, 2397 }, 2398 { 2399 Query: "insert into a values (1)", 2400 ExpectedErr: sql.ErrPrimaryKeyViolation, 2401 }, 2402 { 2403 Query: "select * from b", 2404 Expected: []sql.Row{ 2405 {1}, 2406 }, 2407 }, 2408 }, 2409 }, 2410 { 2411 Name: "trigger before insert, reverts multiple inserts when query fails", 2412 SetUpScript: []string{ 2413 "create table a (i int primary key)", 2414 "create table b (x int)", 2415 "create trigger trig before insert on a for each row insert into b values (new.i);", 2416 }, 2417 Assertions: []ScriptTestAssertion{ 2418 { 2419 Query: "insert into a values (1), (1)", 2420 ExpectedErr: sql.ErrPrimaryKeyViolation, 2421 }, 2422 { 2423 Query: "select * from a", 2424 Expected: []sql.Row{}, 2425 }, 2426 { 2427 Query: "select * from b", 2428 Expected: []sql.Row{}, 2429 }, 2430 { 2431 Query: "insert into a values (0)", 2432 Expected: []sql.Row{ 2433 {types.OkResult{RowsAffected: 1}}, 2434 }, 2435 }, 2436 { 2437 Query: "insert into a values (1), (2), (0)", 2438 ExpectedErr: sql.ErrPrimaryKeyViolation, 2439 }, 2440 { 2441 Query: "select * from a", 2442 Expected: []sql.Row{ 2443 {0}, 2444 }, 2445 }, 2446 { 2447 Query: "select * from b", 2448 Expected: []sql.Row{ 2449 {0}, 2450 }, 2451 }, 2452 }, 2453 }, 2454 { 2455 Name: "trigger after insert, reverts multiple inserts when query fails", 2456 SetUpScript: []string{ 2457 "create table a (i int primary key)", 2458 "create table b (x int)", 2459 "create trigger trig after insert on a for each row insert into b values (new.i);", 2460 }, 2461 Assertions: []ScriptTestAssertion{ 2462 { 2463 Query: "insert into a values (1), (1)", 2464 ExpectedErr: sql.ErrPrimaryKeyViolation, 2465 }, 2466 { 2467 Query: "select * from a", 2468 Expected: []sql.Row{}, 2469 }, 2470 { 2471 Query: "select * from b", 2472 Expected: []sql.Row{}, 2473 }, 2474 { 2475 Query: "insert into a values (0)", 2476 Expected: []sql.Row{ 2477 {types.OkResult{RowsAffected: 1}}, 2478 }, 2479 }, 2480 { 2481 Query: "insert into a values (1), (2), (0)", 2482 ExpectedErr: sql.ErrPrimaryKeyViolation, 2483 }, 2484 { 2485 Query: "select * from a", 2486 Expected: []sql.Row{ 2487 {0}, 2488 }, 2489 }, 2490 { 2491 Query: "select * from b", 2492 Expected: []sql.Row{ 2493 {0}, 2494 }, 2495 }, 2496 }, 2497 }, 2498 // Update Queries that fail, test trigger reverts 2499 { 2500 Name: "trigger before update, reverts insert when query fails", 2501 SetUpScript: []string{ 2502 "create table a (i int primary key)", 2503 "create table b (x int)", 2504 "insert into a values (0)", 2505 "create trigger trig before update on a for each row insert into b values (new.i);", 2506 }, 2507 Assertions: []ScriptTestAssertion{ 2508 { 2509 Query: "update a set i = 1", 2510 Expected: []sql.Row{ 2511 {types.OkResult{ 2512 RowsAffected: 1, 2513 Info: plan.UpdateInfo{ 2514 Matched: 1, 2515 Updated: 1, 2516 }, 2517 }}, 2518 }, 2519 }, 2520 { 2521 Query: "select x from b", 2522 Expected: []sql.Row{ 2523 {1}, 2524 }, 2525 }, 2526 { 2527 Query: "update a set i = 'not int'", 2528 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2529 }, 2530 { 2531 Query: "select * from b", 2532 Expected: []sql.Row{ 2533 {1}, 2534 }, 2535 }, 2536 }, 2537 }, 2538 { 2539 Name: "trigger after update, reverts insert when query fails", 2540 SetUpScript: []string{ 2541 "create table a (i int primary key)", 2542 "create table b (x int)", 2543 "insert into a values (0)", 2544 "create trigger trig after update on a for each row insert into b values (new.i);", 2545 }, 2546 Assertions: []ScriptTestAssertion{ 2547 { 2548 Query: "update a set i = 1", 2549 Expected: []sql.Row{ 2550 {types.OkResult{ 2551 RowsAffected: 1, 2552 Info: plan.UpdateInfo{ 2553 Matched: 1, 2554 Updated: 1, 2555 }, 2556 }}, 2557 }, 2558 }, 2559 { 2560 Query: "select x from b", 2561 Expected: []sql.Row{ 2562 {1}, 2563 }, 2564 }, 2565 { 2566 Query: "update a set i = 'not int'", 2567 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2568 }, 2569 { 2570 Query: "select * from b", 2571 Expected: []sql.Row{ 2572 {1}, 2573 }, 2574 }, 2575 }, 2576 }, 2577 { 2578 Name: "trigger before update, reverts update when query fails", 2579 SetUpScript: []string{ 2580 "create table a (i int primary key)", 2581 "create table b (x int)", 2582 "insert into a values (0)", 2583 "insert into b values (0)", 2584 "create trigger trig before update on a for each row update b set x = x + new.i;", 2585 }, 2586 Assertions: []ScriptTestAssertion{ 2587 { 2588 Query: "update a set i = 1", 2589 Expected: []sql.Row{ 2590 {types.OkResult{ 2591 RowsAffected: 1, 2592 Info: plan.UpdateInfo{ 2593 Matched: 1, 2594 Updated: 1, 2595 }, 2596 }}, 2597 }, 2598 }, 2599 { 2600 Query: "select x from b", 2601 Expected: []sql.Row{ 2602 {1}, 2603 }, 2604 }, 2605 { 2606 Query: "update a set i = 'not int'", 2607 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2608 }, 2609 { 2610 Query: "select * from b", 2611 Expected: []sql.Row{ 2612 {1}, 2613 }, 2614 }, 2615 }, 2616 }, 2617 { 2618 Name: "trigger after update, reverts update when query fails", 2619 SetUpScript: []string{ 2620 "create table a (i int primary key)", 2621 "create table b (x int)", 2622 "insert into a values (0)", 2623 "insert into b values (0)", 2624 "create trigger trig after update on a for each row update b set x = x + new.i;", 2625 }, 2626 Assertions: []ScriptTestAssertion{ 2627 { 2628 Query: "update a set i = 1", 2629 Expected: []sql.Row{ 2630 {types.OkResult{ 2631 RowsAffected: 1, 2632 Info: plan.UpdateInfo{ 2633 Matched: 1, 2634 Updated: 1, 2635 }, 2636 }}, 2637 }, 2638 }, 2639 { 2640 Query: "select x from b", 2641 Expected: []sql.Row{ 2642 {1}, 2643 }, 2644 }, 2645 { 2646 Query: "update a set i = 'not int'", 2647 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2648 }, 2649 { 2650 Query: "select * from b", 2651 Expected: []sql.Row{ 2652 {1}, 2653 }, 2654 }, 2655 }, 2656 }, 2657 { 2658 Name: "trigger before update, reverts delete when query fails", 2659 SetUpScript: []string{ 2660 "create table a (i int primary key)", 2661 "create table b (x int)", 2662 "insert into a values (0)", 2663 "insert into b values (1), (2)", 2664 "create trigger trig before update on a for each row delete from b where x = new.i;", 2665 }, 2666 Assertions: []ScriptTestAssertion{ 2667 { 2668 Query: "update a set i = 1", 2669 Expected: []sql.Row{ 2670 {types.OkResult{ 2671 RowsAffected: 1, 2672 Info: plan.UpdateInfo{ 2673 Matched: 1, 2674 Updated: 1, 2675 }, 2676 }}, 2677 }, 2678 }, 2679 { 2680 Query: "select x from b", 2681 Expected: []sql.Row{ 2682 {2}, 2683 }, 2684 }, 2685 { 2686 Query: "update a set i = 'not int'", 2687 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2688 }, 2689 { 2690 Query: "select * from b", 2691 Expected: []sql.Row{ 2692 {2}, 2693 }, 2694 }, 2695 }, 2696 }, 2697 { 2698 Name: "trigger after update, reverts delete when query fails", 2699 SetUpScript: []string{ 2700 "create table a (i int primary key)", 2701 "create table b (x int)", 2702 "insert into a values (0)", 2703 "insert into b values (1), (2)", 2704 "create trigger trig after update on a for each row delete from b where x = new.i;", 2705 }, 2706 Assertions: []ScriptTestAssertion{ 2707 { 2708 Query: "update a set i = 1", 2709 Expected: []sql.Row{ 2710 {types.OkResult{ 2711 RowsAffected: 1, 2712 Info: plan.UpdateInfo{ 2713 Matched: 1, 2714 Updated: 1, 2715 }, 2716 }}, 2717 }, 2718 }, 2719 { 2720 Query: "select x from b", 2721 Expected: []sql.Row{ 2722 {2}, 2723 }, 2724 }, 2725 { 2726 Query: "update a set i = 'not int'", 2727 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2728 }, 2729 { 2730 Query: "select * from b", 2731 Expected: []sql.Row{ 2732 {2}, 2733 }, 2734 }, 2735 }, 2736 }, 2737 // Multiple triggers and at least one fails, reverts 2738 { 2739 Name: "triggers before and after insert fails, rollback", 2740 SetUpScript: []string{ 2741 "create table a (x int primary key)", 2742 "create table b (y int primary key)", 2743 "create trigger a1 before insert on a for each row insert into b values (NEW.x * 7)", 2744 "create trigger a2 after insert on a for each row insert into b values (New.x * 11)", 2745 }, 2746 Assertions: []ScriptTestAssertion{ 2747 { 2748 Query: "insert into a values (2), (3), (5)", 2749 Expected: []sql.Row{ 2750 {types.NewOkResult(3)}, 2751 }, 2752 }, 2753 { 2754 Query: "select x from a order by 1", 2755 Expected: []sql.Row{ 2756 {2}, {3}, {5}, 2757 }, 2758 }, 2759 { 2760 Query: "select y from b order by 1", 2761 Expected: []sql.Row{ 2762 {14}, {21}, {22}, {33}, {35}, {55}, 2763 }, 2764 }, 2765 { 2766 Query: "insert into a values (2), (3), (5)", 2767 ExpectedErr: sql.ErrPrimaryKeyViolation, 2768 }, 2769 { 2770 Query: "select x from a order by 1", 2771 Expected: []sql.Row{ 2772 {2}, {3}, {5}, 2773 }, 2774 }, 2775 { 2776 Query: "select y from b order by 1", 2777 Expected: []sql.Row{ 2778 {14}, {21}, {22}, {33}, {35}, {55}, 2779 }, 2780 }, 2781 }, 2782 }, 2783 // Queries involving auto_commit = off 2784 { 2785 Name: "autocommit off, trigger before insert, reverts insert when query fails", 2786 SetUpScript: []string{ 2787 "set @@autocommit = off", 2788 "create table a (i int primary key)", 2789 "create table b (x int)", 2790 "create trigger trig before insert on a for each row insert into b values (new.i);", 2791 }, 2792 Assertions: []ScriptTestAssertion{ 2793 { 2794 Query: "insert into a values (1), (2)", 2795 Expected: []sql.Row{ 2796 {types.OkResult{RowsAffected: 2}}, 2797 }, 2798 }, 2799 { 2800 Query: "select x from b order by x", 2801 Expected: []sql.Row{ 2802 {1}, {2}, 2803 }, 2804 }, 2805 { 2806 Query: "insert into a values (1)", 2807 ExpectedErr: sql.ErrPrimaryKeyViolation, 2808 }, 2809 { 2810 Query: "select * from b", 2811 Expected: []sql.Row{ 2812 {1}, {2}, 2813 }, 2814 }, 2815 }, 2816 }, 2817 { 2818 Name: "trigger before update, reverts insert when query fails", 2819 SetUpScript: []string{ 2820 "set @@autocommit = off", 2821 "create table a (i int primary key)", 2822 "create table b (x int)", 2823 "insert into a values (0)", 2824 "create trigger trig before update on a for each row insert into b values (new.i);", 2825 }, 2826 Assertions: []ScriptTestAssertion{ 2827 { 2828 Query: "update a set i = 1", 2829 Expected: []sql.Row{ 2830 {types.OkResult{ 2831 RowsAffected: 1, 2832 Info: plan.UpdateInfo{ 2833 Matched: 1, 2834 Updated: 1, 2835 }, 2836 }}, 2837 }, 2838 }, 2839 { 2840 Query: "select x from b", 2841 Expected: []sql.Row{ 2842 {1}, 2843 }, 2844 }, 2845 { 2846 Query: "update a set i = 'not int'", 2847 ExpectedErrStr: "error: 'not int' is not a valid value for 'int'", 2848 }, 2849 { 2850 Query: "select * from b", 2851 Expected: []sql.Row{ 2852 {1}, 2853 }, 2854 }, 2855 }, 2856 }, 2857 } 2858 2859 // BrokenTriggerQueries contains trigger queries that should work but do not yet 2860 var BrokenTriggerQueries = []ScriptTest{ 2861 { 2862 Name: "update common table multiple times in single insert", 2863 SetUpScript: []string{ 2864 "create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);", 2865 "create table sequence_table (max_id integer PRIMARY KEY);", 2866 "create trigger update_position_id before insert on mytable for each row begin set new.id = (select coalesce(max(max_id),1) from sequence_table); update sequence_table set max_id = max_id + 1; end;", 2867 "insert into sequence_table values (1);", 2868 }, 2869 Assertions: []ScriptTestAssertion{ 2870 // Should produce new keys 2, 3, but instead produces a duplicate key error 2871 { 2872 Query: "insert into mytable () values (), ();", 2873 Expected: []sql.Row{{types.NewOkResult(2)}}, 2874 }, 2875 { 2876 Query: "select * from mytable order by id", 2877 Expected: []sql.Row{ 2878 {1, nil}, 2879 {2, nil}, 2880 {3, nil}, 2881 }, 2882 }, 2883 }, 2884 }, 2885 { 2886 Name: "insert into table multiple times", 2887 SetUpScript: []string{ 2888 "CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);", 2889 "CREATE TABLE test2(pk BIGINT PRIMARY KEY, v1 BIGINT);", 2890 "INSERT INTO test VALUES (0,2),(1,3)", 2891 `CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 2892 BEGIN 2893 insert into test2 values (new.pk * 3, new.v1); 2894 insert into test2 values (new.pk * 5, new.v1); 2895 END;`, 2896 // fails at analysis time thinking that test2 is a duplicate table alias 2897 "INSERT INTO test VALUES (2,4), (6,8);", 2898 }, 2899 Assertions: []ScriptTestAssertion{ 2900 { 2901 Query: "SELECT * FROM test ORDER BY 1", 2902 Expected: []sql.Row{ 2903 {0, 2}, {1, 3}, {2, -440}, 2904 }, 2905 }, 2906 { 2907 Query: "SELECT * FROM test2 ORDER BY 1", 2908 Expected: []sql.Row{ 2909 {2, -440}, 2910 }, 2911 }, 2912 }, 2913 }, 2914 // This test is failing due to how trigger logic handles trigger logic with a different database then the one set 2915 { 2916 Name: "trigger after update, delete from other table", 2917 SetUpScript: []string{ 2918 "create table foo.a (x int primary key)", 2919 "create table foo.b (y int primary key)", 2920 "insert into foo.a values (0), (2), (4), (6), (8)", 2921 "insert into foo.b values (1), (3), (5), (7), (9)", 2922 "use foo", 2923 "create trigger insert_into_b after update on a for each row insert into b values (old.x + new.x + 1)", 2924 "use mydb", 2925 "update foo.a set x = x + 1 where x in (2,4)", 2926 }, 2927 Assertions: []ScriptTestAssertion{ 2928 { 2929 Query: "select x from foo.a order by 1", 2930 Expected: []sql.Row{ 2931 {0}, {3}, {5}, {6}, {8}, 2932 }, 2933 }, 2934 { 2935 Query: "select y from foo.b order by 1", 2936 Expected: []sql.Row{ 2937 {1}, {3}, {7}, 2938 }, 2939 }, 2940 }, 2941 }, 2942 // This test SOMETIMES fails, maybe due to a race condition or something weird happening with references 2943 { 2944 Name: "trigger before update, begin block with references to other table", 2945 SetUpScript: []string{ 2946 "CREATE TABLE a (i int primary key, j int)", 2947 "INSERT INTO a VALUES (0,1),(2,3),(4,5)", 2948 "CREATE TABLE b (x int)", 2949 "INSERT INTO b VALUES (1)", 2950 "CREATE TRIGGER trig BEFORE UPDATE ON a FOR EACH ROW BEGIN SET NEW.i = (SELECT x FROM b); SET NEW.j = OLD.j + NEW.j; UPDATE b SET x = x + 1; END;", 2951 "UPDATE a SET j = 10;", 2952 }, 2953 Assertions: []ScriptTestAssertion{ 2954 { 2955 Query: "SELECT * FROM a ORDER BY 1", 2956 Expected: []sql.Row{ 2957 {1, 11}, {2, 13}, {3, 15}, 2958 }, 2959 }, 2960 { 2961 Query: "SELECT * FROM b ORDER BY x", 2962 Expected: []sql.Row{ 2963 {4}, 2964 }, 2965 }, 2966 }, 2967 }, 2968 { 2969 Name: "trigger after inserts, use updated self reference", 2970 SetUpScript: []string{ 2971 "create table a (i int primary key, j int)", 2972 "create table b (x int primary key)", 2973 "insert into b values (1)", 2974 "create trigger trig after insert on a for each row begin update b set x = (select count(*) from a); end;", 2975 "insert into a values (1,0), (2,0), (3,0)", 2976 }, 2977 Assertions: []ScriptTestAssertion{ 2978 { 2979 Query: "select * from a order by i", 2980 Expected: []sql.Row{ 2981 {1, 0}, {2, 0}, {3, 0}, 2982 }, 2983 }, 2984 { 2985 Query: "select x from b", 2986 Expected: []sql.Row{ 2987 {3}, 2988 }, 2989 }, 2990 { 2991 Query: "insert into a values (4,0), (5,0)", 2992 Expected: []sql.Row{ 2993 {types.OkResult{RowsAffected: 2}}, 2994 }, 2995 }, 2996 }, 2997 }, 2998 } 2999 3000 var TriggerErrorTests = []ScriptTest{ 3001 { 3002 Name: "table doesn't exist", 3003 SetUpScript: []string{ 3004 "create table x (a int primary key, b int, c int)", 3005 }, 3006 Query: "create trigger not_found before insert on y for each row set new.a = new.a + 1", 3007 ExpectedErr: sql.ErrTableNotFound, 3008 }, 3009 { 3010 Name: "trigger errors on execution", 3011 SetUpScript: []string{ 3012 "create table x (a int primary key, b int)", 3013 "create table y (c int primary key not null)", 3014 "create trigger trigger_has_error before insert on x for each row insert into y values (null)", 3015 }, 3016 Query: "insert into x values (1,2)", 3017 ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull, 3018 }, 3019 { 3020 Name: "self update on insert", 3021 SetUpScript: []string{ 3022 "create table a (x int primary key)", 3023 "create trigger a1 before insert on a for each row insert into a values (new.x * 2)", 3024 }, 3025 Query: "insert into a values (1), (2), (3)", 3026 ExpectedErr: sql.ErrTriggerTableInUse, 3027 }, 3028 { 3029 Name: "self update on delete", 3030 SetUpScript: []string{ 3031 "create table a (x int primary key)", 3032 "create trigger a1 before delete on a for each row delete from a", 3033 }, 3034 Query: "delete from a", 3035 ExpectedErr: sql.ErrTriggerTableInUse, 3036 }, 3037 { 3038 Name: "self update on update", 3039 SetUpScript: []string{ 3040 "create table a (x int primary key)", 3041 "create trigger a1 before update on a for each row update a set x = 1", 3042 }, 3043 Query: "update a set x = 2", 3044 ExpectedErr: sql.ErrTriggerTableInUse, 3045 }, 3046 { 3047 Name: "circular dependency", 3048 SetUpScript: []string{ 3049 "create table a (x int primary key)", 3050 "create table b (y int primary key)", 3051 "create trigger a1 before insert on a for each row insert into b values (new.x * 2)", 3052 "create trigger b1 before insert on b for each row insert into a values (new.y * 7)", 3053 }, 3054 Query: "insert into a values (1), (2), (3)", 3055 ExpectedErr: sql.ErrTriggerTableInUse, 3056 }, 3057 { 3058 Name: "circular dependency, nested two deep", 3059 SetUpScript: []string{ 3060 "create table a (x int primary key)", 3061 "create table b (y int primary key)", 3062 "create table c (z int primary key)", 3063 "create trigger a1 before insert on a for each row insert into b values (new.x * 2)", 3064 "create trigger b1 before insert on b for each row insert into c values (new.y * 5)", 3065 "create trigger c1 before insert on c for each row insert into a values (new.z * 7)", 3066 }, 3067 Query: "insert into a values (1), (2), (3)", 3068 ExpectedErr: sql.ErrTriggerTableInUse, 3069 }, 3070 { 3071 Name: "reference to old on insert", 3072 SetUpScript: []string{ 3073 "create table x (a int primary key, b int, c int)", 3074 }, 3075 Query: "create trigger old_on_insert before insert on x for each row set new.c = old.a + 1", 3076 ExpectedErr: sql.ErrTableNotFound, 3077 }, 3078 { 3079 Name: "reference to new on delete", 3080 SetUpScript: []string{ 3081 "create table x (a int primary key, b int, c int)", 3082 }, 3083 Query: "create trigger new_on_delete before delete on x for each row set new.c = old.a + 1", 3084 ExpectedErr: sql.ErrTableNotFound, 3085 }, 3086 { 3087 Name: "set old row on update", 3088 SetUpScript: []string{ 3089 "create table x (a int primary key, b int, c int)", 3090 }, 3091 Query: "create trigger update_old before update on x for each row set old.c = new.a + 1", 3092 ExpectedErr: sql.ErrInvalidUpdateOfOldRow, 3093 }, 3094 { 3095 Name: "set old row on update, begin block", 3096 SetUpScript: []string{ 3097 "create table x (a int primary key, b int, c int)", 3098 }, 3099 Query: "create trigger update_old before update on x for each row BEGIN set old.c = new.a + 1; END", 3100 ExpectedErr: sql.ErrInvalidUpdateOfOldRow, 3101 }, 3102 { 3103 Name: "set new row after insert", 3104 SetUpScript: []string{ 3105 "create table x (a int primary key, b int, c int)", 3106 }, 3107 Query: "create trigger update_new after insert on x for each row set new.c = new.a + 1", 3108 ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger, 3109 }, 3110 { 3111 Name: "set new row after update", 3112 SetUpScript: []string{ 3113 "create table x (a int primary key, b int, c int)", 3114 }, 3115 Query: "create trigger update_new after update on x for each row set new.c = new.a + 1", 3116 ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger, 3117 }, 3118 { 3119 Name: "set new row after update, begin block", 3120 SetUpScript: []string{ 3121 "create table x (a int primary key, b int, c int)", 3122 }, 3123 Query: "create trigger update_new after update on x for each row BEGIN set new.c = new.a + 1; END", 3124 ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger, 3125 }, 3126 { 3127 Name: "source column doesn't exist", 3128 SetUpScript: []string{ 3129 "create table x (a int primary key, b int, c int)", 3130 }, 3131 Query: "create trigger not_found before insert on x for each row set new.d = new.d + 1", 3132 ExpectedErr: sql.ErrTableNotFound, 3133 }, 3134 { 3135 Name: "target column doesn't exist", 3136 SetUpScript: []string{ 3137 "create table x (a int primary key, b int, c int)", 3138 }, 3139 Query: "create trigger not_found before insert on x for each row set new.d = new.a + 1", 3140 ExpectedErr: sql.ErrTableNotFound, 3141 }, 3142 { 3143 Name: "prevent creating trigger over views", 3144 SetUpScript: []string{ 3145 "create table x (a int primary key, b int, c int)", 3146 "create view v as select * from x", 3147 }, 3148 Query: "create trigger trig before insert on v for each row set b = 1", 3149 ExpectedErr: sql.ErrExpectedTableFoundView, 3150 }, 3151 }