insert.sql 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. --
  2. -- insert with DEFAULT in the target_list
  3. --
  4. create table inserttest (col1 int4, col2 int4 NOT NULL, col3 text default 'testing');
  5. insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT, DEFAULT);
  6. insert into inserttest (col2, col3) values (3, DEFAULT);
  7. insert into inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT);
  8. insert into inserttest values (DEFAULT, 5, 'test');
  9. insert into inserttest values (DEFAULT, 7);
  10. select * from inserttest;
  11. --
  12. -- insert with similar expression / target_list values (all fail)
  13. --
  14. insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT);
  15. insert into inserttest (col1, col2, col3) values (1, 2);
  16. insert into inserttest (col1) values (1, 2);
  17. insert into inserttest (col1) values (DEFAULT, DEFAULT);
  18. select * from inserttest;
  19. --
  20. -- VALUES test
  21. --
  22. insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
  23. ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
  24. select * from inserttest;
  25. --
  26. -- TOASTed value test
  27. --
  28. insert into inserttest values(30, 50, repeat('x', 10000));
  29. select col1, col2, char_length(col3) from inserttest;
  30. drop table inserttest;
  31. --
  32. -- tuple larger than fillfactor
  33. --
  34. CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10);
  35. ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain;
  36. -- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize)
  37. INSERT INTO large_tuple_test (select 1, NULL);
  38. -- should still fit on the page
  39. INSERT INTO large_tuple_test (select 2, repeat('a', 1000));
  40. SELECT pg_size_pretty(pg_relation_size('large_tuple_test'::regclass, 'main'));
  41. -- add small record to the second page
  42. INSERT INTO large_tuple_test (select 3, NULL);
  43. -- now this tuple won't fit on the second page, but the insert should
  44. -- still succeed by extending the relation
  45. INSERT INTO large_tuple_test (select 4, repeat('a', 8126));
  46. DROP TABLE large_tuple_test;
  47. --
  48. -- check indirection (field/array assignment), cf bug #14265
  49. --
  50. -- these tests are aware that transformInsertStmt has 3 separate code paths
  51. --
  52. create type insert_test_type as (if1 int, if2 text[]);
  53. create table inserttest (f1 int, f2 int[],
  54. f3 insert_test_type, f4 insert_test_type[]);
  55. insert into inserttest (f2[1], f2[2]) values (1,2);
  56. insert into inserttest (f2[1], f2[2]) values (3,4), (5,6);
  57. insert into inserttest (f2[1], f2[2]) select 7,8;
  58. insert into inserttest (f2[1], f2[2]) values (1,default); -- not supported
  59. insert into inserttest (f3.if1, f3.if2) values (1,array['foo']);
  60. insert into inserttest (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}');
  61. insert into inserttest (f3.if1, f3.if2) select 3, '{baz,quux}';
  62. insert into inserttest (f3.if1, f3.if2) values (1,default); -- not supported
  63. insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar');
  64. insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux');
  65. insert into inserttest (f3.if2[1], f3.if2[2]) select 'bear', 'beer';
  66. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) values ('foo', 'bar');
  67. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) values ('foo', 'bar'), ('baz', 'quux');
  68. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) select 'bear', 'beer';
  69. select * from inserttest;
  70. -- also check reverse-listing
  71. create table inserttest2 (f1 bigint, f2 text);
  72. create rule irule1 as on insert to inserttest2 do also
  73. insert into inserttest (f3.if2[1], f3.if2[2])
  74. values (new.f1,new.f2);
  75. create rule irule2 as on insert to inserttest2 do also
  76. insert into inserttest (f4[1].if1, f4[1].if2[2])
  77. values (1,'fool'),(new.f1,new.f2);
  78. create rule irule3 as on insert to inserttest2 do also
  79. insert into inserttest (f4[1].if1, f4[1].if2[2])
  80. select new.f1, new.f2;
  81. \d+ inserttest2
  82. drop table inserttest2;
  83. drop table inserttest;
  84. drop type insert_test_type;
  85. -- direct partition inserts should check partition bound constraint
  86. create table range_parted (
  87. a text,
  88. b int
  89. ) partition by range (a, (b+0));
  90. -- no partitions, so fail
  91. insert into range_parted values ('a', 11);
  92. create table part1 partition of range_parted for values from ('a', 1) to ('a', 10);
  93. create table part2 partition of range_parted for values from ('a', 10) to ('a', 20);
  94. create table part3 partition of range_parted for values from ('b', 1) to ('b', 10);
  95. create table part4 partition of range_parted for values from ('b', 10) to ('b', 20);
  96. -- fail
  97. insert into part1 values ('a', 11);
  98. insert into part1 values ('b', 1);
  99. -- ok
  100. insert into part1 values ('a', 1);
  101. -- fail
  102. insert into part4 values ('b', 21);
  103. insert into part4 values ('a', 10);
  104. -- ok
  105. insert into part4 values ('b', 10);
  106. -- fail (partition key a has a NOT NULL constraint)
  107. insert into part1 values (null);
  108. -- fail (expression key (b+0) cannot be null either)
  109. insert into part1 values (1);
  110. create table list_parted (
  111. a text,
  112. b int
  113. ) partition by list (lower(a));
  114. create table part_aa_bb partition of list_parted FOR VALUES IN ('aa', 'bb');
  115. create table part_cc_dd partition of list_parted FOR VALUES IN ('cc', 'dd');
  116. create table part_null partition of list_parted FOR VALUES IN (null);
  117. -- fail
  118. insert into part_aa_bb values ('cc', 1);
  119. insert into part_aa_bb values ('AAa', 1);
  120. insert into part_aa_bb values (null);
  121. -- ok
  122. insert into part_cc_dd values ('cC', 1);
  123. insert into part_null values (null, 0);
  124. -- check in case of multi-level partitioned table
  125. create table part_ee_ff partition of list_parted for values in ('ee', 'ff') partition by range (b);
  126. create table part_ee_ff1 partition of part_ee_ff for values from (1) to (10);
  127. create table part_ee_ff2 partition of part_ee_ff for values from (10) to (20);
  128. -- test default partition
  129. create table part_default partition of list_parted default;
  130. -- Negative test: a row, which would fit in other partition, does not fit
  131. -- default partition, even when inserted directly
  132. insert into part_default values ('aa', 2);
  133. insert into part_default values (null, 2);
  134. -- ok
  135. insert into part_default values ('Zz', 2);
  136. -- test if default partition works as expected for multi-level partitioned
  137. -- table as well as when default partition itself is further partitioned
  138. drop table part_default;
  139. create table part_xx_yy partition of list_parted for values in ('xx', 'yy') partition by list (a);
  140. create table part_xx_yy_p1 partition of part_xx_yy for values in ('xx');
  141. create table part_xx_yy_defpart partition of part_xx_yy default;
  142. create table part_default partition of list_parted default partition by range(b);
  143. create table part_default_p1 partition of part_default for values from (20) to (30);
  144. create table part_default_p2 partition of part_default for values from (30) to (40);
  145. -- fail
  146. insert into part_ee_ff1 values ('EE', 11);
  147. insert into part_default_p2 values ('gg', 43);
  148. -- fail (even the parent's, ie, part_ee_ff's partition constraint applies)
  149. insert into part_ee_ff1 values ('cc', 1);
  150. insert into part_default values ('gg', 43);
  151. -- ok
  152. insert into part_ee_ff1 values ('ff', 1);
  153. insert into part_ee_ff2 values ('ff', 11);
  154. insert into part_default_p1 values ('cd', 25);
  155. insert into part_default_p2 values ('de', 35);
  156. insert into list_parted values ('ab', 21);
  157. insert into list_parted values ('xx', 1);
  158. insert into list_parted values ('yy', 2);
  159. select tableoid::regclass, * from list_parted;
  160. -- Check tuple routing for partitioned tables
  161. -- fail
  162. insert into range_parted values ('a', 0);
  163. -- ok
  164. insert into range_parted values ('a', 1);
  165. insert into range_parted values ('a', 10);
  166. -- fail
  167. insert into range_parted values ('a', 20);
  168. -- ok
  169. insert into range_parted values ('b', 1);
  170. insert into range_parted values ('b', 10);
  171. -- fail (partition key (b+0) is null)
  172. insert into range_parted values ('a');
  173. -- Check default partition
  174. create table part_def partition of range_parted default;
  175. -- fail
  176. insert into part_def values ('b', 10);
  177. -- ok
  178. insert into part_def values ('c', 10);
  179. insert into range_parted values (null, null);
  180. insert into range_parted values ('a', null);
  181. insert into range_parted values (null, 19);
  182. insert into range_parted values ('b', 20);
  183. select tableoid::regclass, * from range_parted;
  184. -- ok
  185. insert into list_parted values (null, 1);
  186. insert into list_parted (a) values ('aA');
  187. -- fail (partition of part_ee_ff not found in both cases)
  188. insert into list_parted values ('EE', 0);
  189. insert into part_ee_ff values ('EE', 0);
  190. -- ok
  191. insert into list_parted values ('EE', 1);
  192. insert into part_ee_ff values ('EE', 10);
  193. select tableoid::regclass, * from list_parted;
  194. -- some more tests to exercise tuple-routing with multi-level partitioning
  195. create table part_gg partition of list_parted for values in ('gg') partition by range (b);
  196. create table part_gg1 partition of part_gg for values from (minvalue) to (1);
  197. create table part_gg2 partition of part_gg for values from (1) to (10) partition by range (b);
  198. create table part_gg2_1 partition of part_gg2 for values from (1) to (5);
  199. create table part_gg2_2 partition of part_gg2 for values from (5) to (10);
  200. create table part_ee_ff3 partition of part_ee_ff for values from (20) to (30) partition by range (b);
  201. create table part_ee_ff3_1 partition of part_ee_ff3 for values from (20) to (25);
  202. create table part_ee_ff3_2 partition of part_ee_ff3 for values from (25) to (30);
  203. truncate list_parted;
  204. insert into list_parted values ('aa'), ('cc');
  205. insert into list_parted select 'Ff', s.a from generate_series(1, 29) s(a);
  206. insert into list_parted select 'gg', s.a from generate_series(1, 9) s(a);
  207. insert into list_parted (b) values (1);
  208. select tableoid::regclass::text, a, min(b) as min_b, max(b) as max_b from list_parted group by 1, 2 order by 1;
  209. -- direct partition inserts should check hash partition bound constraint
  210. -- Use hand-rolled hash functions and operator classes to get predictable
  211. -- result on different machines. The hash function for int4 simply returns
  212. -- the sum of the values passed to it and the one for text returns the length
  213. -- of the non-empty string value passed to it or 0.
  214. create or replace function part_hashint4_noop(value int4, seed int8)
  215. returns int8 as $$
  216. select value + seed;
  217. $$ language sql immutable;
  218. create operator class part_test_int4_ops
  219. for type int4
  220. using hash as
  221. operator 1 =,
  222. function 2 part_hashint4_noop(int4, int8);
  223. create or replace function part_hashtext_length(value text, seed int8)
  224. RETURNS int8 AS $$
  225. select length(coalesce(value, ''))::int8
  226. $$ language sql immutable;
  227. create operator class part_test_text_ops
  228. for type text
  229. using hash as
  230. operator 1 =,
  231. function 2 part_hashtext_length(text, int8);
  232. create table hash_parted (
  233. a int
  234. ) partition by hash (a part_test_int4_ops);
  235. create table hpart0 partition of hash_parted for values with (modulus 4, remainder 0);
  236. create table hpart1 partition of hash_parted for values with (modulus 4, remainder 1);
  237. create table hpart2 partition of hash_parted for values with (modulus 4, remainder 2);
  238. create table hpart3 partition of hash_parted for values with (modulus 4, remainder 3);
  239. insert into hash_parted values(generate_series(1,10));
  240. -- direct insert of values divisible by 4 - ok;
  241. insert into hpart0 values(12),(16);
  242. -- fail;
  243. insert into hpart0 values(11);
  244. -- 11 % 4 -> 3 remainder i.e. valid data for hpart3 partition
  245. insert into hpart3 values(11);
  246. -- view data
  247. select tableoid::regclass as part, a, a%4 as "remainder = a % 4"
  248. from hash_parted order by part;
  249. -- test \d+ output on a table which has both partitioned and unpartitioned
  250. -- partitions
  251. \d+ list_parted
  252. -- cleanup
  253. drop table range_parted, list_parted;
  254. drop table hash_parted;
  255. -- test that a default partition added as the first partition accepts any value
  256. -- including null
  257. create table list_parted (a int) partition by list (a);
  258. create table part_default partition of list_parted default;
  259. \d+ part_default
  260. insert into part_default values (null);
  261. insert into part_default values (1);
  262. insert into part_default values (-1);
  263. select tableoid::regclass, a from list_parted;
  264. -- cleanup
  265. drop table list_parted;
  266. -- more tests for certain multi-level partitioning scenarios
  267. create table mlparted (a int, b int) partition by range (a, b);
  268. create table mlparted1 (b int not null, a int not null) partition by range ((b+0));
  269. create table mlparted11 (like mlparted1);
  270. alter table mlparted11 drop a;
  271. alter table mlparted11 add a int;
  272. alter table mlparted11 drop a;
  273. alter table mlparted11 add a int not null;
  274. -- attnum for key attribute 'a' is different in mlparted, mlparted1, and mlparted11
  275. select attrelid::regclass, attname, attnum
  276. from pg_attribute
  277. where attname = 'a'
  278. and (attrelid = 'mlparted'::regclass
  279. or attrelid = 'mlparted1'::regclass
  280. or attrelid = 'mlparted11'::regclass)
  281. order by attrelid::regclass::text;
  282. alter table mlparted1 attach partition mlparted11 for values from (2) to (5);
  283. alter table mlparted attach partition mlparted1 for values from (1, 2) to (1, 10);
  284. -- check that "(1, 2)" is correctly routed to mlparted11.
  285. insert into mlparted values (1, 2);
  286. select tableoid::regclass, * from mlparted;
  287. -- check that proper message is shown after failure to route through mlparted1
  288. insert into mlparted (a, b) values (1, 5);
  289. truncate mlparted;
  290. alter table mlparted add constraint check_b check (b = 3);
  291. -- have a BR trigger modify the row such that the check_b is violated
  292. create function mlparted11_trig_fn()
  293. returns trigger AS
  294. $$
  295. begin
  296. NEW.b := 4;
  297. return NEW;
  298. end;
  299. $$
  300. language plpgsql;
  301. create trigger mlparted11_trig before insert ON mlparted11
  302. for each row execute procedure mlparted11_trig_fn();
  303. -- check that the correct row is shown when constraint check_b fails after
  304. -- "(1, 2)" is routed to mlparted11 (actually "(1, 4)" would be shown due
  305. -- to the BR trigger mlparted11_trig_fn)
  306. insert into mlparted values (1, 2);
  307. drop trigger mlparted11_trig on mlparted11;
  308. drop function mlparted11_trig_fn();
  309. -- check that inserting into an internal partition successfully results in
  310. -- checking its partition constraint before inserting into the leaf partition
  311. -- selected by tuple-routing
  312. insert into mlparted1 (a, b) values (2, 3);
  313. -- check routing error through a list partitioned table when the key is null
  314. create table lparted_nonullpart (a int, b char) partition by list (b);
  315. create table lparted_nonullpart_a partition of lparted_nonullpart for values in ('a');
  316. insert into lparted_nonullpart values (1);
  317. drop table lparted_nonullpart;
  318. -- check that RETURNING works correctly with tuple-routing
  319. alter table mlparted drop constraint check_b;
  320. create table mlparted12 partition of mlparted1 for values from (5) to (10);
  321. create table mlparted2 (b int not null, a int not null);
  322. alter table mlparted attach partition mlparted2 for values from (1, 10) to (1, 20);
  323. create table mlparted3 partition of mlparted for values from (1, 20) to (1, 30);
  324. create table mlparted4 (like mlparted);
  325. alter table mlparted4 drop a;
  326. alter table mlparted4 add a int not null;
  327. alter table mlparted attach partition mlparted4 for values from (1, 30) to (1, 40);
  328. with ins (a, b, c) as
  329. (insert into mlparted (b, a) select s.a, 1 from generate_series(2, 39) s(a) returning tableoid::regclass, *)
  330. select a, b, min(c), max(c) from ins group by a, b order by 1;
  331. alter table mlparted add c text;
  332. create table mlparted5 (c text, a int not null, b int not null) partition by list (c);
  333. create table mlparted5a (a int not null, c text, b int not null);
  334. alter table mlparted5 attach partition mlparted5a for values in ('a');
  335. alter table mlparted attach partition mlparted5 for values from (1, 40) to (1, 50);
  336. alter table mlparted add constraint check_b check (a = 1 and b < 45);
  337. insert into mlparted values (1, 45, 'a');
  338. create function mlparted5abrtrig_func() returns trigger as $$ begin new.c = 'b'; return new; end; $$ language plpgsql;
  339. create trigger mlparted5abrtrig before insert on mlparted5a for each row execute procedure mlparted5abrtrig_func();
  340. insert into mlparted5 (a, b, c) values (1, 40, 'a');
  341. drop table mlparted5;
  342. alter table mlparted drop constraint check_b;
  343. -- Check multi-level default partition
  344. create table mlparted_def partition of mlparted default partition by range(a);
  345. create table mlparted_def1 partition of mlparted_def for values from (40) to (50);
  346. create table mlparted_def2 partition of mlparted_def for values from (50) to (60);
  347. insert into mlparted values (40, 100);
  348. insert into mlparted_def1 values (42, 100);
  349. insert into mlparted_def2 values (54, 50);
  350. -- fail
  351. insert into mlparted values (70, 100);
  352. insert into mlparted_def1 values (52, 50);
  353. insert into mlparted_def2 values (34, 50);
  354. -- ok
  355. create table mlparted_defd partition of mlparted_def default;
  356. insert into mlparted values (70, 100);
  357. select tableoid::regclass, * from mlparted_def;
  358. -- Check multi-level tuple routing with attributes dropped from the
  359. -- top-most parent. First remove the last attribute.
  360. alter table mlparted add d int, add e int;
  361. alter table mlparted drop e;
  362. create table mlparted5 partition of mlparted
  363. for values from (1, 40) to (1, 50) partition by range (c);
  364. create table mlparted5_ab partition of mlparted5
  365. for values from ('a') to ('c') partition by list (c);
  366. -- This partitioned table should remain with no partitions.
  367. create table mlparted5_cd partition of mlparted5
  368. for values from ('c') to ('e') partition by list (c);
  369. create table mlparted5_a partition of mlparted5_ab for values in ('a');
  370. create table mlparted5_b (d int, b int, c text, a int);
  371. alter table mlparted5_ab attach partition mlparted5_b for values in ('b');
  372. truncate mlparted;
  373. insert into mlparted values (1, 2, 'a', 1);
  374. insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
  375. insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
  376. insert into mlparted values (1, 45, 'c', 1); -- goes to mlparted5_cd, fails
  377. insert into mlparted values (1, 45, 'f', 1); -- goes to mlparted5, fails
  378. select tableoid::regclass, * from mlparted order by a, b, c, d;
  379. alter table mlparted drop d;
  380. truncate mlparted;
  381. -- Remove the before last attribute.
  382. alter table mlparted add e int, add d int;
  383. alter table mlparted drop e;
  384. insert into mlparted values (1, 2, 'a', 1);
  385. insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
  386. insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
  387. insert into mlparted values (1, 45, 'c', 1); -- goes to mlparted5_cd, fails
  388. insert into mlparted values (1, 45, 'f', 1); -- goes to mlparted5, fails
  389. select tableoid::regclass, * from mlparted order by a, b, c, d;
  390. alter table mlparted drop d;
  391. drop table mlparted5;
  392. -- check that message shown after failure to find a partition shows the
  393. -- appropriate key description (or none) in various situations
  394. create table key_desc (a int, b int) partition by list ((a+0));
  395. create table key_desc_1 partition of key_desc for values in (1) partition by range (b);
  396. create user regress_insert_other_user;
  397. grant select (a) on key_desc_1 to regress_insert_other_user;
  398. grant insert on key_desc to regress_insert_other_user;
  399. set role regress_insert_other_user;
  400. -- no key description is shown
  401. insert into key_desc values (1, 1);
  402. reset role;
  403. grant select (b) on key_desc_1 to regress_insert_other_user;
  404. set role regress_insert_other_user;
  405. -- key description (b)=(1) is now shown
  406. insert into key_desc values (1, 1);
  407. -- key description is not shown if key contains expression
  408. insert into key_desc values (2, 1);
  409. reset role;
  410. revoke all on key_desc from regress_insert_other_user;
  411. revoke all on key_desc_1 from regress_insert_other_user;
  412. drop role regress_insert_other_user;
  413. drop table key_desc, key_desc_1;
  414. -- test minvalue/maxvalue restrictions
  415. create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
  416. create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, maxvalue);
  417. create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, minvalue);
  418. create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, minvalue);
  419. -- check multi-column range partitioning expression enforces the same
  420. -- constraint as what tuple-routing would determine it to be
  421. create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, maxvalue, maxvalue);
  422. create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10);
  423. create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, maxvalue);
  424. create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
  425. create table mcrparted4 partition of mcrparted for values from (21, minvalue, minvalue) to (30, 20, maxvalue);
  426. create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, maxvalue, maxvalue);
  427. -- null not allowed in range partition
  428. insert into mcrparted values (null, null, null);
  429. -- routed to mcrparted0
  430. insert into mcrparted values (0, 1, 1);
  431. insert into mcrparted0 values (0, 1, 1);
  432. -- routed to mcparted1
  433. insert into mcrparted values (9, 1000, 1);
  434. insert into mcrparted1 values (9, 1000, 1);
  435. insert into mcrparted values (10, 5, -1);
  436. insert into mcrparted1 values (10, 5, -1);
  437. insert into mcrparted values (2, 1, 0);
  438. insert into mcrparted1 values (2, 1, 0);
  439. -- routed to mcparted2
  440. insert into mcrparted values (10, 6, 1000);
  441. insert into mcrparted2 values (10, 6, 1000);
  442. insert into mcrparted values (10, 1000, 1000);
  443. insert into mcrparted2 values (10, 1000, 1000);
  444. -- no partition exists, nor does mcrparted3 accept it
  445. insert into mcrparted values (11, 1, -1);
  446. insert into mcrparted3 values (11, 1, -1);
  447. -- routed to mcrparted5
  448. insert into mcrparted values (30, 21, 20);
  449. insert into mcrparted5 values (30, 21, 20);
  450. insert into mcrparted4 values (30, 21, 20); -- error
  451. -- check rows
  452. select tableoid::regclass::text, * from mcrparted order by 1;
  453. -- cleanup
  454. drop table mcrparted;
  455. -- check that a BR constraint can't make partition contain violating rows
  456. create table brtrigpartcon (a int, b text) partition by list (a);
  457. create table brtrigpartcon1 partition of brtrigpartcon for values in (1);
  458. create or replace function brtrigpartcon1trigf() returns trigger as $$begin new.a := 2; return new; end$$ language plpgsql;
  459. create trigger brtrigpartcon1trig before insert on brtrigpartcon1 for each row execute procedure brtrigpartcon1trigf();
  460. insert into brtrigpartcon values (1, 'hi there');
  461. insert into brtrigpartcon1 values (1, 'hi there');
  462. -- check that the message shows the appropriate column description in a
  463. -- situation where the partitioned table is not the primary ModifyTable node
  464. create table inserttest3 (f1 text default 'foo', f2 text default 'bar', f3 int);
  465. create role regress_coldesc_role;
  466. grant insert on inserttest3 to regress_coldesc_role;
  467. grant insert on brtrigpartcon to regress_coldesc_role;
  468. revoke select on brtrigpartcon from regress_coldesc_role;
  469. set role regress_coldesc_role;
  470. with result as (insert into brtrigpartcon values (1, 'hi there') returning 1)
  471. insert into inserttest3 (f3) select * from result;
  472. reset role;
  473. -- cleanup
  474. revoke all on inserttest3 from regress_coldesc_role;
  475. revoke all on brtrigpartcon from regress_coldesc_role;
  476. drop role regress_coldesc_role;
  477. drop table inserttest3;
  478. drop table brtrigpartcon;
  479. drop function brtrigpartcon1trigf();
  480. -- check that "do nothing" BR triggers work with tuple-routing
  481. create table donothingbrtrig_test (a int, b text) partition by list (a);
  482. create table donothingbrtrig_test1 (b text, a int);
  483. create table donothingbrtrig_test2 (c text, b text, a int);
  484. alter table donothingbrtrig_test2 drop column c;
  485. create or replace function donothingbrtrig_func() returns trigger as $$begin raise notice 'b: %', new.b; return NULL; end$$ language plpgsql;
  486. create trigger donothingbrtrig1 before insert on donothingbrtrig_test1 for each row execute procedure donothingbrtrig_func();
  487. create trigger donothingbrtrig2 before insert on donothingbrtrig_test2 for each row execute procedure donothingbrtrig_func();
  488. alter table donothingbrtrig_test attach partition donothingbrtrig_test1 for values in (1);
  489. alter table donothingbrtrig_test attach partition donothingbrtrig_test2 for values in (2);
  490. insert into donothingbrtrig_test values (1, 'foo'), (2, 'bar');
  491. copy donothingbrtrig_test from stdout;
  492. 1 baz
  493. 2 qux
  494. \.
  495. select tableoid::regclass, * from donothingbrtrig_test;
  496. -- cleanup
  497. drop table donothingbrtrig_test;
  498. drop function donothingbrtrig_func();
  499. -- check multi-column range partitioning with minvalue/maxvalue constraints
  500. create table mcrparted (a text, b int) partition by range(a, b);
  501. create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
  502. create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue);
  503. create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue);
  504. create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0);
  505. create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10);
  506. create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue);
  507. create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue);
  508. create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, maxvalue);
  509. \d+ mcrparted
  510. \d+ mcrparted1_lt_b
  511. \d+ mcrparted2_b
  512. \d+ mcrparted3_c_to_common
  513. \d+ mcrparted4_common_lt_0
  514. \d+ mcrparted5_common_0_to_10
  515. \d+ mcrparted6_common_ge_10
  516. \d+ mcrparted7_gt_common_lt_d
  517. \d+ mcrparted8_ge_d
  518. insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10),
  519. ('comm', -10), ('common', -10), ('common', 0), ('common', 10),
  520. ('commons', 0), ('d', -10), ('e', 0);
  521. select tableoid::regclass, * from mcrparted order by a, b;
  522. drop table mcrparted;
  523. -- check that wholerow vars in the RETURNING list work with partitioned tables
  524. create table returningwrtest (a int) partition by list (a);
  525. create table returningwrtest1 partition of returningwrtest for values in (1);
  526. insert into returningwrtest values (1) returning returningwrtest;
  527. -- check also that the wholerow vars in RETURNING list are converted as needed
  528. alter table returningwrtest add b text;
  529. create table returningwrtest2 (b text, c int, a int);
  530. alter table returningwrtest2 drop c;
  531. alter table returningwrtest attach partition returningwrtest2 for values in (2);
  532. insert into returningwrtest values (2, 'foo') returning returningwrtest;
  533. drop table returningwrtest;