Skip to content
Snippets Groups Projects
create_table.out 31.7 KiB
Newer Older
--
-- CREATE_TABLE
--
--
-- CLASS DEFINITIONS
--
CREATE TABLE hobbies_r (
CREATE TABLE equipment_r (
CREATE TABLE onek (
	twenty		int4,
	hundred		int4,
	thousand	int4,
	twothousand	int4,
	fivethous	int4,
	tenthous	int4,
	stringu1	name,
	stringu2	name,
	string4		name
CREATE TABLE tenk1 (
	twenty		int4,
	hundred		int4,
	thousand	int4,
	twothousand	int4,
	fivethous	int4,
	tenthous	int4,
	stringu1	name,
	stringu2	name,
	string4		name
CREATE TABLE tenk2 (
	unique1 	int4,
	unique2 	int4,
	two 	 	int4,
	four 		int4,
	twenty 		int4,
	hundred 	int4,
	thousand 	int4,
	twothousand int4,
	stringu1	name,
	stringu2	name,
	string4		name
CREATE TABLE person (
CREATE TABLE emp (
CREATE TABLE student (
CREATE TABLE stud_emp (
	percent 	int4
) INHERITS (emp, student);
NOTICE:  merging multiple inherited definitions of column "name"
NOTICE:  merging multiple inherited definitions of column "age"
NOTICE:  merging multiple inherited definitions of column "location"
CREATE TABLE city (
CREATE TABLE dept (
CREATE TABLE slow_emp4000 (
CREATE TABLE fast_emp4000 (
CREATE TABLE road (
CREATE TABLE ihighway () INHERITS (road);
CREATE TABLE shighway (
CREATE TABLE real_city (
	pop			int4,
--
-- test the "star" operators a bit more thoroughly -- this time,
-- throw in lots of NULL fields...
--
-- a is the type root
-- b and c inherit from a (one-level single inheritance)
-- d inherits from b and c (two-level multiple inheritance)
-- e inherits from c (two-level single inheritance)
-- f inherits from e (three-level single inheritance)
--
CREATE TABLE a_star (
	a 			int4
);
CREATE TABLE b_star (
	b 			text
CREATE TABLE c_star (
	c 			name
CREATE TABLE d_star (
	d 			float8
NOTICE:  merging multiple inherited definitions of column "class"
NOTICE:  merging multiple inherited definitions of column "a"
CREATE TABLE e_star (
	e 			int2
CREATE TABLE f_star (
	f 			polygon
CREATE TABLE aggtest (
	a 			int2,
	b			float4
);
CREATE TABLE hash_i4_heap (
CREATE TABLE hash_name_heap (
CREATE TABLE hash_txt_heap (
CREATE TABLE hash_f8_heap (
-- don't include the hash_ovfl_heap stuff in the distribution
-- the data set is too large for what it's worth
-- CREATE TABLE hash_ovfl_heap (
--	x			int4,
--	y			int4
-- );
CREATE TABLE bt_i4_heap (
CREATE TABLE bt_name_heap (
CREATE TABLE bt_txt_heap (
CREATE TABLE bt_f8_heap (
CREATE TABLE array_op_test (
	seqno		int4,
	i			int4[],
	t			text[]
);
CREATE TABLE array_index_op_test (
	seqno		int4,
	i			int4[],
	t			text[]
);
CREATE TABLE testjsonb (
       j jsonb
);
CREATE TABLE unknowntab (
	u unknown    -- fail
);
ERROR:  column "u" has pseudo-type unknown
CREATE TYPE unknown_comptype AS (
	u unknown    -- fail
);
ERROR:  column "u" has pseudo-type unknown
CREATE TABLE IF NOT EXISTS test_tsvector(
	t text,
	a tsvector
CREATE TABLE IF NOT EXISTS test_tsvector(
Robert Haas's avatar
Robert Haas committed
	t text
);
NOTICE:  relation "test_tsvector" already exists, skipping
CREATE UNLOGGED TABLE unlogged1 (a int primary key);			-- OK
CREATE TEMPORARY TABLE unlogged2 (a int primary key);			-- OK
SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname;
    relname     | relkind | relpersistence 
----------------+---------+----------------
 unlogged1      | r       | u
 unlogged1_pkey | i       | u
 unlogged2      | r       | t
 unlogged2_pkey | i       | t
(4 rows)

REINDEX INDEX unlogged1_pkey;
REINDEX INDEX unlogged2_pkey;
SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname;
    relname     | relkind | relpersistence 
----------------+---------+----------------
 unlogged1      | r       | u
 unlogged1_pkey | i       | u
 unlogged2      | r       | t
 unlogged2_pkey | i       | t
(4 rows)

DROP TABLE unlogged2;
Robert Haas's avatar
Robert Haas committed
INSERT INTO unlogged1 VALUES (42);
CREATE UNLOGGED TABLE public.unlogged2 (a int primary key);		-- also OK
CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key);	-- not OK
Robert Haas's avatar
Robert Haas committed
ERROR:  only temporary relations may be created in temporary schemas
LINE 1: CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key);
                              ^
CREATE TABLE pg_temp.implicitly_temp (a int primary key);		-- OK
CREATE TEMP TABLE explicitly_temp (a int primary key);			-- also OK
CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key);		-- also OK
CREATE TEMP TABLE public.temp_to_perm (a int primary key);		-- not OK
Robert Haas's avatar
Robert Haas committed
ERROR:  cannot create temporary relation in non-temporary schema
LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key);
                          ^
Robert Haas's avatar
Robert Haas committed
DROP TABLE unlogged1, public.unlogged2;
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
ERROR:  relation "as_select1" already exists
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
NOTICE:  relation "as_select1" already exists, skipping
DROP TABLE as_select1;
-- check that the oid column is added before the primary key is checked
CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
DROP TABLE oid_pk;
--
-- Partitioned tables
--
-- cannot combine INHERITS and PARTITION BY (although grammar allows)
CREATE TABLE partitioned (
	a int
) INHERITS (some_table) PARTITION BY LIST (a);
ERROR:  cannot create partitioned table as inheritance child
-- cannot use more than 1 column as partition key for list partitioned table
CREATE TABLE partitioned (
	a1 int,
	a2 int
) PARTITION BY LIST (a1, a2);	-- fail
ERROR:  cannot use "list" partition strategy with more than one column
-- unsupported constraint type for partitioned tables
CREATE TABLE partitioned (
	a int PRIMARY KEY
) PARTITION BY RANGE (a);
ERROR:  primary key constraints are not supported on partitioned tables
LINE 2:  a int PRIMARY KEY
               ^
CREATE TABLE pkrel (
	a int PRIMARY KEY
);
CREATE TABLE partitioned (
	a int REFERENCES pkrel(a)
) PARTITION BY RANGE (a);
ERROR:  foreign key constraints are not supported on partitioned tables
LINE 2:  a int REFERENCES pkrel(a)
               ^
DROP TABLE pkrel;
CREATE TABLE partitioned (
	a int UNIQUE
) PARTITION BY RANGE (a);
ERROR:  unique constraints are not supported on partitioned tables
LINE 2:  a int UNIQUE
               ^
CREATE TABLE partitioned (
	a int,
	EXCLUDE USING gist (a WITH &&)
) PARTITION BY RANGE (a);
ERROR:  exclusion constraints are not supported on partitioned tables
LINE 3:  EXCLUDE USING gist (a WITH &&)
         ^
-- prevent column from being used twice in the partition key
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (a, a);
ERROR:  column "a" appears more than once in partition key
-- prevent using prohibited expressions in the key
CREATE FUNCTION retset (a int) RETURNS SETOF int AS $$ SELECT 1; $$ LANGUAGE SQL IMMUTABLE;
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (retset(a));
ERROR:  set-returning functions are not allowed in partition key expressions
DROP FUNCTION retset(int);
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE ((avg(a)));
ERROR:  aggregate functions are not allowed in partition key expression
CREATE TABLE partitioned (
	a int,
	b int
) PARTITION BY RANGE ((avg(a) OVER (PARTITION BY b)));
ERROR:  window functions are not allowed in partition key expression
CREATE TABLE partitioned (
	a int
) PARTITION BY LIST ((a LIKE (SELECT 1)));
ERROR:  cannot use subquery in partition key expression
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (('a'));
ERROR:  cannot use constant expression as partition key
CREATE FUNCTION const_func () RETURNS int AS $$ SELECT 1; $$ LANGUAGE SQL IMMUTABLE;
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (const_func());
ERROR:  cannot use constant expression as partition key
DROP FUNCTION const_func();
-- only accept "list" and "range" as partitioning strategy
CREATE TABLE partitioned (
	a int
) PARTITION BY HASH (a);
ERROR:  unrecognized partitioning strategy "hash"
-- specified column must be present in the table
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (b);
ERROR:  column "b" named in partition key does not exist
-- cannot use system columns in partition key
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (xmin);
ERROR:  cannot use system column "xmin" in partition key
-- functions in key must be immutable
CREATE FUNCTION immut_func (a int) RETURNS int AS $$ SELECT a + random()::int; $$ LANGUAGE SQL;
CREATE TABLE partitioned (
	a int
) PARTITION BY RANGE (immut_func(a));
ERROR:  functions in partition key expression must be marked IMMUTABLE
DROP FUNCTION immut_func(int);
-- cannot contain whole-row references
CREATE TABLE partitioned (
	a	int
) PARTITION BY RANGE ((partitioned));
ERROR:  partition key expressions cannot contain whole-row references
-- prevent using columns of unsupported types in key (type must have a btree operator class)
CREATE TABLE partitioned (
	a point
) PARTITION BY LIST (a);
ERROR:  data type point has no default btree operator class
HINT:  You must specify a btree operator class or define a default btree operator class for the data type.
CREATE TABLE partitioned (
	a point
) PARTITION BY LIST (a point_ops);
ERROR:  operator class "point_ops" does not exist for access method "btree"
CREATE TABLE partitioned (
	a point
) PARTITION BY RANGE (a);
ERROR:  data type point has no default btree operator class
HINT:  You must specify a btree operator class or define a default btree operator class for the data type.
CREATE TABLE partitioned (
	a point
) PARTITION BY RANGE (a point_ops);
ERROR:  operator class "point_ops" does not exist for access method "btree"
-- cannot add NO INHERIT constraints to partitioned tables
CREATE TABLE partitioned (
	a int,
	CONSTRAINT check_a CHECK (a > 0) NO INHERIT
) PARTITION BY RANGE (a);
ERROR:  cannot add NO INHERIT constraint to partitioned table "partitioned"
-- some checks after successful creation of a partitioned table
CREATE FUNCTION plusone(a int) RETURNS INT AS $$ SELECT a+1; $$ LANGUAGE SQL;
CREATE TABLE partitioned (
	a int,
	b int,
	c text,
	d text
) PARTITION BY RANGE (a oid_ops, plusone(b), c collate "default", d collate "C");
-- check relkind
SELECT relkind FROM pg_class WHERE relname = 'partitioned';
 relkind 
---------
(1 row)

-- prevent a function referenced in partition key from being dropped
DROP FUNCTION plusone(int);
ERROR:  cannot drop function plusone(integer) because other objects depend on it
DETAIL:  table partitioned depends on function plusone(integer)
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
-- partitioned table cannot participate in regular inheritance
CREATE TABLE partitioned2 (
	a int,
	b text
) PARTITION BY RANGE ((a+1), substr(b, 1, 5));
CREATE TABLE fail () INHERITS (partitioned2);
ERROR:  cannot inherit from partitioned table "partitioned2"
-- Partition key in describe output
\d partitioned
            Table "public.partitioned"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 b      | integer |           |          | 
 c      | text    |           |          | 
 d      | text    |           |          | 
Partition key: RANGE (a oid_ops, plusone(b), c, d COLLATE "C")
\d+ partitioned2
                                Table "public.partitioned2"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 a      | integer |           |          |         | plain    |              | 
 b      | text    |           |          |         | extended |              | 
Partition key: RANGE (((a + 1)), substr(b, 1, 5))

INSERT INTO partitioned2 VALUES (1, 'hello');
ERROR:  no partition of relation "partitioned2" found for row
DETAIL:  Partition key of the failing row contains ((a + 1), substr(b, 1, 5)) = (2, hello).
CREATE TABLE part2_1 PARTITION OF partitioned2 FOR VALUES FROM (-1, 'aaaaa') TO (100, 'ccccc');
\d+ part2_1
                                  Table "public.part2_1"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 a      | integer |           |          |         | plain    |              | 
 b      | text    |           |          |         | extended |              | 
Partition of: partitioned2 FOR VALUES FROM ('-1', 'aaaaa') TO (100, 'ccccc')
Partition constraint: (((a + 1) IS NOT NULL) AND (substr(b, 1, 5) IS NOT NULL) AND (((a + 1) > '-1'::integer) OR (((a + 1) = '-1'::integer) AND (substr(b, 1, 5) >= 'aaaaa'::text))) AND (((a + 1) < 100) OR (((a + 1) = 100) AND (substr(b, 1, 5) < 'ccccc'::text))))

DROP TABLE partitioned, partitioned2;
--
-- Partitions
--
-- check partition bound syntax
CREATE TABLE list_parted (
	a int
) PARTITION BY LIST (a);
-- syntax allows only string literal, numeric literal and null to be
-- specified for a partition bound value
CREATE TABLE part_1 PARTITION OF list_parted FOR VALUES IN ('1');
CREATE TABLE part_2 PARTITION OF list_parted FOR VALUES IN (2);
CREATE TABLE part_null PARTITION OF list_parted FOR VALUES IN (null);
CREATE TABLE fail_part PARTITION OF list_parted FOR VALUES IN (int '1');
ERROR:  syntax error at or near "int"
LINE 1: ... fail_part PARTITION OF list_parted FOR VALUES IN (int '1');
                                                              ^
CREATE TABLE fail_part PARTITION OF list_parted FOR VALUES IN ('1'::int);
ERROR:  syntax error at or near "::"
LINE 1: ...fail_part PARTITION OF list_parted FOR VALUES IN ('1'::int);
                                                                ^
-- syntax does not allow empty list of values for list partitions
CREATE TABLE fail_part PARTITION OF list_parted FOR VALUES IN ();
ERROR:  syntax error at or near ")"
LINE 1: ...E TABLE fail_part PARTITION OF list_parted FOR VALUES IN ();
                                                                     ^
-- trying to specify range for list partitioned table
CREATE TABLE fail_part PARTITION OF list_parted FOR VALUES FROM (1) TO (2);
ERROR:  invalid bound specification for a list partition
LINE 1: ...BLE fail_part PARTITION OF list_parted FOR VALUES FROM (1) T...
                                                             ^
-- specified literal can't be cast to the partition column data type
CREATE TABLE bools (
	a bool
) PARTITION BY LIST (a);
CREATE TABLE bools_true PARTITION OF bools FOR VALUES IN (1);
ERROR:  specified value cannot be cast to type boolean for column "a"
LINE 1: ...REATE TABLE bools_true PARTITION OF bools FOR VALUES IN (1);
                                                                    ^
DROP TABLE bools;
-- specified literal can be cast, but cast isn't immutable
CREATE TABLE moneyp (
	a money
) PARTITION BY LIST (a);
CREATE TABLE moneyp_10 PARTITION OF moneyp FOR VALUES IN (10);
ERROR:  specified value cannot be cast to type money for column "a"
LINE 1: ...EATE TABLE moneyp_10 PARTITION OF moneyp FOR VALUES IN (10);
                                                                   ^
DETAIL:  The cast requires a non-immutable conversion.
HINT:  Try putting the literal value in single quotes.
CREATE TABLE moneyp_10 PARTITION OF moneyp FOR VALUES IN ('10');
DROP TABLE moneyp;
-- immutable cast should work, though
CREATE TABLE bigintp (
	a bigint
) PARTITION BY LIST (a);
CREATE TABLE bigintp_10 PARTITION OF bigintp FOR VALUES IN (10);
-- fails due to overlap:
CREATE TABLE bigintp_10_2 PARTITION OF bigintp FOR VALUES IN ('10');
ERROR:  partition "bigintp_10_2" would overlap partition "bigintp_10"
DROP TABLE bigintp;
CREATE TABLE range_parted (
	a date
) PARTITION BY RANGE (a);
-- trying to specify list for range partitioned table
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES IN ('a');
ERROR:  invalid bound specification for a range partition
LINE 1: ...BLE fail_part PARTITION OF range_parted FOR VALUES IN ('a');
                                                              ^
-- each of start and end bounds must have same number of values as the
-- length of the partition key
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a', 1) TO ('z');
ERROR:  FROM must specify exactly one value per partitioning column
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z', 1);
ERROR:  TO must specify exactly one value per partitioning column
-- cannot specify null values in range bounds
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (maxvalue);
ERROR:  cannot specify NULL in range bound
-- check if compatible with the specified parent
-- cannot create as partition of a non-partitioned table
CREATE TABLE unparted (
	a int
);
CREATE TABLE fail_part PARTITION OF unparted FOR VALUES IN ('a');
ERROR:  "unparted" is not partitioned
DROP TABLE unparted;
-- cannot create a permanent rel as partition of a temp rel
CREATE TEMP TABLE temp_parted (
	a int
) PARTITION BY LIST (a);
CREATE TABLE fail_part PARTITION OF temp_parted FOR VALUES IN ('a');
ERROR:  cannot create a permanent relation as partition of temporary relation "temp_parted"
DROP TABLE temp_parted;
-- cannot create a table with oids as partition of table without oids
CREATE TABLE no_oids_parted (
	a int
) PARTITION BY RANGE (a) WITHOUT OIDS;
CREATE TABLE fail_part PARTITION OF no_oids_parted FOR VALUES FROM (1) TO (10) WITH OIDS;
ERROR:  cannot create table with OIDs as partition of table without OIDs
DROP TABLE no_oids_parted;
-- If the partitioned table has oids, then the partition must have them.
-- If the WITHOUT OIDS option is specified for partition, it is overridden.
CREATE TABLE oids_parted (
	a int
) PARTITION BY RANGE (a) WITH OIDS;
CREATE TABLE part_forced_oids PARTITION OF oids_parted FOR VALUES FROM (1) TO (10) WITHOUT OIDS;
\d+ part_forced_oids
                             Table "public.part_forced_oids"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+---------+--------------+-------------
 a      | integer |           |          |         | plain   |              | 
Partition of: oids_parted FOR VALUES FROM (1) TO (10)
Partition constraint: ((a IS NOT NULL) AND (a >= 1) AND (a < 10))
Has OIDs: yes

DROP TABLE oids_parted, part_forced_oids;
-- check for partition bound overlap and other invalid specifications
CREATE TABLE list_parted2 (
	a varchar
) PARTITION BY LIST (a);
CREATE TABLE part_null_z PARTITION OF list_parted2 FOR VALUES IN (null, 'z');
CREATE TABLE part_ab PARTITION OF list_parted2 FOR VALUES IN ('a', 'b');
CREATE TABLE fail_part PARTITION OF list_parted2 FOR VALUES IN (null);
ERROR:  partition "fail_part" would overlap partition "part_null_z"
CREATE TABLE fail_part PARTITION OF list_parted2 FOR VALUES IN ('b', 'c');
ERROR:  partition "fail_part" would overlap partition "part_ab"
CREATE TABLE range_parted2 (
	a int
) PARTITION BY RANGE (a);
-- trying to create range partition with empty range
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (0);
ERROR:  empty range bound specified for partition "fail_part"
DETAIL:  Specified lower bound (1) is greater than or equal to upper bound (0).
-- note that the range '[1, 1)' has no elements
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1);
ERROR:  empty range bound specified for partition "fail_part"
DETAIL:  Specified lower bound (1) is greater than or equal to upper bound (1).
CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2);
ERROR:  partition "fail_part" would overlap partition "part0"
CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (maxvalue);
ERROR:  partition "fail_part" would overlap partition "part1"
CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30);
CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (10) TO (30);
ERROR:  partition "fail_part" would overlap partition "part2"
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (10) TO (50);
ERROR:  partition "fail_part" would overlap partition "part2"
-- now check for multi-column range partition key
CREATE TABLE range_parted3 (
	a int,
	b int
) PARTITION BY RANGE (a, (b+1));
CREATE TABLE part00 PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, 1);
ERROR:  partition "fail_part" would overlap partition "part00"
CREATE TABLE part10 PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, 1);
CREATE TABLE part11 PARTITION OF range_parted3 FOR VALUES FROM (1, 1) TO (1, 10);
CREATE TABLE part12 PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, 20);
ERROR:  partition "fail_part" would overlap partition "part12"
-- cannot create a partition that says column b is allowed to range
-- from -infinity to +infinity, while there exist partitions that have
-- more specific ranges
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, maxvalue);
ERROR:  partition "fail_part" would overlap partition "part10"
-- check schema propagation from parent
CREATE TABLE parted (
	a text,
	b int NOT NULL DEFAULT 0,
	CONSTRAINT check_a CHECK (length(a) > 0)
) PARTITION BY LIST (a);
CREATE TABLE part_a PARTITION OF parted FOR VALUES IN ('a');
-- only inherited attributes (never local ones)
SELECT attname, attislocal, attinhcount FROM pg_attribute
  WHERE attrelid = 'part_a'::regclass and attnum > 0
  ORDER BY attnum;
 attname | attislocal | attinhcount 
---------+------------+-------------
 a       | f          |           1
 b       | f          |           1
(2 rows)

-- able to specify column default, column constraint, and table constraint
-- first check the "column specified more than once" error
CREATE TABLE part_b PARTITION OF parted (
	b NOT NULL,
	b DEFAULT 1,
	b CHECK (b >= 0),
	CONSTRAINT check_a CHECK (length(a) > 0)
) FOR VALUES IN ('b');
ERROR:  column "b" specified more than once
CREATE TABLE part_b PARTITION OF parted (
	b NOT NULL DEFAULT 1 CHECK (b >= 0),
	CONSTRAINT check_a CHECK (length(a) > 0)
) FOR VALUES IN ('b');
NOTICE:  merging constraint "check_a" with inherited definition
-- conislocal should be false for any merged constraints
SELECT conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::regclass AND conname = 'check_a';
 conislocal | coninhcount 
------------+-------------
 f          |           1
(1 row)

-- specify PARTITION BY for a partition
CREATE TABLE fail_part_col_not_found PARTITION OF parted FOR VALUES IN ('c') PARTITION BY RANGE (c);
ERROR:  column "c" named in partition key does not exist
CREATE TABLE part_c PARTITION OF parted (b WITH OPTIONS NOT NULL DEFAULT 0) FOR VALUES IN ('c') PARTITION BY RANGE ((b));
-- create a level-2 partition
CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10);
-- Partition bound in describe output
\d+ part_b
                                   Table "public.part_b"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 a      | text    |           |          |         | extended |              | 
 b      | integer |           | not null | 1       | plain    |              | 
Partition of: parted FOR VALUES IN ('b')
Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text))
Check constraints:
    "check_a" CHECK (length(a) > 0)
    "part_b_b_check" CHECK (b >= 0)

-- Both partition bound and partition key in describe output
\d+ part_c
                                   Table "public.part_c"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 a      | text    |           |          |         | extended |              | 
 b      | integer |           | not null | 0       | plain    |              | 
Partition of: parted FOR VALUES IN ('c')
Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text))
Partition key: RANGE (b)
Check constraints:
    "check_a" CHECK (length(a) > 0)
Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10)

-- a level-2 partition's constraint will include the parent's expressions
\d+ part_c_1_10
                                Table "public.part_c_1_10"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 a      | text    |           |          |         | extended |              | 
 b      | integer |           | not null | 0       | plain    |              | 
Partition of: part_c FOR VALUES FROM (1) TO (10)
Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text) AND (b IS NOT NULL) AND (b >= 1) AND (b < 10))
Check constraints:
    "check_a" CHECK (length(a) > 0)

-- Show partition count in the parent's describe output
-- Tempted to include \d+ output listing partitions with bound info but
-- output could vary depending on the order in which partition oids are
-- returned.
\d parted
               Table "public.parted"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 a      | text    |           |          | 
 b      | integer |           | not null | 0
Partition key: LIST (a)
Check constraints:
    "check_a" CHECK (length(a) > 0)
Number of partitions: 3 (Use \d+ to list them.)

-- check that we get the expected partition constraints
CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c);
CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE);
\d+ unbounded_range_part
                           Table "public.unbounded_range_part"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+---------+--------------+-------------
 a      | integer |           |          |         | plain   |              | 
 b      | integer |           |          |         | plain   |              | 
 c      | integer |           |          |         | plain   |              | 
Partition of: range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL))

DROP TABLE unbounded_range_part;
CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE);
\d+ range_parted4_1
                              Table "public.range_parted4_1"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+---------+--------------+-------------
 a      | integer |           |          |         | plain   |              | 
 b      | integer |           |          |         | plain   |              | 
 c      | integer |           |          |         | plain   |              | 
Partition of: range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND (abs(a) <= 1))
CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE);
\d+ range_parted4_2
                              Table "public.range_parted4_2"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+---------+--------------+-------------
 a      | integer |           |          |         | plain   |              | 
 b      | integer |           |          |         | plain   |              | 
 c      | integer |           |          |         | plain   |              | 
Partition of: range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 3) OR ((abs(a) = 3) AND (abs(b) > 4)) OR ((abs(a) = 3) AND (abs(b) = 4) AND (c >= 5))) AND ((abs(a) < 6) OR ((abs(a) = 6) AND (abs(b) <= 7))))
CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE);
\d+ range_parted4_3
                              Table "public.range_parted4_3"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+---------+--------------+-------------
 a      | integer |           |          |         | plain   |              | 
 b      | integer |           |          |         | plain   |              | 
 c      | integer |           |          |         | plain   |              | 
