From 3faf224acea642ce1a536d84a6f2d8e426387449 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 22 Apr 2002 21:46:11 +0000
Subject: [PATCH] Fix incorrect Assert; install a more trustworthy check on
 whether ALTER COLUMN SET STORAGE should be allowed.

---
 src/backend/commands/tablecmds.c | 34 +++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 84e1ae40a5e..49170afd5cb 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.5 2002/04/19 23:13:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.6 2002/04/22 21:46:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -771,10 +771,10 @@ AlterTableAlterColumnFlags(Oid myrelid,
 {
 	Relation	rel;
 	int			newtarget = 1;
-	char        newstorage = 'x';
-	char        *storagemode;
+	char        newstorage = 'p';
 	Relation	attrelation;
 	HeapTuple	tuple;
+	Form_pg_attribute attrtuple;
 
 	rel = heap_open(myrelid, AccessExclusiveLock);
 
@@ -813,9 +813,11 @@ AlterTableAlterColumnFlags(Oid myrelid,
 	else if (*flagType == 'M')
 	{
 		/* STORAGE */
-		Assert(IsA(flagValue, Value));
+		char        *storagemode;
 
+		Assert(IsA(flagValue, String));
 		storagemode = strVal(flagValue);
+
 		if (strcasecmp(storagemode, "plain") == 0)
 			newstorage = 'p';
 		else if (strcasecmp(storagemode, "external") == 0)
@@ -872,26 +874,30 @@ AlterTableAlterColumnFlags(Oid myrelid,
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
 			 RelationGetRelationName(rel), colName);
+	attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
 
-	if (((Form_pg_attribute) GETSTRUCT(tuple))->attnum < 0)
+	if (attrtuple->attnum < 0)
 		elog(ERROR, "ALTER TABLE: cannot change system attribute \"%s\"",
 			 colName);
 	/*
 	 * Now change the appropriate field
 	 */
 	if (*flagType == 'S')
-		((Form_pg_attribute) GETSTRUCT(tuple))->attstattarget = newtarget;
-	else
+		attrtuple->attstattarget = newtarget;
+	else if (*flagType == 'M')
 	{
-		if ((newstorage == 'p') ||
-			(((Form_pg_attribute) GETSTRUCT(tuple))->attlen == -1))
-			((Form_pg_attribute) GETSTRUCT(tuple))->attstorage = newstorage;
+		/*
+		 * safety check: do not allow toasted storage modes unless column
+		 * datatype is TOAST-aware.  We assume the datatype's typstorage
+		 * will be 'p' if and only if it ain't TOAST-aware.
+		 */
+		if (newstorage == 'p' || get_typstorage(attrtuple->atttypid) != 'p')
+			attrtuple->attstorage = newstorage;
 		else
-		{
-			elog(ERROR,
-				 "ALTER TABLE: Fixed-length columns can only have storage \"plain\"");
-		}
+			elog(ERROR, "ALTER TABLE: Column datatype %s can only have storage \"plain\"",
+				 format_type_be(attrtuple->atttypid));
 	}
+
 	simple_heap_update(attrelation, &tuple->t_self, tuple);
 
 	/* keep system catalog indices current */
-- 
GitLab