On Wed, Jun 11, 2014 at 1:19 PM, Fabrízio de Royes Mello <
fabriziome...@gmail.com> wrote:

> Hi all,
>
> As part of GSoC2014 I'm sending a patch to add the capability of change an
> unlogged table to logged [1].
>
>
Hi all,

As part of GSoC2014 and with agreement of my mentor and reviewer (Stephen
Frost) I've send a complement of the first patch to add the capability to
change a regular table to unlogged.

With this patch we finish the main goals of the GSoC2014 and now we'll work
in the additional goals.

Regards,


[1]
https://wiki.postgresql.org/wiki/Allow_an_unlogged_table_to_be_changed_to_logged_GSoC_2014

-- 
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL
>> Timbira: http://www.timbira.com.br
>> Blog sobre TI: http://fabriziomello.blogspot.com
>> Perfil Linkedin: http://br.linkedin.com/in/fabriziomello
>> Twitter: http://twitter.com/fabriziomello
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 69a1e14..424f2e9 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -58,6 +58,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     ENABLE REPLICA RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
     ENABLE ALWAYS RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
     CLUSTER ON <replaceable class="PARAMETER">index_name</replaceable>
+    SET {LOGGED | UNLOGGED}
     SET WITHOUT CLUSTER
     SET WITH OIDS
     SET WITHOUT OIDS
@@ -432,6 +433,20 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
    </varlistentry>
 
    <varlistentry>
+    <term><literal>SET {LOGGED | UNLOGGED}</literal></term>
+    <listitem>
+     <para>
+      This form change the table persistence type from unlogged to permanent or 
+      from unlogged to permanent by rewriting the entire contents of the table 
+      and associated indexes into new disk files.
+     </para>
+     <para>
+      Changing the table persistence type acquires an <literal>ACCESS EXCLUSIVE</literal> lock.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
     <term><literal>SET WITHOUT CLUSTER</literal></term>
     <listitem>
      <para>
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 60d387a..9dfdca2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -125,18 +125,19 @@ static List *on_commits = NIL;
  * a pass determined by subcommand type.
  */
 
-#define AT_PASS_UNSET			-1		/* UNSET will cause ERROR */
-#define AT_PASS_DROP			0		/* DROP (all flavors) */
-#define AT_PASS_ALTER_TYPE		1		/* ALTER COLUMN TYPE */
-#define AT_PASS_OLD_INDEX		2		/* re-add existing indexes */
-#define AT_PASS_OLD_CONSTR		3		/* re-add existing constraints */
-#define AT_PASS_COL_ATTRS		4		/* set other column attributes */
+#define AT_PASS_UNSET				-1		/* UNSET will cause ERROR */
+#define AT_PASS_DROP				0		/* DROP (all flavors) */
+#define AT_PASS_ALTER_TYPE			1		/* ALTER COLUMN TYPE */
+#define AT_PASS_OLD_INDEX			2		/* re-add existing indexes */
+#define AT_PASS_OLD_CONSTR			3		/* re-add existing constraints */
+#define AT_PASS_COL_ATTRS			4		/* set other column attributes */
 /* We could support a RENAME COLUMN pass here, but not currently used */
-#define AT_PASS_ADD_COL			5		/* ADD COLUMN */
-#define AT_PASS_ADD_INDEX		6		/* ADD indexes */
-#define AT_PASS_ADD_CONSTR		7		/* ADD constraints, defaults */
-#define AT_PASS_MISC			8		/* other stuff */
-#define AT_NUM_PASSES			9
+#define AT_PASS_ADD_COL				5		/* ADD COLUMN */
+#define AT_PASS_ADD_INDEX			6		/* ADD indexes */
+#define AT_PASS_ADD_CONSTR			7		/* ADD constraints, defaults */
+#define AT_PASS_MISC				8		/* other stuff */
+#define AT_PASS_SET_LOGGED_UNLOGGED	9		/* SET LOGGED and UNLOGGED */
+#define AT_NUM_PASSES				10
 
 typedef struct AlteredTableInfo
 {
@@ -376,6 +377,7 @@ static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMOD
 static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
 					 char *cmd, List **wqueue, LOCKMODE lockmode,
 					 bool rewrite);
