diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 283d53e203c..e1ec14e1c1b 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1038,6 +1038,8 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
If a table parameter value is set and the
equivalent toast. parameter is not, the TOAST table
will use the table's parameter value.
+ Specifying these parameters for partitioned tables is not supported,
+ but you may specify them for individual leaf partitions.
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 72e12532ab2..de7507aa680 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1000,7 +1000,8 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
* array; this is so that the caller can easily locate the default values.
*
* If there are no options of the given kind, numrelopts is set to 0 and NULL
- * is returned.
+ * is returned (unless options are illegally supplied despite none being
+ * defined, in which case an error occurs).
*
* Note: values of type int, bool and real are allocated as part of the
* returned array. Values of type string are allocated separately and must
@@ -1010,7 +1011,7 @@ relopt_value *
parseRelOptions(Datum options, bool validate, relopt_kind kind,
int *numrelopts)
{
- relopt_value *reloptions;
+ relopt_value *reloptions = NULL;
int numoptions = 0;
int i;
int j;
@@ -1024,21 +1025,18 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
if (relOpts[i]->kinds & kind)
numoptions++;
- if (numoptions == 0)
+ if (numoptions > 0)
{
- *numrelopts = 0;
- return NULL;
- }
+ reloptions = palloc(numoptions * sizeof(relopt_value));
- reloptions = palloc(numoptions * sizeof(relopt_value));
-
- for (i = 0, j = 0; relOpts[i]; i++)
- {
- if (relOpts[i]->kinds & kind)
+ for (i = 0, j = 0; relOpts[i]; i++)
{
- reloptions[j].gen = relOpts[i];
- reloptions[j].isset = false;
- j++;
+ if (relOpts[i]->kinds & kind)
+ {
+ reloptions[j].gen = relOpts[i];
+ reloptions[j].isset = false;
+ j++;
+ }
}
}
@@ -1418,8 +1416,10 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
return (bytea *) rdopts;
case RELKIND_RELATION:
case RELKIND_MATVIEW:
- case RELKIND_PARTITIONED_TABLE:
return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
+ case RELKIND_PARTITIONED_TABLE:
+ return default_reloptions(reloptions, validate,
+ RELOPT_KIND_PARTITIONED);
default:
/* other relkinds are not supported */
return NULL;
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index eee5e2f6caf..1cbe7f907ff 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -293,6 +293,7 @@ heap_create(const char *relname,
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
create_storage = false;
/*
@@ -1347,14 +1348,13 @@ heap_create_with_catalog(const char *relname,
if (oncommit != ONCOMMIT_NOOP)
register_on_commit_action(relid, oncommit);
- if (relpersistence == RELPERSISTENCE_UNLOGGED)
- {
- Assert(relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW ||
- relkind == RELKIND_TOASTVALUE ||
- relkind == RELKIND_PARTITIONED_TABLE);
-
+ /*
+ * Unlogged objects need an init fork, except for partitioned tables which
+ * have no storage at all.
+ */
+ if (relpersistence == RELPERSISTENCE_UNLOGGED &&
+ relkind != RELKIND_PARTITIONED_TABLE)
heap_create_init_fork(new_rel_desc);
- }
/*
* ok, the relation has been cataloged, so close our relations and return
@@ -1378,6 +1378,9 @@ heap_create_with_catalog(const char *relname,
void
heap_create_init_fork(Relation rel)
{
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
+ rel->rd_rel->relkind == RELKIND_MATVIEW ||
+ rel->rd_rel->relkind == RELKIND_TOASTVALUE);
RelationOpenSmgr(rel);
smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
@@ -1824,7 +1827,8 @@ heap_drop_with_catalog(Oid relid)
*/
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
{
RelationDropStorage(rel);
}
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 861977a6083..91b2cd7bb2f 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -48,8 +48,9 @@ typedef enum relopt_kind
RELOPT_KIND_SPGIST = (1 << 8),
RELOPT_KIND_VIEW = (1 << 9),
RELOPT_KIND_BRIN = (1 << 10),
+ RELOPT_KIND_PARTITIONED = (1 << 11),
/* if you add a new kind, make sure you update "last_default" too */
- RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_BRIN,
+ RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_PARTITIONED,
/* some compilers treat enums as signed ints, so we can't use 1 << 31 */
RELOPT_KIND_MAX = (1 << 30)
} relopt_kind;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index bee5711da88..d067b757b0f 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201703292
+#define CATALOG_VERSION_NO 201703311
#endif