<structfield>attcompression</structfield> <type>char</type>
</para>
<para>
- The current compression method of the column. If it is an invalid
- compression method (<literal>'\0'</literal>) then column data will not
- be compressed. Otherwise, <literal>'p'</literal> = pglz compression or
- <literal>'l'</literal> = <productname>LZ4</productname> compression.
+ The current compression method of the column. Typically this is
+ <literal>'\0'</literal> to specify use of the current default setting
+ (see <xref linkend="guc-default-toast-compression"/>). Otherwise,
+ <literal>'p'</literal> selects pglz compression, while
+ <literal>'l'</literal> selects <productname>LZ4</productname>
+ compression. However, this field is ignored
+ whenever <structfield>attstorage</structfield> does not allow
+ compression.
</para></entry>
</row>
<para>
This variable sets the default
<link linkend="storage-toast">TOAST</link>
- compression method for columns of newly-created tables. The
- <command>CREATE TABLE</command> statement can override this default
- by specifying the <literal>COMPRESSION</literal> column option.
-
- The supported compression methods are <literal>pglz</literal> and,
- if <productname>PostgreSQL</productname> was compiled with
- <literal>--with-lz4</literal>, <literal>lz4</literal>.
+ compression method for values of compressible columns.
+ (This can be overridden for individual columns by setting
+ the <literal>COMPRESSION</literal> column option in
+ <command>CREATE TABLE</command> or
+ <command>ALTER TABLE</command>.)
+ The supported compression methods are <literal>pglz</literal> and
+ (if <productname>PostgreSQL</productname> was compiled with
+ <option>--with-lz4</option>) <literal>lz4</literal>.
The default is <literal>pglz</literal>.
</para>
</listitem>
<primary>pg_column_compression</primary>
</indexterm>
<function>pg_column_compression</function> ( <type>"any"</type> )
- <returnvalue>integer</returnvalue>
+ <returnvalue>text</returnvalue>
</para>
<para>
- Shows the compression algorithm that was used to compress a
+ Shows the compression algorithm that was used to compress
an individual variable-length value. Returns <literal>NULL</literal>
if the value is not compressed.
</para></entry>
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( <replaceable>sequence_options</replaceable> ) ] |
UNIQUE <replaceable class="parameter">index_parameters</replaceable> |
PRIMARY KEY <replaceable class="parameter">index_parameters</replaceable> |
- COMPRESSION <replaceable class="parameter">compression_method</replaceable> |
REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
[ ON DELETE <replaceable class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable class="parameter">referential_action</replaceable> ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
</term>
<listitem>
<para>
- This sets the compression method to be used for data inserted into a column.
-
+ This form sets the compression method for a column, determining how
+ values inserted in future will be compressed (if the storage mode
+ permits compression at all).
This does not cause the table to be rewritten, so existing data may still
be compressed with other compression methods. If the table is rewritten with
<command>VACUUM FULL</command> or <command>CLUSTER</command>, or restored
- with <application>pg_restore</application>, then all tuples are rewritten
- with the configured compression methods.
-
- Also, note that when data is inserted from another relation (for example,
- by <command>INSERT ... SELECT</command>), tuples from the source data are
- not necessarily detoasted, and any previously compressed data is retained
- with its existing compression method, rather than recompressing with the
- compression methods of the target columns.
-
+ with <application>pg_restore</application>, then all values are rewritten
+ with the configured compression method.
+ However, when data is inserted from another relation (for example,
+ by <command>INSERT ... SELECT</command>), values from the source table are
+ not necessarily detoasted, so any previously compressed data may retain
+ its existing compression method, rather than being recompressed with the
+ compression method of the target column.
The supported compression
methods are <literal>pglz</literal> and <literal>lz4</literal>.
- <literal>lz4</literal> is available only if <literal>--with-lz4</literal>
- was used when building <productname>PostgreSQL</productname>.
+ (<literal>lz4</literal> is available only if <option>--with-lz4</option>
+ was used when building <productname>PostgreSQL</productname>.) In
+ addition, <replaceable class="parameter">compression_method</replaceable>
+ can be <literal>default</literal>, which selects the default behavior of
+ consulting the <xref linkend="guc-default-toast-compression"/> setting
+ at the time of data insertion to determine the method to use.
</para>
</listitem>
</varlistentry>
<refsynopsisdiv>
<synopsis>
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable class="parameter">table_name</replaceable> ( [
- { <replaceable class="parameter">column_name</replaceable> <replaceable class="parameter">data_type</replaceable> [ COLLATE <replaceable>collation</replaceable> ] [ COMPRESSION <replaceable>compression_method</replaceable> ] [ <replaceable class="parameter">column_constraint</replaceable> [ ... ] ]
+ { <replaceable class="parameter">column_name</replaceable> <replaceable class="parameter">data_type</replaceable> [ COMPRESSION <replaceable>compression_method</replaceable> ] [ COLLATE <replaceable>collation</replaceable> ] [ <replaceable class="parameter">column_constraint</replaceable> [ ... ] ]
| <replaceable>table_constraint</replaceable>
| LIKE <replaceable>source_table</replaceable> [ <replaceable>like_option</replaceable> ... ] }
[, ... ]
<listitem>
<para>
The <literal>COMPRESSION</literal> clause sets the compression method
- for a column. Compression is supported only for variable-width data
- types, and is used only for columns whose storage type is main or
- extended. (See <xref linkend="sql-altertable"/> for information on
- column storage types.) Setting this property for a partitioned table
+ for the column. Compression is supported only for variable-width data
+ types, and is used only when the column's storage mode
+ is <literal>main</literal> or <literal>extended</literal>.
+ (See <xref linkend="sql-altertable"/> for information on
+ column storage modes.) Setting this property for a partitioned table
has no direct effect, because such tables have no storage of their own,
- but the configured value is inherited by newly-created partitions.
+ but the configured value will be inherited by newly-created partitions.
The supported compression methods are <literal>pglz</literal> and
- <literal>lz4</literal>. <literal>lz4</literal> is available only if
- <literal>--with-lz4</literal> was used when building
- <productname>PostgreSQL</productname>. The default
- is <literal>pglz</literal>.
+ <literal>lz4</literal>. (<literal>lz4</literal> is available only if
+ <option>--with-lz4</option> was used when building
+ <productname>PostgreSQL</productname>.) In addition,
+ <replaceable class="parameter">compression_method</replaceable>
+ can be <literal>default</literal> to explicitly specify the default
+ behavior, which is to consult the
+ <xref linkend="guc-default-toast-compression"/> setting at the time of
+ data insertion to determine the method to use.
</para>
</listitem>
</varlistentry>
<para>
Do not output commands to set <acronym>TOAST</acronym> compression
methods.
- With this option, all objects will be created using whichever
- compression method is the default during restore.
+ With this option, all columns will be restored with the default
+ compression setting.
</para>
</listitem>
</varlistentry>
<para>
Do not output commands to set <acronym>TOAST</acronym> compression
methods.
- With this option, all objects will be created using whichever
- compression method is the default during restore.
+ With this option, all columns will be restored with the default
+ compression setting.
</para>
</listitem>
</varlistentry>
-
+
<varlistentry>
<term><option>--no-unlogged-table-data</option></term>
<listitem>
the content of the <acronym>TOAST</acronym> pointer tells that, instead.
</para>
+<para>
+The compression technique used for either in-line or out-of-line compressed
+data can be selected for each column by setting
+the <literal>COMPRESSION</literal> column option in <command>CREATE
+TABLE</command> or <command>ALTER TABLE</command>. The default for columns
+with no explicit setting is to consult the
+<xref linkend="guc-default-toast-compression"/> parameter at the time data is
+inserted.
+</para>
+
<para>
As mentioned, there are multiple types of <acronym>TOAST</acronym> pointer datums.
The oldest and most common type is a pointer to out-of-line data stored in
Further details appear in <xref linkend="storage-toast-inmemory"/>.
</para>
-<para>
-The compression technique used for either in-line or out-of-line compressed
-data can be selected using the <literal>COMPRESSION</literal> option on a per-column
-basis when creating a table. The default for columns with no explicit setting
-is taken from the value of <xref linkend="guc-default-toast-compression" />.
-</para>
-
<sect2 id="storage-toast-ondisk">
<title>Out-of-Line, On-Disk TOAST Storage</title>
* 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);
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)
{
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.
*/
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);
att->attbyval = false;
att->attalign = TYPALIGN_INT;
att->attstorage = TYPSTORAGE_EXTENDED;
- att->attcompression = GetDefaultToastCompression();
+ att->attcompression = InvalidCompressionMethod;
att->attcollation = DEFAULT_COLLATION_OID;
break;
* 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);
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:
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;
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)
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 &&
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
$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';
/* 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
*/
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);
/* ----------------------------------------------------------------
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);
}
/*
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;
/*
* 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);
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,
* matching behavior of index.c ConstructTupleDescriptor()).
*/
SetIndexStorageProperties(rel, attrelation, attnum,
- InvalidCompressionMethod,
- newstorage, lockmode);
+ true, newstorage,
+ false, 0,
+ lockmode);
table_close(attrelation, RowExclusiveLock);
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);
Form_pg_attribute atttableform;
AttrNumber attnum;
char *compression;
- char typstorage;
char cmethod;
ObjectAddress address;
(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;
* 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);
* 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))
%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
%type <list> hash_partbound
%type <defelt> hash_partbound_elem
-%type <str> optColumnCompression
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
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
{
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
{
| 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;
}
;
-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); }
{
{"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
},
{
/* 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 */
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);
processStdStringsEntry(AH, te);
else if (strcmp(te->desc, "SEARCHPATH") == 0)
processSearchPathEntry(AH, te);
- else if (strcmp(te->desc, "TOASTCOMPRESSION") == 0)
- processToastCompressionEntry(AH, te);
}
}
AH->public.searchpath = pg_strdup(te->defn);
}
-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)
{
/* 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;
/*
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");
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,
*/
/*
- * 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)
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:
}
/*
- * 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)
{
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)
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
{
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 ||
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);
false, false);
}
- /* Column compression. */
+ /* Column compression, if relevant */
if (attcompression_col >= 0)
{
char *compression = PQgetvalue(res, i, attcompression_col);
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
{
} 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'
#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);
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202105231
+#define CATALOG_VERSION_NO 202105271
#endif
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');
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
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
--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
(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;
lz4
(2 rows)
-SELECT pg_column_compression(x) FROM mv;
+SELECT pg_column_compression(x) FROM compressmv;
pg_column_compression
-----------------------
lz4
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
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;
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 | |
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
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
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
--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
(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);
-----------------------
(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);
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;
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;
--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
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);
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);
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
\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;