diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 1f0e0fc1fb..d63aebb2ff 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -8085,28 +8085,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - - default_toast_compression (string) - - default_toast_compression configuration parameter - - - - - This variable sets the default - TOAST - compression method for columns of newly-created tables. The - CREATE TABLE statement can override this default - by specifying the COMPRESSION column option. - - The supported compression methods are pglz and - (if configured at the time PostgreSQL was - built) lz4. - The default is pglz. - - - - default_tablespace (string) @@ -8150,6 +8128,28 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + default_toast_compression (enum) + + default_toast_compression configuration parameter + + + + + This variable sets the default + TOAST + compression method for columns of newly-created tables. The + CREATE TABLE statement can override this default + by specifying the COMPRESSION column option. + + The supported compression methods are pglz and + (if configured at the time PostgreSQL was + built) lz4. + The default is pglz. + + + + temp_tablespaces (string) diff --git a/src/backend/access/common/toast_compression.c b/src/backend/access/common/toast_compression.c index 645eb03bf0..52dedac263 100644 --- a/src/backend/access/common/toast_compression.c +++ b/src/backend/access/common/toast_compression.c @@ -23,8 +23,15 @@ #include "fmgr.h" #include "utils/builtins.h" -/* Compile-time default */ -char *default_toast_compression = DEFAULT_TOAST_COMPRESSION; +/* GUC */ +int default_toast_compression = TOAST_PGLZ_COMPRESSION; + +#define NO_LZ4_SUPPORT() \ + ereport(ERROR, \ + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ + errmsg("unsupported LZ4 compression method"), \ + errdetail("This functionality requires the server to be built with lz4 support."), \ + errhint("You need to rebuild PostgreSQL using --with-lz4."))) /* * Compress a varlena using PGLZ. @@ -271,46 +278,41 @@ toast_get_compression_id(struct varlena *attr) } /* - * Validate a new value for the default_toast_compression GUC. + * CompressionNameToMethod - Get compression method from compression name + * + * Search in the available built-in methods. If the compression not found + * in the built-in methods then return InvalidCompressionMethod. */ -bool -check_default_toast_compression(char **newval, void **extra, GucSource source) +char +CompressionNameToMethod(const char *compression) { - if (**newval == '\0') + if (strcmp(compression, "pglz") == 0) + return TOAST_PGLZ_COMPRESSION; + else if (strcmp(compression, "lz4") == 0) { - GUC_check_errdetail("%s cannot be empty.", - "default_toast_compression"); - return false; +#ifndef USE_LZ4 + NO_LZ4_SUPPORT(); +#endif + return TOAST_LZ4_COMPRESSION; } - if (strlen(*newval) >= NAMEDATALEN) - { - GUC_check_errdetail("%s is too long (maximum %d characters).", - "default_toast_compression", NAMEDATALEN - 1); - return false; - } - - if (!CompressionMethodIsValid(CompressionNameToMethod(*newval))) - { - /* - * When source == PGC_S_TEST, don't throw a hard error for a - * nonexistent compression method, only a NOTICE. See comments in - * guc.h. - */ - if (source == PGC_S_TEST) - { - ereport(NOTICE, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("compression method \"%s\" does not exist", - *newval))); - } - else - { - GUC_check_errdetail("Compression method \"%s\" does not exist.", - *newval); - return false; - } - } - - return true; + return InvalidCompressionMethod; +} + +/* + * GetCompressionMethodName - Get compression method name + */ +const char * +GetCompressionMethodName(char method) +{ + switch (method) + { + case TOAST_PGLZ_COMPRESSION: + return "pglz"; + case TOAST_LZ4_COMPRESSION: + return "lz4"; + default: + elog(ERROR, "invalid compression method %c", method); + return NULL; /* keep compiler quiet */ + } } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8bfaa53541..cc0b9f6ad6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -509,6 +509,14 @@ static struct config_enum_entry shared_memory_options[] = { {NULL, 0, false} }; +static struct config_enum_entry default_toast_compression_options[] = { + {"pglz", TOAST_PGLZ_COMPRESSION, false}, +#ifdef USE_LZ4 + {"lz4", TOAST_LZ4_COMPRESSION, false}, +#endif + {NULL, 0, false} +}; + /* * Options for enum values stored in other modules */ @@ -3933,17 +3941,6 @@ static struct config_string ConfigureNamesString[] = check_default_table_access_method, NULL, NULL }, - { - {"default_toast_compression", PGC_USERSET, CLIENT_CONN_STATEMENT, - gettext_noop("Sets the default compression for new columns."), - NULL, - GUC_IS_NAME - }, - &default_toast_compression, - DEFAULT_TOAST_COMPRESSION, - check_default_toast_compression, NULL, NULL - }, - { {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the default tablespace to create tables and indexes in."), @@ -4585,6 +4582,17 @@ static struct config_enum ConfigureNamesEnum[] = NULL, NULL, NULL }, + { + {"default_toast_compression", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Sets the default compression for new columns."), + NULL, + GUC_IS_NAME + }, + &default_toast_compression, + TOAST_PGLZ_COMPRESSION, + default_toast_compression_options, NULL, NULL + }, + { {"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the transaction isolation level of each new transaction."), diff --git a/src/include/access/toast_compression.h b/src/include/access/toast_compression.h index 44b73bd57c..46c2544e31 100644 --- a/src/include/access/toast_compression.h +++ b/src/include/access/toast_compression.h @@ -13,18 +13,26 @@ #ifndef TOAST_COMPRESSION_H #define TOAST_COMPRESSION_H -#include "utils/guc.h" - -/* GUCs */ -extern char *default_toast_compression; - -/* default compression method if not specified. */ -#define DEFAULT_TOAST_COMPRESSION "pglz" +/* + * GUC support. + * + * default_toast_compression is an integer for purposes of the GUC machinery, + * but the value is one of the char values defined below, as they appear in + * pg_attribute.attcompression, e.g. TOAST_PGLZ_COMPRESSION. + */ +extern int default_toast_compression; /* * 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. + * + * 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. */ typedef enum ToastCompressionId { @@ -39,60 +47,13 @@ typedef enum ToastCompressionId */ #define TOAST_PGLZ_COMPRESSION 'p' #define TOAST_LZ4_COMPRESSION 'l' +#define InvalidCompressionMethod '\0' -#define InvalidCompressionMethod '\0' -#define CompressionMethodIsValid(cm) ((bool) ((cm) != InvalidCompressionMethod)) - -#define NO_LZ4_SUPPORT() \ - ereport(ERROR, \ - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ - errmsg("unsupported LZ4 compression method"), \ - errdetail("This functionality requires the server to be built with lz4 support."), \ - errhint("You need to rebuild PostgreSQL using --with-lz4."))) +#define CompressionMethodIsValid(cm) ((cm) != InvalidCompressionMethod) #define IsStorageCompressible(storage) ((storage) != TYPSTORAGE_PLAIN && \ (storage) != TYPSTORAGE_EXTERNAL) -/* - * GetCompressionMethodName - Get compression method name - */ -static inline const char * -GetCompressionMethodName(char method) -{ - switch (method) - { - case TOAST_PGLZ_COMPRESSION: - return "pglz"; - case TOAST_LZ4_COMPRESSION: - return "lz4"; - default: - elog(ERROR, "invalid compression method %c", method); - return NULL; /* keep compiler quiet */ - } -} - -/* - * CompressionNameToMethod - Get compression method from compression name - * - * Search in the available built-in methods. If the compression not found - * in the built-in methods then return InvalidCompressionMethod. - */ -static inline char -CompressionNameToMethod(char *compression) -{ - if (strcmp(compression, "pglz") == 0) - return TOAST_PGLZ_COMPRESSION; - else if (strcmp(compression, "lz4") == 0) - { -#ifndef USE_LZ4 - NO_LZ4_SUPPORT(); -#endif - return TOAST_LZ4_COMPRESSION; - } - - return InvalidCompressionMethod; -} - /* * GetDefaultToastCompression -- get the default toast compression method * @@ -101,7 +62,7 @@ CompressionNameToMethod(char *compression) static inline char GetDefaultToastCompression(void) { - return CompressionNameToMethod(default_toast_compression); + return (char) default_toast_compression; } /* pglz compression/decompression routines */ @@ -115,8 +76,10 @@ extern struct varlena *lz4_compress_datum(const struct varlena *value); extern struct varlena *lz4_decompress_datum(const struct varlena *value); extern struct varlena *lz4_decompress_datum_slice(const struct varlena *value, int32 slicelength); + +/* other stuff */ extern ToastCompressionId toast_get_compression_id(struct varlena *attr); -extern bool check_default_toast_compression(char **newval, void **extra, - GucSource source); +extern char CompressionNameToMethod(const char *compression); +extern const char *GetCompressionMethodName(char method); #endif /* TOAST_COMPRESSION_H */ diff --git a/src/test/regress/expected/compression.out b/src/test/regress/expected/compression.out index c2f2e0e230..566a1877ea 100644 --- a/src/test/regress/expected/compression.out +++ b/src/test/regress/expected/compression.out @@ -234,10 +234,10 @@ DETAIL: pglz versus lz4 -- test default_toast_compression GUC SET default_toast_compression = ''; ERROR: invalid value for parameter "default_toast_compression": "" -DETAIL: default_toast_compression cannot be empty. +HINT: Available values: pglz, lz4. SET default_toast_compression = 'I do not exist compression'; ERROR: invalid value for parameter "default_toast_compression": "I do not exist compression" -DETAIL: Compression method "I do not exist compression" does not exist. +HINT: Available values: pglz, lz4. SET default_toast_compression = 'lz4'; DROP TABLE cmdata2; CREATE TABLE cmdata2 (f1 text); diff --git a/src/test/regress/expected/compression_1.out b/src/test/regress/expected/compression_1.out index 6626f8e927..3990933415 100644 --- a/src/test/regress/expected/compression_1.out +++ b/src/test/regress/expected/compression_1.out @@ -227,14 +227,13 @@ DETAIL: pglz versus lz4 -- test default_toast_compression GUC SET default_toast_compression = ''; ERROR: invalid value for parameter "default_toast_compression": "" -DETAIL: default_toast_compression cannot be empty. +HINT: Available values: pglz. SET default_toast_compression = 'I do not exist compression'; ERROR: invalid value for parameter "default_toast_compression": "I do not exist compression" -DETAIL: Compression method "I do not exist compression" does not exist. +HINT: Available values: pglz. SET default_toast_compression = 'lz4'; -ERROR: unsupported LZ4 compression method -DETAIL: This functionality requires the server to be built with lz4 support. -HINT: You need to rebuild PostgreSQL using --with-lz4. +ERROR: invalid value for parameter "default_toast_compression": "lz4" +HINT: Available values: pglz. DROP TABLE cmdata2; CREATE TABLE cmdata2 (f1 text); \d+ cmdata2