insert.out 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  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. ERROR: null value in column "col2" of relation "inserttest" violates not-null constraint
  7. DETAIL: Failing row contains (null, null, testing).
  8. insert into inserttest (col2, col3) values (3, DEFAULT);
  9. insert into inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT);
  10. insert into inserttest values (DEFAULT, 5, 'test');
  11. insert into inserttest values (DEFAULT, 7);
  12. select * from inserttest;
  13. col1 | col2 | col3
  14. ------+------+---------
  15. | 3 | testing
  16. | 5 | testing
  17. | 5 | test
  18. | 7 | testing
  19. (4 rows)
  20. --
  21. -- insert with similar expression / target_list values (all fail)
  22. --
  23. insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT);
  24. ERROR: INSERT has more target columns than expressions
  25. LINE 1: insert into inserttest (col1, col2, col3) values (DEFAULT, D...
  26. ^
  27. insert into inserttest (col1, col2, col3) values (1, 2);
  28. ERROR: INSERT has more target columns than expressions
  29. LINE 1: insert into inserttest (col1, col2, col3) values (1, 2);
  30. ^
  31. insert into inserttest (col1) values (1, 2);
  32. ERROR: INSERT has more expressions than target columns
  33. LINE 1: insert into inserttest (col1) values (1, 2);
  34. ^
  35. insert into inserttest (col1) values (DEFAULT, DEFAULT);
  36. ERROR: INSERT has more expressions than target columns
  37. LINE 1: insert into inserttest (col1) values (DEFAULT, DEFAULT);
  38. ^
  39. select * from inserttest;
  40. col1 | col2 | col3
  41. ------+------+---------
  42. | 3 | testing
  43. | 5 | testing
  44. | 5 | test
  45. | 7 | testing
  46. (4 rows)
  47. --
  48. -- VALUES test
  49. --
  50. insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
  51. ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
  52. select * from inserttest;
  53. col1 | col2 | col3
  54. ------+------+-----------------
  55. | 3 | testing
  56. | 5 | testing
  57. | 5 | test
  58. | 7 | testing
  59. 10 | 20 | 40
  60. -1 | 2 | testing
  61. 2 | 3 | values are fun!
  62. (7 rows)
  63. --
  64. -- TOASTed value test
  65. --
  66. insert into inserttest values(30, 50, repeat('x', 10000));
  67. select col1, col2, char_length(col3) from inserttest;
  68. col1 | col2 | char_length
  69. ------+------+-------------
  70. | 3 | 7
  71. | 5 | 7
  72. | 5 | 4
  73. | 7 | 7
  74. 10 | 20 | 2
  75. -1 | 2 | 7
  76. 2 | 3 | 15
  77. 30 | 50 | 10000
  78. (8 rows)
  79. drop table inserttest;
  80. --
  81. -- tuple larger than fillfactor
  82. --
  83. CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10);
  84. ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain;
  85. -- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize)
  86. INSERT INTO large_tuple_test (select 1, NULL);
  87. -- should still fit on the page
  88. INSERT INTO large_tuple_test (select 2, repeat('a', 1000));
  89. SELECT pg_size_pretty(pg_relation_size('large_tuple_test'::regclass, 'main'));
  90. pg_size_pretty
  91. ----------------
  92. 8192 bytes
  93. (1 row)
  94. -- add small record to the second page
  95. INSERT INTO large_tuple_test (select 3, NULL);
  96. -- now this tuple won't fit on the second page, but the insert should
  97. -- still succeed by extending the relation
  98. INSERT INTO large_tuple_test (select 4, repeat('a', 8126));
  99. DROP TABLE large_tuple_test;
  100. --
  101. -- check indirection (field/array assignment), cf bug #14265
  102. --
  103. -- these tests are aware that transformInsertStmt has 3 separate code paths
  104. --
  105. create type insert_test_type as (if1 int, if2 text[]);
  106. create table inserttest (f1 int, f2 int[],
  107. f3 insert_test_type, f4 insert_test_type[]);
  108. insert into inserttest (f2[1], f2[2]) values (1,2);
  109. insert into inserttest (f2[1], f2[2]) values (3,4), (5,6);
  110. insert into inserttest (f2[1], f2[2]) select 7,8;
  111. insert into inserttest (f2[1], f2[2]) values (1,default); -- not supported
  112. ERROR: cannot set an array element to DEFAULT
  113. LINE 1: insert into inserttest (f2[1], f2[2]) values (1,default);
  114. ^
  115. insert into inserttest (f3.if1, f3.if2) values (1,array['foo']);
  116. insert into inserttest (f3.if1, f3.if2) values (1,'{foo}'), (2,'{bar}');
  117. insert into inserttest (f3.if1, f3.if2) select 3, '{baz,quux}';
  118. insert into inserttest (f3.if1, f3.if2) values (1,default); -- not supported
  119. ERROR: cannot set a subfield to DEFAULT
  120. LINE 1: insert into inserttest (f3.if1, f3.if2) values (1,default);
  121. ^
  122. insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar');
  123. insert into inserttest (f3.if2[1], f3.if2[2]) values ('foo', 'bar'), ('baz', 'quux');
  124. insert into inserttest (f3.if2[1], f3.if2[2]) select 'bear', 'beer';
  125. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) values ('foo', 'bar');
  126. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) values ('foo', 'bar'), ('baz', 'quux');
  127. insert into inserttest (f4[1].if2[1], f4[1].if2[2]) select 'bear', 'beer';
  128. select * from inserttest;
  129. f1 | f2 | f3 | f4
  130. ----+-------+------------------+------------------------
  131. | {1,2} | |
  132. | {3,4} | |
  133. | {5,6} | |
  134. | {7,8} | |
  135. | | (1,{foo}) |
  136. | | (1,{foo}) |
  137. | | (2,{bar}) |
  138. | | (3,"{baz,quux}") |
  139. | | (,"{foo,bar}") |
  140. | | (,"{foo,bar}") |
  141. | | (,"{baz,quux}") |
  142. | | (,"{bear,beer}") |
  143. | | | {"(,\"{foo,bar}\")"}
  144. | | | {"(,\"{foo,bar}\")"}
  145. | | | {"(,\"{baz,quux}\")"}
  146. | | | {"(,\"{bear,beer}\")"}
  147. (16 rows)
  148. -- also check reverse-listing
  149. create table inserttest2 (f1 bigint, f2 text);
  150. create rule irule1 as on insert to inserttest2 do also
  151. insert into inserttest (f3.if2[1], f3.if2[2])
  152. values (new.f1,new.f2);
  153. create rule irule2 as on insert to inserttest2 do also
  154. insert into inserttest (f4[1].if1, f4[1].if2[2])
  155. values (1,'fool'),(new.f1,new.f2);
  156. create rule irule3 as on insert to inserttest2 do also
  157. insert into inserttest (f4[1].if1, f4[1].if2[2])
  158. select new.f1, new.f2;
  159. \d+ inserttest2
  160. Table "public.inserttest2"
  161. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  162. --------+--------+-----------+----------+---------+----------+--------------+-------------
  163. f1 | bigint | | | | plain | |
  164. f2 | text | | | | extended | |
  165. Rules:
  166. irule1 AS
  167. ON INSERT TO inserttest2 DO INSERT INTO inserttest (f3.if2[1], f3.if2[2])
  168. VALUES (new.f1, new.f2)
  169. irule2 AS
  170. ON INSERT TO inserttest2 DO INSERT INTO inserttest (f4[1].if1, f4[1].if2[2]) VALUES (1,'fool'::text), (new.f1,new.f2)
  171. irule3 AS
  172. ON INSERT TO inserttest2 DO INSERT INTO inserttest (f4[1].if1, f4[1].if2[2]) SELECT new.f1,
  173. new.f2
  174. drop table inserttest2;
  175. drop table inserttest;
  176. drop type insert_test_type;
  177. -- direct partition inserts should check partition bound constraint
  178. create table range_parted (
  179. a text,
  180. b int
  181. ) partition by range (a, (b+0));
  182. -- no partitions, so fail
  183. insert into range_parted values ('a', 11);
  184. ERROR: no partition of relation "range_parted" found for row
  185. DETAIL: Partition key of the failing row contains (a, (b + 0)) = (a, 11).
  186. create table part1 partition of range_parted for values from ('a', 1) to ('a', 10);
  187. create table part2 partition of range_parted for values from ('a', 10) to ('a', 20);
  188. create table part3 partition of range_parted for values from ('b', 1) to ('b', 10);
  189. create table part4 partition of range_parted for values from ('b', 10) to ('b', 20);
  190. -- fail
  191. insert into part1 values ('a', 11);
  192. ERROR: new row for relation "part1" violates partition constraint
  193. DETAIL: Failing row contains (a, 11).
  194. insert into part1 values ('b', 1);
  195. ERROR: new row for relation "part1" violates partition constraint
  196. DETAIL: Failing row contains (b, 1).
  197. -- ok
  198. insert into part1 values ('a', 1);
  199. -- fail
  200. insert into part4 values ('b', 21);
  201. ERROR: new row for relation "part4" violates partition constraint
  202. DETAIL: Failing row contains (b, 21).
  203. insert into part4 values ('a', 10);
  204. ERROR: new row for relation "part4" violates partition constraint
  205. DETAIL: Failing row contains (a, 10).
  206. -- ok
  207. insert into part4 values ('b', 10);
  208. -- fail (partition key a has a NOT NULL constraint)
  209. insert into part1 values (null);
  210. ERROR: new row for relation "part1" violates partition constraint
  211. DETAIL: Failing row contains (null, null).
  212. -- fail (expression key (b+0) cannot be null either)
  213. insert into part1 values (1);
  214. ERROR: new row for relation "part1" violates partition constraint
  215. DETAIL: Failing row contains (1, null).
  216. create table list_parted (
  217. a text,
  218. b int
  219. ) partition by list (lower(a));
  220. create table part_aa_bb partition of list_parted FOR VALUES IN ('aa', 'bb');
  221. create table part_cc_dd partition of list_parted FOR VALUES IN ('cc', 'dd');
  222. create table part_null partition of list_parted FOR VALUES IN (null);
  223. -- fail
  224. insert into part_aa_bb values ('cc', 1);
  225. ERROR: new row for relation "part_aa_bb" violates partition constraint
  226. DETAIL: Failing row contains (cc, 1).
  227. insert into part_aa_bb values ('AAa', 1);
  228. ERROR: new row for relation "part_aa_bb" violates partition constraint
  229. DETAIL: Failing row contains (AAa, 1).
  230. insert into part_aa_bb values (null);
  231. ERROR: new row for relation "part_aa_bb" violates partition constraint
  232. DETAIL: Failing row contains (null, null).
  233. -- ok
  234. insert into part_cc_dd values ('cC', 1);
  235. insert into part_null values (null, 0);
  236. -- check in case of multi-level partitioned table
  237. create table part_ee_ff partition of list_parted for values in ('ee', 'ff') partition by range (b);
  238. create table part_ee_ff1 partition of part_ee_ff for values from (1) to (10);
  239. create table part_ee_ff2 partition of part_ee_ff for values from (10) to (20);
  240. -- test default partition
  241. create table part_default partition of list_parted default;
  242. -- Negative test: a row, which would fit in other partition, does not fit
  243. -- default partition, even when inserted directly
  244. insert into part_default values ('aa', 2);
  245. ERROR: new row for relation "part_default" violates partition constraint
  246. DETAIL: Failing row contains (aa, 2).
  247. insert into part_default values (null, 2);
  248. ERROR: new row for relation "part_default" violates partition constraint
  249. DETAIL: Failing row contains (null, 2).
  250. -- ok
  251. insert into part_default values ('Zz', 2);
  252. -- test if default partition works as expected for multi-level partitioned
  253. -- table as well as when default partition itself is further partitioned
  254. drop table part_default;
  255. create table part_xx_yy partition of list_parted for values in ('xx', 'yy') partition by list (a);
  256. create table part_xx_yy_p1 partition of part_xx_yy for values in ('xx');
  257. create table part_xx_yy_defpart partition of part_xx_yy default;
  258. create table part_default partition of list_parted default partition by range(b);
  259. create table part_default_p1 partition of part_default for values from (20) to (30);
  260. create table part_default_p2 partition of part_default for values from (30) to (40);
  261. -- fail
  262. insert into part_ee_ff1 values ('EE', 11);
  263. ERROR: new row for relation "part_ee_ff1" violates partition constraint
  264. DETAIL: Failing row contains (EE, 11).
  265. insert into part_default_p2 values ('gg', 43);
  266. ERROR: new row for relation "part_default_p2" violates partition constraint
  267. DETAIL: Failing row contains (gg, 43).
  268. -- fail (even the parent's, ie, part_ee_ff's partition constraint applies)
  269. insert into part_ee_ff1 values ('cc', 1);
  270. ERROR: new row for relation "part_ee_ff1" violates partition constraint
  271. DETAIL: Failing row contains (cc, 1).
  272. insert into part_default values ('gg', 43);
  273. ERROR: no partition of relation "part_default" found for row
  274. DETAIL: Partition key of the failing row contains (b) = (43).
  275. -- ok
  276. insert into part_ee_ff1 values ('ff', 1);
  277. insert into part_ee_ff2 values ('ff', 11);
  278. insert into part_default_p1 values ('cd', 25);
  279. insert into part_default_p2 values ('de', 35);
  280. insert into list_parted values ('ab', 21);
  281. insert into list_parted values ('xx', 1);
  282. insert into list_parted values ('yy', 2);
  283. select tableoid::regclass, * from list_parted;
  284. tableoid | a | b
  285. --------------------+----+----
  286. part_cc_dd | cC | 1
  287. part_ee_ff1 | ff | 1
  288. part_ee_ff2 | ff | 11
  289. part_xx_yy_p1 | xx | 1
  290. part_xx_yy_defpart | yy | 2
  291. part_null | | 0
  292. part_default_p1 | cd | 25
  293. part_default_p1 | ab | 21
  294. part_default_p2 | de | 35
  295. (9 rows)
  296. -- Check tuple routing for partitioned tables
  297. -- fail
  298. insert into range_parted values ('a', 0);
  299. ERROR: no partition of relation "range_parted" found for row
  300. DETAIL: Partition key of the failing row contains (a, (b + 0)) = (a, 0).
  301. -- ok
  302. insert into range_parted values ('a', 1);
  303. insert into range_parted values ('a', 10);
  304. -- fail
  305. insert into range_parted values ('a', 20);
  306. ERROR: no partition of relation "range_parted" found for row
  307. DETAIL: Partition key of the failing row contains (a, (b + 0)) = (a, 20).
  308. -- ok
  309. insert into range_parted values ('b', 1);
  310. insert into range_parted values ('b', 10);
  311. -- fail (partition key (b+0) is null)
  312. insert into range_parted values ('a');
  313. ERROR: no partition of relation "range_parted" found for row
  314. DETAIL: Partition key of the failing row contains (a, (b + 0)) = (a, null).
  315. -- Check default partition
  316. create table part_def partition of range_parted default;
  317. -- fail
  318. insert into part_def values ('b', 10);
  319. ERROR: new row for relation "part_def" violates partition constraint
  320. DETAIL: Failing row contains (b, 10).
  321. -- ok
  322. insert into part_def values ('c', 10);
  323. insert into range_parted values (null, null);
  324. insert into range_parted values ('a', null);
  325. insert into range_parted values (null, 19);
  326. insert into range_parted values ('b', 20);
  327. select tableoid::regclass, * from range_parted;
  328. tableoid | a | b
  329. ----------+---+----
  330. part1 | a | 1
  331. part1 | a | 1
  332. part2 | a | 10
  333. part3 | b | 1
  334. part4 | b | 10
  335. part4 | b | 10
  336. part_def | c | 10
  337. part_def | |
  338. part_def | a |
  339. part_def | | 19
  340. part_def | b | 20
  341. (11 rows)
  342. -- ok
  343. insert into list_parted values (null, 1);
  344. insert into list_parted (a) values ('aA');
  345. -- fail (partition of part_ee_ff not found in both cases)
  346. insert into list_parted values ('EE', 0);
  347. ERROR: no partition of relation "part_ee_ff" found for row
  348. DETAIL: Partition key of the failing row contains (b) = (0).
  349. insert into part_ee_ff values ('EE', 0);
  350. ERROR: no partition of relation "part_ee_ff" found for row
  351. DETAIL: Partition key of the failing row contains (b) = (0).
  352. -- ok
  353. insert into list_parted values ('EE', 1);
  354. insert into part_ee_ff values ('EE', 10);
  355. select tableoid::regclass, * from list_parted;
  356. tableoid | a | b
  357. --------------------+----+----
  358. part_aa_bb | aA |
  359. part_cc_dd | cC | 1
  360. part_ee_ff1 | ff | 1
  361. part_ee_ff1 | EE | 1
  362. part_ee_ff2 | ff | 11
  363. part_ee_ff2 | EE | 10
  364. part_xx_yy_p1 | xx | 1
  365. part_xx_yy_defpart | yy | 2
  366. part_null | | 0
  367. part_null | | 1
  368. part_default_p1 | cd | 25
  369. part_default_p1 | ab | 21
  370. part_default_p2 | de | 35
  371. (13 rows)
  372. -- some more tests to exercise tuple-routing with multi-level partitioning
  373. create table part_gg partition of list_parted for values in ('gg') partition by range (b);
  374. create table part_gg1 partition of part_gg for values from (minvalue) to (1);
  375. create table part_gg2 partition of part_gg for values from (1) to (10) partition by range (b);
  376. create table part_gg2_1 partition of part_gg2 for values from (1) to (5);
  377. create table part_gg2_2 partition of part_gg2 for values from (5) to (10);
  378. create table part_ee_ff3 partition of part_ee_ff for values from (20) to (30) partition by range (b);
  379. create table part_ee_ff3_1 partition of part_ee_ff3 for values from (20) to (25);
  380. create table part_ee_ff3_2 partition of part_ee_ff3 for values from (25) to (30);
  381. truncate list_parted;
  382. insert into list_parted values ('aa'), ('cc');
  383. insert into list_parted select 'Ff', s.a from generate_series(1, 29) s(a);
  384. insert into list_parted select 'gg', s.a from generate_series(1, 9) s(a);
  385. insert into list_parted (b) values (1);
  386. 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;
  387. tableoid | a | min_b | max_b
  388. ---------------+----+-------+-------
  389. part_aa_bb | aa | |
  390. part_cc_dd | cc | |
  391. part_ee_ff1 | Ff | 1 | 9
  392. part_ee_ff2 | Ff | 10 | 19
  393. part_ee_ff3_1 | Ff | 20 | 24
  394. part_ee_ff3_2 | Ff | 25 | 29
  395. part_gg2_1 | gg | 1 | 4
  396. part_gg2_2 | gg | 5 | 9
  397. part_null | | 1 | 1
  398. (9 rows)
  399. -- direct partition inserts should check hash partition bound constraint
  400. -- Use hand-rolled hash functions and operator classes to get predictable
  401. -- result on different machines. The hash function for int4 simply returns
  402. -- the sum of the values passed to it and the one for text returns the length
  403. -- of the non-empty string value passed to it or 0.
  404. create or replace function part_hashint4_noop(value int4, seed int8)
  405. returns int8 as $$
  406. select value + seed;
  407. $$ language sql immutable;
  408. create operator class part_test_int4_ops
  409. for type int4
  410. using hash as
  411. operator 1 =,
  412. function 2 part_hashint4_noop(int4, int8);
  413. create or replace function part_hashtext_length(value text, seed int8)
  414. RETURNS int8 AS $$
  415. select length(coalesce(value, ''))::int8
  416. $$ language sql immutable;
  417. create operator class part_test_text_ops
  418. for type text
  419. using hash as
  420. operator 1 =,
  421. function 2 part_hashtext_length(text, int8);
  422. create table hash_parted (
  423. a int
  424. ) partition by hash (a part_test_int4_ops);
  425. create table hpart0 partition of hash_parted for values with (modulus 4, remainder 0);
  426. create table hpart1 partition of hash_parted for values with (modulus 4, remainder 1);
  427. create table hpart2 partition of hash_parted for values with (modulus 4, remainder 2);
  428. create table hpart3 partition of hash_parted for values with (modulus 4, remainder 3);
  429. insert into hash_parted values(generate_series(1,10));
  430. -- direct insert of values divisible by 4 - ok;
  431. insert into hpart0 values(12),(16);
  432. -- fail;
  433. insert into hpart0 values(11);
  434. ERROR: new row for relation "hpart0" violates partition constraint
  435. DETAIL: Failing row contains (11).
  436. -- 11 % 4 -> 3 remainder i.e. valid data for hpart3 partition
  437. insert into hpart3 values(11);
  438. -- view data
  439. select tableoid::regclass as part, a, a%4 as "remainder = a % 4"
  440. from hash_parted order by part;
  441. part | a | remainder = a % 4
  442. --------+----+-------------------
  443. hpart0 | 4 | 0
  444. hpart0 | 8 | 0
  445. hpart0 | 12 | 0
  446. hpart0 | 16 | 0
  447. hpart1 | 1 | 1
  448. hpart1 | 5 | 1
  449. hpart1 | 9 | 1
  450. hpart2 | 2 | 2
  451. hpart2 | 6 | 2
  452. hpart2 | 10 | 2
  453. hpart3 | 3 | 3
  454. hpart3 | 7 | 3
  455. hpart3 | 11 | 3
  456. (13 rows)
  457. -- test \d+ output on a table which has both partitioned and unpartitioned
  458. -- partitions
  459. \d+ list_parted
  460. Partitioned table "public.list_parted"
  461. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  462. --------+---------+-----------+----------+---------+----------+--------------+-------------
  463. a | text | | | | extended | |
  464. b | integer | | | | plain | |
  465. Partition key: LIST (lower(a))
  466. Partitions: part_aa_bb FOR VALUES IN ('aa', 'bb'),
  467. part_cc_dd FOR VALUES IN ('cc', 'dd'),
  468. part_ee_ff FOR VALUES IN ('ee', 'ff'), PARTITIONED,
  469. part_gg FOR VALUES IN ('gg'), PARTITIONED,
  470. part_null FOR VALUES IN (NULL),
  471. part_xx_yy FOR VALUES IN ('xx', 'yy'), PARTITIONED,
  472. part_default DEFAULT, PARTITIONED
  473. -- cleanup
  474. drop table range_parted, list_parted;
  475. drop table hash_parted;
  476. -- test that a default partition added as the first partition accepts any value
  477. -- including null
  478. create table list_parted (a int) partition by list (a);
  479. create table part_default partition of list_parted default;
  480. \d+ part_default
  481. Table "public.part_default"
  482. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  483. --------+---------+-----------+----------+---------+---------+--------------+-------------
  484. a | integer | | | | plain | |
  485. Partition of: list_parted DEFAULT
  486. No partition constraint
  487. insert into part_default values (null);
  488. insert into part_default values (1);
  489. insert into part_default values (-1);
  490. select tableoid::regclass, a from list_parted;
  491. tableoid | a
  492. --------------+----
  493. part_default |
  494. part_default | 1
  495. part_default | -1
  496. (3 rows)
  497. -- cleanup
  498. drop table list_parted;
  499. -- more tests for certain multi-level partitioning scenarios
  500. create table mlparted (a int, b int) partition by range (a, b);
  501. create table mlparted1 (b int not null, a int not null) partition by range ((b+0));
  502. create table mlparted11 (like mlparted1);
  503. alter table mlparted11 drop a;
  504. alter table mlparted11 add a int;
  505. alter table mlparted11 drop a;
  506. alter table mlparted11 add a int not null;
  507. -- attnum for key attribute 'a' is different in mlparted, mlparted1, and mlparted11
  508. select attrelid::regclass, attname, attnum
  509. from pg_attribute
  510. where attname = 'a'
  511. and (attrelid = 'mlparted'::regclass
  512. or attrelid = 'mlparted1'::regclass
  513. or attrelid = 'mlparted11'::regclass)
  514. order by attrelid::regclass::text;
  515. attrelid | attname | attnum
  516. ------------+---------+--------
  517. mlparted | a | 1
  518. mlparted1 | a | 2
  519. mlparted11 | a | 4
  520. (3 rows)
  521. alter table mlparted1 attach partition mlparted11 for values from (2) to (5);
  522. alter table mlparted attach partition mlparted1 for values from (1, 2) to (1, 10);
  523. -- check that "(1, 2)" is correctly routed to mlparted11.
  524. insert into mlparted values (1, 2);
  525. select tableoid::regclass, * from mlparted;
  526. tableoid | a | b
  527. ------------+---+---
  528. mlparted11 | 1 | 2
  529. (1 row)
  530. -- check that proper message is shown after failure to route through mlparted1
  531. insert into mlparted (a, b) values (1, 5);
  532. ERROR: no partition of relation "mlparted1" found for row
  533. DETAIL: Partition key of the failing row contains ((b + 0)) = (5).
  534. truncate mlparted;
  535. alter table mlparted add constraint check_b check (b = 3);
  536. -- have a BR trigger modify the row such that the check_b is violated
  537. create function mlparted11_trig_fn()
  538. returns trigger AS
  539. $$
  540. begin
  541. NEW.b := 4;
  542. return NEW;
  543. end;
  544. $$
  545. language plpgsql;
  546. create trigger mlparted11_trig before insert ON mlparted11
  547. for each row execute procedure mlparted11_trig_fn();
  548. -- check that the correct row is shown when constraint check_b fails after
  549. -- "(1, 2)" is routed to mlparted11 (actually "(1, 4)" would be shown due
  550. -- to the BR trigger mlparted11_trig_fn)
  551. insert into mlparted values (1, 2);
  552. ERROR: new row for relation "mlparted11" violates check constraint "check_b"
  553. DETAIL: Failing row contains (1, 4).
  554. drop trigger mlparted11_trig on mlparted11;
  555. drop function mlparted11_trig_fn();
  556. -- check that inserting into an internal partition successfully results in
  557. -- checking its partition constraint before inserting into the leaf partition
  558. -- selected by tuple-routing
  559. insert into mlparted1 (a, b) values (2, 3);
  560. ERROR: new row for relation "mlparted1" violates partition constraint
  561. DETAIL: Failing row contains (3, 2).
  562. -- check routing error through a list partitioned table when the key is null
  563. create table lparted_nonullpart (a int, b char) partition by list (b);
  564. create table lparted_nonullpart_a partition of lparted_nonullpart for values in ('a');
  565. insert into lparted_nonullpart values (1);
  566. ERROR: no partition of relation "lparted_nonullpart" found for row
  567. DETAIL: Partition key of the failing row contains (b) = (null).
  568. drop table lparted_nonullpart;
  569. -- check that RETURNING works correctly with tuple-routing
  570. alter table mlparted drop constraint check_b;
  571. create table mlparted12 partition of mlparted1 for values from (5) to (10);
  572. create table mlparted2 (b int not null, a int not null);
  573. alter table mlparted attach partition mlparted2 for values from (1, 10) to (1, 20);
  574. create table mlparted3 partition of mlparted for values from (1, 20) to (1, 30);
  575. create table mlparted4 (like mlparted);
  576. alter table mlparted4 drop a;
  577. alter table mlparted4 add a int not null;
  578. alter table mlparted attach partition mlparted4 for values from (1, 30) to (1, 40);
  579. with ins (a, b, c) as
  580. (insert into mlparted (b, a) select s.a, 1 from generate_series(2, 39) s(a) returning tableoid::regclass, *)
  581. select a, b, min(c), max(c) from ins group by a, b order by 1;
  582. a | b | min | max
  583. ------------+---+-----+-----
  584. mlparted11 | 1 | 2 | 4
  585. mlparted12 | 1 | 5 | 9
  586. mlparted2 | 1 | 10 | 19
  587. mlparted3 | 1 | 20 | 29
  588. mlparted4 | 1 | 30 | 39
  589. (5 rows)
  590. alter table mlparted add c text;
  591. create table mlparted5 (c text, a int not null, b int not null) partition by list (c);
  592. create table mlparted5a (a int not null, c text, b int not null);
  593. alter table mlparted5 attach partition mlparted5a for values in ('a');
  594. alter table mlparted attach partition mlparted5 for values from (1, 40) to (1, 50);
  595. alter table mlparted add constraint check_b check (a = 1 and b < 45);
  596. insert into mlparted values (1, 45, 'a');
  597. ERROR: new row for relation "mlparted5a" violates check constraint "check_b"
  598. DETAIL: Failing row contains (1, 45, a).
  599. create function mlparted5abrtrig_func() returns trigger as $$ begin new.c = 'b'; return new; end; $$ language plpgsql;
  600. create trigger mlparted5abrtrig before insert on mlparted5a for each row execute procedure mlparted5abrtrig_func();
  601. insert into mlparted5 (a, b, c) values (1, 40, 'a');
  602. ERROR: new row for relation "mlparted5a" violates partition constraint
  603. DETAIL: Failing row contains (b, 1, 40).
  604. drop table mlparted5;
  605. alter table mlparted drop constraint check_b;
  606. -- Check multi-level default partition
  607. create table mlparted_def partition of mlparted default partition by range(a);
  608. create table mlparted_def1 partition of mlparted_def for values from (40) to (50);
  609. create table mlparted_def2 partition of mlparted_def for values from (50) to (60);
  610. insert into mlparted values (40, 100);
  611. insert into mlparted_def1 values (42, 100);
  612. insert into mlparted_def2 values (54, 50);
  613. -- fail
  614. insert into mlparted values (70, 100);
  615. ERROR: no partition of relation "mlparted_def" found for row
  616. DETAIL: Partition key of the failing row contains (a) = (70).
  617. insert into mlparted_def1 values (52, 50);
  618. ERROR: new row for relation "mlparted_def1" violates partition constraint
  619. DETAIL: Failing row contains (52, 50, null).
  620. insert into mlparted_def2 values (34, 50);
  621. ERROR: new row for relation "mlparted_def2" violates partition constraint
  622. DETAIL: Failing row contains (34, 50, null).
  623. -- ok
  624. create table mlparted_defd partition of mlparted_def default;
  625. insert into mlparted values (70, 100);
  626. select tableoid::regclass, * from mlparted_def;
  627. tableoid | a | b | c
  628. ---------------+----+-----+---
  629. mlparted_def1 | 40 | 100 |
  630. mlparted_def1 | 42 | 100 |
  631. mlparted_def2 | 54 | 50 |
  632. mlparted_defd | 70 | 100 |
  633. (4 rows)
  634. -- Check multi-level tuple routing with attributes dropped from the
  635. -- top-most parent. First remove the last attribute.
  636. alter table mlparted add d int, add e int;
  637. alter table mlparted drop e;
  638. create table mlparted5 partition of mlparted
  639. for values from (1, 40) to (1, 50) partition by range (c);
  640. create table mlparted5_ab partition of mlparted5
  641. for values from ('a') to ('c') partition by list (c);
  642. -- This partitioned table should remain with no partitions.
  643. create table mlparted5_cd partition of mlparted5
  644. for values from ('c') to ('e') partition by list (c);
  645. create table mlparted5_a partition of mlparted5_ab for values in ('a');
  646. create table mlparted5_b (d int, b int, c text, a int);
  647. alter table mlparted5_ab attach partition mlparted5_b for values in ('b');
  648. truncate mlparted;
  649. insert into mlparted values (1, 2, 'a', 1);
  650. insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
  651. insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
  652. insert into mlparted values (1, 45, 'c', 1); -- goes to mlparted5_cd, fails
  653. ERROR: no partition of relation "mlparted5_cd" found for row
  654. DETAIL: Partition key of the failing row contains (c) = (c).
  655. insert into mlparted values (1, 45, 'f', 1); -- goes to mlparted5, fails
  656. ERROR: no partition of relation "mlparted5" found for row
  657. DETAIL: Partition key of the failing row contains (c) = (f).
  658. select tableoid::regclass, * from mlparted order by a, b, c, d;
  659. tableoid | a | b | c | d
  660. -------------+---+----+---+---
  661. mlparted11 | 1 | 2 | a | 1
  662. mlparted5_a | 1 | 40 | a | 1
  663. mlparted5_b | 1 | 45 | b | 1
  664. (3 rows)
  665. alter table mlparted drop d;
  666. truncate mlparted;
  667. -- Remove the before last attribute.
  668. alter table mlparted add e int, add d int;
  669. alter table mlparted drop e;
  670. insert into mlparted values (1, 2, 'a', 1);
  671. insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
  672. insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
  673. insert into mlparted values (1, 45, 'c', 1); -- goes to mlparted5_cd, fails
  674. ERROR: no partition of relation "mlparted5_cd" found for row
  675. DETAIL: Partition key of the failing row contains (c) = (c).
  676. insert into mlparted values (1, 45, 'f', 1); -- goes to mlparted5, fails
  677. ERROR: no partition of relation "mlparted5" found for row
  678. DETAIL: Partition key of the failing row contains (c) = (f).
  679. select tableoid::regclass, * from mlparted order by a, b, c, d;
  680. tableoid | a | b | c | d
  681. -------------+---+----+---+---
  682. mlparted11 | 1 | 2 | a | 1
  683. mlparted5_a | 1 | 40 | a | 1
  684. mlparted5_b | 1 | 45 | b | 1
  685. (3 rows)
  686. alter table mlparted drop d;
  687. drop table mlparted5;
  688. -- check that message shown after failure to find a partition shows the
  689. -- appropriate key description (or none) in various situations
  690. create table key_desc (a int, b int) partition by list ((a+0));
  691. create table key_desc_1 partition of key_desc for values in (1) partition by range (b);
  692. create user regress_insert_other_user;
  693. grant select (a) on key_desc_1 to regress_insert_other_user;
  694. grant insert on key_desc to regress_insert_other_user;
  695. set role regress_insert_other_user;
  696. -- no key description is shown
  697. insert into key_desc values (1, 1);
  698. ERROR: no partition of relation "key_desc_1" found for row
  699. reset role;
  700. grant select (b) on key_desc_1 to regress_insert_other_user;
  701. set role regress_insert_other_user;
  702. -- key description (b)=(1) is now shown
  703. insert into key_desc values (1, 1);
  704. ERROR: no partition of relation "key_desc_1" found for row
  705. DETAIL: Partition key of the failing row contains (b) = (1).
  706. -- key description is not shown if key contains expression
  707. insert into key_desc values (2, 1);
  708. ERROR: no partition of relation "key_desc" found for row
  709. reset role;
  710. revoke all on key_desc from regress_insert_other_user;
  711. revoke all on key_desc_1 from regress_insert_other_user;
  712. drop role regress_insert_other_user;
  713. drop table key_desc, key_desc_1;
  714. -- test minvalue/maxvalue restrictions
  715. create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
  716. create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, maxvalue);
  717. ERROR: every bound following MINVALUE must also be MINVALUE
  718. LINE 1: ...partition of mcrparted for values from (minvalue, 0, 0) to (...
  719. ^
  720. create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, minvalue);
  721. ERROR: every bound following MAXVALUE must also be MAXVALUE
  722. LINE 1: ...r values from (10, 6, minvalue) to (10, maxvalue, minvalue);
  723. ^
  724. create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, minvalue);
  725. ERROR: every bound following MINVALUE must also be MINVALUE
  726. LINE 1: ...ition of mcrparted for values from (21, minvalue, 0) to (30,...
  727. ^
  728. -- check multi-column range partitioning expression enforces the same
  729. -- constraint as what tuple-routing would determine it to be
  730. create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, maxvalue, maxvalue);
  731. create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10);
  732. create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, maxvalue);
  733. create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
  734. create table mcrparted4 partition of mcrparted for values from (21, minvalue, minvalue) to (30, 20, maxvalue);
  735. create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, maxvalue, maxvalue);
  736. -- null not allowed in range partition
  737. insert into mcrparted values (null, null, null);
  738. ERROR: no partition of relation "mcrparted" found for row
  739. DETAIL: Partition key of the failing row contains (a, abs(b), c) = (null, null, null).
  740. -- routed to mcrparted0
  741. insert into mcrparted values (0, 1, 1);
  742. insert into mcrparted0 values (0, 1, 1);
  743. -- routed to mcparted1
  744. insert into mcrparted values (9, 1000, 1);
  745. insert into mcrparted1 values (9, 1000, 1);
  746. insert into mcrparted values (10, 5, -1);
  747. insert into mcrparted1 values (10, 5, -1);
  748. insert into mcrparted values (2, 1, 0);
  749. insert into mcrparted1 values (2, 1, 0);
  750. -- routed to mcparted2
  751. insert into mcrparted values (10, 6, 1000);
  752. insert into mcrparted2 values (10, 6, 1000);
  753. insert into mcrparted values (10, 1000, 1000);
  754. insert into mcrparted2 values (10, 1000, 1000);
  755. -- no partition exists, nor does mcrparted3 accept it
  756. insert into mcrparted values (11, 1, -1);
  757. ERROR: no partition of relation "mcrparted" found for row
  758. DETAIL: Partition key of the failing row contains (a, abs(b), c) = (11, 1, -1).
  759. insert into mcrparted3 values (11, 1, -1);
  760. ERROR: new row for relation "mcrparted3" violates partition constraint
  761. DETAIL: Failing row contains (11, 1, -1).
  762. -- routed to mcrparted5
  763. insert into mcrparted values (30, 21, 20);
  764. insert into mcrparted5 values (30, 21, 20);
  765. insert into mcrparted4 values (30, 21, 20); -- error
  766. ERROR: new row for relation "mcrparted4" violates partition constraint
  767. DETAIL: Failing row contains (30, 21, 20).
  768. -- check rows
  769. select tableoid::regclass::text, * from mcrparted order by 1;
  770. tableoid | a | b | c
  771. ------------+----+------+------
  772. mcrparted0 | 0 | 1 | 1
  773. mcrparted0 | 0 | 1 | 1
  774. mcrparted1 | 9 | 1000 | 1
  775. mcrparted1 | 9 | 1000 | 1
  776. mcrparted1 | 10 | 5 | -1
  777. mcrparted1 | 10 | 5 | -1
  778. mcrparted1 | 2 | 1 | 0
  779. mcrparted1 | 2 | 1 | 0
  780. mcrparted2 | 10 | 6 | 1000
  781. mcrparted2 | 10 | 6 | 1000
  782. mcrparted2 | 10 | 1000 | 1000
  783. mcrparted2 | 10 | 1000 | 1000
  784. mcrparted5 | 30 | 21 | 20
  785. mcrparted5 | 30 | 21 | 20
  786. (14 rows)
  787. -- cleanup
  788. drop table mcrparted;
  789. -- check that a BR constraint can't make partition contain violating rows
  790. create table brtrigpartcon (a int, b text) partition by list (a);
  791. create table brtrigpartcon1 partition of brtrigpartcon for values in (1);
  792. create or replace function brtrigpartcon1trigf() returns trigger as $$begin new.a := 2; return new; end$$ language plpgsql;
  793. create trigger brtrigpartcon1trig before insert on brtrigpartcon1 for each row execute procedure brtrigpartcon1trigf();
  794. insert into brtrigpartcon values (1, 'hi there');
  795. ERROR: new row for relation "brtrigpartcon1" violates partition constraint
  796. DETAIL: Failing row contains (2, hi there).
  797. insert into brtrigpartcon1 values (1, 'hi there');
  798. ERROR: new row for relation "brtrigpartcon1" violates partition constraint
  799. DETAIL: Failing row contains (2, hi there).
  800. -- check that the message shows the appropriate column description in a
  801. -- situation where the partitioned table is not the primary ModifyTable node
  802. create table inserttest3 (f1 text default 'foo', f2 text default 'bar', f3 int);
  803. create role regress_coldesc_role;
  804. grant insert on inserttest3 to regress_coldesc_role;
  805. grant insert on brtrigpartcon to regress_coldesc_role;
  806. revoke select on brtrigpartcon from regress_coldesc_role;
  807. set role regress_coldesc_role;
  808. with result as (insert into brtrigpartcon values (1, 'hi there') returning 1)
  809. insert into inserttest3 (f3) select * from result;
  810. ERROR: new row for relation "brtrigpartcon1" violates partition constraint
  811. DETAIL: Failing row contains (a, b) = (2, hi there).
  812. reset role;
  813. -- cleanup
  814. revoke all on inserttest3 from regress_coldesc_role;
  815. revoke all on brtrigpartcon from regress_coldesc_role;
  816. drop role regress_coldesc_role;
  817. drop table inserttest3;
  818. drop table brtrigpartcon;
  819. drop function brtrigpartcon1trigf();
  820. -- check that "do nothing" BR triggers work with tuple-routing
  821. create table donothingbrtrig_test (a int, b text) partition by list (a);
  822. create table donothingbrtrig_test1 (b text, a int);
  823. create table donothingbrtrig_test2 (c text, b text, a int);
  824. alter table donothingbrtrig_test2 drop column c;
  825. create or replace function donothingbrtrig_func() returns trigger as $$begin raise notice 'b: %', new.b; return NULL; end$$ language plpgsql;
  826. create trigger donothingbrtrig1 before insert on donothingbrtrig_test1 for each row execute procedure donothingbrtrig_func();
  827. create trigger donothingbrtrig2 before insert on donothingbrtrig_test2 for each row execute procedure donothingbrtrig_func();
  828. alter table donothingbrtrig_test attach partition donothingbrtrig_test1 for values in (1);
  829. alter table donothingbrtrig_test attach partition donothingbrtrig_test2 for values in (2);
  830. insert into donothingbrtrig_test values (1, 'foo'), (2, 'bar');
  831. NOTICE: b: foo
  832. NOTICE: b: bar
  833. copy donothingbrtrig_test from stdout;
  834. NOTICE: b: baz
  835. NOTICE: b: qux
  836. select tableoid::regclass, * from donothingbrtrig_test;
  837. tableoid | a | b
  838. ----------+---+---
  839. (0 rows)
  840. -- cleanup
  841. drop table donothingbrtrig_test;
  842. drop function donothingbrtrig_func();
  843. -- check multi-column range partitioning with minvalue/maxvalue constraints
  844. create table mcrparted (a text, b int) partition by range(a, b);
  845. create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
  846. create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue);
  847. create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue);
  848. create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0);
  849. create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10);
  850. create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue);
  851. create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue);
  852. create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, maxvalue);
  853. \d+ mcrparted
  854. Partitioned table "public.mcrparted"
  855. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  856. --------+---------+-----------+----------+---------+----------+--------------+-------------
  857. a | text | | | | extended | |
  858. b | integer | | | | plain | |
  859. Partition key: RANGE (a, b)
  860. Partitions: mcrparted1_lt_b FOR VALUES FROM (MINVALUE, MINVALUE) TO ('b', MINVALUE),
  861. mcrparted2_b FOR VALUES FROM ('b', MINVALUE) TO ('c', MINVALUE),
  862. mcrparted3_c_to_common FOR VALUES FROM ('c', MINVALUE) TO ('common', MINVALUE),
  863. mcrparted4_common_lt_0 FOR VALUES FROM ('common', MINVALUE) TO ('common', 0),
  864. mcrparted5_common_0_to_10 FOR VALUES FROM ('common', 0) TO ('common', 10),
  865. mcrparted6_common_ge_10 FOR VALUES FROM ('common', 10) TO ('common', MAXVALUE),
  866. mcrparted7_gt_common_lt_d FOR VALUES FROM ('common', MAXVALUE) TO ('d', MINVALUE),
  867. mcrparted8_ge_d FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, MAXVALUE)
  868. \d+ mcrparted1_lt_b
  869. Table "public.mcrparted1_lt_b"
  870. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  871. --------+---------+-----------+----------+---------+----------+--------------+-------------
  872. a | text | | | | extended | |
  873. b | integer | | | | plain | |
  874. Partition of: mcrparted FOR VALUES FROM (MINVALUE, MINVALUE) TO ('b', MINVALUE)
  875. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a < 'b'::text))
  876. \d+ mcrparted2_b
  877. Table "public.mcrparted2_b"
  878. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  879. --------+---------+-----------+----------+---------+----------+--------------+-------------
  880. a | text | | | | extended | |
  881. b | integer | | | | plain | |
  882. Partition of: mcrparted FOR VALUES FROM ('b', MINVALUE) TO ('c', MINVALUE)
  883. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a >= 'b'::text) AND (a < 'c'::text))
  884. \d+ mcrparted3_c_to_common
  885. Table "public.mcrparted3_c_to_common"
  886. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  887. --------+---------+-----------+----------+---------+----------+--------------+-------------
  888. a | text | | | | extended | |
  889. b | integer | | | | plain | |
  890. Partition of: mcrparted FOR VALUES FROM ('c', MINVALUE) TO ('common', MINVALUE)
  891. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a >= 'c'::text) AND (a < 'common'::text))
  892. \d+ mcrparted4_common_lt_0
  893. Table "public.mcrparted4_common_lt_0"
  894. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  895. --------+---------+-----------+----------+---------+----------+--------------+-------------
  896. a | text | | | | extended | |
  897. b | integer | | | | plain | |
  898. Partition of: mcrparted FOR VALUES FROM ('common', MINVALUE) TO ('common', 0)
  899. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a = 'common'::text) AND (b < 0))
  900. \d+ mcrparted5_common_0_to_10
  901. Table "public.mcrparted5_common_0_to_10"
  902. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  903. --------+---------+-----------+----------+---------+----------+--------------+-------------
  904. a | text | | | | extended | |
  905. b | integer | | | | plain | |
  906. Partition of: mcrparted FOR VALUES FROM ('common', 0) TO ('common', 10)
  907. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a = 'common'::text) AND (b >= 0) AND (b < 10))
  908. \d+ mcrparted6_common_ge_10
  909. Table "public.mcrparted6_common_ge_10"
  910. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  911. --------+---------+-----------+----------+---------+----------+--------------+-------------
  912. a | text | | | | extended | |
  913. b | integer | | | | plain | |
  914. Partition of: mcrparted FOR VALUES FROM ('common', 10) TO ('common', MAXVALUE)
  915. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a = 'common'::text) AND (b >= 10))
  916. \d+ mcrparted7_gt_common_lt_d
  917. Table "public.mcrparted7_gt_common_lt_d"
  918. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  919. --------+---------+-----------+----------+---------+----------+--------------+-------------
  920. a | text | | | | extended | |
  921. b | integer | | | | plain | |
  922. Partition of: mcrparted FOR VALUES FROM ('common', MAXVALUE) TO ('d', MINVALUE)
  923. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a > 'common'::text) AND (a < 'd'::text))
  924. \d+ mcrparted8_ge_d
  925. Table "public.mcrparted8_ge_d"
  926. Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
  927. --------+---------+-----------+----------+---------+----------+--------------+-------------
  928. a | text | | | | extended | |
  929. b | integer | | | | plain | |
  930. Partition of: mcrparted FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, MAXVALUE)
  931. Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a >= 'd'::text))
  932. insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10),
  933. ('comm', -10), ('common', -10), ('common', 0), ('common', 10),
  934. ('commons', 0), ('d', -10), ('e', 0);
  935. select tableoid::regclass, * from mcrparted order by a, b;
  936. tableoid | a | b
  937. ---------------------------+---------+-----
  938. mcrparted1_lt_b | aaa | 0
  939. mcrparted2_b | b | 0
  940. mcrparted2_b | bz | 10
  941. mcrparted3_c_to_common | c | -10
  942. mcrparted3_c_to_common | comm | -10
  943. mcrparted4_common_lt_0 | common | -10
  944. mcrparted5_common_0_to_10 | common | 0
  945. mcrparted6_common_ge_10 | common | 10
  946. mcrparted7_gt_common_lt_d | commons | 0
  947. mcrparted8_ge_d | d | -10
  948. mcrparted8_ge_d | e | 0
  949. (11 rows)
  950. drop table mcrparted;
  951. -- check that wholerow vars in the RETURNING list work with partitioned tables
  952. create table returningwrtest (a int) partition by list (a);
  953. create table returningwrtest1 partition of returningwrtest for values in (1);
  954. insert into returningwrtest values (1) returning returningwrtest;
  955. returningwrtest
  956. -----------------
  957. (1)
  958. (1 row)
  959. -- check also that the wholerow vars in RETURNING list are converted as needed
  960. alter table returningwrtest add b text;
  961. create table returningwrtest2 (b text, c int, a int);
  962. alter table returningwrtest2 drop c;
  963. alter table returningwrtest attach partition returningwrtest2 for values in (2);
  964. insert into returningwrtest values (2, 'foo') returning returningwrtest;
  965. returningwrtest
  966. -----------------
  967. (2,foo)
  968. (1 row)
  969. drop table returningwrtest;