Partition of: range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 6) OR ((abs(a) = 6) AND (abs(b) >= 8))) AND (abs(a) <= 9))

DROP TABLE range_parted4;
-- cleanup
DROP TABLE parted, list_parted, range_parted, list_parted2, range_parted2, range_parted3;
-- comments on partitioned tables columns
CREATE TABLE parted_col_comment (a int, b text) PARTITION BY LIST (a);
COMMENT ON TABLE parted_col_comment IS 'Am partitioned table';
COMMENT ON COLUMN parted_col_comment.a IS 'Partition key';
SELECT obj_description('parted_col_comment'::regclass);
   obj_description    
----------------------
 Am partitioned table
(1 row)

\d+ parted_col_comment
                              Table "public.parted_col_comment"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target |  Description  
--------+---------+-----------+----------+---------+----------+--------------+---------------
 a      | integer |           |          |         | plain    |              | Partition key
 b      | text    |           |          |         | extended |              | 
Partition key: LIST (a)

DROP TABLE parted_col_comment;
-- list partitioning on array type column
CREATE TABLE arrlp (a int[]) PARTITION BY LIST (a);
CREATE TABLE arrlp12 PARTITION OF arrlp FOR VALUES IN ('{1}', '{2}');
\d+ arrlp12
                                   Table "public.arrlp12"
 Column |   Type    | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+-----------+-----------+----------+---------+----------+--------------+-------------
 a      | integer[] |           |          |         | extended |              | 
Partition of: arrlp FOR VALUES IN ('{1}', '{2}')
Partition constraint: ((a IS NOT NULL) AND (((a)::anyarray OPERATOR(pg_catalog.=) '{1}'::integer[]) OR ((a)::anyarray OPERATOR(pg_catalog.=) '{2}'::integer[])))

DROP TABLE arrlp;