From 4fd87fe098b513ee8120198af51011c4b133d846 Mon Sep 17 00:00:00 2001 From: Zhijie Hou Date: Mon, 13 Apr 2026 11:24:51 +0800 Subject: [PATCH vPOC] Refactor the parsing code --- src/backend/replication/slot.c | 67 ++------------------------ src/backend/replication/syncrep.c | 4 ++ src/backend/replication/syncrep_gram.y | 2 +- src/include/replication/syncrep.h | 1 + 4 files changed, 10 insertions(+), 64 deletions(-) diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 38826fa4a41..f696d90cb2e 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -222,7 +222,6 @@ static void ReplicationSlotDropPtr(ReplicationSlot *slot); static void RestoreSlotFromDisk(const char *name); static void CreateSlotOnDisk(ReplicationSlot *slot); static void SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel); -static bool IsPrioritySyncStandbySlotsSyntax(const char *value); /* * Register shared memory space needed for replication slots. @@ -2997,52 +2996,6 @@ GetSlotInvalidationCauseName(ReplicationSlotInvalidationCause cause) return "none"; /* to keep compiler quiet */ } -/* - * Return true if value starts with explicit priority syntax: - * - * FIRST N (...) - * N (...) - * - * This is used to distinguish explicit priority syntax from simple list - * syntax whose first slot name may start with "first". - */ -static bool -IsPrioritySyncStandbySlotsSyntax(const char *value) -{ - const char *p = value; - - /* Skip leading whitespace */ - while (*p && isspace((unsigned char) *p)) - p++; - - /* - * Accept either explicit FIRST N (...) or bare N (...) priority syntax. - * If the input starts with FIRST, it must be followed by whitespace. - */ - if (pg_strncasecmp(p, "FIRST", 5) == 0) - { - p += 5; - - if (!isspace((unsigned char) *p)) - return false; - - while (*p && isspace((unsigned char) *p)) - p++; - } - - if (!isdigit((unsigned char) *p)) - return false; - - while (*p && isdigit((unsigned char) *p)) - p++; - - /* Explicit priority syntax then requires a parenthesized member list */ - while (*p && isspace((unsigned char) *p)) - p++; - - return (*p == '('); -} - /* * GUC check_hook for synchronized_standby_slots * @@ -3109,27 +3062,15 @@ check_synchronized_standby_slots(char **newval, void **extra, GucSource source) } /* - * When using simple list syntax (e.g., "slot1, slot2"), the parser - * returns num_sync=1 and SYNC_REP_PRIORITY. We interpret this as - * "wait for ALL slots" by setting num_sync to nmembers. + * When using simple list syntax (e.g., "slot1, slot2"), we interpret + * this as "wait for ALL slots" by setting num_sync to nmembers. * * This differs from synchronous_standby_names where "standby1, standby2" * means "wait for first 1 standby". For synchronized_standby_slots, * requiring all slots provides safer failover semantics by default. */ - if (syncrep_parse_result->num_sync == 1 && - syncrep_parse_result->syncrep_method == SYNC_REP_PRIORITY && - syncrep_parse_result->nmembers > 1) - { - /* - * Distinguish simple list syntax from explicit priority syntax - * ("FIRST N (...)" or "N (...)"). This prevents a list whose - * first slot name starts with "first" (for example, - * "firstslot, secondslot") from being misclassified. - */ - if (!IsPrioritySyncStandbySlotsSyntax(*newval)) - syncrep_parse_result->num_sync = syncrep_parse_result->nmembers; - } + if (syncrep_parse_result->syncrep_method == SYNC_REP_DEFAULT) + syncrep_parse_result->num_sync = syncrep_parse_result->nmembers; /* validate every member name as a slot name */ mname = syncrep_parse_result->member_names; diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 46a778f0917..34fbac06e48 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -1103,6 +1103,10 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source) return false; } + /* Default to FIRST 1 (name ...) priority method if not specified */ + if (syncrep_parse_result->syncrep_method == SYNC_REP_DEFAULT) + syncrep_parse_result->syncrep_method = SYNC_REP_PRIORITY; + /* GUC extra value must be guc_malloc'd, not palloc'd */ pconf = (SyncRepConfigData *) guc_malloc(LOG, syncrep_parse_result->config_size); diff --git a/src/backend/replication/syncrep_gram.y b/src/backend/replication/syncrep_gram.y index 1b9d7b2edc4..f1550e109ef 100644 --- a/src/backend/replication/syncrep_gram.y +++ b/src/backend/replication/syncrep_gram.y @@ -65,7 +65,7 @@ result: ; standby_config: - standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); } + standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_DEFAULT); } | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); } | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); } | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); } diff --git a/src/include/replication/syncrep.h b/src/include/replication/syncrep.h index 24e22f9cafa..9554271907d 100644 --- a/src/include/replication/syncrep.h +++ b/src/include/replication/syncrep.h @@ -34,6 +34,7 @@ /* syncrep_method of SyncRepConfigData */ #define SYNC_REP_PRIORITY 0 #define SYNC_REP_QUORUM 1 +#define SYNC_REP_DEFAULT 2 /* * SyncRepGetCandidateStandbys returns an array of these structs, -- 2.53.0.windows.2