1-- 2-- RULES 3-- From Jan's original setup_ruletest.sql and run_ruletest.sql 4-- - thomas 1998-09-13 5-- 6-- 7-- Tables and rules for the view test 8-- 9CREATE TABLE rtest_t1 ( 10 a int4, 11 b int4 12); 13 14CREATE TABLE rtest_t2 ( 15 a int4, 16 b int4 17); 18 19CREATE TABLE rtest_t3 ( 20 a int4, 21 b int4 22); 23 24CREATE VIEW rtest_v1 AS 25SELECT 26 * 27FROM 28 rtest_t1; 29 30CREATE RULE rtest_v1_ins AS ON INSERT TO rtest_v1 31 DO INSTEAD 32 INSERT INTO rtest_t1 VALUES (NEW.a, NEW.b); 33 34CREATE RULE rtest_v1_upd AS ON UPDATE 35 TO rtest_v1 36 DO INSTEAD 37 UPDATE 38 rtest_t1 SET 39 a = NEW.a, 40 b = NEW.b WHERE 41 a = OLD.a; 42 43CREATE RULE rtest_v1_del AS ON DELETE TO rtest_v1 44 DO INSTEAD 45 DELETE FROM rtest_t1 46 WHERE a = OLD.a; 47 48-- Test comments 49COMMENT ON RULE rtest_v1_bad ON rtest_v1 IS 'bad rule'; 50 51COMMENT ON RULE rtest_v1_del ON rtest_v1 IS 'delete rule'; 52 53COMMENT ON RULE rtest_v1_del ON rtest_v1 IS NULL; 54 55-- 56-- Tables and rules for the constraint update/delete test 57-- 58-- Note: 59-- Now that we have multiple action rule support, we check 60-- both possible syntaxes to define them (The last action 61-- can but must not have a semicolon at the end). 62-- 63CREATE TABLE rtest_system ( 64 sysname text, 65 sysdesc text 66); 67 68CREATE TABLE rtest_interface ( 69 sysname text, 70 ifname text 71); 72 73CREATE TABLE rtest_person ( 74 pname text, 75 pdesc text 76); 77 78CREATE TABLE rtest_admin ( 79 pname text, 80 sysname text 81); 82 83CREATE RULE rtest_sys_upd AS ON UPDATE 84 TO rtest_system 85 DO ALSO 86 ( UPDATE 87 rtest_interface SET 88 sysname = NEW.sysname WHERE 89 sysname = OLD.sysname; 90 91UPDATE 92 rtest_admin 93SET 94 sysname = new.sysname 95WHERE 96 sysname = old.sysname); 97 98CREATE RULE rtest_sys_del AS ON DELETE TO rtest_system 99 DO ALSO 100 ( DELETE FROM rtest_interface 101 WHERE sysname = OLD.sysname; 102 103DELETE FROM rtest_admin 104WHERE sysname = old.sysname; 105 106); 107 108CREATE RULE rtest_pers_upd AS ON UPDATE 109 TO rtest_person 110 DO ALSO 111 UPDATE 112 rtest_admin SET 113 pname = NEW.pname WHERE 114 pname = OLD.pname; 115 116CREATE RULE rtest_pers_del AS ON DELETE TO rtest_person 117 DO ALSO 118 DELETE FROM rtest_admin 119 WHERE pname = OLD.pname; 120 121-- 122-- Tables and rules for the logging test 123-- 124CREATE TABLE rtest_emp ( 125 ename char(20), 126 salary money 127); 128 129CREATE TABLE rtest_emplog ( 130 ename char(20), 131 who name, 132 action char(10), 133 newsal money, 134 oldsal money 135); 136 137CREATE TABLE rtest_empmass ( 138 ename char(20), 139 salary money 140); 141 142CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog VALUES (NEW.ename, CURRENT_USER, 'hired', NEW.salary, '0.00'); 143 144CREATE RULE rtest_emp_upd AS ON UPDATE 145 TO rtest_emp WHERE 146 NEW.salary != OLD.salary DO INSERT INTO rtest_emplog VALUES (NEW.ename, CURRENT_USER, 'honored', NEW.salary, OLD.salary); 147 148CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog VALUES (OLD.ename, CURRENT_USER, 'fired', '0.00', OLD.salary); 149 150-- 151-- Tables and rules for the multiple cascaded qualified instead 152-- rule test 153-- 154CREATE TABLE rtest_t4 ( 155 a int4, 156 b text 157); 158 159CREATE TABLE rtest_t5 ( 160 a int4, 161 b text 162); 163 164CREATE TABLE rtest_t6 ( 165 a int4, 166 b text 167); 168 169CREATE TABLE rtest_t7 ( 170 a int4, 171 b text 172); 173 174CREATE TABLE rtest_t8 ( 175 a int4, 176 b text 177); 178 179CREATE TABLE rtest_t9 ( 180 a int4, 181 b text 182); 183 184CREATE RULE rtest_t4_ins1 AS ON INSERT TO rtest_t4 WHERE 185 NEW.a >= 10 186 AND NEW.a < 20 187 DO INSTEAD 188 INSERT INTO rtest_t5 VALUES (NEW.a, NEW.b); 189 190CREATE RULE rtest_t4_ins2 AS ON INSERT TO rtest_t4 WHERE 191 NEW.a >= 20 192 AND NEW.a < 30 DO INSERT INTO rtest_t6 VALUES (NEW.a, NEW.b); 193 194CREATE RULE rtest_t5_ins AS ON INSERT TO rtest_t5 WHERE 195 NEW.a > 15 DO INSERT INTO rtest_t7 VALUES (NEW.a, NEW.b); 196 197CREATE RULE rtest_t6_ins AS ON INSERT TO rtest_t6 WHERE 198 NEW.a > 25 199 DO INSTEAD 200 INSERT INTO rtest_t8 VALUES (NEW.a, NEW.b); 201 202-- 203-- Tables and rules for the rule fire order test 204-- 205-- As of PG 7.3, the rules should fire in order by name, regardless 206-- of INSTEAD attributes or creation order. 207-- 208CREATE TABLE rtest_order1 ( 209 a int4 210); 211 212CREATE TABLE rtest_order2 ( 213 a int4, 214 b int4, 215 c text 216); 217 218CREATE SEQUENCE rtest_seq; 219 220CREATE RULE rtest_order_r3 AS ON INSERT TO rtest_order1 221 DO INSTEAD 222 INSERT INTO rtest_order2 VALUES (NEW.a, nextval('rtest_seq'), 'rule 3 - this should run 3rd'); 223 224CREATE RULE rtest_order_r4 AS ON INSERT TO rtest_order1 WHERE 225 a < 100 226 DO INSTEAD 227 INSERT INTO rtest_order2 VALUES (NEW.a, nextval('rtest_seq'), 'rule 4 - this should run 4th'); 228 229CREATE RULE rtest_order_r2 AS ON INSERT TO rtest_order1 DO INSERT INTO rtest_order2 VALUES (NEW.a, nextval('rtest_seq'), 'rule 2 - this should run 2nd'); 230 231CREATE RULE rtest_order_r1 AS ON INSERT TO rtest_order1 232 DO INSTEAD 233 INSERT INTO rtest_order2 VALUES (NEW.a, nextval('rtest_seq'), 'rule 1 - this should run 1st'); 234 235-- 236-- Tables and rules for the instead nothing test 237-- 238CREATE TABLE rtest_nothn1 ( 239 a int4, 240 b text 241); 242 243CREATE TABLE rtest_nothn2 ( 244 a int4, 245 b text 246); 247 248CREATE TABLE rtest_nothn3 ( 249 a int4, 250 b text 251); 252 253CREATE TABLE rtest_nothn4 ( 254 a int4, 255 b text 256); 257 258CREATE RULE rtest_nothn_r1 AS ON INSERT TO rtest_nothn1 WHERE 259 NEW.a >= 10 260 AND NEW.a < 20 261 DO INSTEAD 262 NOTHING; 263 264CREATE RULE rtest_nothn_r2 AS ON INSERT TO rtest_nothn1 WHERE 265 NEW.a >= 30 266 AND NEW.a < 40 267 DO INSTEAD 268 NOTHING; 269 270CREATE RULE rtest_nothn_r3 AS ON INSERT TO rtest_nothn2 WHERE 271 NEW.a >= 100 272 DO INSTEAD 273 INSERT INTO rtest_nothn3 VALUES (NEW.a, NEW.b); 274 275CREATE RULE rtest_nothn_r4 AS ON INSERT TO rtest_nothn2 276 DO INSTEAD 277 NOTHING; 278 279-- 280-- Tests on a view that is select * of a table 281-- and has insert/update/delete instead rules to 282-- behave close like the real table. 283-- 284-- 285-- We need test date later 286-- 287INSERT INTO rtest_t2 288 VALUES (1, 21); 289 290INSERT INTO rtest_t2 291 VALUES (2, 22); 292 293INSERT INTO rtest_t2 294 VALUES (3, 23); 295 296INSERT INTO rtest_t3 297 VALUES (1, 31); 298 299INSERT INTO rtest_t3 300 VALUES (2, 32); 301 302INSERT INTO rtest_t3 303 VALUES (3, 33); 304 305INSERT INTO rtest_t3 306 VALUES (4, 34); 307 308INSERT INTO rtest_t3 309 VALUES (5, 35); 310 311-- insert values 312INSERT INTO rtest_v1 313 VALUES (1, 11); 314 315INSERT INTO rtest_v1 316 VALUES (2, 12); 317 318SELECT 319 * 320FROM 321 rtest_v1; 322 323-- delete with constant expression 324DELETE FROM rtest_v1 325WHERE a = 1; 326 327SELECT 328 * 329FROM 330 rtest_v1; 331 332INSERT INTO rtest_v1 333 VALUES (1, 11); 334 335DELETE FROM rtest_v1 336WHERE b = 12; 337 338SELECT 339 * 340FROM 341 rtest_v1; 342 343INSERT INTO rtest_v1 344 VALUES (2, 12); 345 346INSERT INTO rtest_v1 347 VALUES (2, 13); 348 349SELECT 350 * 351FROM 352 rtest_v1; 353 354* * Remember the DELETE rule ON rtest_v1: It says * * 355 DO INSTEAD 356 DELETE FROM rtest_t1 357 WHERE a = old.a * * So this time BOTH ROWS WITH a = 2 must get deleted \p 358 \r 359 DELETE FROM rtest_v1 360 WHERE b = 12; 361 362SELECT 363 * 364FROM 365 rtest_v1; 366 367DELETE FROM rtest_v1; 368 369-- insert select 370INSERT INTO rtest_v1 371SELECT 372 * 373FROM 374 rtest_t2; 375 376SELECT 377 * 378FROM 379 rtest_v1; 380 381DELETE FROM rtest_v1; 382 383-- same with swapped targetlist 384INSERT INTO rtest_v1 (b, a) 385SELECT 386 b, 387 a 388FROM 389 rtest_t2; 390 391SELECT 392 * 393FROM 394 rtest_v1; 395 396-- now with only one target attribute 397INSERT INTO rtest_v1 (a) 398SELECT 399 a 400FROM 401 rtest_t3; 402 403SELECT 404 * 405FROM 406 rtest_v1; 407 408SELECT 409 * 410FROM 411 rtest_v1 412WHERE 413 b ISNULL; 414 415-- let attribute a differ (must be done on rtest_t1 - see above) 416UPDATE 417 rtest_t1 418SET 419 a = a + 10 420WHERE 421 b ISNULL; 422 423DELETE FROM rtest_v1 424WHERE b ISNULL; 425 426SELECT 427 * 428FROM 429 rtest_v1; 430 431-- now updates with constant expression 432UPDATE 433 rtest_v1 434SET 435 b = 42 436WHERE 437 a = 2; 438 439SELECT 440 * 441FROM 442 rtest_v1; 443 444UPDATE 445 rtest_v1 446SET 447 b = 99 448WHERE 449 b = 42; 450 451SELECT 452 * 453FROM 454 rtest_v1; 455 456UPDATE 457 rtest_v1 458SET 459 b = 88 460WHERE 461 b < 50; 462 463SELECT 464 * 465FROM 466 rtest_v1; 467 468DELETE FROM rtest_v1; 469 470INSERT INTO rtest_v1 471SELECT 472 rtest_t2.a, 473 rtest_t3.b 474FROM 475 rtest_t2, 476 rtest_t3 477WHERE 478 rtest_t2.a = rtest_t3.a; 479 480SELECT 481 * 482FROM 483 rtest_v1; 484 485-- updates in a mergejoin 486UPDATE 487 rtest_v1 488SET 489 b = rtest_t2.b 490FROM 491 rtest_t2 492WHERE 493 rtest_v1.a = rtest_t2.a; 494 495SELECT 496 * 497FROM 498 rtest_v1; 499 500INSERT INTO rtest_v1 501SELECT 502 * 503FROM 504 rtest_t3; 505 506SELECT 507 * 508FROM 509 rtest_v1; 510 511UPDATE 512 rtest_t1 513SET 514 a = a + 10 515WHERE 516 b > 30; 517 518SELECT 519 * 520FROM 521 rtest_v1; 522 523UPDATE 524 rtest_v1 525SET 526 a = rtest_t3.a + 20 527FROM 528 rtest_t3 529WHERE 530 rtest_v1.b = rtest_t3.b; 531 532SELECT 533 * 534FROM 535 rtest_v1; 536 537-- 538-- Test for constraint updates/deletes 539-- 540INSERT INTO rtest_system 541 VALUES ('orion', 'Linux Jan Wieck'); 542 543INSERT INTO rtest_system 544 VALUES ('notjw', 'WinNT Jan Wieck (notebook)'); 545 546INSERT INTO rtest_system 547 VALUES ('neptun', 'Fileserver'); 548 549INSERT INTO rtest_interface 550 VALUES ('orion', 'eth0'); 551 552INSERT INTO rtest_interface 553 VALUES ('orion', 'eth1'); 554 555INSERT INTO rtest_interface 556 VALUES ('notjw', 'eth0'); 557 558INSERT INTO rtest_interface 559 VALUES ('neptun', 'eth0'); 560 561INSERT INTO rtest_person 562 VALUES ('jw', 'Jan Wieck'); 563 564INSERT INTO rtest_person 565 VALUES ('bm', 'Bruce Momjian'); 566 567INSERT INTO rtest_admin 568 VALUES ('jw', 'orion'); 569 570INSERT INTO rtest_admin 571 VALUES ('jw', 'notjw'); 572 573INSERT INTO rtest_admin 574 VALUES ('bm', 'neptun'); 575 576UPDATE 577 rtest_system 578SET 579 sysname = 'pluto' 580WHERE 581 sysname = 'neptun'; 582 583SELECT 584 * 585FROM 586 rtest_interface; 587 588SELECT 589 * 590FROM 591 rtest_admin; 592 593UPDATE 594 rtest_person 595SET 596 pname = 'jwieck' 597WHERE 598 pdesc = 'Jan Wieck'; 599 600-- Note: use ORDER BY here to ensure consistent output across all systems. 601-- The above UPDATE affects two rows with equal keys, so they could be 602-- updated in either order depending on the whim of the local qsort(). 603SELECT 604 * 605FROM 606 rtest_admin 607ORDER BY 608 pname, 609 sysname; 610 611DELETE FROM rtest_system 612WHERE sysname = 'orion'; 613 614SELECT 615 * 616FROM 617 rtest_interface; 618 619SELECT 620 * 621FROM 622 rtest_admin; 623 624-- 625-- Rule qualification test 626-- 627INSERT INTO rtest_emp 628 VALUES ('wiecc', '5000.00'); 629 630INSERT INTO rtest_emp 631 VALUES ('gates', '80000.00'); 632 633UPDATE 634 rtest_emp 635SET 636 ename = 'wiecx' 637WHERE 638 ename = 'wiecc'; 639 640UPDATE 641 rtest_emp 642SET 643 ename = 'wieck', 644 salary = '6000.00' 645WHERE 646 ename = 'wiecx'; 647 648UPDATE 649 rtest_emp 650SET 651 salary = '7000.00' 652WHERE 653 ename = 'wieck'; 654 655DELETE FROM rtest_emp 656WHERE ename = 'gates'; 657 658SELECT 659 ename, 660 who = CURRENT_USER AS "matches user", 661 action, 662 newsal, 663 oldsal 664FROM 665 rtest_emplog 666ORDER BY 667 ename, 668 action, 669 newsal; 670 671INSERT INTO rtest_empmass 672 VALUES ('meyer', '4000.00'); 673 674INSERT INTO rtest_empmass 675 VALUES ('maier', '5000.00'); 676 677INSERT INTO rtest_empmass 678 VALUES ('mayr', '6000.00'); 679 680INSERT INTO rtest_emp 681SELECT 682 * 683FROM 684 rtest_empmass; 685 686SELECT 687 ename, 688 who = CURRENT_USER AS "matches user", 689 action, 690 newsal, 691 oldsal 692FROM 693 rtest_emplog 694ORDER BY 695 ename, 696 action, 697 newsal; 698 699UPDATE 700 rtest_empmass 701SET 702 salary = salary + '1000.00'; 703 704UPDATE 705 rtest_emp 706SET 707 salary = rtest_empmass.salary 708FROM 709 rtest_empmass 710WHERE 711 rtest_emp.ename = rtest_empmass.ename; 712 713SELECT 714 ename, 715 who = CURRENT_USER AS "matches user", 716 action, 717 newsal, 718 oldsal 719FROM 720 rtest_emplog 721ORDER BY 722 ename, 723 action, 724 newsal; 725 726DELETE FROM rtest_emp USING rtest_empmass 727WHERE rtest_emp.ename = rtest_empmass.ename; 728 729SELECT 730 ename, 731 who = CURRENT_USER AS "matches user", 732 action, 733 newsal, 734 oldsal 735FROM 736 rtest_emplog 737ORDER BY 738 ename, 739 action, 740 newsal; 741 742-- 743-- Multiple cascaded qualified instead rule test 744-- 745INSERT INTO rtest_t4 746 VALUES (1, 'Record should go to rtest_t4'); 747 748INSERT INTO rtest_t4 749 VALUES (2, 'Record should go to rtest_t4'); 750 751INSERT INTO rtest_t4 752 VALUES (10, 'Record should go to rtest_t5'); 753 754INSERT INTO rtest_t4 755 VALUES (15, 'Record should go to rtest_t5'); 756 757INSERT INTO rtest_t4 758 VALUES (19, 'Record should go to rtest_t5 and t7'); 759 760INSERT INTO rtest_t4 761 VALUES (20, 'Record should go to rtest_t4 and t6'); 762 763INSERT INTO rtest_t4 764 VALUES (26, 'Record should go to rtest_t4 and t8'); 765 766INSERT INTO rtest_t4 767 VALUES (28, 'Record should go to rtest_t4 and t8'); 768 769INSERT INTO rtest_t4 770 VALUES (30, 'Record should go to rtest_t4'); 771 772INSERT INTO rtest_t4 773 VALUES (40, 'Record should go to rtest_t4'); 774 775SELECT 776 * 777FROM 778 rtest_t4; 779 780SELECT 781 * 782FROM 783 rtest_t5; 784 785SELECT 786 * 787FROM 788 rtest_t6; 789 790SELECT 791 * 792FROM 793 rtest_t7; 794 795SELECT 796 * 797FROM 798 rtest_t8; 799 800DELETE FROM rtest_t4; 801 802DELETE FROM rtest_t5; 803 804DELETE FROM rtest_t6; 805 806DELETE FROM rtest_t7; 807 808DELETE FROM rtest_t8; 809 810INSERT INTO rtest_t9 811 VALUES (1, 'Record should go to rtest_t4'); 812 813INSERT INTO rtest_t9 814 VALUES (2, 'Record should go to rtest_t4'); 815 816INSERT INTO rtest_t9 817 VALUES (10, 'Record should go to rtest_t5'); 818 819INSERT INTO rtest_t9 820 VALUES (15, 'Record should go to rtest_t5'); 821 822INSERT INTO rtest_t9 823 VALUES (19, 'Record should go to rtest_t5 and t7'); 824 825INSERT INTO rtest_t9 826 VALUES (20, 'Record should go to rtest_t4 and t6'); 827 828INSERT INTO rtest_t9 829 VALUES (26, 'Record should go to rtest_t4 and t8'); 830 831INSERT INTO rtest_t9 832 VALUES (28, 'Record should go to rtest_t4 and t8'); 833 834INSERT INTO rtest_t9 835 VALUES (30, 'Record should go to rtest_t4'); 836 837INSERT INTO rtest_t9 838 VALUES (40, 'Record should go to rtest_t4'); 839 840INSERT INTO rtest_t4 841SELECT 842 * 843FROM 844 rtest_t9 845WHERE 846 a < 20; 847 848SELECT 849 * 850FROM 851 rtest_t4; 852 853SELECT 854 * 855FROM 856 rtest_t5; 857 858SELECT 859 * 860FROM 861 rtest_t6; 862 863SELECT 864 * 865FROM 866 rtest_t7; 867 868SELECT 869 * 870FROM 871 rtest_t8; 872 873INSERT INTO rtest_t4 874SELECT 875 * 876FROM 877 rtest_t9 878WHERE 879 b ~ 'and t8'; 880 881SELECT 882 * 883FROM 884 rtest_t4; 885 886SELECT 887 * 888FROM 889 rtest_t5; 890 891SELECT 892 * 893FROM 894 rtest_t6; 895 896SELECT 897 * 898FROM 899 rtest_t7; 900 901SELECT 902 * 903FROM 904 rtest_t8; 905 906INSERT INTO rtest_t4 907SELECT 908 a + 1, 909 b 910FROM 911 rtest_t9 912WHERE 913 a IN (20, 30, 40); 914 915SELECT 916 * 917FROM 918 rtest_t4; 919 920SELECT 921 * 922FROM 923 rtest_t5; 924 925SELECT 926 * 927FROM 928 rtest_t6; 929 930SELECT 931 * 932FROM 933 rtest_t7; 934 935SELECT 936 * 937FROM 938 rtest_t8; 939 940-- 941-- Check that the ordering of rules fired is correct 942-- 943INSERT INTO rtest_order1 944 VALUES (1); 945 946SELECT 947 * 948FROM 949 rtest_order2; 950 951-- 952-- Check if instead nothing w/without qualification works 953-- 954INSERT INTO rtest_nothn1 955 VALUES (1, 'want this'); 956 957INSERT INTO rtest_nothn1 958 VALUES (2, 'want this'); 959 960INSERT INTO rtest_nothn1 961 VALUES (10, 'don''t want this'); 962 963INSERT INTO rtest_nothn1 964 VALUES (19, 'don''t want this'); 965 966INSERT INTO rtest_nothn1 967 VALUES (20, 'want this'); 968 969INSERT INTO rtest_nothn1 970 VALUES (29, 'want this'); 971 972INSERT INTO rtest_nothn1 973 VALUES (30, 'don''t want this'); 974 975INSERT INTO rtest_nothn1 976 VALUES (39, 'don''t want this'); 977 978INSERT INTO rtest_nothn1 979 VALUES (40, 'want this'); 980 981INSERT INTO rtest_nothn1 982 VALUES (50, 'want this'); 983 984INSERT INTO rtest_nothn1 985 VALUES (60, 'want this'); 986 987SELECT 988 * 989FROM 990 rtest_nothn1; 991 992INSERT INTO rtest_nothn2 993 VALUES (10, 'too small'); 994 995INSERT INTO rtest_nothn2 996 VALUES (50, 'too small'); 997 998INSERT INTO rtest_nothn2 999 VALUES (100, 'OK'); 1000 1001INSERT INTO rtest_nothn2 1002 VALUES (200, 'OK'); 1003 1004SELECT 1005 * 1006FROM 1007 rtest_nothn2; 1008 1009SELECT 1010 * 1011FROM 1012 rtest_nothn3; 1013 1014DELETE FROM rtest_nothn1; 1015 1016DELETE FROM rtest_nothn2; 1017 1018DELETE FROM rtest_nothn3; 1019 1020INSERT INTO rtest_nothn4 1021 VALUES (1, 'want this'); 1022 1023INSERT INTO rtest_nothn4 1024 VALUES (2, 'want this'); 1025 1026INSERT INTO rtest_nothn4 1027 VALUES (10, 'don''t want this'); 1028 1029INSERT INTO rtest_nothn4 1030 VALUES (19, 'don''t want this'); 1031 1032INSERT INTO rtest_nothn4 1033 VALUES (20, 'want this'); 1034 1035INSERT INTO rtest_nothn4 1036 VALUES (29, 'want this'); 1037 1038INSERT INTO rtest_nothn4 1039 VALUES (30, 'don''t want this'); 1040 1041INSERT INTO rtest_nothn4 1042 VALUES (39, 'don''t want this'); 1043 1044INSERT INTO rtest_nothn4 1045 VALUES (40, 'want this'); 1046 1047INSERT INTO rtest_nothn4 1048 VALUES (50, 'want this'); 1049 1050INSERT INTO rtest_nothn4 1051 VALUES (60, 'want this'); 1052 1053INSERT INTO rtest_nothn1 1054SELECT 1055 * 1056FROM 1057 rtest_nothn4; 1058 1059SELECT 1060 * 1061FROM 1062 rtest_nothn1; 1063 1064DELETE FROM rtest_nothn4; 1065 1066INSERT INTO rtest_nothn4 1067 VALUES (10, 'too small'); 1068 1069INSERT INTO rtest_nothn4 1070 VALUES (50, 'too small'); 1071 1072INSERT INTO rtest_nothn4 1073 VALUES (100, 'OK'); 1074 1075INSERT INTO rtest_nothn4 1076 VALUES (200, 'OK'); 1077 1078INSERT INTO rtest_nothn2 1079SELECT 1080 * 1081FROM 1082 rtest_nothn4; 1083 1084SELECT 1085 * 1086FROM 1087 rtest_nothn2; 1088 1089SELECT 1090 * 1091FROM 1092 rtest_nothn3; 1093 1094CREATE TABLE rtest_view1 ( 1095 a int4, 1096 b text, 1097 v bool 1098); 1099 1100CREATE TABLE rtest_view2 ( 1101 a int4 1102); 1103 1104CREATE TABLE rtest_view3 ( 1105 a int4, 1106 b text 1107); 1108 1109CREATE TABLE rtest_view4 ( 1110 a int4, 1111 b text, 1112 c int4 1113); 1114 1115CREATE VIEW rtest_vview1 AS 1116SELECT 1117 a, 1118 b 1119FROM 1120 rtest_view1 X 1121WHERE 1122 0 < ( 1123 SELECT 1124 count(*) 1125 FROM 1126 rtest_view2 Y 1127 WHERE 1128 Y.a = X.a); 1129 1130CREATE VIEW rtest_vview2 AS 1131SELECT 1132 a, 1133 b 1134FROM 1135 rtest_view1 1136WHERE 1137 v; 1138 1139CREATE VIEW rtest_vview3 AS 1140SELECT 1141 a, 1142 b 1143FROM 1144 rtest_vview2 X 1145WHERE 1146 0 < ( 1147 SELECT 1148 count(*) 1149 FROM 1150 rtest_view2 Y 1151 WHERE 1152 Y.a = X.a); 1153 1154CREATE VIEW rtest_vview4 AS 1155SELECT 1156 X.a, 1157 X.b, 1158 count(Y.a) AS refcount 1159FROM 1160 rtest_view1 X, 1161 rtest_view2 Y 1162WHERE 1163 X.a = Y.a 1164GROUP BY 1165 X.a, 1166 X.b; 1167 1168CREATE FUNCTION rtest_viewfunc1 (int4) 1169 RETURNS int4 1170 AS 'select count(*)::int4 from rtest_view2 where a = $1' 1171 LANGUAGE sql; 1172 1173CREATE VIEW rtest_vview5 AS 1174SELECT 1175 a, 1176 b, 1177 rtest_viewfunc1 (a) AS refcount 1178FROM 1179 rtest_view1; 1180 1181INSERT INTO rtest_view1 1182 VALUES (1, 'item 1', 't'); 1183 1184INSERT INTO rtest_view1 1185 VALUES (2, 'item 2', 't'); 1186 1187INSERT INTO rtest_view1 1188 VALUES (3, 'item 3', 't'); 1189 1190INSERT INTO rtest_view1 1191 VALUES (4, 'item 4', 'f'); 1192 1193INSERT INTO rtest_view1 1194 VALUES (5, 'item 5', 't'); 1195 1196INSERT INTO rtest_view1 1197 VALUES (6, 'item 6', 'f'); 1198 1199INSERT INTO rtest_view1 1200 VALUES (7, 'item 7', 't'); 1201 1202INSERT INTO rtest_view1 1203 VALUES (8, 'item 8', 't'); 1204 1205INSERT INTO rtest_view2 1206 VALUES (2); 1207 1208INSERT INTO rtest_view2 1209 VALUES (2); 1210 1211INSERT INTO rtest_view2 1212 VALUES (4); 1213 1214INSERT INTO rtest_view2 1215 VALUES (5); 1216 1217INSERT INTO rtest_view2 1218 VALUES (7); 1219 1220INSERT INTO rtest_view2 1221 VALUES (7); 1222 1223INSERT INTO rtest_view2 1224 VALUES (7); 1225 1226INSERT INTO rtest_view2 1227 VALUES (7); 1228 1229SELECT 1230 * 1231FROM 1232 rtest_vview1; 1233 1234SELECT 1235 * 1236FROM 1237 rtest_vview2; 1238 1239SELECT 1240 * 1241FROM 1242 rtest_vview3; 1243 1244SELECT 1245 * 1246FROM 1247 rtest_vview4 1248ORDER BY 1249 a, 1250 b; 1251 1252SELECT 1253 * 1254FROM 1255 rtest_vview5; 1256 1257INSERT INTO rtest_view3 1258SELECT 1259 * 1260FROM 1261 rtest_vview1 1262WHERE 1263 a < 7; 1264 1265SELECT 1266 * 1267FROM 1268 rtest_view3; 1269 1270DELETE FROM rtest_view3; 1271 1272INSERT INTO rtest_view3 1273SELECT 1274 * 1275FROM 1276 rtest_vview2 1277WHERE 1278 a != 5 1279 AND b !~ '2'; 1280 1281SELECT 1282 * 1283FROM 1284 rtest_view3; 1285 1286DELETE FROM rtest_view3; 1287 1288INSERT INTO rtest_view3 1289SELECT 1290 * 1291FROM 1292 rtest_vview3; 1293 1294SELECT 1295 * 1296FROM 1297 rtest_view3; 1298 1299DELETE FROM rtest_view3; 1300 1301INSERT INTO rtest_view4 1302SELECT 1303 * 1304FROM 1305 rtest_vview4 1306WHERE 1307 3 > refcount; 1308 1309SELECT 1310 * 1311FROM 1312 rtest_view4 1313ORDER BY 1314 a, 1315 b; 1316 1317DELETE FROM rtest_view4; 1318 1319INSERT INTO rtest_view4 1320SELECT 1321 * 1322FROM 1323 rtest_vview5 1324WHERE 1325 a > 2 1326 AND refcount = 0; 1327 1328SELECT 1329 * 1330FROM 1331 rtest_view4; 1332 1333DELETE FROM rtest_view4; 1334 1335-- 1336-- Test for computations in views 1337-- 1338CREATE TABLE rtest_comp ( 1339 part text, 1340 unit char(4), 1341 size float 1342); 1343 1344CREATE TABLE rtest_unitfact ( 1345 unit char(4), 1346 factor float 1347); 1348 1349CREATE VIEW rtest_vcomp AS 1350SELECT 1351 X.part, 1352 (X.size * Y.factor) AS size_in_cm 1353FROM 1354 rtest_comp X, 1355 rtest_unitfact Y 1356WHERE 1357 X.unit = Y.unit; 1358 1359INSERT INTO rtest_unitfact 1360 VALUES ('m', 100.0); 1361 1362INSERT INTO rtest_unitfact 1363 VALUES ('cm', 1.0); 1364 1365INSERT INTO rtest_unitfact 1366 VALUES ('inch', 2.54); 1367 1368INSERT INTO rtest_comp 1369 VALUES ('p1', 'm', 5.0); 1370 1371INSERT INTO rtest_comp 1372 VALUES ('p2', 'm', 3.0); 1373 1374INSERT INTO rtest_comp 1375 VALUES ('p3', 'cm', 5.0); 1376 1377INSERT INTO rtest_comp 1378 VALUES ('p4', 'cm', 15.0); 1379 1380INSERT INTO rtest_comp 1381 VALUES ('p5', 'inch', 7.0); 1382 1383INSERT INTO rtest_comp 1384 VALUES ('p6', 'inch', 4.4); 1385 1386SELECT 1387 * 1388FROM 1389 rtest_vcomp 1390ORDER BY 1391 part; 1392 1393SELECT 1394 * 1395FROM 1396 rtest_vcomp 1397WHERE 1398 size_in_cm > 10.0 1399ORDER BY 1400 size_in_cm USING >; 1401 1402-- 1403-- In addition run the (slightly modified) queries from the 1404-- programmers manual section on the rule system. 1405-- 1406CREATE TABLE shoe_data ( 1407 shoename char(10), -- primary key 1408 sh_avail integer, -- available # of pairs 1409 slcolor char(10), -- preferred shoelace color 1410 slminlen float, -- minimum shoelace length 1411 slmaxlen float, -- maximum shoelace length 1412 slunit char(8) -- length unit 1413); 1414 1415CREATE TABLE shoelace_data ( 1416 sl_name char(10), -- primary key 1417 sl_avail integer, -- available # of pairs 1418 sl_color char(10), -- shoelace color 1419 sl_len float, -- shoelace length 1420 sl_unit char(8) -- length unit 1421); 1422 1423CREATE TABLE unit ( 1424 un_name char(8), -- the primary key 1425 un_fact float -- factor to transform to cm 1426); 1427 1428CREATE VIEW shoe AS 1429SELECT 1430 sh.shoename, 1431 sh.sh_avail, 1432 sh.slcolor, 1433 sh.slminlen, 1434 sh.slminlen * un.un_fact AS slminlen_cm, 1435 sh.slmaxlen, 1436 sh.slmaxlen * un.un_fact AS slmaxlen_cm, 1437 sh.slunit 1438FROM 1439 shoe_data sh, 1440 unit un 1441WHERE 1442 sh.slunit = un.un_name; 1443 1444CREATE VIEW shoelace AS 1445SELECT 1446 s.sl_name, 1447 s.sl_avail, 1448 s.sl_color, 1449 s.sl_len, 1450 s.sl_unit, 1451 s.sl_len * u.un_fact AS sl_len_cm 1452FROM 1453 shoelace_data s, 1454 unit u 1455WHERE 1456 s.sl_unit = u.un_name; 1457 1458CREATE VIEW shoe_ready AS 1459SELECT 1460 rsh.shoename, 1461 rsh.sh_avail, 1462 rsl.sl_name, 1463 rsl.sl_avail, 1464 int4smaller(rsh.sh_avail, rsl.sl_avail) AS total_avail 1465FROM 1466 shoe rsh, 1467 shoelace rsl 1468WHERE 1469 rsl.sl_color = rsh.slcolor 1470 AND rsl.sl_len_cm >= rsh.slminlen_cm 1471 AND rsl.sl_len_cm <= rsh.slmaxlen_cm; 1472 1473INSERT INTO unit 1474 VALUES ('cm', 1.0); 1475 1476INSERT INTO unit 1477 VALUES ('m', 100.0); 1478 1479INSERT INTO unit 1480 VALUES ('inch', 2.54); 1481 1482INSERT INTO shoe_data 1483 VALUES ('sh1', 2, 'black', 70.0, 90.0, 'cm'); 1484 1485INSERT INTO shoe_data 1486 VALUES ('sh2', 0, 'black', 30.0, 40.0, 'inch'); 1487 1488INSERT INTO shoe_data 1489 VALUES ('sh3', 4, 'brown', 50.0, 65.0, 'cm'); 1490 1491INSERT INTO shoe_data 1492 VALUES ('sh4', 3, 'brown', 40.0, 50.0, 'inch'); 1493 1494INSERT INTO shoelace_data 1495 VALUES ('sl1', 5, 'black', 80.0, 'cm'); 1496 1497INSERT INTO shoelace_data 1498 VALUES ('sl2', 6, 'black', 100.0, 'cm'); 1499 1500INSERT INTO shoelace_data 1501 VALUES ('sl3', 0, 'black', 35.0, 'inch'); 1502 1503INSERT INTO shoelace_data 1504 VALUES ('sl4', 8, 'black', 40.0, 'inch'); 1505 1506INSERT INTO shoelace_data 1507 VALUES ('sl5', 4, 'brown', 1.0, 'm'); 1508 1509INSERT INTO shoelace_data 1510 VALUES ('sl6', 0, 'brown', 0.9, 'm'); 1511 1512INSERT INTO shoelace_data 1513 VALUES ('sl7', 7, 'brown', 60, 'cm'); 1514 1515INSERT INTO shoelace_data 1516 VALUES ('sl8', 1, 'brown', 40, 'inch'); 1517 1518-- SELECTs in doc 1519SELECT 1520 * 1521FROM 1522 shoelace 1523ORDER BY 1524 sl_name; 1525 1526SELECT 1527 * 1528FROM 1529 shoe_ready 1530WHERE 1531 total_avail >= 2 1532ORDER BY 1533 1; 1534 1535CREATE TABLE shoelace_log ( 1536 sl_name char(10), -- shoelace changed 1537 sl_avail integer, -- new available value 1538 log_who name, -- who did it 1539 log_when timestamp -- when 1540); 1541 1542-- Want "log_who" to be CURRENT_USER, 1543-- but that is non-portable for the regression test 1544-- - thomas 1999-02-21 1545CREATE RULE log_shoelace AS ON UPDATE 1546 TO shoelace_data WHERE 1547 NEW.sl_avail != OLD.sl_avail DO INSERT INTO shoelace_log VALUES (NEW.sl_name, NEW.sl_avail, 'Al Bundy', 'epoch'); 1548 1549UPDATE 1550 shoelace_data 1551SET 1552 sl_avail = 6 1553WHERE 1554 sl_name = 'sl7'; 1555 1556SELECT 1557 * 1558FROM 1559 shoelace_log; 1560 1561CREATE RULE shoelace_ins AS ON INSERT TO shoelace 1562 DO INSTEAD 1563 INSERT INTO shoelace_data VALUES (NEW.sl_name, NEW.sl_avail, NEW.sl_color, NEW.sl_len, NEW.sl_unit); 1564 1565CREATE RULE shoelace_upd AS ON UPDATE 1566 TO shoelace 1567 DO INSTEAD 1568 UPDATE 1569 shoelace_data SET 1570 sl_name = NEW.sl_name, 1571 sl_avail = NEW.sl_avail, 1572 sl_color = NEW.sl_color, 1573 sl_len = NEW.sl_len, 1574 sl_unit = NEW.sl_unit WHERE 1575 sl_name = OLD.sl_name; 1576 1577CREATE RULE shoelace_del AS ON DELETE TO shoelace 1578 DO INSTEAD 1579 DELETE FROM shoelace_data 1580 WHERE sl_name = OLD.sl_name; 1581 1582CREATE TABLE shoelace_arrive ( 1583 arr_name char(10), 1584 arr_quant integer 1585); 1586 1587CREATE TABLE shoelace_ok ( 1588 ok_name char(10), 1589 ok_quant integer 1590); 1591 1592CREATE RULE shoelace_ok_ins AS ON INSERT TO shoelace_ok 1593 DO INSTEAD 1594 UPDATE 1595 shoelace SET 1596 sl_avail = sl_avail + NEW.ok_quant WHERE 1597 sl_name = NEW.ok_name; 1598 1599INSERT INTO shoelace_arrive 1600 VALUES ('sl3', 10); 1601 1602INSERT INTO shoelace_arrive 1603 VALUES ('sl6', 20); 1604 1605INSERT INTO shoelace_arrive 1606 VALUES ('sl8', 20); 1607 1608SELECT 1609 * 1610FROM 1611 shoelace 1612ORDER BY 1613 sl_name; 1614 1615INSERT INTO shoelace_ok 1616SELECT 1617 * 1618FROM 1619 shoelace_arrive; 1620 1621SELECT 1622 * 1623FROM 1624 shoelace 1625ORDER BY 1626 sl_name; 1627 1628SELECT 1629 * 1630FROM 1631 shoelace_log 1632ORDER BY 1633 sl_name; 1634 1635CREATE VIEW shoelace_obsolete AS 1636SELECT 1637 * 1638FROM 1639 shoelace 1640WHERE 1641 NOT EXISTS ( 1642 SELECT 1643 shoename 1644 FROM 1645 shoe 1646 WHERE 1647 slcolor = sl_color); 1648 1649CREATE VIEW shoelace_candelete AS 1650SELECT 1651 * 1652FROM 1653 shoelace_obsolete 1654WHERE 1655 sl_avail = 0; 1656 1657INSERT INTO shoelace 1658 VALUES ('sl9', 0, 'pink', 35.0, 'inch', 0.0); 1659 1660INSERT INTO shoelace 1661 VALUES ('sl10', 1000, 'magenta', 40.0, 'inch', 0.0); 1662 1663-- Unsupported (even though a similar updatable view construct is) 1664INSERT INTO shoelace 1665 VALUES ('sl10', 1000, 'magenta', 40.0, 'inch', 0.0) 1666ON CONFLICT 1667 DO NOTHING; 1668 1669SELECT 1670 * 1671FROM 1672 shoelace_obsolete 1673ORDER BY 1674 sl_len_cm; 1675 1676SELECT 1677 * 1678FROM 1679 shoelace_candelete; 1680 1681DELETE FROM shoelace 1682WHERE EXISTS ( 1683 SELECT 1684 * 1685 FROM 1686 shoelace_candelete 1687 WHERE 1688 sl_name = shoelace.sl_name); 1689 1690SELECT 1691 * 1692FROM 1693 shoelace 1694ORDER BY 1695 sl_name; 1696 1697SELECT 1698 * 1699FROM 1700 shoe 1701ORDER BY 1702 shoename; 1703 1704SELECT 1705 count(*) 1706FROM 1707 shoe; 1708 1709-- 1710-- Simple test of qualified ON INSERT ... this did not work in 7.0 ... 1711-- 1712CREATE TABLE rules_foo ( 1713 f1 int 1714); 1715 1716CREATE TABLE rules_foo2 ( 1717 f1 int 1718); 1719 1720CREATE RULE rules_foorule AS ON INSERT TO rules_foo WHERE 1721 f1 < 100 1722 DO INSTEAD 1723 NOTHING; 1724 1725INSERT INTO rules_foo 1726 VALUES (1); 1727 1728INSERT INTO rules_foo 1729 VALUES (1001); 1730 1731SELECT 1732 * 1733FROM 1734 rules_foo; 1735 1736DROP RULE rules_foorule ON rules_foo; 1737 1738-- this should fail because f1 is not exposed for unqualified reference: 1739CREATE RULE rules_foorule AS ON INSERT TO rules_foo WHERE 1740 f1 < 100 1741 DO INSTEAD 1742 INSERT INTO rules_foo2 VALUES (f1); 1743 1744-- this is the correct way: 1745CREATE RULE rules_foorule AS ON INSERT TO rules_foo WHERE 1746 f1 < 100 1747 DO INSTEAD 1748 INSERT INTO rules_foo2 VALUES (NEW.f1); 1749 1750INSERT INTO rules_foo 1751 VALUES (2); 1752 1753INSERT INTO rules_foo 1754 VALUES (100); 1755 1756SELECT 1757 * 1758FROM 1759 rules_foo; 1760 1761SELECT 1762 * 1763FROM 1764 rules_foo2; 1765 1766DROP RULE rules_foorule ON rules_foo; 1767 1768DROP TABLE rules_foo; 1769 1770DROP TABLE rules_foo2; 1771 1772-- 1773-- Test rules containing INSERT ... SELECT, which is a very ugly special 1774-- case as of 7.1. Example is based on bug report from Joel Burton. 1775-- 1776CREATE TABLE pparent ( 1777 pid int, 1778 txt text 1779); 1780 1781INSERT INTO pparent 1782 VALUES (1, 'parent1'); 1783 1784INSERT INTO pparent 1785 VALUES (2, 'parent2'); 1786 1787CREATE TABLE cchild ( 1788 pid int, 1789 descrip text 1790); 1791 1792INSERT INTO cchild 1793 VALUES (1, 'descrip1'); 1794 1795CREATE VIEW vview AS 1796SELECT 1797 pparent.pid, 1798 txt, 1799 descrip 1800FROM 1801 pparent 1802 LEFT JOIN cchild USING (pid); 1803 1804CREATE RULE rrule AS ON UPDATE 1805 TO vview 1806 DO INSTEAD 1807 (INSERT INTO cchild (pid, descrip) 1808 SELECT 1809 OLD.pid, 1810 NEW.descrip WHERE 1811 OLD.descrip ISNULL; 1812 1813UPDATE 1814 cchild 1815SET 1816 descrip = new.descrip 1817WHERE 1818 cchild.pid = old.pid; 1819 1820); 1821 1822SELECT 1823 * 1824FROM 1825 vview; 1826 1827UPDATE 1828 vview 1829SET 1830 descrip = 'test1' 1831WHERE 1832 pid = 1; 1833 1834SELECT 1835 * 1836FROM 1837 vview; 1838 1839UPDATE 1840 vview 1841SET 1842 descrip = 'test2' 1843WHERE 1844 pid = 2; 1845 1846SELECT 1847 * 1848FROM 1849 vview; 1850 1851UPDATE 1852 vview 1853SET 1854 descrip = 'test3' 1855WHERE 1856 pid = 3; 1857 1858SELECT 1859 * 1860FROM 1861 vview; 1862 1863SELECT 1864 * 1865FROM 1866 cchild; 1867 1868DROP RULE rrule ON vview; 1869 1870DROP VIEW vview; 1871 1872DROP TABLE pparent; 1873 1874DROP TABLE cchild; 1875 1876-- 1877-- Check that ruleutils are working 1878-- 1879-- temporarily disable fancy output, so view changes create less diff noise 1880a \t 1881SELECT 1882 viewname, 1883 definition 1884FROM 1885 pg_views 1886WHERE 1887 schemaname IN ('pg_catalog', 'public') 1888ORDER BY 1889 viewname; 1890 1891SELECT 1892 tablename, 1893 rulename, 1894 definition 1895FROM 1896 pg_rules 1897WHERE 1898 schemaname IN ('pg_catalog', 'public') 1899ORDER BY 1900 tablename, 1901 rulename; 1902 1903-- restore normal output mode 1904a \t 1905-- 1906-- CREATE OR REPLACE RULE 1907-- 1908CREATE TABLE ruletest_tbl ( 1909 a int, 1910 b int 1911); 1912 1913CREATE TABLE ruletest_tbl2 ( 1914 a int, 1915 b int 1916); 1917 1918CREATE OR REPLACE RULE myrule AS ON INSERT TO ruletest_tbl 1919 DO INSTEAD 1920 INSERT INTO ruletest_tbl2 1921 VALUES ( 1922 10, 10 1923); 1924 1925INSERT INTO ruletest_tbl 1926 VALUES (99, 99); 1927 1928CREATE OR REPLACE RULE myrule AS ON INSERT TO ruletest_tbl 1929 DO INSTEAD 1930 INSERT INTO ruletest_tbl2 1931 VALUES ( 1932 1000, 1000 1933); 1934 1935INSERT INTO ruletest_tbl 1936 VALUES (99, 99); 1937 1938SELECT 1939 * 1940FROM 1941 ruletest_tbl2; 1942 1943-- Check that rewrite rules splitting one INSERT into multiple 1944-- conditional statements does not disable FK checking. 1945CREATE TABLE rule_and_refint_t1 ( 1946 id1a integer, 1947 id1b integer, 1948 PRIMARY KEY (id1a, id1b) 1949); 1950 1951CREATE TABLE rule_and_refint_t2 ( 1952 id2a integer, 1953 id2c integer, 1954 PRIMARY KEY (id2a, id2c) 1955); 1956 1957CREATE TABLE rule_and_refint_t3 ( 1958 id3a integer, 1959 id3b integer, 1960 id3c integer, 1961 data text, 1962 PRIMARY KEY (id3a, id3b, id3c), 1963 FOREIGN KEY (id3a, id3b) REFERENCES rule_and_refint_t1 (id1a, id1b), 1964 FOREIGN KEY (id3a, id3c) REFERENCES rule_and_refint_t2 (id2a, id2c) 1965); 1966 1967INSERT INTO rule_and_refint_t1 1968 VALUES (1, 11); 1969 1970INSERT INTO rule_and_refint_t1 1971 VALUES (1, 12); 1972 1973INSERT INTO rule_and_refint_t1 1974 VALUES (2, 21); 1975 1976INSERT INTO rule_and_refint_t1 1977 VALUES (2, 22); 1978 1979INSERT INTO rule_and_refint_t2 1980 VALUES (1, 11); 1981 1982INSERT INTO rule_and_refint_t2 1983 VALUES (1, 12); 1984 1985INSERT INTO rule_and_refint_t2 1986 VALUES (2, 21); 1987 1988INSERT INTO rule_and_refint_t2 1989 VALUES (2, 22); 1990 1991INSERT INTO rule_and_refint_t3 1992 VALUES (1, 11, 11, 'row1'); 1993 1994INSERT INTO rule_and_refint_t3 1995 VALUES (1, 11, 12, 'row2'); 1996 1997INSERT INTO rule_and_refint_t3 1998 VALUES (1, 12, 11, 'row3'); 1999 2000INSERT INTO rule_and_refint_t3 2001 VALUES (1, 12, 12, 'row4'); 2002 2003INSERT INTO rule_and_refint_t3 2004 VALUES (1, 11, 13, 'row5'); 2005 2006INSERT INTO rule_and_refint_t3 2007 VALUES (1, 13, 11, 'row6'); 2008 2009-- Ordinary table 2010INSERT INTO rule_and_refint_t3 2011 VALUES (1, 13, 11, 'row6') 2012ON CONFLICT 2013 DO NOTHING; 2014 2015-- rule not fired, so fk violation 2016INSERT INTO rule_and_refint_t3 2017 VALUES (1, 13, 11, 'row6') 2018ON CONFLICT (id3a, id3b, id3c) 2019 DO UPDATE SET 2020 id3b = excluded.id3b; 2021 2022-- rule fired, so unsupported 2023INSERT INTO shoelace 2024 VALUES ('sl9', 0, 'pink', 35.0, 'inch', 0.0) 2025ON CONFLICT (sl_name) 2026 DO UPDATE SET 2027 sl_avail = excluded.sl_avail; 2028 2029CREATE RULE rule_and_refint_t3_ins AS ON INSERT TO rule_and_refint_t3 WHERE (EXISTS ( 2030 SELECT 2031 1 FROM 2032 rule_and_refint_t3 WHERE (((rule_and_refint_t3.id3a = NEW.id3a) 2033 AND (rule_and_refint_t3.id3b = NEW.id3b)) 2034 AND (rule_and_refint_t3.id3c = NEW.id3c)))) 2035 DO INSTEAD 2036 UPDATE 2037 rule_and_refint_t3 SET 2038 data = NEW.data WHERE (((rule_and_refint_t3.id3a = NEW.id3a) 2039 AND (rule_and_refint_t3.id3b = NEW.id3b)) 2040 AND (rule_and_refint_t3.id3c = NEW.id3c)); 2041 2042INSERT INTO rule_and_refint_t3 2043 VALUES (1, 11, 13, 'row7'); 2044 2045INSERT INTO rule_and_refint_t3 2046 VALUES (1, 13, 11, 'row8'); 2047 2048-- 2049-- disallow dropping a view's rule (bug #5072) 2050-- 2051CREATE VIEW rules_fooview AS 2052SELECT 2053 'rules_foo'::text; 2054 2055DROP RULE "_RETURN" ON rules_fooview; 2056 2057DROP VIEW rules_fooview; 2058 2059-- 2060-- test conversion of table to view (needed to load some pg_dump files) 2061-- 2062CREATE TABLE rules_fooview ( 2063 x int, 2064 y text 2065); 2066 2067SELECT 2068 xmin, 2069 * 2070FROM 2071 rules_fooview; 2072 2073CREATE RULE "_RETURN" AS ON 2074SELECT 2075 TO rules_fooview 2076 DO INSTEAD 2077 SELECT 2078 1 AS x, 2079 'aaa'::text AS y; 2080 2081SELECT 2082 * 2083FROM 2084 rules_fooview; 2085 2086SELECT 2087 xmin, 2088 * 2089FROM 2090 rules_fooview; 2091 2092-- fail, views don't have such a column 2093SELECT 2094 reltoastrelid, 2095 relkind, 2096 relfrozenxid 2097FROM 2098 pg_class 2099WHERE 2100 oid = 'rules_fooview'::regclass; 2101 2102DROP VIEW rules_fooview; 2103 2104-- trying to convert a partitioned table to view is not allowed 2105CREATE TABLE rules_fooview ( 2106 x int, 2107 y text 2108) 2109PARTITION BY LIST (x); 2110 2111CREATE RULE "_RETURN" AS ON 2112SELECT 2113 TO rules_fooview 2114 DO INSTEAD 2115 SELECT 2116 1 AS x, 2117 'aaa'::text AS y; 2118 2119-- nor can one convert a partition to view 2120CREATE TABLE rules_fooview_part PARTITION OF rules_fooview 2121FOR VALUES IN (1); 2122 2123CREATE RULE "_RETURN" AS ON 2124SELECT 2125 TO rules_fooview_part 2126 DO INSTEAD 2127 SELECT 2128 1 AS x, 2129 'aaa'::text AS y; 2130 2131-- 2132-- check for planner problems with complex inherited UPDATES 2133-- 2134CREATE TABLE id ( 2135 id serial PRIMARY KEY, 2136 name text 2137); 2138 2139-- currently, must respecify PKEY for each inherited subtable 2140CREATE TABLE test_1 ( 2141 id integer PRIMARY KEY 2142) 2143INHERITS ( 2144 id 2145); 2146 2147CREATE TABLE test_2 ( 2148 id integer PRIMARY KEY 2149) 2150INHERITS ( 2151 id 2152); 2153 2154CREATE TABLE test_3 ( 2155 id integer PRIMARY KEY 2156) 2157INHERITS ( 2158 id 2159); 2160 2161INSERT INTO test_1 (name) 2162 VALUES ('Test 1'); 2163 2164INSERT INTO test_1 (name) 2165 VALUES ('Test 2'); 2166 2167INSERT INTO test_2 (name) 2168 VALUES ('Test 3'); 2169 2170INSERT INTO test_2 (name) 2171 VALUES ('Test 4'); 2172 2173INSERT INTO test_3 (name) 2174 VALUES ('Test 5'); 2175 2176INSERT INTO test_3 (name) 2177 VALUES ('Test 6'); 2178 2179CREATE VIEW id_ordered AS 2180SELECT 2181 * 2182FROM 2183 id 2184ORDER BY 2185 id; 2186 2187CREATE RULE update_id_ordered AS ON UPDATE 2188 TO id_ordered 2189 DO INSTEAD 2190 UPDATE 2191 id SET 2192 name = NEW.name WHERE 2193 id = OLD.id; 2194 2195SELECT 2196 * 2197FROM 2198 id_ordered; 2199 2200UPDATE 2201 id_ordered 2202SET 2203 name = 'update 2' 2204WHERE 2205 id = 2; 2206 2207UPDATE 2208 id_ordered 2209SET 2210 name = 'update 4' 2211WHERE 2212 id = 4; 2213 2214UPDATE 2215 id_ordered 2216SET 2217 name = 'update 5' 2218WHERE 2219 id = 5; 2220 2221SELECT 2222 * 2223FROM 2224 id_ordered; 2225 2226DROP TABLE id CASCADE; 2227 2228-- 2229-- check corner case where an entirely-dummy subplan is created by 2230-- constraint exclusion 2231-- 2232CREATE temp TABLE t1 ( 2233 a integer PRIMARY KEY 2234); 2235 2236CREATE temp TABLE t1_1 ( 2237 CHECK (a >= 0 AND a < 10) 2238) 2239INHERITS ( 2240 t1 2241); 2242 2243CREATE temp TABLE t1_2 ( 2244 CHECK (a >= 10 AND a < 20) 2245) 2246INHERITS ( 2247 t1 2248); 2249 2250CREATE RULE t1_ins_1 AS ON INSERT TO t1 WHERE 2251 NEW.a >= 0 2252 AND NEW.a < 10 2253 DO INSTEAD 2254 INSERT INTO t1_1 VALUES (NEW.a); 2255 2256CREATE RULE t1_ins_2 AS ON INSERT TO t1 WHERE 2257 NEW.a >= 10 2258 AND NEW.a < 20 2259 DO INSTEAD 2260 INSERT INTO t1_2 VALUES (NEW.a); 2261 2262CREATE RULE t1_upd_1 AS ON UPDATE 2263 TO t1 WHERE 2264 OLD.a >= 0 2265 AND OLD.a < 10 2266 DO INSTEAD 2267 UPDATE 2268 t1_1 SET 2269 a = NEW.a WHERE 2270 a = OLD.a; 2271 2272CREATE RULE t1_upd_2 AS ON UPDATE 2273 TO t1 WHERE 2274 OLD.a >= 10 2275 AND OLD.a < 20 2276 DO INSTEAD 2277 UPDATE 2278 t1_2 SET 2279 a = NEW.a WHERE 2280 a = OLD.a; 2281 2282SET constraint_exclusion = ON; 2283 2284INSERT INTO t1 2285SELECT 2286 * 2287FROM 2288 generate_series(5, 19, 1) g; 2289 2290UPDATE 2291 t1 2292SET 2293 a = 4 2294WHERE 2295 a = 5; 2296 2297SELECT 2298 * 2299FROM 2300 ONLY t1; 2301 2302SELECT 2303 * 2304FROM 2305 ONLY t1_1; 2306 2307SELECT 2308 * 2309FROM 2310 ONLY t1_2; 2311 2312RESET constraint_exclusion; 2313 2314-- test various flavors of pg_get_viewdef() 2315SELECT 2316 pg_get_viewdef('shoe'::regclass) AS unpretty; 2317 2318SELECT 2319 pg_get_viewdef('shoe'::regclass, TRUE) AS pretty; 2320 2321SELECT 2322 pg_get_viewdef('shoe'::regclass, 0) AS prettier; 2323 2324-- 2325-- check multi-row VALUES in rules 2326-- 2327CREATE TABLE rules_src ( 2328 f1 int, 2329 f2 int 2330); 2331 2332CREATE TABLE rules_log ( 2333 f1 int, 2334 f2 int, 2335 tag text 2336); 2337 2338INSERT INTO rules_src 2339 VALUES (1, 2), (11, 12); 2340 2341CREATE RULE r1 AS ON UPDATE 2342 TO rules_src 2343 DO ALSO 2344 INSERT INTO rules_log VALUES (OLD.*, 'old'), (NEW.*, 'new'); 2345 2346UPDATE 2347 rules_src 2348SET 2349 f2 = f2 + 1; 2350 2351UPDATE 2352 rules_src 2353SET 2354 f2 = f2 * 10; 2355 2356SELECT 2357 * 2358FROM 2359 rules_src; 2360 2361SELECT 2362 * 2363FROM 2364 rules_log; 2365 2366CREATE RULE r2 AS ON UPDATE 2367 TO rules_src 2368 DO ALSO 2369 VALUES (OLD.*, 2370 'old'), 2371 (NEW.*, 2372 'new'); 2373 2374UPDATE 2375 rules_src 2376SET 2377 f2 = f2 / 10; 2378 2379SELECT 2380 * 2381FROM 2382 rules_src; 2383 2384SELECT 2385 * 2386FROM 2387 rules_log; 2388 2389CREATE RULE r3 AS ON DELETE TO rules_src DO NOTIFY rules_src_deletion; 2390 2391\d+ rules_src 2392-- 2393-- Ensure an aliased target relation for insert is correctly deparsed. 2394-- 2395CREATE RULE r4 AS ON INSERT TO rules_src 2396 DO INSTEAD 2397 INSERT INTO rules_log AS trgt 2398 SELECT 2399 NEW.* RETURNING 2400 trgt.f1, 2401 trgt.f2; 2402 2403CREATE RULE r5 AS ON UPDATE 2404 TO rules_src 2405 DO INSTEAD 2406 UPDATE 2407 rules_log AS trgt SET 2408 tag = 'updated' WHERE 2409 trgt.f1 = NEW.f1; 2410 2411\d+ rules_src 2412-- 2413-- check alter rename rule 2414-- 2415CREATE TABLE rule_t1 ( 2416 a int 2417); 2418 2419CREATE VIEW rule_v1 AS 2420SELECT 2421 * 2422FROM 2423 rule_t1; 2424 2425CREATE RULE InsertRule AS ON INSERT TO rule_v1 2426 DO INSTEAD 2427 INSERT INTO rule_t1 VALUES (NEW.a); 2428 2429ALTER RULE InsertRule ON rule_v1 RENAME TO NewInsertRule; 2430 2431INSERT INTO rule_v1 2432 VALUES (1); 2433 2434SELECT 2435 * 2436FROM 2437 rule_v1; 2438 2439\d+ rule_v1 2440-- 2441-- error conditions for alter rename rule 2442-- 2443ALTER RULE InsertRule ON rule_v1 RENAME TO NewInsertRule; 2444 2445-- doesn't exist 2446ALTER RULE NewInsertRule ON rule_v1 RENAME TO "_RETURN"; 2447 2448-- already exists 2449ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; 2450 2451-- ON SELECT rule cannot be renamed 2452DROP VIEW rule_v1; 2453 2454DROP TABLE rule_t1; 2455 2456-- 2457-- check display of VALUES in view definitions 2458-- 2459CREATE VIEW rule_v1 AS 2460VALUES (1, 2461 2); 2462 2463\d+ rule_v1 2464DROP VIEW rule_v1; 2465 2466CREATE VIEW rule_v1 (x) AS 2467VALUES (1, 2468 2); 2469 2470\d+ rule_v1 2471DROP VIEW rule_v1; 2472 2473CREATE VIEW rule_v1 (x) AS 2474SELECT 2475 * 2476FROM ( 2477 VALUES (1, 2)) v; 2478 2479\d+ rule_v1 2480DROP VIEW rule_v1; 2481 2482CREATE VIEW rule_v1 (x) AS 2483SELECT 2484 * 2485FROM ( 2486 VALUES (1, 2)) v (q, w); 2487 2488\d+ rule_v1 2489DROP VIEW rule_v1; 2490 2491-- 2492-- Check DO INSTEAD rules with ON CONFLICT 2493-- 2494CREATE TABLE hats ( 2495 hat_name char(10) PRIMARY KEY, 2496 hat_color char(10) -- hat color 2497); 2498 2499CREATE TABLE hat_data ( 2500 hat_name char(10), 2501 hat_color char(10) -- hat color 2502); 2503 2504CREATE UNIQUE INDEX hat_data_unique_idx ON hat_data (hat_name COLLATE "C" bpchar_pattern_ops); 2505 2506-- DO NOTHING with ON CONFLICT 2507CREATE RULE hat_nosert AS ON INSERT TO hats 2508 DO INSTEAD 2509 INSERT INTO hat_data VALUES (NEW.hat_name, NEW.hat_color) 2510ON CONFLICT (hat_name COLLATE "C" bpchar_pattern_ops) 2511WHERE 2512 hat_color = 'green' 2513 DO NOTHING RETURNING 2514 *; 2515 2516SELECT 2517 definition 2518FROM 2519 pg_rules 2520WHERE 2521 tablename = 'hats' 2522ORDER BY 2523 rulename; 2524 2525-- Works (projects row) 2526INSERT INTO hats 2527 VALUES ('h7', 'black') 2528RETURNING 2529 *; 2530 2531-- Works (does nothing) 2532INSERT INTO hats 2533 VALUES ('h7', 'black') 2534RETURNING 2535 *; 2536 2537SELECT 2538 tablename, 2539 rulename, 2540 definition 2541FROM 2542 pg_rules 2543WHERE 2544 tablename = 'hats'; 2545 2546DROP RULE hat_nosert ON hats; 2547 2548-- DO NOTHING without ON CONFLICT 2549CREATE RULE hat_nosert_all AS ON INSERT TO hats 2550 DO INSTEAD 2551 INSERT INTO hat_data VALUES (NEW.hat_name, NEW.hat_color) 2552ON CONFLICT 2553 DO NOTHING RETURNING 2554 *; 2555 2556SELECT 2557 definition 2558FROM 2559 pg_rules 2560WHERE 2561 tablename = 'hats' 2562ORDER BY 2563 rulename; 2564 2565DROP RULE hat_nosert_all ON hats; 2566 2567-- Works (does nothing) 2568INSERT INTO hats 2569 VALUES ('h7', 'black') 2570RETURNING 2571 *; 2572 2573-- DO UPDATE with a WHERE clause 2574CREATE RULE hat_upsert AS ON INSERT TO hats 2575 DO INSTEAD 2576 INSERT INTO hat_data VALUES (NEW.hat_name, NEW.hat_color) 2577ON CONFLICT (hat_name) 2578 DO UPDATE SET 2579 hat_name = hat_data.hat_name, hat_color = excluded.hat_color WHERE 2580 excluded.hat_color <> 'forbidden' 2581 AND hat_data.* != excluded.* RETURNING 2582 *; 2583 2584SELECT 2585 definition 2586FROM 2587 pg_rules 2588WHERE 2589 tablename = 'hats' 2590ORDER BY 2591 rulename; 2592 2593-- Works (does upsert) 2594INSERT INTO hats 2595 VALUES ('h8', 'black') 2596RETURNING 2597 *; 2598 2599SELECT 2600 * 2601FROM 2602 hat_data 2603WHERE 2604 hat_name = 'h8'; 2605 2606INSERT INTO hats 2607 VALUES ('h8', 'white') 2608RETURNING 2609 *; 2610 2611SELECT 2612 * 2613FROM 2614 hat_data 2615WHERE 2616 hat_name = 'h8'; 2617 2618INSERT INTO hats 2619 VALUES ('h8', 'forbidden') 2620RETURNING 2621 *; 2622 2623SELECT 2624 * 2625FROM 2626 hat_data 2627WHERE 2628 hat_name = 'h8'; 2629 2630SELECT 2631 tablename, 2632 rulename, 2633 definition 2634FROM 2635 pg_rules 2636WHERE 2637 tablename = 'hats'; 2638 2639-- ensure explain works for on insert conflict rules 2640EXPLAIN ( 2641 COSTS OFF 2642) INSERT INTO hats 2643 VALUES ('h8', 'forbidden') 2644RETURNING 2645 *; 2646 2647-- ensure upserting into a rule, with a CTE (different offsets!) works 2648WITH data ( 2649 hat_name, 2650 hat_color 2651) AS MATERIALIZED ( 2652 VALUES ( 2653 'h8', 'green' 2654), 2655 ( 2656 'h9', 'blue' 2657), 2658 ( 2659 'h7', 'forbidden' 2660)) 2661INSERT INTO hats 2662SELECT 2663 * 2664FROM 2665 data 2666RETURNING 2667 *; 2668 2669EXPLAIN ( 2670 COSTS OFF 2671) WITH data (hat_name, 2672 hat_color) AS MATERIALIZED ( 2673 VALUES ('h8', 'green'), 2674 ('h9', 'blue'), 2675 ('h7', 'forbidden')) 2676INSERT INTO hats 2677SELECT 2678 * 2679FROM 2680 data 2681RETURNING 2682 *; 2683 2684SELECT 2685 * 2686FROM 2687 hat_data 2688WHERE 2689 hat_name IN ('h8', 'h9', 'h7') 2690ORDER BY 2691 hat_name; 2692 2693DROP RULE hat_upsert ON hats; 2694 2695DROP TABLE hats; 2696 2697DROP TABLE hat_data; 2698 2699-- test for pg_get_functiondef properly regurgitating SET parameters 2700-- Note that the function is kept around to stress pg_dump. 2701CREATE FUNCTION func_with_set_params () 2702 RETURNS integer 2703 AS 'select 1;' 2704 LANGUAGE SQL 2705 SET search_path TO PG_CATALOG SET extra_float_digits TO 2 SET work_mem TO '4MB' SET datestyle TO iso, mdy SET local_preload_libraries TO "Mixed/Case", 'c:/''a"/path', '', '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' IMMUTABLE STRICT; 2706 2707SELECT 2708 pg_get_functiondef('func_with_set_params()'::regprocedure); 2709 2710-- tests for pg_get_*def with invalid objects 2711SELECT 2712 pg_get_constraintdef(0); 2713 2714SELECT 2715 pg_get_functiondef(0); 2716 2717SELECT 2718 pg_get_indexdef(0); 2719 2720SELECT 2721 pg_get_ruledef(0); 2722 2723SELECT 2724 pg_get_statisticsobjdef (0); 2725 2726SELECT 2727 pg_get_triggerdef(0); 2728 2729SELECT 2730 pg_get_viewdef(0); 2731 2732SELECT 2733 pg_get_function_arguments(0); 2734 2735SELECT 2736 pg_get_function_identity_arguments(0); 2737 2738SELECT 2739 pg_get_function_result(0); 2740 2741SELECT 2742 pg_get_function_arg_default (0, 0); 2743 2744SELECT 2745 pg_get_function_arg_default ('pg_class'::regclass, 0); 2746 2747SELECT 2748 pg_get_partkeydef (0); 2749 2750-- test rename for a rule defined on a partitioned table 2751CREATE TABLE rules_parted_table ( 2752 a int 2753) 2754PARTITION BY LIST (a); 2755 2756CREATE TABLE rules_parted_table_1 PARTITION OF rules_parted_table 2757FOR VALUES IN (1); 2758 2759CREATE RULE rules_parted_table_insert AS ON INSERT TO rules_parted_table 2760 DO INSTEAD 2761 INSERT INTO rules_parted_table_1 VALUES (NEW.*); 2762 2763ALTER RULE rules_parted_table_insert ON rules_parted_table RENAME TO rules_parted_table_insert_redirect; 2764 2765DROP TABLE rules_parted_table; 2766 2767-- 2768-- Test enabling/disabling 2769-- 2770CREATE TABLE ruletest1 ( 2771 a int 2772); 2773 2774CREATE TABLE ruletest2 ( 2775 b int 2776); 2777 2778CREATE RULE rule1 AS ON INSERT TO ruletest1 2779 DO INSTEAD 2780 INSERT INTO ruletest2 VALUES (NEW.*); 2781 2782INSERT INTO ruletest1 2783 VALUES (1); 2784 2785ALTER TABLE ruletest1 DISABLE RULE rule1; 2786 2787INSERT INTO ruletest1 2788 VALUES (2); 2789 2790ALTER TABLE ruletest1 ENABLE RULE rule1; 2791 2792SET session_replication_role = REPLICA; 2793 2794INSERT INTO ruletest1 2795 VALUES (3); 2796 2797ALTER TABLE ruletest1 ENABLE REPLICA RULE rule1; 2798 2799INSERT INTO ruletest1 2800 VALUES (4); 2801 2802RESET session_replication_role; 2803 2804INSERT INTO ruletest1 2805 VALUES (5); 2806 2807SELECT 2808 * 2809FROM 2810 ruletest1; 2811 2812SELECT 2813 * 2814FROM 2815 ruletest2; 2816 2817DROP TABLE ruletest1; 2818 2819DROP TABLE ruletest2; 2820 2821