diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/brin/brin_tuple.c | 5 | ||||
-rw-r--r-- | src/backend/access/common/indextuple.c | 13 | ||||
-rw-r--r-- | src/backend/access/common/toast_internals.c | 6 | ||||
-rw-r--r-- | src/backend/access/common/tupdesc.c | 7 | ||||
-rw-r--r-- | src/backend/access/heap/heapam_handler.c | 12 | ||||
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 7 | ||||
-rw-r--r-- | src/backend/catalog/genbki.pl | 4 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 2 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 124 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 38 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 8 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup.h | 2 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 34 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 107 | ||||
-rw-r--r-- | src/bin/psql/describe.c | 10 | ||||
-rw-r--r-- | src/include/access/toast_compression.h | 24 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_attribute.h | 8 | ||||
-rw-r--r-- | src/test/regress/expected/compression.out | 42 | ||||
-rw-r--r-- | src/test/regress/expected/compression_1.out | 46 | ||||
-rw-r--r-- | src/test/regress/sql/compression.sql | 23 |
21 files changed, 193 insertions, 331 deletions
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index ee05372f795..09e563b1f08 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -232,11 +232,10 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple, * same compression method. Otherwise we have to use the * default method. */ - if (att->atttypid == atttype->type_id && - CompressionMethodIsValid(att->attcompression)) + if (att->atttypid == atttype->type_id) compression = att->attcompression; else - compression = GetDefaultToastCompression(); + compression = InvalidCompressionMethod; cvalue = toast_compress_datum(value, compression); diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index 52125604113..8df882da7a7 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -104,18 +104,9 @@ index_form_tuple(TupleDesc tupleDescriptor, att->attstorage == TYPSTORAGE_MAIN)) { Datum cvalue; - char compression = att->attcompression; - /* - * If the compression method is not valid, use the default. We - * don't expect this to happen for regular index columns, which - * inherit the setting from the corresponding table column, but we - * do expect it to happen whenever an expression is indexed. - */ - if (!CompressionMethodIsValid(compression)) - compression = GetDefaultToastCompression(); - - cvalue = toast_compress_datum(untoasted_values[i], compression); + cvalue = toast_compress_datum(untoasted_values[i], + att->attcompression); if (DatumGetPointer(cvalue) != NULL) { diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c index 8d2a9964c3f..c7b9ade5742 100644 --- a/src/backend/access/common/toast_internals.c +++ b/src/backend/access/common/toast_internals.c @@ -53,10 +53,12 @@ toast_compress_datum(Datum value, char cmethod) Assert(!VARATT_IS_EXTERNAL(DatumGetPointer(value))); Assert(!VARATT_IS_COMPRESSED(DatumGetPointer(value))); - Assert(CompressionMethodIsValid(cmethod)); - valsize = VARSIZE_ANY_EXHDR(DatumGetPointer(value)); + /* If the compression method is not valid, use the current default */ + if (!CompressionMethodIsValid(cmethod)) + cmethod = default_toast_compression; + /* * Call appropriate compression routine for the compression method. */ diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index affbc509bdc..4c63bd4dc64 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -642,10 +642,7 @@ TupleDescInitEntry(TupleDesc desc, att->attbyval = typeForm->typbyval; att->attalign = typeForm->typalign; att->attstorage = typeForm->typstorage; - if (IsStorageCompressible(typeForm->typstorage)) - att->attcompression = GetDefaultToastCompression(); - else - att->attcompression = InvalidCompressionMethod; + att->attcompression = InvalidCompressionMethod; att->attcollation = typeForm->typcollation; ReleaseSysCache(tuple); @@ -711,7 +708,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc, att->attbyval = false; att->attalign = TYPALIGN_INT; att->attstorage = TYPSTORAGE_EXTENDED; - att->attcompression = GetDefaultToastCompression(); + att->attcompression = InvalidCompressionMethod; att->attcollation = DEFAULT_COLLATION_OID; break; diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 8e6e8d51698..e2cd79ec546 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2483,10 +2483,10 @@ reform_and_rewrite_tuple(HeapTuple tuple, * perform the compression here; we just need to decompress. That * will trigger recompression later on. */ - struct varlena *new_value; ToastCompressionId cmid; char cmethod; + char targetmethod; new_value = (struct varlena *) DatumGetPointer(values[i]); cmid = toast_get_compression_id(new_value); @@ -2495,7 +2495,7 @@ reform_and_rewrite_tuple(HeapTuple tuple, if (cmid == TOAST_INVALID_COMPRESSION_ID) continue; - /* convert compression id to compression method */ + /* convert existing compression id to compression method */ switch (cmid) { case TOAST_PGLZ_COMPRESSION_ID: @@ -2506,10 +2506,16 @@ reform_and_rewrite_tuple(HeapTuple tuple, break; default: elog(ERROR, "invalid compression method id %d", cmid); + cmethod = '\0'; /* keep compiler quiet */ } + /* figure out what the target method is */ + targetmethod = TupleDescAttr(newTupDesc, i)->attcompression; + if (!CompressionMethodIsValid(targetmethod)) + targetmethod = default_toast_compression; + /* if compression method doesn't match then detoast the value */ - if (TupleDescAttr(newTupDesc, i)->attcompression != cmethod) + if (targetmethod != cmethod) { values[i] = PointerGetDatum(detoast_attr(new_value)); values_free[i] = true; diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 62abd008ccf..94ab5ca0954 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -701,6 +701,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness) attrtypes[attnum]->attbyval = Ap->am_typ.typbyval; attrtypes[attnum]->attalign = Ap->am_typ.typalign; attrtypes[attnum]->attstorage = Ap->am_typ.typstorage; + attrtypes[attnum]->attcompression = InvalidCompressionMethod; attrtypes[attnum]->attcollation = Ap->am_typ.typcollation; /* if an array type, assume 1-dimensional attribute */ if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0) @@ -715,6 +716,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness) attrtypes[attnum]->attbyval = TypInfo[typeoid].byval; attrtypes[attnum]->attalign = TypInfo[typeoid].align; attrtypes[attnum]->attstorage = TypInfo[typeoid].storage; + attrtypes[attnum]->attcompression = InvalidCompressionMethod; attrtypes[attnum]->attcollation = TypInfo[typeoid].collation; /* if an array type, assume 1-dimensional attribute */ if (TypInfo[typeoid].elem != InvalidOid && @@ -724,11 +726,6 @@ DefineAttr(char *name, char *type, int attnum, int nullness) attrtypes[attnum]->attndims = 0; } - if (IsStorageCompressible(attrtypes[attnum]->attstorage)) - attrtypes[attnum]->attcompression = GetDefaultToastCompression(); - else - attrtypes[attnum]->attcompression = InvalidCompressionMethod; - /* * If a system catalog column is collation-aware, force it to use C * collation, so that its behavior is independent of the database's diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl index 112b3affdfd..f893ae4f453 100644 --- a/src/backend/catalog/genbki.pl +++ b/src/backend/catalog/genbki.pl @@ -899,9 +899,7 @@ sub morph_row_for_pgattr $row->{attbyval} = $type->{typbyval}; $row->{attalign} = $type->{typalign}; $row->{attstorage} = $type->{typstorage}; - - $row->{attcompression} = - $type->{typstorage} ne 'p' && $type->{typstorage} ne 'e' ? 'p' : '\0'; + $row->{attcompression} = '\0'; # set attndims if it's an array type $row->{attndims} = $type->{typcategory} eq 'A' ? '1' : '0'; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 3dfe2e8a565..afa830d9248 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1719,8 +1719,6 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) /* Unset this so no one tries to look up the generation expression */ attStruct->attgenerated = '\0'; - attStruct->attcompression = InvalidCompressionMethod; - /* * Change the column name to something that isn't likely to conflict */ 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)) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index aaf1a51f685..9ee90e3f13a 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -561,6 +561,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <node> TableConstraint TableLikeClause %type <ival> TableLikeOptionList TableLikeOption +%type <str> column_compression opt_column_compression %type <list> ColQualList %type <node> ColConstraint ColConstraintElem ConstraintAttr %type <ival> key_actions key_delete key_match key_update key_action @@ -609,7 +610,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list> hash_partbound %type <defelt> hash_partbound_elem -%type <str> optColumnCompression /* * Non-keyword token types. These are hard-wired into the "flex" lexer. @@ -2302,6 +2302,15 @@ alter_table_cmd: n->def = (Node *) makeString($6); $$ = (Node *)n; } + /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET COMPRESSION <cm> */ + | ALTER opt_column ColId SET column_compression + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetCompression; + n->name = $3; + n->def = (Node *) makeString($5); + $$ = (Node *)n; + } /* ALTER TABLE <name> ALTER [COLUMN] <colname> ADD GENERATED ... AS IDENTITY ... */ | ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList { @@ -2346,15 +2355,6 @@ alter_table_cmd: n->missing_ok = true; $$ = (Node *)n; } - /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET (COMPRESSION <cm>) */ - | ALTER opt_column ColId SET optColumnCompression - { - AlterTableCmd *n = makeNode(AlterTableCmd); - n->subtype = AT_SetCompression; - n->name = $3; - n->def = (Node *) makeString($5); - $$ = (Node *)n; - } /* ALTER TABLE <name> DROP [COLUMN] IF EXISTS <colname> [RESTRICT|CASCADE] */ | DROP opt_column IF_P EXISTS ColId opt_drop_behavior { @@ -3462,7 +3462,7 @@ TypedTableElement: | TableConstraint { $$ = $1; } ; -columnDef: ColId Typename optColumnCompression create_generic_options ColQualList +columnDef: ColId Typename opt_column_compression create_generic_options ColQualList { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; @@ -3522,13 +3522,15 @@ columnOptions: ColId ColQualList } ; -optColumnCompression: - COMPRESSION name - { - $$ = $2; - } - | /*EMPTY*/ { $$ = NULL; } - ; +column_compression: + COMPRESSION ColId { $$ = $2; } + | COMPRESSION DEFAULT { $$ = pstrdup("default"); } + ; + +opt_column_compression: + column_compression { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; ColQualList: ColQualList ColConstraint { $$ = lappend($1, $2); } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ee731044b63..87bc6887046 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4651,13 +4651,13 @@ static struct config_enum ConfigureNamesEnum[] = { {"default_toast_compression", PGC_USERSET, CLIENT_CONN_STATEMENT, - gettext_noop("Sets the default compression for new columns."), - NULL, - GUC_IS_NAME + gettext_noop("Sets the default compression method for compressible values."), + NULL }, &default_toast_compression, TOAST_PGLZ_COMPRESSION, - default_toast_compression_options, NULL, NULL + default_toast_compression_options, + NULL, NULL, NULL }, { diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index fc054af5ba1..3c1cd858a85 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -208,8 +208,6 @@ typedef struct Archive /* other important stuff */ char *searchpath; /* search_path to set during restore */ - char *default_toast_compression; /* default TOAST compression to - * set during restore */ char *use_role; /* Issue SET ROLE to this */ /* error handling */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 86de26a4bf0..6b046e7734d 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -86,7 +86,6 @@ static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam); static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te); -static void processToastCompressionEntry(ArchiveHandle *AH, TocEntry *te); static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH); static RestorePass _tocEntryRestorePass(TocEntry *te); static bool _tocEntryIsACL(TocEntry *te); @@ -2638,8 +2637,6 @@ ReadToc(ArchiveHandle *AH) processStdStringsEntry(AH, te); else if (strcmp(te->desc, "SEARCHPATH") == 0) processSearchPathEntry(AH, te); - else if (strcmp(te->desc, "TOASTCOMPRESSION") == 0) - processToastCompressionEntry(AH, te); } } @@ -2698,29 +2695,6 @@ processSearchPathEntry(ArchiveHandle *AH, TocEntry *te) } static void -processToastCompressionEntry(ArchiveHandle *AH, TocEntry *te) -{ - /* te->defn should have the form SET default_toast_compression = 'x'; */ - char *defn = pg_strdup(te->defn); - char *ptr1; - char *ptr2 = NULL; - - ptr1 = strchr(defn, '\''); - if (ptr1) - ptr2 = strchr(++ptr1, '\''); - if (ptr2) - { - *ptr2 = '\0'; - AH->public.default_toast_compression = pg_strdup(ptr1); - } - else - fatal("invalid TOASTCOMPRESSION item: %s", - te->defn); - - free(defn); -} - -static void StrictNamesCheck(RestoreOptions *ropt) { const char *missing_name; @@ -2779,8 +2753,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) /* These items are treated specially */ if (strcmp(te->desc, "ENCODING") == 0 || strcmp(te->desc, "STDSTRINGS") == 0 || - strcmp(te->desc, "SEARCHPATH") == 0 || - strcmp(te->desc, "TOASTCOMPRESSION") == 0) + strcmp(te->desc, "SEARCHPATH") == 0) return REQ_SPECIAL; /* @@ -3103,11 +3076,6 @@ _doSetFixedOutputState(ArchiveHandle *AH) if (AH->public.searchpath) ahprintf(AH, "%s", AH->public.searchpath); - /* Select the dump-time default_toast_compression */ - if (AH->public.default_toast_compression) - ahprintf(AH, "SET default_toast_compression = '%s';\n", - AH->public.default_toast_compression); - /* Make sure function checking is disabled */ ahprintf(AH, "SET check_function_bodies = false;\n"); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 339c3937180..8f53cc7c3b8 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -276,7 +276,6 @@ static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf, static void dumpEncoding(Archive *AH); static void dumpStdStrings(Archive *AH); static void dumpSearchPath(Archive *AH); -static void dumpToastCompression(Archive *AH); static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout, PQExpBuffer upgrade_buffer, Oid pg_type_oid, @@ -925,13 +924,11 @@ main(int argc, char **argv) */ /* - * First the special entries for ENCODING, STDSTRINGS, SEARCHPATH and - * TOASTCOMPRESSION. + * First the special entries for ENCODING, STDSTRINGS, and SEARCHPATH. */ dumpEncoding(fout); dumpStdStrings(fout); dumpSearchPath(fout); - dumpToastCompression(fout); /* The database items are always next, unless we don't want them at all */ if (dopt.outputCreateDB) @@ -3398,58 +3395,6 @@ dumpSearchPath(Archive *AH) destroyPQExpBuffer(path); } -/* - * dumpToastCompression: save the dump-time default TOAST compression in the - * archive - */ -static void -dumpToastCompression(Archive *AH) -{ - char *toast_compression; - PQExpBuffer qry; - - if (AH->dopt->no_toast_compression) - { - /* we don't intend to dump the info, so no need to fetch it either */ - return; - } - - if (AH->remoteVersion < 140000) - { - /* pre-v14, the only method was pglz */ - toast_compression = pg_strdup("pglz"); - } - else - { - PGresult *res; - - res = ExecuteSqlQueryForSingleRow(AH, "SHOW default_toast_compression"); - toast_compression = pg_strdup(PQgetvalue(res, 0, 0)); - PQclear(res); - } - - qry = createPQExpBuffer(); - appendPQExpBufferStr(qry, "SET default_toast_compression = "); - appendStringLiteralAH(qry, toast_compression, AH); - appendPQExpBufferStr(qry, ";\n"); - - pg_log_info("saving default_toast_compression = %s", toast_compression); - - ArchiveEntry(AH, nilCatalogId, createDumpId(), - ARCHIVE_OPTS(.tag = "TOASTCOMPRESSION", - .description = "TOASTCOMPRESSION", - .section = SECTION_PRE_DATA, - .createStmt = qry->data)); - - /* - * Also save it in AH->default_toast_compression, in case we're doing - * plain text dump. - */ - AH->default_toast_compression = toast_compression; - - destroyPQExpBuffer(qry); -} - /* * getBlobs: @@ -16399,29 +16344,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) } /* - * Dump per-column attributes. - */ - if (tbinfo->attoptions[j][0] != '\0') - appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET (%s);\n", - foreign, qualrelname, - fmtId(tbinfo->attnames[j]), - tbinfo->attoptions[j]); - - /* - * Dump per-column fdw options. - */ - if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && - tbinfo->attfdwoptions[j][0] != '\0') - appendPQExpBuffer(q, - "ALTER FOREIGN TABLE %s ALTER COLUMN %s OPTIONS (\n" - " %s\n" - ");\n", - qualrelname, - fmtId(tbinfo->attnames[j]), - tbinfo->attfdwoptions[j]); - - /* - * Dump per-column compression, if different from default. + * Dump per-column compression, if it's been set. */ if (!dopt->no_toast_compression) { @@ -16440,14 +16363,34 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) break; } - if (cmname != NULL && - (fout->default_toast_compression == NULL || - strcmp(cmname, fout->default_toast_compression) != 0)) + if (cmname != NULL) appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET COMPRESSION %s;\n", foreign, qualrelname, fmtId(tbinfo->attnames[j]), cmname); } + + /* + * Dump per-column attributes. + */ + if (tbinfo->attoptions[j][0] != '\0') + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET (%s);\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j]), + tbinfo->attoptions[j]); + + /* + * Dump per-column fdw options. + */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && + tbinfo->attfdwoptions[j][0] != '\0') + appendPQExpBuffer(q, + "ALTER FOREIGN TABLE %s ALTER COLUMN %s OPTIONS (\n" + " %s\n" + ");\n", + qualrelname, + fmtId(tbinfo->attnames[j]), + tbinfo->attfdwoptions[j]); } /* end loop over columns */ if (ftoptions) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 3e39fdb5452..195f8d8cd2d 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -1636,9 +1636,9 @@ describeOneTableDetails(const char *schemaname, indexdef_col = -1, fdwopts_col = -1, attstorage_col = -1, + attcompression_col = -1, attstattarget_col = -1, - attdescr_col = -1, - attcompression_col = -1; + attdescr_col = -1; int numrows; struct { @@ -2055,7 +2055,7 @@ describeOneTableDetails(const char *schemaname, appendPQExpBufferStr(&buf, ",\n a.attstorage"); attstorage_col = cols++; - /* compression info */ + /* compression info, if relevant to relkind */ if (pset.sversion >= 140000 && !pset.hide_compression && (tableinfo.relkind == RELKIND_RELATION || @@ -2259,7 +2259,7 @@ describeOneTableDetails(const char *schemaname, if (fdwopts_col >= 0) printTableAddCell(&cont, PQgetvalue(res, i, fdwopts_col), false, false); - /* Storage and Description */ + /* Storage mode, if relevant */ if (attstorage_col >= 0) { char *storage = PQgetvalue(res, i, attstorage_col); @@ -2273,7 +2273,7 @@ describeOneTableDetails(const char *schemaname, false, false); } - /* Column compression. */ + /* Column compression, if relevant */ if (attcompression_col >= 0) { char *compression = PQgetvalue(res, i, attcompression_col); diff --git a/src/include/access/toast_compression.h b/src/include/access/toast_compression.h index 9e2c1cbe1a6..c992ece4c4a 100644 --- a/src/include/access/toast_compression.h +++ b/src/include/access/toast_compression.h @@ -23,16 +23,16 @@ extern int default_toast_compression; /* - * Built-in compression method-id. The toast compression header will store + * Built-in compression method ID. The toast compression header will store * this in the first 2 bits of the raw length. These built-in compression - * method-id are directly mapped to the built-in compression methods. + * method IDs are directly mapped to the built-in compression methods. * * Don't use these values for anything other than understanding the meaning * of the raw bits from a varlena; in particular, if the goal is to identify * a compression method, use the constants TOAST_PGLZ_COMPRESSION, etc. * below. We might someday support more than 4 compression methods, but * we can never have more than 4 values in this enum, because there are - * only 2 bits available in the places where this is used. + * only 2 bits available in the places where this is stored. */ typedef enum ToastCompressionId { @@ -42,8 +42,9 @@ typedef enum ToastCompressionId } ToastCompressionId; /* - * Built-in compression methods. pg_attribute will store this in the - * attcompression column. + * Built-in compression methods. pg_attribute will store these in the + * attcompression column. In attcompression, InvalidCompressionMethod + * denotes the default behavior. */ #define TOAST_PGLZ_COMPRESSION 'p' #define TOAST_LZ4_COMPRESSION 'l' @@ -51,19 +52,6 @@ typedef enum ToastCompressionId #define CompressionMethodIsValid(cm) ((cm) != InvalidCompressionMethod) -#define IsStorageCompressible(storage) ((storage) != TYPSTORAGE_PLAIN && \ - (storage) != TYPSTORAGE_EXTERNAL) - -/* - * GetDefaultToastCompression -- get the default toast compression method - * - * This exists to hide the use of the default_toast_compression GUC variable. - */ -static inline char -GetDefaultToastCompression(void) -{ - return (char) default_toast_compression; -} /* pglz compression/decompression routines */ extern struct varlena *pglz_compress_datum(const struct varlena *value); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 958f12e66a1..9fe49fa2911 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202105231 +#define CATALOG_VERSION_NO 202105271 #endif diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 1e260162146..603392fe81b 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -126,8 +126,12 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75, char attstorage; /* - * Compression method. Must be InvalidCompressionMethod if and only if - * typstorage is 'plain' or 'external'. + * attcompression sets the current compression method of the attribute. + * Typically this is InvalidCompressionMethod ('\0') to specify use of the + * current default setting (see default_toast_compression). Otherwise, + * 'p' selects pglz compression, while 'l' selects LZ4 compression. + * However, this field is ignored whenever attstorage does not allow + * compression. */ char attcompression BKI_DEFAULT('\0'); diff --git a/src/test/regress/expected/compression.out b/src/test/regress/expected/compression.out index 61e97cb33ce..5c645e46500 100644 --- a/src/test/regress/expected/compression.out +++ b/src/test/regress/expected/compression.out @@ -53,7 +53,7 @@ SELECT * INTO cmmove1 FROM cmdata; Table "public.cmmove1" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | text | | | | extended | pglz | | + f1 | text | | | | extended | | | SELECT pg_column_compression(f1) FROM cmmove1; pg_column_compression @@ -146,7 +146,7 @@ ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE varchar; Table "public.cmdata2" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+-------------------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | character varying | | | | extended | pglz | | + f1 | character varying | | | | extended | | | ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE int USING f1::integer; \d+ cmdata2 @@ -158,6 +158,7 @@ ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE int USING f1::integer; --changing column storage should not impact the compression method --but the data should not be compressed ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE varchar; +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION pglz; \d+ cmdata2 Table "public.cmdata2" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description @@ -179,12 +180,12 @@ SELECT pg_column_compression(f1) FROM cmdata2; (1 row) -- test compression with materialized view -CREATE MATERIALIZED VIEW mv(x) AS SELECT * FROM cmdata1; -\d+ mv - Materialized view "public.mv" +CREATE MATERIALIZED VIEW compressmv(x) AS SELECT * FROM cmdata1; +\d+ compressmv + Materialized view "public.compressmv" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+------+-----------+----------+---------+----------+-------------+--------------+------------- - x | text | | | | extended | pglz | | + x | text | | | | extended | | | View definition: SELECT cmdata1.f1 AS x FROM cmdata1; @@ -196,7 +197,7 @@ SELECT pg_column_compression(f1) FROM cmdata1; lz4 (2 rows) -SELECT pg_column_compression(x) FROM mv; +SELECT pg_column_compression(x) FROM compressmv; pg_column_compression ----------------------- lz4 @@ -222,7 +223,7 @@ SELECT pg_column_compression(f1) FROM cmpart2; pglz (1 row) --- test compression with inheritence, error +-- test compression with inheritance, error CREATE TABLE cminh() INHERITS(cmdata, cmdata1); NOTICE: merging multiple inherited definitions of column "f1" ERROR: column "f1" has a compression method conflict @@ -239,14 +240,6 @@ SET default_toast_compression = 'I do not exist compression'; ERROR: invalid value for parameter "default_toast_compression": "I do not exist compression" HINT: Available values: pglz, lz4. SET default_toast_compression = 'lz4'; -DROP TABLE cmdata2; -CREATE TABLE cmdata2 (f1 text); -\d+ cmdata2 - Table "public.cmdata2" - Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description ---------+------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | text | | | | extended | lz4 | | - SET default_toast_compression = 'pglz'; -- test alter compression method ALTER TABLE cmdata ALTER COLUMN f1 SET COMPRESSION lz4; @@ -266,10 +259,17 @@ SELECT pg_column_compression(f1) FROM cmdata; lz4 (2 rows) --- test alter compression method for the materialized view -ALTER MATERIALIZED VIEW mv ALTER COLUMN x SET COMPRESSION lz4; -\d+ mv - Materialized view "public.mv" +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION default; +\d+ cmdata2 + Table "public.cmdata2" + Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description +--------+-------------------+-----------+----------+---------+---------+-------------+--------------+------------- + f1 | character varying | | | | plain | | | + +-- test alter compression method for materialized views +ALTER MATERIALIZED VIEW compressmv ALTER COLUMN x SET COMPRESSION lz4; +\d+ compressmv + Materialized view "public.compressmv" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+------+-----------+----------+---------+----------+-------------+--------------+------------- x | text | | | | extended | lz4 | | @@ -277,7 +277,7 @@ View definition: SELECT cmdata1.f1 AS x FROM cmdata1; --- test alter compression method for the partitioned table +-- test alter compression method for partitioned tables ALTER TABLE cmpart1 ALTER COLUMN f1 SET COMPRESSION pglz; ALTER TABLE cmpart2 ALTER COLUMN f1 SET COMPRESSION lz4; -- new data should be compressed with the current compression method diff --git a/src/test/regress/expected/compression_1.out b/src/test/regress/expected/compression_1.out index d03d6255ae3..aac96037fcf 100644 --- a/src/test/regress/expected/compression_1.out +++ b/src/test/regress/expected/compression_1.out @@ -50,7 +50,7 @@ SELECT * INTO cmmove1 FROM cmdata; Table "public.cmmove1" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | text | | | | extended | pglz | | + f1 | text | | | | extended | | | SELECT pg_column_compression(f1) FROM cmmove1; pg_column_compression @@ -144,7 +144,7 @@ ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE varchar; Table "public.cmdata2" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description --------+-------------------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | character varying | | | | extended | pglz | | + f1 | character varying | | | | extended | | | ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE int USING f1::integer; \d+ cmdata2 @@ -156,6 +156,7 @@ ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE int USING f1::integer; --changing column storage should not impact the compression method --but the data should not be compressed ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE varchar; +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION pglz; \d+ cmdata2 Table "public.cmdata2" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description @@ -177,18 +178,18 @@ SELECT pg_column_compression(f1) FROM cmdata2; (1 row) -- test compression with materialized view -CREATE MATERIALIZED VIEW mv(x) AS SELECT * FROM cmdata1; +CREATE MATERIALIZED VIEW compressmv(x) AS SELECT * FROM cmdata1; ERROR: relation "cmdata1" does not exist -LINE 1: CREATE MATERIALIZED VIEW mv(x) AS SELECT * FROM cmdata1; - ^ -\d+ mv +LINE 1: ...TE MATERIALIZED VIEW compressmv(x) AS SELECT * FROM cmdata1; + ^ +\d+ compressmv SELECT pg_column_compression(f1) FROM cmdata1; ERROR: relation "cmdata1" does not exist LINE 1: SELECT pg_column_compression(f1) FROM cmdata1; ^ -SELECT pg_column_compression(x) FROM mv; -ERROR: relation "mv" does not exist -LINE 1: SELECT pg_column_compression(x) FROM mv; +SELECT pg_column_compression(x) FROM compressmv; +ERROR: relation "compressmv" does not exist +LINE 1: SELECT pg_column_compression(x) FROM compressmv; ^ -- test compression with partition CREATE TABLE cmpart(f1 text COMPRESSION lz4) PARTITION BY HASH(f1); @@ -217,7 +218,7 @@ SELECT pg_column_compression(f1) FROM cmpart2; ----------------------- (0 rows) --- test compression with inheritence, error +-- test compression with inheritance, error CREATE TABLE cminh() INHERITS(cmdata, cmdata1); ERROR: relation "cmdata1" does not exist CREATE TABLE cminh(f1 TEXT COMPRESSION lz4) INHERITS(cmdata); @@ -234,14 +235,6 @@ HINT: Available values: pglz. SET default_toast_compression = 'lz4'; ERROR: invalid value for parameter "default_toast_compression": "lz4" HINT: Available values: pglz. -DROP TABLE cmdata2; -CREATE TABLE cmdata2 (f1 text); -\d+ cmdata2 - Table "public.cmdata2" - Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description ---------+------+-----------+----------+---------+----------+-------------+--------------+------------- - f1 | text | | | | extended | pglz | | - SET default_toast_compression = 'pglz'; -- test alter compression method ALTER TABLE cmdata ALTER COLUMN f1 SET COMPRESSION lz4; @@ -264,11 +257,18 @@ SELECT pg_column_compression(f1) FROM cmdata; pglz (2 rows) --- test alter compression method for the materialized view -ALTER MATERIALIZED VIEW mv ALTER COLUMN x SET COMPRESSION lz4; -ERROR: relation "mv" does not exist -\d+ mv --- test alter compression method for the partitioned table +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION default; +\d+ cmdata2 + Table "public.cmdata2" + Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description +--------+-------------------+-----------+----------+---------+---------+-------------+--------------+------------- + f1 | character varying | | | | plain | | | + +-- test alter compression method for materialized views +ALTER MATERIALIZED VIEW compressmv ALTER COLUMN x SET COMPRESSION lz4; +ERROR: relation "compressmv" does not exist +\d+ compressmv +-- test alter compression method for partitioned tables ALTER TABLE cmpart1 ALTER COLUMN f1 SET COMPRESSION pglz; ERROR: relation "cmpart1" does not exist ALTER TABLE cmpart2 ALTER COLUMN f1 SET COMPRESSION lz4; diff --git a/src/test/regress/sql/compression.sql b/src/test/regress/sql/compression.sql index 76d1776d832..35557c1f7de 100644 --- a/src/test/regress/sql/compression.sql +++ b/src/test/regress/sql/compression.sql @@ -69,6 +69,7 @@ ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE int USING f1::integer; --changing column storage should not impact the compression method --but the data should not be compressed ALTER TABLE cmdata2 ALTER COLUMN f1 TYPE varchar; +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION pglz; \d+ cmdata2 ALTER TABLE cmdata2 ALTER COLUMN f1 SET STORAGE plain; \d+ cmdata2 @@ -76,10 +77,10 @@ INSERT INTO cmdata2 VALUES (repeat('123456789', 800)); SELECT pg_column_compression(f1) FROM cmdata2; -- test compression with materialized view -CREATE MATERIALIZED VIEW mv(x) AS SELECT * FROM cmdata1; -\d+ mv +CREATE MATERIALIZED VIEW compressmv(x) AS SELECT * FROM cmdata1; +\d+ compressmv SELECT pg_column_compression(f1) FROM cmdata1; -SELECT pg_column_compression(x) FROM mv; +SELECT pg_column_compression(x) FROM compressmv; -- test compression with partition CREATE TABLE cmpart(f1 text COMPRESSION lz4) PARTITION BY HASH(f1); @@ -92,7 +93,7 @@ INSERT INTO cmpart VALUES (repeat('123456789', 4004)); SELECT pg_column_compression(f1) FROM cmpart1; SELECT pg_column_compression(f1) FROM cmpart2; --- test compression with inheritence, error +-- test compression with inheritance, error CREATE TABLE cminh() INHERITS(cmdata, cmdata1); CREATE TABLE cminh(f1 TEXT COMPRESSION lz4) INHERITS(cmdata); @@ -100,9 +101,6 @@ CREATE TABLE cminh(f1 TEXT COMPRESSION lz4) INHERITS(cmdata); SET default_toast_compression = ''; SET default_toast_compression = 'I do not exist compression'; SET default_toast_compression = 'lz4'; -DROP TABLE cmdata2; -CREATE TABLE cmdata2 (f1 text); -\d+ cmdata2 SET default_toast_compression = 'pglz'; -- test alter compression method @@ -111,11 +109,14 @@ INSERT INTO cmdata VALUES (repeat('123456789', 4004)); \d+ cmdata SELECT pg_column_compression(f1) FROM cmdata; --- test alter compression method for the materialized view -ALTER MATERIALIZED VIEW mv ALTER COLUMN x SET COMPRESSION lz4; -\d+ mv +ALTER TABLE cmdata2 ALTER COLUMN f1 SET COMPRESSION default; +\d+ cmdata2 + +-- test alter compression method for materialized views +ALTER MATERIALIZED VIEW compressmv ALTER COLUMN x SET COMPRESSION lz4; +\d+ compressmv --- test alter compression method for the partitioned table +-- test alter compression method for partitioned tables ALTER TABLE cmpart1 ALTER COLUMN f1 SET COMPRESSION pglz; ALTER TABLE cmpart2 ALTER COLUMN f1 SET COMPRESSION lz4; |