|
1 | 1 | use std::collections::HashMap; |
2 | 2 | use std::num::NonZeroUsize; |
3 | | -use std::sync::{Arc, Mutex}; |
| 3 | +use std::sync::{Arc, LazyLock, Mutex}; |
4 | 4 |
|
5 | 5 | use lru::LruCache; |
6 | 6 | use pgt_query_ext::diagnostics::*; |
7 | 7 | use pgt_text_size::TextRange; |
8 | 8 | use pgt_tokenizer::tokenize; |
| 9 | +use regex::Regex; |
9 | 10 |
|
10 | 11 | use super::statement_identifier::StatementId; |
11 | 12 |
|
@@ -82,13 +83,27 @@ impl PgQueryStore { |
82 | 83 | let range = TextRange::new(start.try_into().unwrap(), end.try_into().unwrap()); |
83 | 84 |
|
84 | 85 | let r = pgt_query::parse_plpgsql(statement.content()) |
85 | | - .map_err(|err| SyntaxDiagnostic::new(err.to_string(), Some(range))); |
| 86 | + .or_else(|e| match &e { |
| 87 | + // ignore `is not a known variable` for composite types because libpg_query reports a false positive. |
| 88 | + // https://github.com/pganalyze/libpg_query/issues/159 |
| 89 | + pgt_query::Error::Parse(err) if is_composite_type_error(err) => Ok(()), |
| 90 | + _ => Err(e), |
| 91 | + }) |
| 92 | + .map_err(|e| SyntaxDiagnostic::new(e.to_string(), Some(range))); |
| 93 | + |
86 | 94 | cache.put(statement.clone(), r.clone()); |
87 | 95 |
|
88 | 96 | Some(r) |
89 | 97 | } |
90 | 98 | } |
91 | 99 |
|
| 100 | +static COMPOSITE_TYPE_ERROR_RE: LazyLock<Regex> = |
| 101 | + LazyLock::new(|| Regex::new(r#"\\?"([^"\\]+\.[^"\\]+)\\?" is not a known variable"#).unwrap()); |
| 102 | + |
| 103 | +fn is_composite_type_error(err: &str) -> bool { |
| 104 | + COMPOSITE_TYPE_ERROR_RE.is_match(err) |
| 105 | +} |
| 106 | + |
92 | 107 | /// Converts named parameters in a SQL query string to positional parameters. |
93 | 108 | /// |
94 | 109 | /// This function scans the input SQL string for named parameters (e.g., `@param`, `:param`, `:'param'`) |
|
0 commit comments