From 51e9982701eee197a9c6ae54830e4d6683f8a032 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 1 Jul 2021 11:33:32 -0400 Subject: [PATCH v3 1/7] Flexible options for BASE_BACKUP and CREATE_REPLICATION_SLOT. Previously, these replication commands used an entirely hard-coded syntax, but that's hard to extend. Instead, adopt the same kind of syntax we've used for SQL commands such as VACUUM, ANALYZE, COPY, and EXPLAIN, where it's not necessary for all of the option names to be parser keywords. This commit does not remove support for the old syntax. It just adds the new one as an additional option, and makes pg_basebackup prefer the new syntax when the server is new enough to support it. v2: Fix compile error. v3: Fix inverted test, as reported by Tushar Ahuja. v4: Adjustments for v15. --- src/backend/replication/basebackup.c | 33 ++--- .../libpqwalreceiver/libpqwalreceiver.c | 8 +- src/backend/replication/repl_gram.y | 116 +++++++++++++++--- src/backend/replication/walsender.c | 17 +-- src/bin/pg_basebackup/pg_basebackup.c | 65 ++++++---- src/bin/pg_basebackup/streamutil.c | 102 +++++++++++++-- src/bin/pg_basebackup/streamutil.h | 12 ++ 7 files changed, 273 insertions(+), 80 deletions(-) diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index e09108d0ec..b0b52d3b1a 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -19,6 +19,7 @@ #include "access/xlog_internal.h" /* for pg_start/stop_backup */ #include "catalog/pg_type.h" #include "common/file_perm.h" +#include "commands/defrem.h" #include "commands/progress.h" #include "lib/stringinfo.h" #include "libpq/libpq.h" @@ -787,7 +788,7 @@ parse_basebackup_options(List *options, basebackup_options *opt) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->label = strVal(defel->arg); + opt->label = defGetString(defel); o_label = true; } else if (strcmp(defel->defname, "progress") == 0) @@ -796,7 +797,7 @@ parse_basebackup_options(List *options, basebackup_options *opt) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->progress = true; + opt->progress = defGetBoolean(defel); o_progress = true; } else if (strcmp(defel->defname, "fast") == 0) @@ -805,16 +806,16 @@ parse_basebackup_options(List *options, basebackup_options *opt) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->fastcheckpoint = true; + opt->fastcheckpoint = defGetBoolean(defel); o_fast = true; } - else if (strcmp(defel->defname, "nowait") == 0) + else if (strcmp(defel->defname, "wait") == 0) { if (o_nowait) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->nowait = true; + opt->nowait = !defGetBoolean(defel); o_nowait = true; } else if (strcmp(defel->defname, "wal") == 0) @@ -823,19 +824,19 @@ parse_basebackup_options(List *options, basebackup_options *opt) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->includewal = true; + opt->includewal = defGetBoolean(defel); o_wal = true; } else if (strcmp(defel->defname, "max_rate") == 0) { - long maxrate; + int64 maxrate; if (o_maxrate) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - maxrate = intVal(defel->arg); + maxrate = defGetInt64(defel); if (maxrate < MAX_RATE_LOWER || maxrate > MAX_RATE_UPPER) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), @@ -851,21 +852,21 @@ parse_basebackup_options(List *options, basebackup_options *opt) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - opt->sendtblspcmapfile = true; + opt->sendtblspcmapfile = defGetBoolean(defel); o_tablespace_map = true; } - else if (strcmp(defel->defname, "noverify_checksums") == 0) + else if (strcmp(defel->defname, "verify_checksums") == 0) { if (o_noverify_checksums) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("duplicate option \"%s\"", defel->defname))); - noverify_checksums = true; + noverify_checksums = !defGetBoolean(defel); o_noverify_checksums = true; } else if (strcmp(defel->defname, "manifest") == 0) { - char *optval = strVal(defel->arg); + char *optval = defGetString(defel); bool manifest_bool; if (o_manifest) @@ -890,7 +891,7 @@ parse_basebackup_options(List *options, basebackup_options *opt) } else if (strcmp(defel->defname, "manifest_checksums") == 0) { - char *optval = strVal(defel->arg); + char *optval = defGetString(defel); if (o_manifest_checksums) ereport(ERROR, @@ -905,8 +906,10 @@ parse_basebackup_options(List *options, basebackup_options *opt) o_manifest_checksums = true; } else - elog(ERROR, "option \"%s\" not recognized", - defel->defname); + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option \"%s\" not recognized", + defel->defname)); } if (opt->label == NULL) opt->label = "base backup"; diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 6eaa84a031..37a0d1c79a 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -871,19 +871,19 @@ libpqrcv_create_slot(WalReceiverConn *conn, const char *slotname, switch (snapshot_action) { case CRS_EXPORT_SNAPSHOT: - appendStringInfoString(&cmd, " EXPORT_SNAPSHOT"); + appendStringInfoString(&cmd, " (EXPORT_SNAPSHOT TRUE)"); break; case CRS_NOEXPORT_SNAPSHOT: - appendStringInfoString(&cmd, " NOEXPORT_SNAPSHOT"); + appendStringInfoString(&cmd, " (EXPORT_SNAPSHOT FALSE)"); break; case CRS_USE_SNAPSHOT: - appendStringInfoString(&cmd, " USE_SNAPSHOT"); + appendStringInfoString(&cmd, " (USE_SNAPSHOT)"); break; } } else { - appendStringInfoString(&cmd, " PHYSICAL RESERVE_WAL"); + appendStringInfoString(&cmd, " PHYSICAL (RESERVE_WAL)"); } res = libpqrcv_PQexec(conn->streamConn, cmd.data); diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y index e1e8ec29cc..69e990cda3 100644 --- a/src/backend/replication/repl_gram.y +++ b/src/backend/replication/repl_gram.y @@ -95,16 +95,16 @@ static SQLCmd *make_sqlcmd(void); %type base_backup start_replication start_logical_replication create_replication_slot drop_replication_slot identify_system timeline_history show sql_cmd -%type base_backup_opt_list -%type base_backup_opt +%type base_backup_legacy_opt_list generic_option_list +%type base_backup_legacy_opt generic_option %type opt_timeline %type plugin_options plugin_opt_list %type plugin_opt_elem %type plugin_opt_arg -%type opt_slot var_name +%type opt_slot var_name ident_or_keyword %type opt_temporary -%type create_slot_opt_list -%type create_slot_opt +%type create_slot_options create_slot_legacy_opt_list +%type create_slot_legacy_opt %% @@ -157,12 +157,24 @@ var_name: IDENT { $$ = $1; } ; /* + * BASE_BACKUP ( option [ 'value' ] [, ...] ) + * + * We also still support the legacy syntax: + * * BASE_BACKUP [LABEL '