Skip to content

Commit d18655c

Browse files
committed
Refactor code parsing compression option values (-Z/--compress)
This commit moves the code in charge of deparsing the method and detail strings fed later to parse_compress_specification() to a common routine, where the backward-compatible case of only an integer being found (N = 0 => "none", N > 1 => gzip at level N) is handled. Note that this has a side-effect for pg_basebackup, as we now attempt to detect "server-" and "client-" before checking for the integer-only pre-14 grammar, where values like server-N and client-N (without the follow-up detail string) are now valid rather than failing because of an unsupported method name. Past grammars are still handled the same way, but these flavors are now authorized, and would now switch to consider N = 0 as no compression and N > 1 as gzip with the compression level used as N, with the caller still controlling if the compression method should be done server-side, client-side or is unspecified. The documentation of pg_basebackup is updated to reflect that. This benefits other code paths that would like to rely on the same logic as pg_basebackup and pg_receivewal with option values used for compression specifications, one area discussed lately being pg_dump. Author: Georgios Kokolatos, Michael Paquier Discussion: https://postgr.es/m/O4mutIrCES8ZhlXJiMvzsivT7ztAMja2lkdL1LJx6O5f22I2W8PBIeLKz7mDLwxHoibcnRAYJXm1pH4tyUNC4a8eDzLn22a6Pb1S74Niexg=@pm.me
1 parent d74a366 commit d18655c

File tree

5 files changed

+82
-108
lines changed

5 files changed

+82
-108
lines changed

doc/src/sgml/ref/pg_basebackup.sgml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,18 @@ PostgreSQL documentation
416416
</para>
417417
<para>
418418
The compression method can be set to <literal>gzip</literal>,
419-
<literal>lz4</literal>, <literal>zstd</literal>, or
420-
<literal>none</literal> for no compression. A compression detail
421-
string can optionally be specified. If the detail string is an
422-
integer, it specifies the compression level. Otherwise, it should be
423-
a comma-separated list of items, each of the form
424-
<literal>keyword</literal> or <literal>keyword=value</literal>.
419+
<literal>lz4</literal>, <literal>zstd</literal>,
420+
<literal>none</literal> for no compression or an integer (no
421+
compression if 0, <literal>gzip</literal> if greater than 0).
422+
A compression detail string can optionally be specified.
423+
If the detail string is an integer, it specifies the compression
424+
level. Otherwise, it should be a comma-separated list of items,
425+
each of the form <literal>keyword</literal> or
426+
<literal>keyword=value</literal>.
425427
Currently, the supported keywords are <literal>level</literal>
426428
and <literal>workers</literal>.
429+
The detail string cannot be used when the compression method
430+
is specified as a plain integer.
427431
</para>
428432
<para>
429433
If no compression level is specified, the default compression level