+static void ATPostAlterSetLoggedUnlogged(Oid relid);
 static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
 static void TryReuseForeignKey(Oid oldId, Constraint *con);
 static void change_owner_fix_column_acls(Oid relationOid,
@@ -402,6 +404,13 @@ static void ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockm
 static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
 static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
 static void ATExecGenericOptions(Relation rel, List *options);
+static void ATPrepSetLogged(Relation rel);
+static void ATPrepSetUnLogged(Relation rel);
+static void ATExecSetLogged(Relation rel);
+static void ATExecSetUnLogged(Relation rel);
+
+static void AlterTableSetLoggedCheckForeignConstraints(Relation rel);
+static void AlterTableSetLoggedOrUnlogged(Relation rel, bool toLogged);
 
 static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
 				   ForkNumber forkNum, char relpersistence);
@@ -2854,6 +2863,8 @@ AlterTableGetLockLevel(List *cmds)
 			case AT_AddIndexConstraint:
 			case AT_ReplicaIdentity:
 			case AT_SetNotNull:
+			case AT_SetLogged:
+			case AT_SetUnLogged:
 				cmd_lockmode = AccessExclusiveLock;
 				break;
 
@@ -3245,6 +3256,15 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			/* No command-specific prep needed */
 			pass = AT_PASS_MISC;
 			break;
+		case AT_SetLogged:
+		case AT_SetUnLogged:
+			ATSimplePermissions(rel, ATT_TABLE);
+			if (cmd->subtype == AT_SetLogged)
+				ATPrepSetLogged(rel);			/* SET LOGGED */
+			else
+				ATPrepSetUnLogged(rel);			/* SET UNLOGGED */
+			pass = AT_PASS_SET_LOGGED_UNLOGGED;
+			break;
 		default:				/* oops */
 			elog(ERROR, "unrecognized alter table type: %d",
 				 (int) cmd->subtype);
@@ -3307,6 +3327,9 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
 				ATPostAlterTypeCleanup(wqueue, tab, lockmode);
 
 			relation_close(rel, NoLock);
+
+			if (pass == AT_PASS_SET_LOGGED_UNLOGGED)
+				ATPostAlterSetLoggedUnlogged(RelationGetRelid(rel));
 		}
 	}
 
@@ -3526,6 +3549,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		case AT_GenericOptions:
 			ATExecGenericOptions(rel, (List *) cmd->def);
 			break;
+		case AT_SetLogged:
+			ATExecSetLogged(rel);
+			break;
+		case AT_SetUnLogged:
+			ATExecSetUnLogged(rel);
+			break;
 		default:				/* oops */
 			elog(ERROR, "unrecognized alter table type: %d",
 				 (int) cmd->subtype);
