mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Allow specifying STORAGE attribute for a new table
Previously, the STORAGE specification was only available in ALTER TABLE. This makes it available in CREATE TABLE as well. Also make the code and the documentation for STORAGE and COMPRESSION attributes consistent. Author: Teodor Sigaev <teodor@sigaev.ru> Author: Aleksander Alekseev <aleksander@timescale.com> Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com> Reviewed-by: wenjing zeng <wjzeng2012@gmail.com> Reviewed-by: Matthias van de Meent <boekewurm+postgres@gmail.com> Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Discussion: https://postgr.es/m/de83407a-ae3d-a8e1-a788-920eb334f25b@sigaev.ru
This commit is contained in:
@ -593,7 +593,7 @@ static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKM
|
||||
static void ATExecGenericOptions(Relation rel, List *options);
|
||||
static void ATExecSetRowSecurity(Relation rel, bool rls);
|
||||
static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
|
||||
static ObjectAddress ATExecSetCompression(AlteredTableInfo *tab, Relation rel,
|
||||
static ObjectAddress ATExecSetCompression(Relation rel,
|
||||
const char *column, Node *newValue, LOCKMODE lockmode);
|
||||
|
||||
static void index_copy_data(Relation rel, RelFileLocator newrlocator);
|
||||
@ -633,6 +633,7 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
|
||||
static List *GetParentedForeignKeyRefs(Relation partition);
|
||||
static void ATDetachCheckNoForeignKeyRefs(Relation partition);
|
||||
static char GetAttributeCompression(Oid atttypid, char *compression);
|
||||
static char GetAttributeStorage(Oid atttypid, const char *storagemode);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -931,6 +932,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
||||
if (colDef->compression)
|
||||
attr->attcompression = GetAttributeCompression(attr->atttypid,
|
||||
colDef->compression);
|
||||
|
||||
if (colDef->storage_name)
|
||||
attr->attstorage = GetAttributeStorage(attr->atttypid, colDef->storage_name);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4963,8 +4967,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
|
||||
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
|
||||
address = ATExecSetStorage(rel, cmd->name, cmd->def, lockmode);
|
||||
break;
|
||||
case AT_SetCompression:
|
||||
address = ATExecSetCompression(tab, rel, cmd->name, cmd->def,
|
||||
case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
|
||||
address = ATExecSetCompression(rel, cmd->name, cmd->def,
|
||||
lockmode);
|
||||
break;
|
||||
case AT_DropColumn: /* DROP COLUMN */
|
||||
@ -6820,7 +6824,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
attribute.atttypmod = typmod;
|
||||
attribute.attbyval = tform->typbyval;
|
||||
attribute.attalign = tform->typalign;
|
||||
attribute.attstorage = tform->typstorage;
|
||||
if (colDef->storage_name)
|
||||
attribute.attstorage = GetAttributeStorage(typeOid, colDef->storage_name);
|
||||
else
|
||||
attribute.attstorage = tform->typstorage;
|
||||
attribute.attcompression = GetAttributeCompression(typeOid,
|
||||
colDef->compression);
|
||||
attribute.attnotnull = colDef->is_not_null;
|
||||
@ -8263,33 +8270,12 @@ SetIndexStorageProperties(Relation rel, Relation attrelation,
|
||||
static ObjectAddress
|
||||
ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
|
||||
{
|
||||
char *storagemode;
|
||||
char newstorage;
|
||||
Relation attrelation;
|
||||
HeapTuple tuple;
|
||||
Form_pg_attribute attrtuple;
|
||||
AttrNumber attnum;
|
||||
ObjectAddress address;
|
||||
|
||||
storagemode = strVal(newValue);
|
||||
|
||||
if (pg_strcasecmp(storagemode, "plain") == 0)
|
||||
newstorage = TYPSTORAGE_PLAIN;
|
||||
else if (pg_strcasecmp(storagemode, "external") == 0)
|
||||
newstorage = TYPSTORAGE_EXTERNAL;
|
||||
else if (pg_strcasecmp(storagemode, "extended") == 0)
|
||||
newstorage = TYPSTORAGE_EXTENDED;
|
||||
else if (pg_strcasecmp(storagemode, "main") == 0)
|
||||
newstorage = TYPSTORAGE_MAIN;
|
||||
else
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid storage type \"%s\"",
|
||||
storagemode)));
|
||||
newstorage = 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
attrelation = table_open(AttributeRelationId, RowExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
|
||||
@ -8308,17 +8294,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
|
||||
errmsg("cannot alter system column \"%s\"",
|
||||
colName)));
|
||||
|
||||
/*
|
||||
* safety check: do not allow toasted storage modes unless column datatype
|
||||
* is TOAST-aware.
|
||||
*/
|
||||
if (newstorage == TYPSTORAGE_PLAIN || TypeIsToastable(attrtuple->atttypid))
|
||||
attrtuple->attstorage = newstorage;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column data type %s can only have storage PLAIN",
|
||||
format_type_be(attrtuple->atttypid))));
|
||||
attrtuple->attstorage = GetAttributeStorage(attrtuple->atttypid, strVal(newValue));
|
||||
|
||||
CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
|
||||
|
||||
@ -8326,17 +8302,17 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
|
||||
RelationGetRelid(rel),
|
||||
attrtuple->attnum);
|
||||
|
||||
heap_freetuple(tuple);
|
||||
|
||||
/*
|
||||
* Apply the change to indexes as well (only for simple index columns,
|
||||
* matching behavior of index.c ConstructTupleDescriptor()).
|
||||
*/
|
||||
SetIndexStorageProperties(rel, attrelation, attnum,
|
||||
true, newstorage,
|
||||
true, attrtuple->attstorage,
|
||||
false, 0,
|
||||
lockmode);
|
||||
|
||||
heap_freetuple(tuple);
|
||||
|
||||
table_close(attrelation, RowExclusiveLock);
|
||||
|
||||
ObjectAddressSubSet(address, RelationRelationId,
|
||||
@ -16156,8 +16132,7 @@ ATExecGenericOptions(Relation rel, List *options)
|
||||
* Return value is the address of the modified column
|
||||
*/
|
||||
static ObjectAddress
|
||||
ATExecSetCompression(AlteredTableInfo *tab,
|
||||
Relation rel,
|
||||
ATExecSetCompression(Relation rel,
|
||||
const char *column,
|
||||
Node *newValue,
|
||||
LOCKMODE lockmode)
|
||||
@ -19287,3 +19262,38 @@ GetAttributeCompression(Oid atttypid, char *compression)
|
||||
|
||||
return cmethod;
|
||||
}
|
||||
|
||||
/*
|
||||
* resolve column storage specification
|
||||
*/
|
||||
static char
|
||||
GetAttributeStorage(Oid atttypid, const char *storagemode)
|
||||
{
|
||||
char cstorage = 0;
|
||||
|
||||
if (pg_strcasecmp(storagemode, "plain") == 0)
|
||||
cstorage = TYPSTORAGE_PLAIN;
|
||||
else if (pg_strcasecmp(storagemode, "external") == 0)
|
||||
cstorage = TYPSTORAGE_EXTERNAL;
|
||||
else if (pg_strcasecmp(storagemode, "extended") == 0)
|
||||
cstorage = TYPSTORAGE_EXTENDED;
|
||||
else if (pg_strcasecmp(storagemode, "main") == 0)
|
||||
cstorage = TYPSTORAGE_MAIN;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid storage type \"%s\"",
|
||||
storagemode)));
|
||||
|
||||
/*
|
||||
* safety check: do not allow toasted storage modes unless column datatype
|
||||
* is TOAST-aware.
|
||||
*/
|
||||
if (!(cstorage == TYPSTORAGE_PLAIN || TypeIsToastable(atttypid)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column data type %s can only have storage PLAIN",
|
||||
format_type_be(atttypid))));
|
||||
|
||||
return cstorage;
|
||||
}
|
||||
|
Reference in New Issue
Block a user