src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -956,27 +956,12 @@ parse_max_rate(char *src)
956956
* at a later stage.
957957
*/
958958
static void
959-
parse_compress_options(char *option, char **algorithm, char **detail,
960-
CompressionLocation *locationres)
959+
backup_parse_compress_options(char *option, char **algorithm, char **detail,
960+
CompressionLocation *locationres)
961961
{
962-
char *sep;
963-
char *endp;
964-
965962
/*
966-
* Check whether the compression specification consists of a bare integer.
967-
*
968-
* If so, for backward compatibility, assume gzip.
963+
* Strip off any "client-" or "server-" prefix, calculating the location.
969964
*/
970-
(void) strtol(option, &endp, 10);
971-
if (*endp == '\0')
972-
{
973-
*locationres = COMPRESS_LOCATION_UNSPECIFIED;
974-
*algorithm = pstrdup("gzip");
975-
*detail = pstrdup(option);
976-
return;
977-
}
978-
979-
/* Strip off any "client-" or "server-" prefix. */
980965
if (strncmp(option, "server-", 7) == 0)
981966
{
982967
*locationres = COMPRESS_LOCATION_SERVER;
@@ -990,27 +975,8 @@ parse_compress_options(char *option, char **algorithm, char **detail,
990975
else
991976
*locationres = COMPRESS_LOCATION_UNSPECIFIED;
992977

993-
/*
994-
* Check whether there is a compression detail following the algorithm
995-
* name.
996-
*/
997-
sep = strchr(option, ':');
998-
if (sep == NULL)
999-
{
1000-
*algorithm = pstrdup(option);
1001-
*detail = NULL;
1002-
}
1003-
else
1004-
{
1005-
char *alg;
1006-
1007-
alg = palloc((sep - option) + 1);
1008-
memcpy(alg, option, sep - option);
1009-
alg[sep - option] = '\0';
1010-
1011-
*algorithm = alg;
1012-
*detail = pstrdup(sep + 1);
1013-
}
978+
/* fallback to the common parsing for the algorithm and detail */
979+
parse_compress_options(option, algorithm, detail);
1014980
}
1015981

1016982
/*
@@ -2411,8 +2377,8 @@ main(int argc, char **argv)
24112377
compressloc = COMPRESS_LOCATION_UNSPECIFIED;
24122378
break;
24132379
case 'Z':
2414-
parse_compress_options(optarg, &compression_algorithm,
2415-
&compression_detail, &compressloc);
2380+
backup_parse_compress_options(optarg, &compression_algorithm,
2381+
&compression_detail, &compressloc);
24162382
break;
24172383
case 'c':
24182384
if (pg_strcasecmp(optarg, "fast") == 0)

src/bin/pg_basebackup/pg_receivewal.c

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ static XLogRecPtr endpos = InvalidXLogRecPtr;
5757

5858

5959
static void usage(void);
60-
static void parse_compress_options(char *option, char **algorithm,
61-
char **detail);
6260
static DIR *get_destination_dir(char *dest_folder);
6361
static void close_destination_dir(DIR *dest_dir, char *dest_folder);
6462
static XLogRecPtr FindStreamingStart(uint32 *tli);
@@ -109,65 +107,6 @@ usage(void)
109107
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
110108
}
111109

112-
/*
113-
* Basic parsing of a value specified for -Z/--compress
114-
*
115-
* The parsing consists of a METHOD:DETAIL string fed later on to a more
116-
* advanced routine in charge of proper validation checks. This only extracts
117-
* METHOD and DETAIL. If only an integer is found, the method is implied by
118-
* the value specified.
119-
*/
120-
static void
121-
parse_compress_options(char *option, char **algorithm, char **detail)
122-
{
123-
char *sep;
124-
char *endp;
125-
long result;
126-
127-
/*
128-
* Check whether the compression specification consists of a bare integer.
129-
*
130-
* For backward-compatibility, assume "none" if the integer found is zero
131-
* and "gzip" otherwise.
132-
*/
133-
result = strtol(option, &endp, 10);
134-
if (*endp == '\0')
135-
{
136-
if (result == 0)
137-
{
138-
*algorithm = pstrdup("none");
139-
*detail = NULL;
140-
}
141-
else
142-
{
143-
*algorithm = pstrdup("gzip");
144-
*detail = pstrdup(option);
145-
}
146-
return;
147-
}
148-
149-
/*
150-
* Check whether there is a compression detail following the algorithm
151-
* name.
152-
*/
153-
sep = strchr(option, ':');
154-
if (sep == NULL)
155-
{
156-
*algorithm = pstrdup(option);
157-
*detail = NULL;
158-
}
159-
else
160-
{
161-
char *alg;
162-
163-
alg = palloc((sep - option) + 1);
164-
memcpy(alg, option, sep - option);
165-
alg[sep - option] = '\0';
166-
167-
*algorithm = alg;
168-
*detail = pstrdup(sep + 1);
169-
}
170-
}
171110

172111
/*
173112
* Check if the filename looks like a WAL file, letting caller know if this

src/common/compression.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,66 @@ validate_compress_specification(pg_compress_specification *spec)
356356

357357
return NULL;
358358
}
359+
360+
#ifdef FRONTEND
361+
362+
/*
363+
* Basic parsing of a value specified through a command-line option, commonly
364+
* -Z/--compress.
365+
*
366+
* The parsing consists of a METHOD:DETAIL string fed later to
367+
* parse_compress_specification(). This only extracts METHOD and DETAIL.
368+
* If only an integer is found, the method is implied by the value specified.
369+
*/
370+
void
371+
parse_compress_options(const char *option, char **algorithm, char **detail)
372+
{
373+
char *sep;
374+
char *endp;
375+
long result;
376+
377+
/*
378+
* Check whether the compression specification consists of a bare integer.
379+
*
380+
* For backward-compatibility, assume "none" if the integer found is zero
381+
* and "gzip" otherwise.
382+
*/
383+
result = strtol(option, &endp, 10);
384+
if (*endp == '\0')
385+
{
386+
if (result == 0)
387+
{
388+
*algorithm = pstrdup("none");
389+
*detail = NULL;
390+
}
391+
else
392+
{
393+
*algorithm = pstrdup("gzip");
394+
*detail = pstrdup(option);
395+
}
396+
return;
397+
}
398+
399+
/*
400+
* Check whether there is a compression detail following the algorithm
401+
* name.
402+
*/
403+
sep = strchr(option, ':');
404+
if (sep == NULL)
405+
{
406+
*algorithm = pstrdup(option);
407+
*detail = NULL;
408+
}
409+
else
410+
{
411+
char *alg;
412+
413+
alg = palloc((sep - option) + 1);
414+
memcpy(alg, option, sep - option);
415+
alg[sep - option] = '\0';
416+
417+
*algorithm = alg;
418+
*detail = pstrdup(sep + 1);
419+
}
420+
}
421+
#endif /* FRONTEND */

src/include/common/compression.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ typedef struct pg_compress_specification
3333
char *parse_error; /* NULL if parsing was OK, else message */
3434
} pg_compress_specification;
3535

36+
extern void parse_compress_options(const char *option, char **algorithm,
37+
char **detail);
3638
extern bool parse_compress_algorithm(char *name, pg_compress_algorithm *algorithm);
3739
extern const char *get_compress_algorithm_name(pg_compress_algorithm algorithm);
3840

0 commit comments

Comments
 (0)