Skip to content

Commit 74a72e4

Browse files
authored
Fix bug in quote_standby_name() function (patroni#3161)
According to Postgres docs "ANY" and "FIRST" keywords are supposed to be double-quoted. Ref: https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES
1 parent 4c951a2 commit 74a72e4

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

patroni/postgresql/sync.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .. import global_config
99
from ..collections import CaseInsensitiveDict, CaseInsensitiveSet
1010
from ..dcs import Cluster
11-
from ..psycopg import quote_ident as _quote_ident
11+
from ..psycopg import quote_ident
1212

1313
if TYPE_CHECKING: # pragma: no cover
1414
from . import Postgresql
@@ -31,9 +31,14 @@
3131
""", re.X)
3232

3333

34-
def quote_ident(value: str) -> str:
35-
"""Very simplified version of `psycopg` :func:`quote_ident` function."""
36-
return value if SYNC_STANDBY_NAME_RE.match(value) else _quote_ident(value)
34+
def quote_standby_name(value: str) -> str:
35+
"""Quote provided *value* if it is nenecessary.
36+
37+
:param value: name of a synchronous standby.
38+
39+
:returns: a quoted value if it is required or the original one.
40+
"""
41+
return value if SYNC_STANDBY_NAME_RE.match(value) and value.lower() not in ('first', 'any') else quote_ident(value)
3742

3843

3944
class _SSN(NamedTuple):
@@ -391,7 +396,7 @@ def set_synchronous_standby_names(self, sync: Collection[str], num: Optional[int
391396
if has_asterisk:
392397
sync = ['*']
393398
else:
394-
sync = [quote_ident(x) for x in sorted(sync)]
399+
sync = [quote_standby_name(x) for x in sorted(sync)]
395400

396401
if self._postgresql.supports_multiple_sync and len(sync) > 1:
397402
if num is None:

tests/test_sync.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ def value_in_conf():
128128
self.assertEqual(value_in_conf(), "synchronous_standby_names = 'ANY 1 (*)'")
129129

130130
mock_reload.reset_mock()
131-
self.s.set_synchronous_standby_names(['a', 'b'], 1)
131+
self.s.set_synchronous_standby_names(['any', 'b'], 1)
132132
mock_reload.assert_called()
133-
self.assertEqual(value_in_conf(), "synchronous_standby_names = 'ANY 1 (a,b)'")
133+
self.assertEqual(value_in_conf(), "synchronous_standby_names = 'ANY 1 (\"any\",b)'")
134134

135135
mock_reload.reset_mock()
136136
self.s.set_synchronous_standby_names(['a', 'b'], 3)

0 commit comments

Comments
 (0)