Skip to content

Commit 83c5d81

Browse files
Nikita-stralamb
andauthored
solve stack overflow on RecursionLimitExceeded during debug building (apache#1171)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent 05af4e0 commit 83c5d81

1 file changed

Lines changed: 64 additions & 33 deletions

File tree

src/parser/mod.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ impl<'a> Parser<'a> {
470470
Keyword::ANALYZE => Ok(self.parse_analyze()?),
471471
Keyword::SELECT | Keyword::WITH | Keyword::VALUES => {
472472
self.prev_token();
473-
Ok(Statement::Query(Box::new(self.parse_query()?)))
473+
Ok(Statement::Query(self.parse_boxed_query()?))
474474
}
475475
Keyword::TRUNCATE => Ok(self.parse_truncate()?),
476476
Keyword::ATTACH => Ok(self.parse_attach_database()?),
@@ -530,7 +530,7 @@ impl<'a> Parser<'a> {
530530
},
531531
Token::LParen => {
532532
self.prev_token();
533-
Ok(Statement::Query(Box::new(self.parse_query()?)))
533+
Ok(Statement::Query(self.parse_boxed_query()?))
534534
}
535535
_ => self.expected("an SQL statement", next_token),
536536
}
@@ -1084,7 +1084,7 @@ impl<'a> Parser<'a> {
10841084
let expr =
10851085
if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
10861086
self.prev_token();
1087-
Expr::Subquery(Box::new(self.parse_query()?))
1087+
Expr::Subquery(self.parse_boxed_query()?)
10881088
} else {
10891089
let exprs = self.parse_comma_separated(Parser::parse_expr)?;
10901090
match exprs.len() {
@@ -1465,7 +1465,7 @@ impl<'a> Parser<'a> {
14651465
self.expect_token(&Token::LParen)?;
14661466
let exists_node = Expr::Exists {
14671467
negated,
1468-
subquery: Box::new(self.parse_query()?),
1468+
subquery: self.parse_boxed_query()?,
14691469
};
14701470
self.expect_token(&Token::RParen)?;
14711471
Ok(exists_node)
@@ -1654,9 +1654,9 @@ impl<'a> Parser<'a> {
16541654

16551655
// Parses an array constructed from a subquery
16561656
pub fn parse_array_subquery(&mut self) -> Result<Expr, ParserError> {
1657-
let query = self.parse_query()?;
1657+
let query = self.parse_boxed_query()?;
16581658
self.expect_token(&Token::RParen)?;
1659-
Ok(Expr::ArraySubquery(Box::new(query)))
1659+
Ok(Expr::ArraySubquery(query))
16601660
}
16611661

16621662
/// Parse a SQL LISTAGG expression, e.g. `LISTAGG(...) WITHIN GROUP (ORDER BY ...)`.
@@ -2554,7 +2554,7 @@ impl<'a> Parser<'a> {
25542554
self.prev_token();
25552555
Expr::InSubquery {
25562556
expr: Box::new(expr),
2557-
subquery: Box::new(self.parse_query()?),
2557+
subquery: self.parse_boxed_query()?,
25582558
negated,
25592559
}
25602560
} else {
@@ -3637,7 +3637,7 @@ impl<'a> Parser<'a> {
36373637
}
36383638

36393639
self.expect_keyword(Keyword::AS)?;
3640-
let query = Box::new(self.parse_query()?);
3640+
let query = self.parse_boxed_query()?;
36413641
// Optional `WITH [ CASCADED | LOCAL ] CHECK OPTION` is widely supported here.
36423642

36433643
let with_no_schema_binding = dialect_of!(self is RedshiftSqlDialect | GenericDialect)
@@ -4032,7 +4032,7 @@ impl<'a> Parser<'a> {
40324032

40334033
self.expect_keyword(Keyword::FOR)?;
40344034

4035-
let query = Some(Box::new(self.parse_query()?));
4035+
let query = Some(self.parse_boxed_query()?);
40364036

40374037
Ok(Statement::Declare {
40384038
stmts: vec![Declare {
@@ -4126,7 +4126,7 @@ impl<'a> Parser<'a> {
41264126
match self.peek_token().token {
41274127
Token::Word(w) if w.keyword == Keyword::SELECT => (
41284128
Some(DeclareType::Cursor),
4129-
Some(Box::new(self.parse_query()?)),
4129+
Some(self.parse_boxed_query()?),
41304130
None,
41314131
None,
41324132
),
@@ -4650,7 +4650,7 @@ impl<'a> Parser<'a> {
46504650

46514651
// Parse optional `AS ( query )`
46524652
let query = if self.parse_keyword(Keyword::AS) {
4653-
Some(Box::new(self.parse_query()?))
4653+
Some(self.parse_boxed_query()?)
46544654
} else {
46554655
None
46564656
};
@@ -5646,7 +5646,7 @@ impl<'a> Parser<'a> {
56465646
let with_options = self.parse_options(Keyword::WITH)?;
56475647

56485648
self.expect_keyword(Keyword::AS)?;
5649-
let query = Box::new(self.parse_query()?);
5649+
let query = self.parse_boxed_query()?;
56505650

56515651
Ok(Statement::AlterView {
56525652
name,
@@ -5686,7 +5686,7 @@ impl<'a> Parser<'a> {
56865686
pub fn parse_copy(&mut self) -> Result<Statement, ParserError> {
56875687
let source;
56885688
if self.consume_token(&Token::LParen) {
5689-
source = CopySource::Query(Box::new(self.parse_query()?));
5689+
source = CopySource::Query(self.parse_boxed_query()?);
56905690
self.expect_token(&Token::RParen)?;
56915691
} else {
56925692
let table_name = self.parse_object_name(false)?;
@@ -6910,6 +6910,15 @@ impl<'a> Parser<'a> {
69106910
}
69116911
}
69126912

6913+
/// Call's [`Self::parse_query`] returning a `Box`'ed result.
6914+
///
6915+
/// This function can be used to reduce the stack size required in debug
6916+
/// builds. Instead of `sizeof(Query)` only a pointer (`Box<Query>`)
6917+
/// is used.
6918+
fn parse_boxed_query(&mut self) -> Result<Box<Query>, ParserError> {
6919+
self.parse_query().map(Box::new)
6920+
}
6921+
69136922
/// Parse a query expression, i.e. a `SELECT` statement optionally
69146923
/// preceded with some `WITH` CTE declarations and optionally followed
69156924
/// by `ORDER BY`. Unlike some other parse_... methods, this one doesn't
@@ -6924,13 +6933,10 @@ impl<'a> Parser<'a> {
69246933
} else {
69256934
None
69266935
};
6927-
69286936
if self.parse_keyword(Keyword::INSERT) {
6929-
let insert = self.parse_insert()?;
6930-
69316937
Ok(Query {
69326938
with,
6933-
body: Box::new(SetExpr::Insert(insert)),
6939+
body: self.parse_insert_setexpr_boxed()?,
69346940
limit: None,
69356941
limit_by: vec![],
69366942
order_by: vec![],
@@ -6940,10 +6946,9 @@ impl<'a> Parser<'a> {
69406946
for_clause: None,
69416947
})
69426948
} else if self.parse_keyword(Keyword::UPDATE) {
6943-
let update = self.parse_update()?;
69446949
Ok(Query {
69456950
with,
6946-
body: Box::new(SetExpr::Update(update)),
6951+
body: self.parse_update_setexpr_boxed()?,
69476952
limit: None,
69486953
limit_by: vec![],
69496954
order_by: vec![],
@@ -6953,7 +6958,7 @@ impl<'a> Parser<'a> {
69536958
for_clause: None,
69546959
})
69556960
} else {
6956-
let body = Box::new(self.parse_query_body(0)?);
6961+
let body = self.parse_boxed_query_body(0)?;
69576962

69586963
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
69596964
self.parse_comma_separated(Parser::parse_order_by_expr)?
@@ -7143,7 +7148,7 @@ impl<'a> Parser<'a> {
71437148
}
71447149
}
71457150
self.expect_token(&Token::LParen)?;
7146-
let query = Box::new(self.parse_query()?);
7151+
let query = self.parse_boxed_query()?;
71477152
self.expect_token(&Token::RParen)?;
71487153
let alias = TableAlias {
71497154
name,
@@ -7167,7 +7172,7 @@ impl<'a> Parser<'a> {
71677172
}
71687173
}
71697174
self.expect_token(&Token::LParen)?;
7170-
let query = Box::new(self.parse_query()?);
7175+
let query = self.parse_boxed_query()?;
71717176
self.expect_token(&Token::RParen)?;
71727177
let alias = TableAlias { name, columns };
71737178
Cte {
@@ -7183,6 +7188,15 @@ impl<'a> Parser<'a> {
71837188
Ok(cte)
71847189
}
71857190

7191+
/// Call's [`Self::parse_query_body`] returning a `Box`'ed result.
7192+
///
7193+
/// This function can be used to reduce the stack size required in debug
7194+
/// builds. Instead of `sizeof(QueryBody)` only a pointer (`Box<QueryBody>`)
7195+
/// is used.
7196+
fn parse_boxed_query_body(&mut self, precedence: u8) -> Result<Box<SetExpr>, ParserError> {
7197+
self.parse_query_body(precedence).map(Box::new)
7198+
}
7199+
71867200
/// Parse a "query body", which is an expression with roughly the
71877201
/// following grammar:
71887202
/// ```sql
@@ -7191,16 +7205,19 @@ impl<'a> Parser<'a> {
71917205
/// subquery ::= query_body [ order_by_limit ]
71927206
/// set_operation ::= query_body { 'UNION' | 'EXCEPT' | 'INTERSECT' } [ 'ALL' ] query_body
71937207
/// ```
7208+
///
7209+
/// If you need `Box<SetExpr>` then maybe there is sense to use `parse_boxed_query_body`
7210+
/// due to prevent stack overflow in debug building(to reserve less memory on stack).
71947211
pub fn parse_query_body(&mut self, precedence: u8) -> Result<SetExpr, ParserError> {
71957212
// We parse the expression using a Pratt parser, as in `parse_expr()`.
71967213
// Start by parsing a restricted SELECT or a `(subquery)`:
71977214
let mut expr = if self.parse_keyword(Keyword::SELECT) {
7198-
SetExpr::Select(Box::new(self.parse_select()?))
7215+
SetExpr::Select(self.parse_select().map(Box::new)?)
71997216
} else if self.consume_token(&Token::LParen) {
72007217
// CTEs are not allowed here, but the parser currently accepts them
7201-
let subquery = self.parse_query()?;
7218+
let subquery = self.parse_boxed_query()?;
72027219
self.expect_token(&Token::RParen)?;
7203-
SetExpr::Query(Box::new(subquery))
7220+
SetExpr::Query(subquery)
72047221
} else if self.parse_keyword(Keyword::VALUES) {
72057222
let is_mysql = dialect_of!(self is MySqlDialect);
72067223
SetExpr::Values(self.parse_values(is_mysql)?)
@@ -7233,7 +7250,7 @@ impl<'a> Parser<'a> {
72337250
left: Box::new(expr),
72347251
op: op.unwrap(),
72357252
set_quantifier,
7236-
right: Box::new(self.parse_query_body(next_precedence)?),
7253+
right: self.parse_boxed_query_body(next_precedence)?,
72377254
};
72387255
}
72397256

@@ -8147,7 +8164,7 @@ impl<'a> Parser<'a> {
81478164
&mut self,
81488165
lateral: IsLateral,
81498166
) -> Result<TableFactor, ParserError> {
8150-
let subquery = Box::new(self.parse_query()?);
8167+
let subquery = self.parse_boxed_query()?;
81518168
self.expect_token(&Token::RParen)?;
81528169
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
81538170
Ok(TableFactor::Derived {
@@ -8395,6 +8412,13 @@ impl<'a> Parser<'a> {
83958412
Ok(insert.clone())
83968413
}
83978414

8415+
/// Parse an INSERT statement, returning a `Box`ed SetExpr
8416+
///
8417+
/// This is used to reduce the size of the stack frames in debug builds
8418+
fn parse_insert_setexpr_boxed(&mut self) -> Result<Box<SetExpr>, ParserError> {
8419+
Ok(Box::new(SetExpr::Insert(self.parse_insert()?)))
8420+
}
8421+
83988422
/// Parse an INSERT statement
83998423
pub fn parse_insert(&mut self) -> Result<Statement, ParserError> {
84008424
let or = if !dialect_of!(self is SQLiteDialect) {
@@ -8445,7 +8469,7 @@ impl<'a> Parser<'a> {
84458469
} else {
84468470
None
84478471
};
8448-
let source = Box::new(self.parse_query()?);
8472+
let source = self.parse_boxed_query()?;
84498473
Ok(Statement::Directory {
84508474
local,
84518475
path,
@@ -8478,7 +8502,7 @@ impl<'a> Parser<'a> {
84788502
// Hive allows you to specify columns after partitions as well if you want.
84798503
let after_columns = self.parse_parenthesized_column_list(Optional, false)?;
84808504

8481-
let source = Some(Box::new(self.parse_query()?));
8505+
let source = Some(self.parse_boxed_query()?);
84828506

84838507
(columns, partitioned, after_columns, source)
84848508
};
@@ -8581,6 +8605,13 @@ impl<'a> Parser<'a> {
85818605
}
85828606
}
85838607

8608+
/// Parse an UPDATE statement, returning a `Box`ed SetExpr
8609+
///
8610+
/// This is used to reduce the size of the stack frames in debug builds
8611+
fn parse_update_setexpr_boxed(&mut self) -> Result<Box<SetExpr>, ParserError> {
8612+
Ok(Box::new(SetExpr::Update(self.parse_update()?)))
8613+
}
8614+
85848615
pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
85858616
let table = self.parse_table_and_joins()?;
85868617
self.expect_keyword(Keyword::SET)?;
@@ -8686,11 +8717,11 @@ impl<'a> Parser<'a> {
86868717
.is_some()
86878718
{
86888719
self.prev_token();
8689-
let subquery = self.parse_query()?;
8720+
let subquery = self.parse_boxed_query()?;
86908721
self.expect_token(&Token::RParen)?;
86918722
return Ok((
86928723
vec![FunctionArg::Unnamed(FunctionArgExpr::from(Expr::Subquery(
8693-
Box::new(subquery),
8724+
subquery,
86948725
)))],
86958726
vec![],
86968727
));
@@ -9204,7 +9235,7 @@ impl<'a> Parser<'a> {
92049235

92059236
pub fn parse_unload(&mut self) -> Result<Statement, ParserError> {
92069237
self.expect_token(&Token::LParen)?;
9207-
let query = self.parse_query()?;
9238+
let query = self.parse_boxed_query()?;
92089239
self.expect_token(&Token::RParen)?;
92099240

92109241
self.expect_keyword(Keyword::TO)?;
@@ -9213,7 +9244,7 @@ impl<'a> Parser<'a> {
92139244
let with_options = self.parse_options(Keyword::WITH)?;
92149245

92159246
Ok(Statement::Unload {
9216-
query: Box::new(query),
9247+
query,
92179248
to,
92189249
with: with_options,
92199250
})

0 commit comments

Comments
 (0)