summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/create_foreign_table.sgml2
-rw-r--r--doc/src/sgml/ref/create_table.sgml4
-rw-r--r--src/backend/parser/gram.y68
-rw-r--r--src/bin/pg_dump/pg_dump.c17
-rw-r--r--src/test/regress/expected/create_table.out2
-rw-r--r--src/test/regress/expected/sanity_check.out3
-rw-r--r--src/test/regress/expected/typed_table.out37
-rw-r--r--src/test/regress/sql/create_table.sql2
-rw-r--r--src/test/regress/sql/typed_table.sql21
9 files changed, 94 insertions, 62 deletions
diff --git a/doc/src/sgml/ref/create_foreign_table.sgml b/doc/src/sgml/ref/create_foreign_table.sgml
index 5d0dcf567b5..065c982082d 100644
--- a/doc/src/sgml/ref/create_foreign_table.sgml
+++ b/doc/src/sgml/ref/create_foreign_table.sgml
@@ -29,7 +29,7 @@ CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name
CREATE FOREIGN TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable>
PARTITION OF <replaceable class="PARAMETER">parent_table</replaceable> [ (
- { <replaceable class="PARAMETER">column_name</replaceable> WITH OPTIONS [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
+ { <replaceable class="PARAMETER">column_name</replaceable> [ WITH OPTIONS ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
| <replaceable>table_constraint</replaceable> }
[, ... ]
) ] <replaceable class="PARAMETER">partition_bound_spec</replaceable>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index a3dc744efa5..484f81898b3 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -35,7 +35,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable>
OF <replaceable class="PARAMETER">type_name</replaceable> [ (
- { <replaceable class="PARAMETER">column_name</replaceable> WITH OPTIONS [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
+ { <replaceable class="PARAMETER">column_name</replaceable> [ WITH OPTIONS ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
| <replaceable>table_constraint</replaceable> }
[, ... ]
) ]
@@ -46,7 +46,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable>
PARTITION OF <replaceable class="PARAMETER">parent_table</replaceable> [ (
- { <replaceable class="PARAMETER">column_name</replaceable> [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
+ { <replaceable class="PARAMETER">column_name</replaceable> [ WITH OPTIONS ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
| <replaceable>table_constraint</replaceable> }
[, ... ]
) ] FOR VALUES <replaceable class="PARAMETER">partition_bound_spec</replaceable>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 89d2836c49a..21cdc7c7da4 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -576,8 +576,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <str> part_strategy
%type <partelem> part_elem
%type <list> part_params
-%type <list> OptPartitionElementList PartitionElementList
-%type <node> PartitionElement
%type <node> ForValues
%type <node> partbound_datum
%type <list> partbound_datum_list
@@ -3131,7 +3129,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$$ = (Node *)n;
}
| CREATE OptTemp TABLE qualified_name PARTITION OF qualified_name
- OptPartitionElementList ForValues OptPartitionSpec OptWith
+ OptTypedTableElementList ForValues OptPartitionSpec OptWith
OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
@@ -3150,7 +3148,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
$$ = (Node *)n;
}
| CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name PARTITION OF
- qualified_name OptPartitionElementList ForValues OptPartitionSpec
+ qualified_name OptTypedTableElementList ForValues OptPartitionSpec
OptWith OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
@@ -3213,11 +3211,6 @@ OptTypedTableElementList:
| /*EMPTY*/ { $$ = NIL; }
;
-OptPartitionElementList:
- '(' PartitionElementList ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
-
TableElementList:
TableElement
{
@@ -3240,17 +3233,6 @@ TypedTableElementList:
}
;
-PartitionElementList:
- PartitionElement
- {
- $$ = list_make1($1);
- }
- | PartitionElementList ',' PartitionElement
- {
- $$ = lappend($1, $3);
- }
- ;
-
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
@@ -3262,28 +3244,6 @@ TypedTableElement:
| TableConstraint { $$ = $1; }
;
-PartitionElement:
- TableConstraint { $$ = $1; }
- | ColId ColQualList
- {
- ColumnDef *n = makeNode(ColumnDef);
- n->colname = $1;
- n->typeName = NULL;
- n->inhcount = 0;
- n->is_local = true;
- n->is_not_null = false;
- n->is_from_type = false;
- n->storage = 0;
- n->raw_default = NULL;
- n->cooked_default = NULL;
- n->collOid = InvalidOid;
- SplitColQualList($2, &n->constraints, &n->collClause,
- yyscanner);
- n->location = @1;
- $$ = (Node *) n;
- }
- ;
-
columnDef: ColId Typename create_generic_options ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
@@ -3305,7 +3265,25 @@ columnDef: ColId Typename create_generic_options ColQualList
}
;
-columnOptions: ColId WITH OPTIONS ColQualList
+columnOptions: ColId ColQualList
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->typeName = NULL;
+ n->inhcount = 0;
+ n->is_local = true;
+ n->is_not_null = false;
+ n->is_from_type = false;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collOid = InvalidOid;
+ SplitColQualList($2, &n->constraints, &n->collClause,
+ yyscanner);
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ | ColId WITH OPTIONS ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
@@ -4872,7 +4850,7 @@ CreateForeignTableStmt:
$$ = (Node *) n;
}
| CREATE FOREIGN TABLE qualified_name
- PARTITION OF qualified_name OptPartitionElementList ForValues
+ PARTITION OF qualified_name OptTypedTableElementList ForValues
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
@@ -4893,7 +4871,7 @@ CreateForeignTableStmt:
$$ = (Node *) n;
}
| CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name
- PARTITION OF qualified_name OptPartitionElementList ForValues
+ PARTITION OF qualified_name OptTypedTableElementList ForValues
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index e9b5c8a4483..2fda350faa2 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -15267,13 +15267,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
continue;
}
- /* Attribute type */
- if ((tbinfo->reloftype || tbinfo->partitionOf) &&
- !dopt->binary_upgrade)
- {
- appendPQExpBufferStr(q, " WITH OPTIONS");
- }
- else
+ /*
+ * Attribute type
+ *
+ * In binary-upgrade mode, we always include the type.
+ * If we aren't in binary-upgrade mode, then we skip the
+ * type when creating a typed table ('OF type_name') or a
+ * partition ('PARTITION OF'), since the type comes from
+ * the parent/partitioned table.
+ */
+ if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->partitionOf))
{
appendPQExpBuffer(q, " %s",
tbinfo->atttypnames[j]);
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index b6c75d2e81f..3f94250df28 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -624,7 +624,7 @@ SELECT conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::reg
-- 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 FOR VALUES IN ('c') PARTITION BY RANGE ((b));
+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
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 753ad81e43f..6750152e0f4 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -93,6 +93,9 @@ onek|t
onek2|t
path_tbl|f
person|f
+persons|f
+persons2|t
+persons3|t
pg_aggregate|t
pg_am|t
pg_amop|t
diff --git a/src/test/regress/expected/typed_table.out b/src/test/regress/expected/typed_table.out
index 141d3bcf87c..5cdd019244e 100644
--- a/src/test/regress/expected/typed_table.out
+++ b/src/test/regress/expected/typed_table.out
@@ -1,3 +1,7 @@
+-- Clean up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+DROP TYPE IF EXISTS person_type CASCADE;
+RESET client_min_messages;
CREATE TABLE ttable1 OF nothing;
ERROR: type "nothing" does not exist
CREATE TYPE person_type AS (id int, name text);
@@ -102,7 +106,32 @@ SELECT id, namelen(persons) FROM persons;
1 | 4
(1 row)
-DROP TYPE person_type CASCADE;
-NOTICE: drop cascades to 2 other objects
-DETAIL: drop cascades to table persons
-drop cascades to function namelen(person_type)
+CREATE TABLE persons2 OF person_type (
+ id WITH OPTIONS PRIMARY KEY,
+ UNIQUE (name)
+);
+\d persons2
+ Table "public.persons2"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+---------
+ id | integer | | not null |
+ name | text | | |
+Indexes:
+ "persons2_pkey" PRIMARY KEY, btree (id)
+ "persons2_name_key" UNIQUE CONSTRAINT, btree (name)
+Typed table of type: person_type
+
+CREATE TABLE persons3 OF person_type (
+ PRIMARY KEY (id),
+ name NOT NULL DEFAULT ''
+);
+\d persons3
+ Table "public.persons3"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+----------
+ id | integer | | not null |
+ name | text | | not null | ''::text
+Indexes:
+ "persons3_pkey" PRIMARY KEY, btree (id)
+Typed table of type: person_type
+
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index b00d9e87b82..f08942f7d21 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -578,7 +578,7 @@ SELECT conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::reg
-- specify PARTITION BY for a partition
CREATE TABLE fail_part_col_not_found PARTITION OF parted FOR VALUES IN ('c') PARTITION BY RANGE (c);
-CREATE TABLE part_c PARTITION OF parted FOR VALUES IN ('c') PARTITION BY RANGE ((b));
+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);
diff --git a/src/test/regress/sql/typed_table.sql b/src/test/regress/sql/typed_table.sql
index 25aaccb8bcd..1cdceef3637 100644
--- a/src/test/regress/sql/typed_table.sql
+++ b/src/test/regress/sql/typed_table.sql
@@ -1,3 +1,10 @@
+-- Clean up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+
+DROP TYPE IF EXISTS person_type CASCADE;
+
+RESET client_min_messages;
+
CREATE TABLE ttable1 OF nothing;
CREATE TYPE person_type AS (id int, name text);
@@ -60,4 +67,16 @@ INSERT INTO persons VALUES (1, 'test');
CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$;
SELECT id, namelen(persons) FROM persons;
-DROP TYPE person_type CASCADE;
+CREATE TABLE persons2 OF person_type (
+ id WITH OPTIONS PRIMARY KEY,
+ UNIQUE (name)
+);
+
+\d persons2
+
+CREATE TABLE persons3 OF person_type (
+ PRIMARY KEY (id),
+ name NOT NULL DEFAULT ''
+);
+
+\d persons3