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>
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> }
[, ... ]
) ]
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>
%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
$$ = (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);
$$ = (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);
| /*EMPTY*/ { $$ = NIL; }
;
-OptPartitionElementList:
- '(' PartitionElementList ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
-
TableElementList:
TableElement
{
}
;
-PartitionElementList:
- PartitionElement
- {
- $$ = list_make1($1);
- }
- | PartitionElementList ',' PartitionElement
- {
- $$ = lappend($1, $3);
- }
- ;
-
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
| 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);
}
;
-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;
$$ = (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);
$$ = (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);
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]);
-- 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
onek2|t
path_tbl|f
person|f
+persons|f
+persons2|t
+persons3|t
pg_aggregate|t
pg_am|t
pg_amop|t
+-- 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);
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
+
-- 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);
+-- 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);
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