aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-05-27 13:24:24 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-05-27 13:24:27 -0400
commite6241d8e030fbd2746b3ea3f44e728224298f35b (patch)
treee4bfc50561023459635cb9faf0873fee1e891013 /src/backend/commands/tablecmds.c
parenta717e5c771610cf8607f2423ab3ab6b5d30f44ea (diff)
downloadpostgresql-e6241d8e030fbd2746b3ea3f44e728224298f35b.tar.gz
postgresql-e6241d8e030fbd2746b3ea3f44e728224298f35b.zip
Rethink definition of pg_attribute.attcompression.
Redefine '\0' (InvalidCompressionMethod) as meaning "if we need to compress, use the current setting of default_toast_compression". This allows '\0' to be a suitable default choice regardless of datatype, greatly simplifying code paths that initialize tupledescs and the like. It seems like a more user-friendly approach as well, because now the default compression choice doesn't migrate into table definitions, meaning that changing default_toast_compression is usually sufficient to flip an installation's behavior; one needn't tediously issue per-column ALTER SET COMPRESSION commands. Along the way, fix a few minor bugs and documentation issues with the per-column-compression feature. Adopt more robust APIs for SetIndexStorageProperties and GetAttributeCompression. Bump catversion because typical contents of attcompression will now be different. We could get away without doing that, but it seems better to ensure v14 installations all agree on this. (We already forced initdb for beta2, anyway.) Discussion: https://postgr.es/m/626613.1621787110@sss.pgh.pa.us
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r--src/backend/commands/tablecmds.c124
1 files changed, 47 insertions, 77 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 11e91c4ad33..028e8ac46b3 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -601,7 +601,7 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
Relation partitionTbl);
static List *GetParentedForeignKeyRefs(Relation partition);
static void ATDetachCheckNoForeignKeyRefs(Relation partition);
-static char GetAttributeCompression(Form_pg_attribute att, char *compression);
+static char GetAttributeCompression(Oid atttypid, char *compression);
/* ----------------------------------------------------------------
@@ -897,17 +897,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
if (colDef->generated)
attr->attgenerated = colDef->generated;
- /*
- * lookup attribute's compression method and store it in the
- * attr->attcompression.
- */
- if (relkind == RELKIND_RELATION ||
- relkind == RELKIND_PARTITIONED_TABLE ||
- relkind == RELKIND_MATVIEW)
- attr->attcompression =
- GetAttributeCompression(attr, colDef->compression);
- else
- attr->attcompression = InvalidCompressionMethod;
+ if (colDef->compression)
+ attr->attcompression = GetAttributeCompression(attr->atttypid,
+ colDef->compression);
}
/*
@@ -6602,13 +6594,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
attribute.attbyval = tform->typbyval;
attribute.attalign = tform->typalign;
attribute.attstorage = tform->typstorage;
- /* do not set compression in views etc */
- if (rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- attribute.attcompression = GetAttributeCompression(&attribute,
- colDef->compression);
- else
- attribute.attcompression = InvalidCompressionMethod;
+ attribute.attcompression = GetAttributeCompression(typeOid,
+ colDef->compression);
attribute.attnotnull = colDef->is_not_null;
attribute.atthasdef = false;
attribute.atthasmissing = false;
@@ -7995,23 +7982,24 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
/*
* Helper function for ATExecSetStorage and ATExecSetCompression
*
- * Set the attcompression and/or attstorage for the respective index attribute
- * if the respective input values are valid.
+ * Set the attstorage and/or attcompression fields for index columns
+ * associated with the specified table column.
*/
static void
SetIndexStorageProperties(Relation rel, Relation attrelation,
- AttrNumber attnum, char newcompression,
- char newstorage, LOCKMODE lockmode)
+ AttrNumber attnum,
+ bool setstorage, char newstorage,
+ bool setcompression, char newcompression,
+ LOCKMODE lockmode)
{
- HeapTuple tuple;
ListCell *lc;
- Form_pg_attribute attrtuple;
foreach(lc, RelationGetIndexList(rel))
{
Oid indexoid = lfirst_oid(lc);
Relation indrel;
AttrNumber indattnum = 0;
+ HeapTuple tuple;
indrel = index_open(indexoid, lockmode);
@@ -8034,14 +8022,14 @@ SetIndexStorageProperties(Relation rel, Relation attrelation,
if (HeapTupleIsValid(tuple))
{
- attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
+ Form_pg_attribute attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
- if (CompressionMethodIsValid(newcompression))
- attrtuple->attcompression = newcompression;
-
- if (newstorage != '\0')
+ if (setstorage)
attrtuple->attstorage = newstorage;
+ if (setcompression)
+ attrtuple->attcompression = newcompression;
+
CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(RelationRelationId,
@@ -8134,8 +8122,9 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
* matching behavior of index.c ConstructTupleDescriptor()).
*/
SetIndexStorageProperties(rel, attrelation, attnum,
- InvalidCompressionMethod,
- newstorage, lockmode);
+ true, newstorage,
+ false, 0,
+ lockmode);
table_close(attrelation, RowExclusiveLock);
@@ -12299,23 +12288,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
attTup->attbyval = tform->typbyval;
attTup->attalign = tform->typalign;
attTup->attstorage = tform->typstorage;
-
- /* Setup attribute compression */
- if (rel->rd_rel->relkind == RELKIND_RELATION ||
- rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- {
- /*
- * No compression for plain/external storage, otherwise, default
- * compression method if it is not already set, refer comments atop
- * attcompression parameter in pg_attribute.h.
- */
- if (!IsStorageCompressible(tform->typstorage))
- attTup->attcompression = InvalidCompressionMethod;
- else if (!CompressionMethodIsValid(attTup->attcompression))
- attTup->attcompression = GetDefaultToastCompression();
- }
- else
- attTup->attcompression = InvalidCompressionMethod;
+ attTup->attcompression = InvalidCompressionMethod;
ReleaseSysCache(typeTuple);
@@ -15613,7 +15586,6 @@ ATExecSetCompression(AlteredTableInfo *tab,
Form_pg_attribute atttableform;
AttrNumber attnum;
char *compression;
- char typstorage;
char cmethod;
ObjectAddress address;
@@ -15638,17 +15610,11 @@ ATExecSetCompression(AlteredTableInfo *tab,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter system column \"%s\"", column)));
- typstorage = get_typstorage(atttableform->atttypid);
-
- /* prevent from setting compression methods for uncompressible type */
- if (!IsStorageCompressible(typstorage))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("column data type %s does not support compression",
- format_type_be(atttableform->atttypid))));
-
- /* get the attribute compression method. */
- cmethod = GetAttributeCompression(atttableform, compression);
+ /*
+ * Check that column type is compressible, then get the attribute
+ * compression method code
+ */
+ cmethod = GetAttributeCompression(atttableform->atttypid, compression);
/* update pg_attribute entry */
atttableform->attcompression = cmethod;
@@ -15662,7 +15628,10 @@ ATExecSetCompression(AlteredTableInfo *tab,
* Apply the change to indexes as well (only for simple index columns,
* matching behavior of index.c ConstructTupleDescriptor()).
*/
- SetIndexStorageProperties(rel, attrel, attnum, cmethod, '\0', lockmode);
+ SetIndexStorageProperties(rel, attrel, attnum,
+ false, 0,
+ true, cmethod,
+ lockmode);
heap_freetuple(tuple);
@@ -18612,29 +18581,30 @@ ATDetachCheckNoForeignKeyRefs(Relation partition)
* resolve column compression specification to compression method.
*/
static char
-GetAttributeCompression(Form_pg_attribute att, char *compression)
+GetAttributeCompression(Oid atttypid, char *compression)
{
- char typstorage = get_typstorage(att->atttypid);
char cmethod;
+ if (compression == NULL || strcmp(compression, "default") == 0)
+ return InvalidCompressionMethod;
+
/*
- * No compression for plain/external storage, refer comments atop
- * attcompression parameter in pg_attribute.h
+ * To specify a nondefault method, the column data type must be toastable.
+ * Note this says nothing about whether the column's attstorage setting
+ * permits compression; we intentionally allow attstorage and
+ * attcompression to be independent. But with a non-toastable type,
+ * attstorage could not be set to a value that would permit compression.
+ *
+ * We don't actually need to enforce this, since nothing bad would happen
+ * if attcompression were non-default; it would never be consulted. But
+ * it seems more user-friendly to complain about a certainly-useless
+ * attempt to set the property.
*/
- if (!IsStorageCompressible(typstorage))
- {
- if (compression == NULL)
- return InvalidCompressionMethod;
-
+ if (!TypeIsToastable(atttypid))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("column data type %s does not support compression",
- format_type_be(att->atttypid))));
- }
-
- /* fallback to default compression if it's not specified */
- if (compression == NULL)
- return GetDefaultToastCompression();
+ format_type_be(atttypid))));
cmethod = CompressionNameToMethod(compression);
if (!CompressionMethodIsValid(cmethod))