Skip to content

Commit f0416d6

Browse files
authored
Merge pull request #20 from donga-gao/main
Issue add sql_segment
2 parents b08b7d5 + a644ee5 commit f0416d6

File tree

13 files changed

+89
-84
lines changed

13 files changed

+89
-84
lines changed

src/alter.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,9 +521,7 @@ fn parse_add_alter_specification<'a>(
521521

522522
if let Some(s) = &if_not_exists_span {
523523
if parser.options.dialect.is_maria() {
524-
parser
525-
.issues
526-
.push(Issue::err("IF NOT EXIST is not supported", s));
524+
parser.add_error("IF NOT EXIST is not supported", s);
527525
}
528526
}
529527

src/create.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,7 @@ fn parse_create_type<'a>(
940940
) -> Result<Statement<'a>, ParseError> {
941941
let type_span = parser.consume_keyword(Keyword::TYPE)?;
942942
if !parser.options.dialect.is_postgresql() {
943-
parser.issues.push(Issue::err(
944-
"CREATE TYPE only supported by postgresql",
945-
&type_span,
946-
));
943+
parser.add_error("CREATE TYPE only supported by postgresql", &type_span);
947944
}
948945
let name = parser.consume_plain_identifier()?;
949946
let as_enum_span = parser.consume_keywords(&[Keyword::AS, Keyword::ENUM])?;
@@ -1052,10 +1049,10 @@ fn parse_create_index<'a>(
10521049
if let Some(where_span) = parser.skip_keyword(Keyword::WHERE) {
10531050
let where_expr = parse_expression(parser, false)?;
10541051
if parser.options.dialect.is_maria() {
1055-
parser.issues.push(Issue::err(
1052+
parser.add_error(
10561053
"Partial indexes not supported",
10571054
&where_span.join_span(&where_expr),
1058-
));
1055+
);
10591056
}
10601057
where_ = Some((where_span, where_expr));
10611058
}

src/delete.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ pub(crate) fn parse_delete<'a>(parser: &mut Parser<'a, '_>) -> Result<Delete<'a>
147147

148148
if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
149149
if !using.is_empty() {
150-
parser.issues.push(Issue::err(
150+
parser.add_error(
151151
"Using not allowed in delete with table names before FROM",
152152
&using_span,
153-
));
153+
);
154154
}
155155
loop {
156156
using.push(parse_table_reference(parser)?);

src/drop.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -454,15 +454,10 @@ pub(crate) fn parse_drop<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a
454454
};
455455

456456
if v.on.is_none() && parser.options.dialect.is_maria() {
457-
parser
458-
.issues
459-
.push(Issue::err("On required for index drops in MariaDb", &v));
457+
parser.add_error("On required for index drops in MariaDb", &v);
460458
}
461459
if v.on.is_some() && parser.options.dialect.is_postgresql() {
462-
parser.issues.push(Issue::err(
463-
"On not supported for index drops in PostgreSQL",
464-
&v,
465-
));
460+
parser.add_error("On not supported for index drops in PostgreSQL", &v);
466461
}
467462
Ok(Statement::DropIndex(v))
468463
}

src/expression.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,7 @@ fn parse_function<'a>(
736736
Token::Ident(_, Keyword::JSON_VALUE) => Function::JsonValue,
737737
Token::Ident(v, k) if !k.reserved() => Function::Other(v),
738738
_ => {
739-
parser
740-
.issues
741-
.push(crate::Issue::err("Unknown function", &span));
739+
parser.add_error("Unknown function", &span);
742740
Function::Unknown
743741
}
744742
};

