1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-29 10:41:53 +03:00

Remove support for unlogged on partitioned tables

The following commands were allowed on partitioned tables, with
different effects:
1) ALTER TABLE SET [UN]LOGGED did not issue an error, and did not update
pg_class.relpersistence.
2) CREATE UNLOGGED TABLE was working with pg_class.relpersistence marked
as initially defined, but partitions did not inherit the UNLOGGED
property, which was confusing.

This commit causes the commands mentioned above to fail for partitioned
tables, instead.

pg_dump is tweaked so as partitioned tables marked as UNLOGGED ignore
the option when dumped from older server versions.  pgbench needs a
tweak for --unlogged and --partitions=N to ignore the UNLOGGED option on
the partitioned tables created, its partitions still being unlogged.

Author: Michael Paquier
Reviewed-by: Nathan Bossart
Discussion: https://postgr.es/m/ZiiyGFTBNkqcMQi_@paquier.xyz
This commit is contained in:
Michael Paquier
2024-10-03 10:55:02 +09:00
parent 554d3a18f3
commit e2bab2d792
7 changed files with 38 additions and 4 deletions

View File

@ -797,6 +797,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
(for identity or serial columns). However, it is also possible to (for identity or serial columns). However, it is also possible to
change the persistence of such sequences separately. change the persistence of such sequences separately.
</para> </para>
<para>
This form is not supported for partitioned tables.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -220,6 +220,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
If this is specified, any sequences created together with the unlogged If this is specified, any sequences created together with the unlogged
table (for identity or serial columns) are also created as unlogged. table (for identity or serial columns) are also created as unlogged.
</para> </para>
<para>
This form is not supported for partitioned tables.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -734,6 +734,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
else else
partitioned = false; partitioned = false;
if (relkind == RELKIND_PARTITIONED_TABLE &&
stmt->relation->relpersistence == RELPERSISTENCE_UNLOGGED)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("partitioned tables cannot be unlogged")));
/* /*
* Look up the namespace in which we are supposed to create the relation, * Look up the namespace in which we are supposed to create the relation,
* check we have permission to create there, lock it against concurrent * check we have permission to create there, lock it against concurrent
@ -4993,8 +4999,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
break; break;
case AT_SetLogged: /* SET LOGGED */ case AT_SetLogged: /* SET LOGGED */
case AT_SetUnLogged: /* SET UNLOGGED */ case AT_SetUnLogged: /* SET UNLOGGED */
ATSimplePermissions(cmd->subtype, rel, ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_SEQUENCE);
ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_SEQUENCE);
if (tab->chgPersistence) if (tab->chgPersistence)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

View File

@ -15915,8 +15915,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
binary_upgrade_set_pg_class_oids(fout, q, binary_upgrade_set_pg_class_oids(fout, q,
tbinfo->dobj.catId.oid); tbinfo->dobj.catId.oid);
/*
* PostgreSQL 18 has disabled UNLOGGED for partitioned tables, so
* ignore it when dumping if it was set in this case.
*/
appendPQExpBuffer(q, "CREATE %s%s %s", appendPQExpBuffer(q, "CREATE %s%s %s",
tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED &&
tbinfo->relkind != RELKIND_PARTITIONED_TABLE) ?
"UNLOGGED " : "", "UNLOGGED " : "",
reltypename, reltypename,
qualrelname); qualrelname);

View File

@ -4865,7 +4865,7 @@ initCreateTables(PGconn *con)
/* Construct new create table statement. */ /* Construct new create table statement. */
printfPQExpBuffer(&query, "create%s table %s(%s)", printfPQExpBuffer(&query, "create%s table %s(%s)",
unlogged_tables ? " unlogged" : "", (unlogged_tables && partition_method == PART_NONE) ? " unlogged" : "",
ddl->table, ddl->table,
(scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols); (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);

View File

@ -50,6 +50,16 @@ ERROR: cannot create temporary relation in non-temporary schema
LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key); LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key);
^ ^
DROP TABLE unlogged1, public.unlogged2; DROP TABLE unlogged1, public.unlogged2;
CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail
ERROR: partitioned tables cannot be unlogged
CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok
ALTER TABLE unlogged1 SET LOGGED; -- fails
ERROR: ALTER action SET LOGGED cannot be performed on relation "unlogged1"
DETAIL: This operation is not supported for partitioned tables.
ALTER TABLE unlogged1 SET UNLOGGED; -- fails
ERROR: ALTER action SET UNLOGGED cannot be performed on relation "unlogged1"
DETAIL: This operation is not supported for partitioned tables.
DROP TABLE unlogged1;
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
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 ERROR: relation "as_select1" already exists

View File

@ -30,6 +30,12 @@ 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 CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
DROP TABLE unlogged1, public.unlogged2; DROP TABLE unlogged1, public.unlogged2;
CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail
CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok
ALTER TABLE unlogged1 SET LOGGED; -- fails
ALTER TABLE unlogged1 SET UNLOGGED; -- fails
DROP TABLE unlogged1;
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';