From ab549545900f35f93f42f6475af2dda95124f383 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Mon, 15 Jun 2026 14:28:25 -0700 Subject: [PATCH] feat: enable parser for LISTEN/NOTIFY/UNLISTEN --- pgdog/src/backend/pool/cluster.rs | 1 - pgdog/src/frontend/regex_parser.rs | 34 +++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/pgdog/src/backend/pool/cluster.rs b/pgdog/src/backend/pool/cluster.rs index 6ae654486..13f36f5ee 100644 --- a/pgdog/src/backend/pool/cluster.rs +++ b/pgdog/src/backend/pool/cluster.rs @@ -524,7 +524,6 @@ impl Cluster { || self.router_needed() || self.dry_run() || self.prepared_statements() == &PreparedStatements::Full - || self.pub_sub_enabled() || self.regex_parser.use_parser(request) } } diff --git a/pgdog/src/frontend/regex_parser.rs b/pgdog/src/frontend/regex_parser.rs index 75b4e3791..2cbceb621 100644 --- a/pgdog/src/frontend/regex_parser.rs +++ b/pgdog/src/frontend/regex_parser.rs @@ -8,7 +8,9 @@ use crate::frontend::ClientRequest; /// allowed before a statement keyword. static COMMENT_PREFIX: &str = r"(?i)^\s*(?:(?:--[^\n]*\n|/\*[\s\S]*?\*/)\s*)*"; -static CMD_BASE: &[&str] = &["(RE)?SET", "BEGIN", "COMMIT", "ROLLBACK"]; +static CMD_BASE: &[&str] = &[ + "(RE)?SET", "BEGIN", "COMMIT", "ROLLBACK", "LISTEN", "UNLISTEN", "NOTIFY", +]; static CMD_ADVISORY: &[&str] = &[ r"(?i)\bpg_advisory_lock\b", @@ -151,6 +153,36 @@ mod test { assert!(matches(" ROLLBACK")); } + #[test] + fn test_listen() { + assert!(matches("LISTEN test_channel")); + assert!(matches("listen test_channel")); + assert!(matches(" LISTEN test_channel")); + assert!(matches("LISTEN \"test-channel\"")); + assert!(matches("/* comment */ LISTEN test_channel")); + assert!(matches("-- comment\nLISTEN test_channel")); + } + + #[test] + fn test_unlisten() { + assert!(matches("UNLISTEN test_channel")); + assert!(matches("unlisten test_channel")); + assert!(matches(" UNLISTEN test_channel")); + assert!(matches("UNLISTEN *")); + assert!(matches("/* comment */ UNLISTEN test_channel")); + assert!(matches("-- comment\nUNLISTEN *")); + } + + #[test] + fn test_notify() { + assert!(matches("NOTIFY test_channel")); + assert!(matches("notify test_channel")); + assert!(matches(" NOTIFY test_channel")); + assert!(matches("NOTIFY test_channel, 'payload'")); + assert!(matches("/* comment */ NOTIFY test_channel")); + assert!(matches("-- comment\nNOTIFY test_channel, 'payload'")); + } + #[test] fn test_advisory_lock() { let l = QueryParserLevel::SessionControlAndLocks;