@@ -10419,6 +10448,226 @@ ATExecGenericOptions(Relation rel, List *options)
 }
 
 /*
+ * ALTER TABLE <name> SET LOGGED
+ *
+ * Change the table persistence type from unlogged to permanent by
+ * rewriting the entire contents of the table and associated indexes
+ * into new disk files.
+ *
+ * The ATPrepSetLogged function check all precondictions to perform
+ * the operation:
+ * - check if the target table is unlogged
+ * - check if not exists a foreign key to other unlogged table
+ */
+static void
+ATPrepSetLogged(Relation rel)
+{
+	/* check if is an unlogged relation */
+	if (rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+				 errmsg("table %s is not unlogged",
+				 RelationGetRelationName(rel))));
+
+	/* check fk constraints */
+	AlterTableSetLoggedCheckForeignConstraints(rel);
+}
+
+static void
+AlterTableSetLoggedCheckForeignConstraints(Relation rel)
+{
+	Relation	pg_constraint;
+	HeapTuple	tuple;
+	SysScanDesc scan;
+	ScanKeyData skey[1];
+
+	/*
+	 * Fetch the constraint tuple from pg_constraint.
+	 */
+	pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
+
+	ScanKeyInit(&skey[0],
+				Anum_pg_constraint_conrelid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelationGetRelid(rel)));
+
+	scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
+				  NULL, 1, skey);
+
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+		if (con->contype == CONSTRAINT_FOREIGN)
+		{
+			Relation relfk = relation_open(con->confrelid, AccessShareLock);
+
+			if (RelationGetRelid(rel) != con->confrelid &&
+				relfk->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+						 errmsg("table %s references unlogged table %s",
+								 RelationGetRelationName(rel),
+								 RelationGetRelationName(relfk))));
+
+			relation_close(relfk, AccessShareLock);
+		}
+	}
+
+	systable_endscan(scan);
+
+	heap_close(pg_constraint, AccessShareLock);
+}
+
+/*
+ * ALTER TABLE <name> SET UNLOGGED
+ *
+ * Change the table persistence type from permanent to unlogged by
+ * rewriting the entire contents of the table and associated indexes
+ * into new disk files.
+ *
+ * The ATPrepSetUnLogged function check all precondictions to perform
+ * the operation:
+ * - check if the target table is permanent
+ */
+static void
+ATPrepSetUnLogged(Relation rel)
+{
+	/* check if is an permanent relation */
+	if (rel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+				 errmsg("table %s is not permanent",
+				 RelationGetRelationName(rel))));
+}
+
+/*
+ * The AlterTableChangeCatalogToLoggedOrUnlogged function perform the 
+ * catalog changes, i.e. update pg_class.relpersistence to 'p' or 'u'
+ */
+static void
+AlterTableChangeCatalogToLoggedOrUnlogged(Relation rel, Relation relrelation, bool toLogged)
+{
+	HeapTuple		tuple;
+	Form_pg_class	pg_class_form;
+
+	tuple = SearchSysCacheCopy1(RELOID,
+								 ObjectIdGetDatum(RelationGetRelid(rel)));
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for relation %u",
+			 RelationGetRelid(rel));
+
+	pg_class_form = (Form_pg_class) GETSTRUCT(tuple);
+
+	Assert(pg_class_form->relpersistence ==
+		((toLogged) ? RELPERSISTENCE_UNLOGGED : RELPERSISTENCE_PERMANENT));
+
+	pg_class_form->relpersistence = toLogged ?
+			RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
+
+	simple_heap_update(relrelation, &tuple->t_self, tuple);
+
+	/* keep catalog indexes current */
+	CatalogUpdateIndexes(relrelation, tuple);
+
+	heap_freetuple(tuple);
+}
+
+/*
+ * ALTER TABLE <name> SET LOGGED
+ *
+ * The ATExecSetLogged execute the code to change a relation from
+ * a unlogged to persistence state
+ */
+static void
+ATExecSetLogged(Relation rel)
+{
+	AlterTableSetLoggedOrUnlogged(rel, true);
+}
+
+/*
+ * ALTER TABLE <name> SET UNLOGGED
+ *
+ * The ATExecSetUnLogged execute the code to change a relation from
+ * a persistence to unlogged state
+ */
+static void
+ATExecSetUnLogged(Relation rel)
+{
+	AlterTableSetLoggedOrUnlogged(rel, false);
+}
+
+/*
+ * The AlterTableSetLoggedOrUnlogged function contains the main logic
+ * of the operation, changing the catalog for main heap, toast and indexes
+ */
+static void
+AlterTableSetLoggedOrUnlogged(Relation rel, bool toLogged)
+{
+	Oid			relid;
+	Relation	indexRelation;
+	ScanKeyData skey;
+	SysScanDesc scan;
+	HeapTuple	indexTuple;
+	Relation	relrel;
+
+	relid = RelationGetRelid(rel);
+
+	/* open pg_class to update relpersistence */
+	relrel = heap_open(RelationRelationId, RowExclusiveLock);
+
+	/* main heap */
+	AlterTableChangeCatalogToLoggedOrUnlogged(rel, relrel, toLogged);
+
+	/* toast heap, if any */
+	if (OidIsValid(rel->rd_rel->reltoastrelid))
+	{
+		Relation	toastrel;
+
+		toastrel = heap_open(rel->rd_rel->reltoastrelid, AccessShareLock);
+		AlterTableChangeCatalogToLoggedOrUnlogged(toastrel, relrel, toLogged);
+		heap_close(toastrel, AccessShareLock);
+	}
+
+	/* Prepare to scan pg_index for entries having indrelid = this rel. */
+	indexRelation = heap_open(IndexRelationId, AccessShareLock);
+	ScanKeyInit(&skey,
+				Anum_pg_index_indrelid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				relid);
+
+	scan = systable_beginscan(indexRelation, IndexIndrelidIndexId, true,
+							  NULL, 1, &skey);
+
+	while (HeapTupleIsValid(indexTuple = systable_getnext(scan)))
+	{
+		Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
+		Relation indxrel = index_open(index->indexrelid, AccessShareLock);
+
+		AlterTableChangeCatalogToLoggedOrUnlogged(indxrel, relrel, toLogged);
+
+		index_close(indxrel, AccessShareLock);
+	}
+
+	systable_endscan(scan);
+	heap_close(indexRelation, AccessShareLock);
+
+	heap_close(relrel, RowExclusiveLock);
+}
+
+/*
+ * ALTER TABLE <name> SET { LOGGED | UNLOGGED }
+ *
+ * The ATPostAlterSetLoggedUnlogged function is called after all to
+ * guarantee that heap is closed to perform the cluster_rel
+ */
+static void
+ATPostAlterSetLoggedUnlogged(Oid relid)
+{
+	/* rebuild the relation using CLUSTER algorithm */
+	cluster_rel(relid, InvalidOid, false, false);
+}
+
+/*
  * Execute ALTER TABLE SET SCHEMA
  */
 Oid
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 605c9b4..a784d73 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -566,7 +566,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 	LABEL LANGUAGE LARGE_P LAST_P LATERAL_P LC_COLLATE_P LC_CTYPE_P
 	LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
