diff --git a/pgdog/src/frontend/router/parser/context.rs b/pgdog/src/frontend/router/parser/context.rs index 85614fba3..8b6c5d09b 100644 --- a/pgdog/src/frontend/router/parser/context.rs +++ b/pgdog/src/frontend/router/parser/context.rs @@ -149,4 +149,14 @@ impl<'a> QueryParserContext<'a> { pub(super) fn expanded_explain(&self) -> bool { self.expanded_explain } + + /// Are we running in session mode? + /// + /// In session mode, queries are forwarded to the server without + /// parsing or validation beyond what's required for routing. + pub(super) fn is_session_mode(&self) -> bool { + self.router_context + .cluster + .pooler_mode() == crate::config::PoolerMode::Session + } } diff --git a/pgdog/src/frontend/router/parser/query/set.rs b/pgdog/src/frontend/router/parser/query/set.rs index d2b4cffca..9a8a8c0e9 100644 --- a/pgdog/src/frontend/router/parser/query/set.rs +++ b/pgdog/src/frontend/router/parser/query/set.rs @@ -60,11 +60,19 @@ impl QueryParser { /// - All SETs → returns `Ok(Some(Command::Set { .. }))` /// - No SETs → returns `Ok(None)`, caller falls through to default parsing /// - Mix of SET + non-SET → returns `Err(MultiStatementMixedSet)` + /// + /// In session mode, the entire check is bypassed (`Ok(None)`) so that + /// all multi-statement queries are forwarded to the server verbatim. pub(super) fn try_multi_set( &mut self, stmts: &[RawStmt], context: &QueryParserContext, ) -> Result, Error> { + // In session mode, pass through without validation — the server + // owns the session and can handle mixed SET + other statements. + if context.is_session_mode() { + return Ok(None); + } let mut params = Vec::with_capacity(stmts.len()); let mut has_set = false; let mut has_other = false;