src/insert_replace.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -291,17 +291,13 @@ pub(crate) fn parse_insert_replace<'a>(
291291
InsertReplaceFlag::LowPriority(_) => {}
292292
InsertReplaceFlag::HighPriority(s) => {
293293
if !insert {
294-
parser
295-
.issues
296-
.push(Issue::err("Not supported for replace", s));
294+
parser.add_error("Not supported for replace", s);
297295
}
298296
}
299297
InsertReplaceFlag::Delayed(_) => {}
300298
InsertReplaceFlag::Ignore(s) => {
301299
if !insert {
302-
parser
303-
.issues
304-
.push(Issue::err("Not supported for replace", s));
300+
parser.add_error("Not supported for replace", s);
305301
}
306302
}
307303
}
@@ -373,8 +369,16 @@ pub(crate) fn parse_insert_replace<'a>(
373369
}
374370
if let Some(cs) = columns.opt_span() {
375371
parser.issues.push(
376-
Issue::err("Columns may not be used here", &cs)
377-
.frag("Together with SET", &set_span),
372+
Issue::err(
373+
"Columns may not be used here",
374+
&cs,
375+
&parser.sql_segment(cs.span()),
376+
)
377+
.frag(
378+
"Together with SET",
379+
&set_span,
380+
&parser.sql_segment(set_span.span()),
381+
),
378382
);
379383
}
380384
set = Some(InsertReplaceSet { set_span, pairs });
@@ -410,10 +414,10 @@ pub(crate) fn parse_insert_replace<'a>(
410414
}
411415
}
412416
if !parser.options.dialect.is_maria() {
413-
parser.issues.push(Issue::err(
417+
parser.add_error(
414418
"Only support by mariadb",
415419
&on_duplicate_key_update_span.join_span(&pairs),
416-
));
420+
);
417421
}
418422
(
419423
Some(InsertReplaceOnDuplicateKeyUpdate {
@@ -490,9 +494,7 @@ pub(crate) fn parse_insert_replace<'a>(
490494
};
491495

492496
if !parser.options.dialect.is_postgresql() {
493-
parser
494-
.issues
495-
.push(Issue::err("Only support by postgesql", &on_conflict));
497+
parser.add_error("Only support by postgesql", &on_conflict);
496498
}
497499

498500
(None, Some(on_conflict))

src/issue.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
use alloc::{string::String, vec::Vec};
1414

15-
use crate::{Span, Spanned};
15+
use crate::{SString, Span, Spanned};
1616

1717
/// Level of an issues
1818
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
@@ -23,41 +23,50 @@ pub enum Level {
2323

2424
/// An issue encountered during parsing, or later stages
2525
#[derive(Clone, PartialEq, Eq, Debug)]
26-
pub struct Issue {
26+
pub struct Issue<'a> {
2727
/// The level of the issue
2828
pub level: Level,
2929
/// The primary message of the issue
3030
pub message: String,
3131
/// The span to attach the primary message to
3232
pub span: Span,
33-
/// List of secondary messages and spans
34-
pub fragments: Vec<(String, Span)>,
33+
/// The sql segment of the issue
34+
pub sql_segment: &'a str,
35+
/// List of secondary messages , spans and sql segments
36+
pub fragments: Vec<(String, Span, &'a str)>,
3537
}
3638

37-
impl Issue {
39+
impl<'a> Issue<'a> {
3840
/// Construct an error with given message and span
39-
pub fn err(message: impl Into<String>, span: &impl Spanned) -> Self {
41+
pub fn err(message: impl Into<String>, span: &impl Spanned, sql_segment: &'a str) -> Self {
4042
Issue {
4143
level: Level::Error,
4244
message: message.into(),
4345
span: span.span(),
46+
sql_segment,
4447
fragments: Vec::new(),
4548
}
4649
}
4750

4851
/// Construct a warning with given message and span
49-
pub fn warn(message: impl Into<String>, span: &impl Spanned) -> Self {
52+
pub fn warn(message: impl Into<String>, span: &impl Spanned, sql_segment: &'a str) -> Self {
5053
Issue {
5154
level: Level::Warning,
5255
message: message.into(),
5356
span: span.span(),
57+
sql_segment,
5458
fragments: Vec::new(),
5559
}
5660
}
5761

5862
/// Add a fragment with the given message and span
59-
pub fn frag(mut self, message: impl Into<String>, span: &impl Spanned) -> Self {
60-
self.fragments.push((message.into(), span.span()));
63+
pub fn frag(
64+
mut self,
65+
message: impl Into<String>,
66+
span: &impl Spanned,
67+
sql_segment: &'a str,
68+
) -> Self {
69+
self.fragments.push((message.into(), span.span(),sql_segment));
6170
self
6271
}
6372
}

src/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<'a> Lexer<'a> {
147147
}
148148
}
149149

150-
fn s(&self, span: Span) -> &'a str {
150+
pub(crate) fn s(&self, span: Span) -> &'a str {
151151
core::str::from_utf8(&self.src.as_bytes()[span]).unwrap()
152152
}
153153

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ macro_rules! issue_todo {
227227
/// added to issues
228228
pub fn parse_statements<'a>(
229229
src: &'a str,
230-
issues: &mut Vec<Issue>,
230+
issues: &mut Vec<Issue<'a>>,
231231
options: &ParseOptions,
232232
) -> Vec<Statement<'a>> {
233233
let mut parser = Parser::new(src, issues, options);
@@ -240,7 +240,7 @@ pub fn parse_statements<'a>(
240240
/// added to issues
241241
pub fn parse_statement<'a>(
242242
src: &'a str,
243-
issues: &mut Vec<Issue>,
243+
issues: &mut Vec<Issue<'a>>,
244244
options: &ParseOptions,
245245
) -> Option<Statement<'a>> {
246246
let mut parser = Parser::new(src, issues, options);

src/parser.rs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub(crate) struct Parser<'a, 'b> {
2828
pub(crate) token: Token<'a>,
2929
pub(crate) span: Span,
3030
pub(crate) lexer: Lexer<'a>,
31-
pub(crate) issues: &'b mut Vec<Issue>,
31+
pub(crate) issues: &'b mut Vec<Issue<'a>>,
3232
pub(crate) arg: usize,
3333
pub(crate) delimiter: Token<'a>,
3434
pub(crate) options: &'b ParseOptions,
@@ -91,7 +91,11 @@ impl<'a> alloc::fmt::Display for SingleQuotedString<'a> {
9191
}
9292

9393
impl<'a, 'b> Parser<'a, 'b> {
94-
pub(crate) fn new(src: &'a str, issues: &'b mut Vec<Issue>, options: &'b ParseOptions) -> Self {
94+
pub(crate) fn new(
95+
src: &'a str,
96+
issues: &'b mut Vec<Issue<'a>>,
97+
options: &'b ParseOptions,
98+
) -> Self {
9599
let mut lexer = Lexer::new(src);
96100
let (token, span) = lexer.next_token();
97101
Self {
@@ -194,8 +198,17 @@ impl<'a, 'b> Parser<'a, 'b> {
194198
}
195199

196200
pub(crate) fn expected_error(&mut self, name: &'static str) {
201+
self.add_error(format!("Expected '{}' here", name), &self.span.span());
202+
}
203+
204+
pub(crate) fn add_error(&mut self, message: impl Into<String>, span: &impl Spanned) {
205+
self.issues
206+
.push(Issue::err(message, span, self.lexer.s(span.span())));
207+
}
208+
209+
pub(crate) fn add_warn(&mut self, message: impl Into<String>, span: &impl Spanned) {
197210
self.issues
198-
.push(Issue::err(format!("Expected '{}' here", name), &self.span));
211+
.push(Issue::warn(message, span, self.sql_segment(span.span())));
199212
}
200213

201214
pub(crate) fn expected_failure<T>(&mut self, name: &'static str) -> Result<T, ParseError> {
@@ -212,17 +225,14 @@ impl<'a, 'b> Parser<'a, 'b> {
212225
Token::Ident(v, kw) => {
213226
let v = *v;
214227
if kw.reserved() {
215-
self.issues.push(Issue::err(
228+
self.add_error(
216229
format!("'{}' is a reserved identifier use `{}`", v, v),
217230
&span,
218-
));
231+
);
219232
} else if kw != &Keyword::QUOTED_IDENTIFIER
220233
&& self.options.warn_unquoted_identifiers
221234
{
222-
self.issues.push(Issue::warn(
223-
format!("identifiers should be quoted as `{}`", v),
224-
&span,
225-
));
235+
self.add_warn(format!("identifiers should be quoted as `{}`", v), &span);
226236
}
227237
Ok(Identifier::new(v, span))
228238
}
@@ -235,23 +245,23 @@ impl<'a, 'b> Parser<'a, 'b> {
235245
Token::Ident(v, kw) => {
236246
let v = *v;
237247
if kw.reserved() {
238-
self.issues.push(Issue::err(
248+
self.add_error(
239249
format!("'{}' is a reserved identifier use `{}`", v, v),
240-
&self.span,
241-
));
250+
&self.span.span(),
251+
);
242252
} else if kw != &Keyword::QUOTED_IDENTIFIER
243253
&& self.options.warn_unquoted_identifiers
244254
{
245-
self.issues.push(Issue::warn(
255+
self.add_warn(
246256
format!("identifiers should be quoted as `{}`", v),
247-
&self.span,
248-
));
257+
&self.span.span(),
258+
);
249259
} else if kw == &Keyword::QUOTED_IDENTIFIER && self.options.dialect.is_postgresql()
250260
{
251-
self.issues.push(Issue::err(
261+
self.add_error(
252262
"quoted identifiers not supported by postgresql",
253-
&self.span,
254-
));
263+
&self.span.span(),
264+
);
255265
}
256266
Ok(Identifier::new(v, self.consume()))
257267
}
@@ -268,14 +278,14 @@ impl<'a, 'b> Parser<'a, 'b> {
268278
if !v.chars().all(|c| c.is_ascii_uppercase())
269279
&& self.options.warn_none_capital_keywords
270280
{
271-
self.issues.push(Issue::warn(
281+
self.add_warn(
272282
format!(
273283
"keyword {} should be in ALL CAPS {}",
274284
v,
275285
v.to_ascii_uppercase()
276286
),
277-
&self.span,
278-
));
287+
&self.span.span(),
288+
);
279289
}
280290
Ok(self.consume())
281291
}
@@ -389,7 +399,7 @@ impl<'a, 'b> Parser<'a, 'b> {
389399
}
390400

391401
pub(crate) fn error<T>(&mut self, message: impl Into<String>) -> Result<T, ParseError> {
392-
self.issues.push(Issue::err(message, &self.span));
402+
self.add_error(message, &self.span.span());
393403
Err(ParseError::Unrecovered)
394404
}
395405

@@ -400,4 +410,7 @@ impl<'a, 'b> Parser<'a, 'b> {
400410
pub(crate) fn todo<T>(&mut self, file: &'static str, line: u32) -> Result<T, ParseError> {
401411
self.error(format!("Not yet implemented at {}:{}", file, line))
402412
}
413+
pub(crate) fn sql_segment(&self, span: Span) -> &'a str {
414+
&self.lexer.s(span)
415+
}
403416
}

src/select.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,10 @@ pub(crate) fn parse_table_reference_inner<'a>(
332332

333333
if !index_hints.is_empty() {
334334
if !parser.options.dialect.is_maria() {
335-
parser.issues.push(Issue::err(
335+
parser.add_error(
336336
"Index hints only supported by MariaDb",
337337
&index_hints.opt_span().unwrap(),
338-
));
338+
);
339339
}
340340
}
341341

@@ -830,9 +830,7 @@ pub(crate) fn parse_select<'a>(parser: &mut Parser<'a, '_>) -> Result<Select<'a>
830830

831831
if let LockStrength::NoKeyUpdate(s) | LockStrength::KeyShare(s) = &strength {
832832
if !parser.options.dialect.is_postgresql() {
833-
parser
834-
.issues
835-
.push(Issue::err("Only support by PostgreSQL", s));
833+
parser.add_error("Only support by PostgreSQL", s);
836834
}
837835
}
838836

0 commit comments

Comments
 (0)