-	LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P
+	LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOGGED
 
 	MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
 
@@ -2201,6 +2201,20 @@ alter_table_cmd:
 					n->def = $3;
 					$$ = (Node *)n;
 				}
+			/* ALTER TABLE <name> SET LOGGED  */
+			| SET LOGGED
+				{
+					AlterTableCmd *n = makeNode(AlterTableCmd);
+					n->subtype = AT_SetLogged;
+					$$ = (Node *)n;
+				}
+			/* ALTER TABLE <name> SET UNLOGGED  */
+			| SET UNLOGGED
+				{
+					AlterTableCmd *n = makeNode(AlterTableCmd);
+					n->subtype = AT_SetUnLogged;
+					$$ = (Node *)n;
+				}
 			| alter_generic_options
 				{
 					AlterTableCmd *n = makeNode(AlterTableCmd);
@@ -12967,6 +12981,7 @@ unreserved_keyword:
 			| LOCAL
 			| LOCATION
 			| LOCK_P
+			| LOGGED
 			| MAPPING
 			| MATCH
 			| MATERIALIZED
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index be5c3c5..f2a2759 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1641,7 +1641,7 @@ psql_completion(const char *text, int start, int end)
 			 pg_strcasecmp(prev_wd, "SET") == 0)
 	{
 		static const char *const list_TABLESET[] =
-		{"(", "WITHOUT", "TABLESPACE", "SCHEMA", NULL};
+		{"(", "WITHOUT", "TABLESPACE", "SCHEMA", "LOGGED", "UNLOGGED", NULL};
 
 		COMPLETE_WITH_LIST(list_TABLESET);
 	}
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ff126eb..dc9f8fa 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1331,7 +1331,9 @@ typedef enum AlterTableType
 	AT_AddOf,					/* OF <type_name> */
 	AT_DropOf,					/* NOT OF */
 	AT_ReplicaIdentity,			/* REPLICA IDENTITY */
-	AT_GenericOptions			/* OPTIONS (...) */
+	AT_GenericOptions,			/* OPTIONS (...) */
+	AT_SetLogged,				/* SET LOGGED */
+	AT_SetUnLogged				/* SET UNLOGGED */
 } AlterTableType;
 
 typedef struct ReplicaIdentityStmt
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 61fae22..b62ce0e 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -231,6 +231,7 @@ PG_KEYWORD("localtime", LOCALTIME, RESERVED_KEYWORD)
 PG_KEYWORD("localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD)
 PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD)
 PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD)
 PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD)
 PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD)
 PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD)
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 9b89e58..516627e 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2426,3 +2426,60 @@ TRUNCATE old_system_table;
 ALTER TABLE old_system_table DROP CONSTRAINT new_system_table_pkey;
 ALTER TABLE old_system_table DROP COLUMN othercol;
 DROP TABLE old_system_table;
