Skip to content

Commit 2901bc3

Browse files
authored
fix(query): fix replace into partial parse insert source (#18085)
* fix(query): fix replace into partial parse insert source * fix * add tests * fix tests
1 parent 11e41b2 commit 2901bc3

File tree

7 files changed

+47
-35
lines changed

7 files changed

+47
-35
lines changed

src/query/ast/src/ast/statements/replace.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct ReplaceStmt {
3131
pub catalog: Option<Identifier>,
3232
pub database: Option<Identifier>,
3333
pub table: Identifier,
34+
pub is_conflict: bool,
3435
pub on_conflict_columns: Vec<Identifier>,
3536
pub columns: Vec<Identifier>,
3637
pub source: InsertSource,
@@ -59,7 +60,10 @@ impl Display for ReplaceStmt {
5960
}
6061

6162
// on_conflict_columns must be non-empty
62-
write!(f, " ON CONFLICT")?;
63+
write!(f, " ON")?;
64+
if self.is_conflict {
65+
write!(f, " CONFLICT")?;
66+
}
6367
write!(f, " (")?;
6468
write_comma_separated_list(f, &self.on_conflict_columns)?;
6569
write!(f, ")")?;

src/query/ast/src/parser/statement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2955,7 +2955,7 @@ pub fn replace_stmt(allow_raw: bool) -> impl FnMut(Input) -> IResult<Statement>
29552955
(catalog, database, table),
29562956
opt_columns,
29572957
_,
2958-
_,
2958+
opt_conflict,
29592959
_,
29602960
on_conflict_columns,
29612961
_,
@@ -2967,6 +2967,7 @@ pub fn replace_stmt(allow_raw: bool) -> impl FnMut(Input) -> IResult<Statement>
29672967
catalog,
29682968
database,
29692969
table,
2970+
is_conflict: opt_conflict.is_some(),
29702971
on_conflict_columns,
29712972
columns: opt_columns
29722973
.map(|(_, columns, _)| columns)

src/query/ast/tests/it/testdata/stmt.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ Some(
777777
---------- Input ----------
778778
replace into test on(c) select sum(c) as c from source group by v;
779779
---------- Output ---------
780-
REPLACE INTO test ON CONFLICT (c) SELECT sum(c) AS c FROM source GROUP BY v
780+
REPLACE INTO test ON (c) SELECT sum(c) AS c FROM source GROUP BY v
781781
---------- AST ------------
782782
Replace(
783783
ReplaceStmt {
@@ -792,6 +792,7 @@ Replace(
792792
quote: None,
793793
ident_type: None,
794794
},
795+
is_conflict: false,
795796
on_conflict_columns: [
796797
Identifier {
797798
span: Some(
@@ -1028,7 +1029,7 @@ Explain {
10281029
---------- Input ----------
10291030
explain replace into test on(c) select sum(c) as c from source group by v;
10301031
---------- Output ---------
1031-
EXPLAIN REPLACE INTO test ON CONFLICT (c) SELECT sum(c) AS c FROM source GROUP BY v
1032+
EXPLAIN REPLACE INTO test ON (c) SELECT sum(c) AS c FROM source GROUP BY v
10321033
---------- AST ------------
10331034
Explain {
10341035
kind: Plan,
@@ -1049,6 +1050,7 @@ Explain {
10491050
quote: None,
10501051
ident_type: None,
10511052
},
1053+
is_conflict: false,
10521054
on_conflict_columns: [
10531055
Identifier {
10541056
span: Some(

src/query/sql/src/planner/binder/replace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl Binder {
4040
catalog,
4141
database,
4242
table,
43+
is_conflict: _,
4344
on_conflict_columns,
4445
columns,
4546
source,

src/query/sql/src/planner/planner.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use databend_common_ast::ast::Expr;
1919
use databend_common_ast::ast::InsertSource;
2020
use databend_common_ast::ast::InsertStmt;
2121
use databend_common_ast::ast::Literal;
22+
use databend_common_ast::ast::ReplaceStmt;
2223
use databend_common_ast::ast::Statement;
2324
use databend_common_ast::parser::parse_raw_insert_stmt;
2425
use databend_common_ast::parser::parse_raw_replace_stmt;
@@ -50,7 +51,6 @@ use crate::NameResolutionContext;
5051
use crate::VariableNormalizer;
5152

5253
const PROBE_INSERT_INITIAL_TOKENS: usize = 128;
53-
const PROBE_INSERT_MAX_TOKENS: usize = 128 * 8;
5454

5555
pub struct Planner {
5656
pub(crate) ctx: Arc<dyn TableContext>,
@@ -180,40 +180,39 @@ impl Planner {
180180
let mut maybe_partial_insert = false;
181181

182182
if is_insert_or_replace_stmt && matches!(tokenizer.peek(), Some(Ok(_))) {
183-
if let Ok(PlanExtras {
184-
statement:
185-
Statement::Insert(InsertStmt {
186-
source: InsertSource::Select { .. },
187-
..
188-
}),
189-
..
190-
}) = &res
191-
{
192-
maybe_partial_insert = true;
183+
match res {
184+
Ok(PlanExtras {
185+
statement:
186+
Statement::Insert(InsertStmt {
187+
source: InsertSource::Select { .. },
188+
..
189+
}),
190+
..
191+
})
192+
| Ok(PlanExtras {
193+
statement:
194+
Statement::Replace(ReplaceStmt {
195+
source: InsertSource::Select { .. },
196+
..
197+
}),
198+
..
199+
}) => {
200+
maybe_partial_insert = true;
201+
}
202+
_ => {}
193203
}
194204
}
195205

196206
if (maybe_partial_insert || res.is_err()) && matches!(tokenizer.peek(), Some(Ok(_))) {
197207
// Remove the EOI.
198208
tokens.pop();
199-
// Tokenize more and try again.
200-
if !maybe_partial_insert && tokens.len() < PROBE_INSERT_MAX_TOKENS {
201-
let iter = (&mut tokenizer)
202-
.take(tokens.len() * 2)
203-
.take_while(|token| token.is_ok())
204-
.map(|token| token.unwrap())
205-
// Make sure the tokens stream is always ended with EOI.
206-
.chain(std::iter::once(Token::new_eoi(&final_sql)));
207-
tokens.extend(iter);
208-
} else {
209-
// Take the whole tokenizer
210-
let iter = (&mut tokenizer)
211-
.take_while(|token| token.is_ok())
212-
.map(|token| token.unwrap())
213-
// Make sure the tokens stream is always ended with EOI.
214-
.chain(std::iter::once(Token::new_eoi(&final_sql)));
215-
tokens.extend(iter);
216-
};
209+
// Take the whole tokenizer
210+
let iter = (&mut tokenizer)
211+
.take_while(|token| token.is_ok())
212+
.map(|token| token.unwrap())
213+
// Make sure the tokens stream is always ended with EOI.
214+
.chain(std::iter::once(Token::new_eoi(&final_sql)));
215+
tokens.extend(iter);
217216
} else {
218217
return res;
219218
}

src/tests/sqlsmith/src/sql_gen/dml.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ impl<'a, R: Rng + 'a> SqlGenerator<'a, R> {
195195
catalog: None,
196196
database: table.db_name.clone(),
197197
table: table.name.clone(),
198+
is_conflict: true,
198199
on_conflict_columns,
199200
columns,
200201
source,

tests/sqllogictests/suites/base/09_fuse_engine/09_0023_replace_into.test

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ select * from t order by c;
514514
3
515515

516516
statement ok
517-
create or replace table test (c int);
517+
create or replace table test (c int64);
518518

519519
statement ok
520520
create or replace table source (c int, v string);
@@ -536,5 +536,9 @@ select sum(c) from test;
536536
statement ok
537537
explain replace into test on(c) select sum(c) as c from source group by v;
538538

539+
# partial parse insert source
539540
statement ok
540-
DROP DATABASE db_09_0023
541+
replace into test (c) on conflict (c) select sum(c) as c from source where c >= 0 and c >= 1 and c >= 2 and c >= 3 and c >= 4 and c >= 5 and c >= 6 and c >= 7 and c >= 8 and c >= 9 and c >= 10 and c >= 11 and c >= 12 and c >= 13 and c >= 14 and c >= 15 and c >= 16 and c >= 17 and c >= 18 and c >= 19 and c >= 20 and c >= 21 and c >=22 and c >= 23 and c >= 24 and true and true and now() >= '2025-01-01' and date(now()) < date(add_hours(now(),24));
542+
543+
statement ok
544+
DROP DATABASE db_09_0023

0 commit comments

Comments
 (0)