Skip to content

Commit bfc8770

Browse files
committed
Include UPDATE keyword in statement span
1 parent 308a723 commit bfc8770

File tree

7 files changed

+67
-20
lines changed

7 files changed

+67
-20
lines changed

src/ast/dml.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ use sqlparser_derive::{Visit, VisitMut};
2727
use crate::display_utils::{indented_list, Indent, SpaceOrNewline};
2828

2929
use super::{
30-
display_comma_separated, query::InputFormatClause, Assignment, Expr, FromTable, Ident,
31-
InsertAliases, MysqlInsertPriority, ObjectName, OnInsert, OrderByExpr, Query, SelectItem,
32-
Setting, SqliteOnConflict, TableObject, TableWithJoins, UpdateTableFromKind,
30+
display_comma_separated, helpers::attached_token::AttachedToken, query::InputFormatClause,
31+
Assignment, Expr, FromTable, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnInsert,
32+
OrderByExpr, Query, SelectItem, Setting, SqliteOnConflict, TableObject, TableWithJoins,
33+
UpdateTableFromKind,
3334
};
3435

3536
/// INSERT statement.
@@ -246,6 +247,8 @@ impl Display for Delete {
246247
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
247248
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
248249
pub struct Update {
250+
/// Token for the `UPDATE` keyword
251+
pub update_token: AttachedToken,
249252
/// TABLE
250253
pub table: TableWithJoins,
251254
/// Column assignments

src/ast/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2787,10 +2787,11 @@ impl fmt::Display for Declare {
27872787
}
27882788

27892789
/// Sql options of a `CREATE TABLE` statement.
2790-
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2790+
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
27912791
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27922792
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
27932793
pub enum CreateTableOptions {
2794+
#[default]
27942795
None,
27952796
/// Options specified using the `WITH` keyword.
27962797
/// e.g. `WITH (description = "123")`
@@ -2819,12 +2820,6 @@ pub enum CreateTableOptions {
28192820
TableProperties(Vec<SqlOption>),
28202821
}
28212822

2822-
impl Default for CreateTableOptions {
2823-
fn default() -> Self {
2824-
Self::None
2825-
}
2826-
}
2827-
28282823
impl fmt::Display for CreateTableOptions {
28292824
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28302825
match self {

src/ast/spans.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ impl Spanned for Delete {
867867
impl Spanned for Update {
868868
fn span(&self) -> Span {
869869
let Update {
870+
update_token,
870871
table,
871872
assignments,
872873
from,
@@ -878,6 +879,7 @@ impl Spanned for Update {
878879

879880
union_spans(
880881
core::iter::once(table.span())
882+
.chain(core::iter::once(update_token.0.span))
881883
.chain(assignments.iter().map(|i| i.span()))
882884
.chain(from.iter().map(|i| i.span()))
883885
.chain(selection.iter().map(|i| i.span()))
@@ -2535,4 +2537,22 @@ ALTER TABLE users
25352537
assert_eq!(stmt_span.start, (2, 13).into());
25362538
assert_eq!(stmt_span.end, (4, 11).into());
25372539
}
2540+
2541+
#[test]
2542+
fn test_update_statement_span() {
2543+
let sql = r#"-- foo
2544+
UPDATE foo
2545+
/* bar */
2546+
SET bar = 3
2547+
WHERE quux > 42 ;
2548+
"#;
2549+
2550+
let r = Parser::parse_sql(&crate::dialect::GenericDialect, sql).unwrap();
2551+
assert_eq!(1, r.len());
2552+
2553+
let stmt_span = r[0].span();
2554+
2555+
assert_eq!(stmt_span.start, (2, 7).into());
2556+
assert_eq!(stmt_span.end, (5, 17).into());
2557+
}
25382558
}

src/parser/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ impl<'a> Parser<'a> {
590590
Keyword::INSERT => self.parse_insert(),
591591
Keyword::REPLACE => self.parse_replace(),
592592
Keyword::UNCACHE => self.parse_uncache_table(),
593-
Keyword::UPDATE => self.parse_update(),
593+
Keyword::UPDATE => self.parse_update(next_token),
594594
Keyword::ALTER => self.parse_alter(),
595595
Keyword::CALL => self.parse_call(),
596596
Keyword::COPY => self.parse_copy(),
@@ -12009,7 +12009,7 @@ impl<'a> Parser<'a> {
1200912009
} else if self.parse_keyword(Keyword::UPDATE) {
1201012010
Ok(Query {
1201112011
with,
12012-
body: self.parse_update_setexpr_boxed()?,
12012+
body: self.parse_update_setexpr_boxed(self.get_current_token().clone())?,
1201312013
order_by: None,
1201412014
limit_clause: None,
1201512015
fetch: None,
@@ -15734,11 +15734,14 @@ impl<'a> Parser<'a> {
1573415734
/// Parse an UPDATE statement, returning a `Box`ed SetExpr
1573515735
///
1573615736
/// This is used to reduce the size of the stack frames in debug builds
15737-
fn parse_update_setexpr_boxed(&mut self) -> Result<Box<SetExpr>, ParserError> {
15738-
Ok(Box::new(SetExpr::Update(self.parse_update()?)))
15737+
fn parse_update_setexpr_boxed(
15738+
&mut self,
15739+
update_token: TokenWithSpan,
15740+
) -> Result<Box<SetExpr>, ParserError> {
15741+
Ok(Box::new(SetExpr::Update(self.parse_update(update_token)?)))
1573915742
}
1574015743

15741-
pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
15744+
pub fn parse_update(&mut self, update_token: TokenWithSpan) -> Result<Statement, ParserError> {
1574215745
let or = self.parse_conflict_clause();
1574315746
let table = self.parse_table_and_joins()?;
1574415747
let from_before_set = if self.parse_keyword(Keyword::FROM) {
@@ -15773,6 +15776,7 @@ impl<'a> Parser<'a> {
1577315776
None
1577415777
};
1577515778
Ok(Update {
15779+
update_token: update_token.into(),
1577615780
table,
1577715781
assignments,
1577815782
from,

tests/sqlparser_common.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ use sqlparser::dialect::{
3939
};
4040
use sqlparser::keywords::{Keyword, ALL_KEYWORDS};
4141
use sqlparser::parser::{Parser, ParserError, ParserOptions};
42-
use sqlparser::tokenizer::Tokenizer;
43-
use sqlparser::tokenizer::{Location, Span};
42+
use sqlparser::tokenizer::{Location, Span, TokenWithSpan};
43+
use sqlparser::tokenizer::{Token, Tokenizer};
4444
use test_utils::{
4545
all_dialects, all_dialects_where, all_dialects_with_options, alter_table_op, assert_eq_vec,
4646
call, expr_from_projection, join, number, only, table, table_alias, table_from_name,
@@ -440,6 +440,10 @@ fn parse_update_set_from() {
440440
assert_eq!(
441441
stmt,
442442
Statement::Update(Update {
443+
update_token: AttachedToken(TokenWithSpan {
444+
token: Token::make_keyword("UPDATE"),
445+
span: Span::new((1, 1).into(), (1, 7).into()),
446+
}),
443447
table: TableWithJoins {
444448
relation: table_from_name(ObjectName::from(vec![Ident::new("t1")])),
445449
joins: vec![],
@@ -535,6 +539,7 @@ fn parse_update_with_table_alias() {
535539
returning,
536540
or: None,
537541
limit: None,
542+
update_token,
538543
}) => {
539544
assert_eq!(
540545
TableWithJoins {
@@ -583,6 +588,13 @@ fn parse_update_with_table_alias() {
583588
selection
584589
);
585590
assert_eq!(None, returning);
591+
assert_eq!(
592+
AttachedToken(TokenWithSpan {
593+
token: Token::make_keyword("UPDATE"),
594+
span: Span::new((1, 1).into(), (1, 7).into()),
595+
}),
596+
update_token
597+
);
586598
}
587599
_ => unreachable!(),
588600
}

tests/sqlparser_mysql.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use sqlparser::ast::MysqlInsertPriority::{Delayed, HighPriority, LowPriority};
2626
use sqlparser::ast::*;
2727
use sqlparser::dialect::{GenericDialect, MySqlDialect};
2828
use sqlparser::parser::{ParserError, ParserOptions};
29-
use sqlparser::tokenizer::Span;
3029
use sqlparser::tokenizer::Token;
30+
use sqlparser::tokenizer::{Span, TokenWithSpan};
3131
use test_utils::*;
3232

3333
#[macro_use]
@@ -2623,6 +2623,7 @@ fn parse_update_with_joins() {
26232623
returning,
26242624
or: None,
26252625
limit: None,
2626+
update_token,
26262627
}) => {
26272628
assert_eq!(
26282629
TableWithJoins {
@@ -2697,6 +2698,13 @@ fn parse_update_with_joins() {
26972698
selection
26982699
);
26992700
assert_eq!(None, returning);
2701+
assert_eq!(
2702+
AttachedToken(TokenWithSpan {
2703+
token: Token::make_keyword("UPDATE"),
2704+
span: Span::new((1, 1).into(), (1, 7).into()),
2705+
}),
2706+
update_token
2707+
);
27002708
}
27012709
_ => unreachable!(),
27022710
}

tests/sqlparser_sqlite.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#[macro_use]
2323
mod test_utils;
2424

25+
use sqlparser::ast::helpers::attached_token::AttachedToken;
2526
use sqlparser::keywords::Keyword;
2627
use test_utils::*;
2728

@@ -30,7 +31,7 @@ use sqlparser::ast::Value::Placeholder;
3031
use sqlparser::ast::*;
3132
use sqlparser::dialect::{GenericDialect, SQLiteDialect};
3233
use sqlparser::parser::{ParserError, ParserOptions};
33-
use sqlparser::tokenizer::Token;
34+
use sqlparser::tokenizer::{Span, Token, TokenWithSpan};
3435

3536
#[test]
3637
fn pragma_no_value() {
@@ -494,7 +495,11 @@ fn parse_update_tuple_row_values() {
494495
},
495496
from: None,
496497
returning: None,
497-
limit: None
498+
limit: None,
499+
update_token: AttachedToken(TokenWithSpan {
500+
token: Token::make_keyword("UPDATE"),
501+
span: Span::new((1, 1).into(), (1, 7).into())
502+
})
498503
})
499504
);
500505
}

0 commit comments

Comments
 (0)