+-- set logged
+CREATE UNLOGGED TABLE unlogged1(f1 SERIAL PRIMARY KEY);
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^unlogged1' ORDER BY 1;
+     relname      | relpersistence | original_relfilenode 
+------------------+----------------+----------------------
+ unlogged1        | u              | t
+ unlogged1_f1_seq | p              | t
+ unlogged1_pkey   | u              | t
+(3 rows)
+
+CREATE UNLOGGED TABLE unlogged2(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES unlogged1); -- fk reference
+CREATE UNLOGGED TABLE unlogged3(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES unlogged3); -- self fk reference
+ALTER TABLE unlogged3 SET LOGGED;
+ALTER TABLE unlogged2 SET LOGGED;
+ERROR:  table unlogged2 references unlogged table unlogged1
+ALTER TABLE unlogged1 SET LOGGED;
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^unlogged1' ORDER BY 1;
+     relname      | relpersistence | original_relfilenode 
+------------------+----------------+----------------------
+ unlogged1        | p              | f
+ unlogged1_f1_seq | p              | t
+ unlogged1_pkey   | p              | f
+(3 rows)
+
+ALTER TABLE unlogged1 SET LOGGED;
+ERROR:  table unlogged1 is not unlogged
+DROP TABLE unlogged3;
+DROP TABLE unlogged2;
+DROP TABLE unlogged1;
+-- set unlogged
+CREATE TABLE logged1(f1 SERIAL PRIMARY KEY);
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^logged1' ORDER BY 1;
+    relname     | relpersistence | original_relfilenode 
+----------------+----------------+----------------------
+ logged1        | p              | t
+ logged1_f1_seq | p              | t
+ logged1_pkey   | p              | t
+(3 rows)
+
+CREATE TABLE logged2(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES logged1); -- fk reference
+CREATE TABLE logged3(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES logged3); -- self fk reference
+ALTER TABLE logged3 SET UNLOGGED;
+ALTER TABLE logged2 SET UNLOGGED;
+ALTER TABLE logged1 SET UNLOGGED;
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^logged1' ORDER BY 1;
+    relname     | relpersistence | original_relfilenode 
+----------------+----------------+----------------------
+ logged1        | u              | f
+ logged1_f1_seq | p              | t
+ logged1_pkey   | u              | f
+(3 rows)
+
+ALTER TABLE logged1 SET UNLOGGED;
+ERROR:  table logged1 is not permanent
+DROP TABLE logged3;
+DROP TABLE logged2;
+DROP TABLE logged1;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 22a2dd0..26f7375 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1624,3 +1624,32 @@ TRUNCATE old_system_table;
 ALTER TABLE old_system_table DROP CONSTRAINT new_system_table_pkey;
 ALTER TABLE old_system_table DROP COLUMN othercol;
 DROP TABLE old_system_table;
+
+-- set logged
+CREATE UNLOGGED TABLE unlogged1(f1 SERIAL PRIMARY KEY);
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^unlogged1' ORDER BY 1;
+CREATE UNLOGGED TABLE unlogged2(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES unlogged1); -- fk reference
+CREATE UNLOGGED TABLE unlogged3(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES unlogged3); -- self fk reference
+ALTER TABLE unlogged3 SET LOGGED;
+ALTER TABLE unlogged2 SET LOGGED;
+ALTER TABLE unlogged1 SET LOGGED;
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^unlogged1' ORDER BY 1;
+ALTER TABLE unlogged1 SET LOGGED;
+DROP TABLE unlogged3;
+DROP TABLE unlogged2;
+DROP TABLE unlogged1;
+
+-- set unlogged
+CREATE TABLE logged1(f1 SERIAL PRIMARY KEY);
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^logged1' ORDER BY 1;
+CREATE TABLE logged2(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES logged1); -- fk reference
+CREATE TABLE logged3(f1 SERIAL PRIMARY KEY, f2 INTEGER REFERENCES logged3); -- self fk reference
+ALTER TABLE logged3 SET UNLOGGED;
+ALTER TABLE logged2 SET UNLOGGED;
+ALTER TABLE logged1 SET UNLOGGED;
+SELECT relname, relpersistence, oid = relfilenode AS original_relfilenode FROM pg_class WHERE relname ~ '^logged1' ORDER BY 1;
+ALTER TABLE logged1 SET UNLOGGED;
+DROP TABLE logged3;
+DROP TABLE logged2;
+DROP TABLE logged1;
+
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to