From 5cc6f18abeee603ce07b04af1da24635d22f2b06 Mon Sep 17 00:00:00 2001 From: psteinroe Date: Tue, 12 Aug 2025 23:30:01 +0200 Subject: [PATCH 1/2] fix: add support for named param ala $name --- crates/pgt_tokenizer/src/lib.rs | 47 ++++++++++++------- ...enizer__tests__named_param_dollar_raw.snap | 23 +++++++++ crates/pgt_tokenizer/src/token.rs | 3 ++ 3 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 crates/pgt_tokenizer/src/snapshots/pgt_tokenizer__tests__named_param_dollar_raw.snap diff --git a/crates/pgt_tokenizer/src/lib.rs b/crates/pgt_tokenizer/src/lib.rs index 80b66363..83b9ba44 100644 --- a/crates/pgt_tokenizer/src/lib.rs +++ b/crates/pgt_tokenizer/src/lib.rs @@ -186,9 +186,29 @@ impl Cursor<'_> { '$' => { // Dollar quoted strings if is_ident_start(self.first()) || self.first() == '$' { - self.dollar_quoted_string() + // Get the start sequence of the dollar quote, i.e., 'foo' in $foo$hello$foo$ + // if ident does not continue and there is no terminating dollar + // sign, we have a positional param `$name` + let mut start = vec![]; + loop { + match self.first() { + '$' => { + self.bump(); + break self.dollar_quoted_string(start); + } + c if is_ident_cont(c) => { + self.bump(); + start.push(c); + } + _ => { + break TokenKind::NamedParam { + kind: NamedParamKind::DollarRaw, + }; + } + } + } } else { - // Parameters + // positional parameter, e.g. `$1` while self.first().is_ascii_digit() { self.bump(); } @@ -490,22 +510,7 @@ impl Cursor<'_> { } // https://www.postgresql.org/docs/16/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING - fn dollar_quoted_string(&mut self) -> TokenKind { - // Get the start sequence of the dollar quote, i.e., 'foo' in - // $foo$hello$foo$ - let mut start = vec![]; - while let Some(c) = self.bump() { - match c { - '$' => { - self.bump(); - break; - } - _ => { - start.push(c); - } - } - } - + fn dollar_quoted_string(&mut self, start: Vec) -> TokenKind { // we have a dollar quoted string deliminated with `$$` if start.is_empty() { loop { @@ -658,6 +663,12 @@ mod tests { assert_debug_snapshot!(result); } + #[test] + fn named_param_dollar_raw() { + let result = lex("select 1 from c where id = $id;"); + assert_debug_snapshot!(result); + } + #[test] fn named_param_colon_raw() { let result = lex("select 1 from c where id = :id;"); diff --git a/crates/pgt_tokenizer/src/snapshots/pgt_tokenizer__tests__named_param_dollar_raw.snap b/crates/pgt_tokenizer/src/snapshots/pgt_tokenizer__tests__named_param_dollar_raw.snap new file mode 100644 index 00000000..db0f9412 --- /dev/null +++ b/crates/pgt_tokenizer/src/snapshots/pgt_tokenizer__tests__named_param_dollar_raw.snap @@ -0,0 +1,23 @@ +--- +source: crates/pgt_tokenizer/src/lib.rs +expression: result +snapshot_kind: text +--- +[ + "select" @ Ident, + " " @ Space, + "1" @ Literal { kind: Int { base: Decimal, empty_int: false } }, + " " @ Space, + "from" @ Ident, + " " @ Space, + "c" @ Ident, + " " @ Space, + "where" @ Ident, + " " @ Space, + "id" @ Ident, + " " @ Space, + "=" @ Eq, + " " @ Space, + "$id" @ NamedParam { kind: DollarRaw }, + ";" @ Semi, +] diff --git a/crates/pgt_tokenizer/src/token.rs b/crates/pgt_tokenizer/src/token.rs index e3dbaee2..da98a229 100644 --- a/crates/pgt_tokenizer/src/token.rs +++ b/crates/pgt_tokenizer/src/token.rs @@ -132,6 +132,9 @@ pub enum NamedParamKind { /// /// Used in: psql ColonIdentifier { terminated: bool }, + + /// e.g. `$name` + DollarRaw, } /// Parsed token. From afcb252dd77a6e4bcb8d7ba381173242eb7143be Mon Sep 17 00:00:00 2001 From: psteinroe Date: Tue, 12 Aug 2025 23:33:20 +0200 Subject: [PATCH 2/2] progress --- crates/pgt_workspace/src/workspace/server.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/pgt_workspace/src/workspace/server.rs b/crates/pgt_workspace/src/workspace/server.rs index f4a9561f..f0a39dbf 100644 --- a/crates/pgt_workspace/src/workspace/server.rs +++ b/crates/pgt_workspace/src/workspace/server.rs @@ -511,8 +511,6 @@ impl Workspace for WorkspaceServer { .await .unwrap_or_else(|_| vec![]); - println!("{:#?}", plpgsql_check_results); - for d in plpgsql_check_results { let r = d.span.map(|span| span + range.start()); diagnostics.push(