From 28c7236534634498265c3e4d6544c836052f009f Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Thu, 10 Mar 2022 20:16:19 -0600
Subject: [PATCH 5/5] pg_basebackup: support Zstd negative compression levels

"higher than maximum" is bogus

TODO: each compression methods should enforce its own levels
---
 src/backend/replication/basebackup_zstd.c |  2 +-
 src/bin/pg_basebackup/bbstreamer_zstd.c   | 16 +++++++---------
 src/common/backup_compression.c           |  6 +++++-
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/backend/replication/basebackup_zstd.c b/src/backend/replication/basebackup_zstd.c
index b900604f59f..e18535bcc13 100644
--- a/src/backend/replication/basebackup_zstd.c
+++ b/src/backend/replication/basebackup_zstd.c
@@ -84,7 +84,7 @@ bbsink_zstd_new(bbsink *next, bc_specification *compress)
 	else
 	{
 		compresslevel = compress->level;
-		Assert(compresslevel >= 1 && compresslevel <= 22);
+		Assert(compresslevel >= -7 && compresslevel <= 22 && compresslevel != 0);
 	}
 
 	if (compress->options & BACKUP_COMPRESSION_OPTION_WORKERS)
diff --git a/src/bin/pg_basebackup/bbstreamer_zstd.c b/src/bin/pg_basebackup/bbstreamer_zstd.c
index 3c7396a1373..31fbf2d0bc3 100644
--- a/src/bin/pg_basebackup/bbstreamer_zstd.c
+++ b/src/bin/pg_basebackup/bbstreamer_zstd.c
@@ -89,16 +89,14 @@ bbstreamer_zstd_compressor_new(bbstreamer *next, bc_specification *compress)
 	}
 
 	/* Initialize stream compression preferences */
-	if ((compress->options & BACKUP_COMPRESSION_OPTION_LEVEL) == 0)
-		compresslevel = 0;
-	else
-		compresslevel = compress->level;
-	ret = ZSTD_CCtx_setParameter(streamer->cctx, ZSTD_c_compressionLevel,
-								 compresslevel);
-	if (ZSTD_isError(ret))
+
+	if (compress->options & BACKUP_COMPRESSION_OPTION_LEVEL)
 	{
-		pg_log_error("could not set zstd compression level to %d: %s",
-					 compresslevel, ZSTD_getErrorName(ret));
+		ret = ZSTD_CCtx_setParameter(streamer->cctx, ZSTD_c_compressionLevel,
+							   compress->level);
+		if (ZSTD_isError(ret))
+			pg_log_error("could not set compression level to: %d: %s",
+					compress->level, ZSTD_getErrorName(ret));
 		exit(1);
 	}
 
diff --git a/src/common/backup_compression.c b/src/common/backup_compression.c
index f43a5608e65..b568eccd65f 100644
--- a/src/common/backup_compression.c
+++ b/src/common/backup_compression.c
@@ -265,13 +265,17 @@ validate_bc_specification(bc_specification *spec)
 		else if (spec->algorithm == BACKUP_COMPRESSION_LZ4)
 			max_level = 12;
 		else if (spec->algorithm == BACKUP_COMPRESSION_ZSTD)
+		{
 			max_level = 22;
+			/* The minimum level depends on the version.. */
+			min_level = -7;
+		}
 		else
 			return psprintf(_("compression algorithm \"%s\" does not accept a compression level"),
 							get_bc_algorithm_name(spec->algorithm));
 
 		if (spec->level < min_level || spec->level > max_level)
-			return psprintf(_("compression algorithm \"%s\" expects a compression level between %d and %d"),
+			return psprintf(_("compression algorithm \"%s\" expects a nonzero compression level between %d and %d"),
 							get_bc_algorithm_name(spec->algorithm),
 							min_level, max_level);
 	}
-- 
2.17.1

