@@ -593,7 +593,7 @@ static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKM
593593static void ATExecGenericOptions(Relation rel, List *options);
594594static void ATExecSetRowSecurity(Relation rel, bool rls);
595595static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
596- static ObjectAddress ATExecSetCompression(AlteredTableInfo *tab, Relation rel,
596+ static ObjectAddress ATExecSetCompression(Relation rel,
597597 const char *column, Node *newValue, LOCKMODE lockmode);
598598
599599static void index_copy_data(Relation rel, RelFileLocator newrlocator);
@@ -633,6 +633,7 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
633633static List *GetParentedForeignKeyRefs(Relation partition);
634634static void ATDetachCheckNoForeignKeyRefs(Relation partition);
635635static char GetAttributeCompression(Oid atttypid, char *compression);
636+ static char GetAttributeStorage(Oid atttypid, const char *storagemode);
636637
637638
638639/* ----------------------------------------------------------------
@@ -931,6 +932,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
931932 if (colDef->compression)
932933 attr->attcompression = GetAttributeCompression(attr->atttypid,
933934 colDef->compression);
935+
936+ if (colDef->storage_name)
937+ attr->attstorage = GetAttributeStorage(attr->atttypid, colDef->storage_name);
934938 }
935939
936940 /*
@@ -4963,8 +4967,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
49634967 case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
49644968 address = ATExecSetStorage(rel, cmd->name, cmd->def, lockmode);
49654969 break;
4966- case AT_SetCompression:
4967- address = ATExecSetCompression(tab, rel, cmd->name, cmd->def,
4970+ case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
4971+ address = ATExecSetCompression(rel, cmd->name, cmd->def,
49684972 lockmode);
49694973 break;
49704974 case AT_DropColumn: /* DROP COLUMN */
@@ -6820,7 +6824,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
68206824 attribute.atttypmod = typmod;
68216825 attribute.attbyval = tform->typbyval;
68226826 attribute.attalign = tform->typalign;
6823- attribute.attstorage = tform->typstorage;
6827+ if (colDef->storage_name)
6828+ attribute.attstorage = GetAttributeStorage(typeOid, colDef->storage_name);
6829+ else
6830+ attribute.attstorage = tform->typstorage;
68246831 attribute.attcompression = GetAttributeCompression(typeOid,
68256832 colDef->compression);
68266833 attribute.attnotnull = colDef->is_not_null;
@@ -8263,33 +8270,12 @@ SetIndexStorageProperties(Relation rel, Relation attrelation,
82638270static ObjectAddress
82648271ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
82658272{
8266- char *storagemode;
8267- char newstorage;
82688273 Relation attrelation;
82698274 HeapTuple tuple;
82708275 Form_pg_attribute attrtuple;
82718276 AttrNumber attnum;
82728277 ObjectAddress address;
82738278
8274- storagemode = strVal(newValue);
8275-
8276- if (pg_strcasecmp(storagemode, "plain") == 0)
8277- newstorage = TYPSTORAGE_PLAIN;
8278- else if (pg_strcasecmp(storagemode, "external") == 0)
8279- newstorage = TYPSTORAGE_EXTERNAL;
8280- else if (pg_strcasecmp(storagemode, "extended") == 0)
8281- newstorage = TYPSTORAGE_EXTENDED;
8282- else if (pg_strcasecmp(storagemode, "main") == 0)
8283- newstorage = TYPSTORAGE_MAIN;
8284- else
8285- {
8286- ereport(ERROR,
8287- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8288- errmsg("invalid storage type \"%s\"",
8289- storagemode)));
8290- newstorage = 0; /* keep compiler quiet */
8291- }
8292-
82938279 attrelation = table_open(AttributeRelationId, RowExclusiveLock);
82948280
82958281 tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
@@ -8308,35 +8294,25 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
83088294 errmsg("cannot alter system column \"%s\"",
83098295 colName)));
83108296
8311- /*
8312- * safety check: do not allow toasted storage modes unless column datatype
8313- * is TOAST-aware.
8314- */
8315- if (newstorage == TYPSTORAGE_PLAIN || TypeIsToastable(attrtuple->atttypid))
8316- attrtuple->attstorage = newstorage;
8317- else
8318- ereport(ERROR,
8319- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8320- errmsg("column data type %s can only have storage PLAIN",
8321- format_type_be(attrtuple->atttypid))));
8297+ attrtuple->attstorage = GetAttributeStorage(attrtuple->atttypid, strVal(newValue));
83228298
83238299 CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
83248300
83258301 InvokeObjectPostAlterHook(RelationRelationId,
83268302 RelationGetRelid(rel),
83278303 attrtuple->attnum);
83288304
8329- heap_freetuple(tuple);
8330-
83318305 /*
83328306 * Apply the change to indexes as well (only for simple index columns,
83338307 * matching behavior of index.c ConstructTupleDescriptor()).
83348308 */
83358309 SetIndexStorageProperties(rel, attrelation, attnum,
8336- true, newstorage ,
8310+ true, attrtuple->attstorage ,
83378311 false, 0,
83388312 lockmode);
83398313
8314+ heap_freetuple(tuple);
8315+
83408316 table_close(attrelation, RowExclusiveLock);
83418317
83428318 ObjectAddressSubSet(address, RelationRelationId,
@@ -16156,8 +16132,7 @@ ATExecGenericOptions(Relation rel, List *options)
1615616132 * Return value is the address of the modified column
1615716133 */
1615816134static ObjectAddress
16159- ATExecSetCompression(AlteredTableInfo *tab,
16160- Relation rel,
16135+ ATExecSetCompression(Relation rel,
1616116136 const char *column,
1616216137 Node *newValue,
1616316138 LOCKMODE lockmode)
@@ -19287,3 +19262,38 @@ GetAttributeCompression(Oid atttypid, char *compression)
1928719262
1928819263 return cmethod;
1928919264}
19265+
19266+ /*
19267+ * resolve column storage specification
19268+ */
19269+ static char
19270+ GetAttributeStorage(Oid atttypid, const char *storagemode)
19271+ {
19272+ char cstorage = 0;
19273+
19274+ if (pg_strcasecmp(storagemode, "plain") == 0)
19275+ cstorage = TYPSTORAGE_PLAIN;
19276+ else if (pg_strcasecmp(storagemode, "external") == 0)
19277+ cstorage = TYPSTORAGE_EXTERNAL;
19278+ else if (pg_strcasecmp(storagemode, "extended") == 0)
19279+ cstorage = TYPSTORAGE_EXTENDED;
19280+ else if (pg_strcasecmp(storagemode, "main") == 0)
19281+ cstorage = TYPSTORAGE_MAIN;
19282+ else
19283+ ereport(ERROR,
19284+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
19285+ errmsg("invalid storage type \"%s\"",
19286+ storagemode)));
19287+
19288+ /*
19289+ * safety check: do not allow toasted storage modes unless column datatype
19290+ * is TOAST-aware.
19291+ */
19292+ if (!(cstorage == TYPSTORAGE_PLAIN || TypeIsToastable(atttypid)))
19293+ ereport(ERROR,
19294+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
19295+ errmsg("column data type %s can only have storage PLAIN",
19296+ format_type_be(atttypid))));
19297+
19298+ return cstorage;
19299+ }
0 commit comments