Skip to content

Commit a06ce1b

Browse files
authored
fix: invalid sequence step (#18800)
* fix: transform_async_function inserting multiple data in one sql causes step to be ignored * fix: Sequence inserting multiple data in one sql causes step to be ignored * fix: codefmt * chore: move step check on `bind_table` * chore: codefmt * chore: fix stmt-error.txt
1 parent 7475471 commit a06ce1b

File tree

9 files changed

+156
-82
lines changed

9 files changed

+156
-82
lines changed

src/meta/api/src/sequence_nextval_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ where KV: kvapi::KVApi<Error = MetaError> + ?Sized
7373
}
7474

7575
// update meta
76-
self.sequence_meta.current += count;
76+
self.sequence_meta.current += count * self.sequence_meta.step as u64;
7777

7878
let condition = vec![txn_cond_eq_seq(&self.ident, self.sequence_meta.seq)];
7979
let if_then = vec![

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3432,12 +3432,6 @@ pub fn column_def(i: Input) -> IResult<ColumnDefinition> {
34323432
ErrorKind::Other("DEFAULT and AUTOINCREMENT cannot exist at the same time"),
34333433
)));
34343434
}
3435-
if !is_ordered {
3436-
return Err(nom::Err::Error(Error::from_error_kind(
3437-
i,
3438-
ErrorKind::Other("AUTOINCREMENT only support ORDER now"),
3439-
)));
3440-
}
34413435
def.expr = Some(ColumnExpr::AutoIncrement {
34423436
start,
34433437
step,

src/query/ast/tests/it/parser.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ fn test_statement_error() {
10181018
r#"CREATE TABLE t(c1 NULLABLE(int) NOT NULL);"#,
10191019
r#"create table a (c1 decimal(38), c2 int) partition by ();"#,
10201020
r#"CREATE TABLE t(c1 int, c2 int) partition by (c1, c2) PROPERTIES ("read.split.target-size"='134217728', "read.split.metadata-target-size"=33554432);"#,
1021-
r#"create table a.b (c integer autoincrement (10, 20) NOORDER)"#,
10221021
r#"drop table if a.b"#,
10231022
r#"show table"#,
10241023
r#"show column"#,

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,6 @@ error:
111111
| while parsing `CREATE [OR REPLACE] TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`
112112

113113

114-
---------- Input ----------
115-
create table a.b (c integer autoincrement (10, 20) NOORDER)
116-
---------- Output ---------
117-
error:
118-
--> SQL:1:59
119-
|
120-
1 | create table a.b (c integer autoincrement (10, 20) NOORDER)
121-
| ------ ^ AUTOINCREMENT only support ORDER now
122-
| |
123-
| while parsing `CREATE [OR REPLACE] TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`
124-
125-
126114
---------- Input ----------
127115
drop table if a.b
128116
---------- Output ---------

src/query/service/src/pipelines/processors/transforms/transform_async_function.rs

Lines changed: 84 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ use databend_common_expression::FromData;
2727
use databend_common_meta_app::principal::AutoIncrementKey;
2828
use databend_common_meta_app::schema::GetAutoIncrementNextValueReq;
2929
use databend_common_meta_app::schema::GetSequenceNextValueReq;
30+
use databend_common_meta_app::schema::GetSequenceReply;
3031
use databend_common_meta_app::schema::GetSequenceReq;
3132
use databend_common_meta_app::schema::SequenceIdent;
3233
use databend_common_pipeline_transforms::processors::AsyncTransform;
3334
use databend_common_sql::binder::AsyncFunctionDesc;
3435
use databend_common_storages_fuse::TableContext;
36+
use databend_common_users::GrantObjectVisibilityChecker;
3537
use databend_common_users::Object;
3638

3739
use crate::pipelines::processors::transforms::transform_dictionary::DictionaryOperator;
@@ -135,26 +137,30 @@ impl TransformAsyncFunction {
135137
} else {
136138
// Get or create the sequence counter
137139
let counter = counter_lock.read().await;
140+
let fn_range_collect = |start: u64, end: u64, step: i64| {
141+
(0..end - start)
142+
.map(|num| start + num * step as u64)
143+
.collect::<Vec<_>>()
144+
};
145+
// We need to fetch more sequence numbers
146+
let catalog = ctx.get_default_catalog()?;
138147

139148
// Try to reserve sequence numbers from the counter
140149
if let Some((start, _end)) = counter.try_reserve(count) {
150+
let step = fetcher.step(&ctx, &catalog).await?;
141151
// We have enough sequence numbers in the current batch
142-
let range = start..start + count;
143-
UInt64Type::from_data(range.collect::<Vec<u64>>())
152+
UInt64Type::from_data(fn_range_collect(start, start + count, step))
144153
} else {
145154
// drop the read lock and get the write lock
146155
drop(counter);
147156
let counter = counter_lock.write().await;
148157
{
149158
// try reserve again
150159
if let Some((start, _end)) = counter.try_reserve(count) {
160+
let step = fetcher.step(&ctx, &catalog).await?;
151161
// We have enough sequence numbers in the current batch
152-
let range = start..start + count;
153-
UInt64Type::from_data(range.collect::<Vec<u64>>())
162+
UInt64Type::from_data(fn_range_collect(start, count, step))
154163
} else {
155-
// We need to fetch more sequence numbers
156-
let catalog = ctx.get_default_catalog()?;
157-
158164
// Get current state of the counter
159165
let current = counter.current.load(Ordering::Relaxed);
160166
let max = counter.max.load(Ordering::Relaxed);
@@ -163,7 +169,11 @@ impl TransformAsyncFunction {
163169
let remaining = max.saturating_sub(current);
164170
let to_fetch = count.saturating_sub(remaining);
165171

166-
let (start, batch_size) = fetcher.fetch(&ctx, &catalog, to_fetch).await?;
172+
let NextValFetchResult {
173+
start,
174+
batch_size,
175+
step,
176+
} = fetcher.fetch(&ctx, &catalog, to_fetch).await?;
167177

168178
// If we have remaining numbers, use them first
169179
if remaining > 0 {
@@ -175,14 +185,16 @@ impl TransformAsyncFunction {
175185

176186
// Add the remaining numbers
177187
let remaining_to_use = remaining.min(count);
178-
numbers.extend(
179-
(current..current + remaining_to_use).collect::<Vec<u64>>(),
180-
);
188+
numbers.extend(fn_range_collect(
189+
current,
190+
current + remaining_to_use,
191+
step,
192+
));
181193

182194
// Add numbers from the new batch if needed
183195
if remaining_to_use < count {
184196
let new_needed = count - remaining_to_use;
185-
numbers.extend((start..start + new_needed).collect::<Vec<u64>>());
197+
numbers.extend(fn_range_collect(start, start + new_needed, step));
186198
// Update the counter to reflect that we've used some of the new batch
187199
counter.current.store(start + new_needed, Ordering::SeqCst);
188200
}
@@ -192,8 +204,7 @@ impl TransformAsyncFunction {
192204
// No remaining numbers, just use the new batch
193205
counter.update_batch(start + count, batch_size - count);
194206
// Return the sequence numbers needed for this request
195-
let range = start..start + count;
196-
UInt64Type::from_data(range.collect::<Vec<u64>>())
207+
UInt64Type::from_data(fn_range_collect(start, start + count, step))
197208
}
198209
}
199210
}
@@ -211,7 +222,15 @@ pub trait NextValFetcher {
211222
ctx: &QueryContext,
212223
catalog: &Arc<dyn Catalog>,
213224
to_fetch: u64,
214-
) -> Result<(u64 /* start */, u64 /* batch */)>;
225+
) -> Result<NextValFetchResult>;
226+
227+
async fn step(&self, ctx: &QueryContext, catalog: &Arc<dyn Catalog>) -> Result<i64>;
228+
}
229+
230+
pub struct NextValFetchResult {
231+
start: u64,
232+
batch_size: u64,
233+
step: i64,
215234
}
216235

217236
pub struct SequenceNextValFetcher {
@@ -224,20 +243,8 @@ impl NextValFetcher for SequenceNextValFetcher {
224243
ctx: &QueryContext,
225244
catalog: &Arc<dyn Catalog>,
226245
to_fetch: u64,
227-
) -> Result<(u64, u64)> {
228-
let visibility_checker = if ctx
229-
.get_settings()
230-
.get_enable_experimental_sequence_privilege_check()?
231-
{
232-
Some(ctx.get_visibility_checker(false, Object::Sequence).await?)
233-
} else {
234-
None
235-
};
236-
237-
let req = GetSequenceReq {
238-
ident: self.sequence_ident.clone(),
239-
};
240-
let resp = catalog.get_sequence(req, &visibility_checker).await?;
246+
) -> Result<NextValFetchResult> {
247+
let (resp, visibility_checker) = self.get_sequence(ctx, catalog).await?;
241248
let step_size = resp.meta.step as u64;
242249

243250
// Calculate batch size - take the larger of count or step_size
@@ -252,7 +259,42 @@ impl NextValFetcher for SequenceNextValFetcher {
252259
let resp = catalog
253260
.get_sequence_next_value(req, &visibility_checker)
254261
.await?;
255-
Ok((resp.start, batch_size))
262+
Ok(NextValFetchResult {
263+
start: resp.start,
264+
batch_size,
265+
step: resp.step,
266+
})
267+
}
268+
269+
async fn step(&self, ctx: &QueryContext, catalog: &Arc<dyn Catalog>) -> Result<i64> {
270+
self.get_sequence(ctx, catalog)
271+
.await
272+
.map(|(resp, _)| resp.meta.step)
273+
}
274+
}
275+
276+
impl SequenceNextValFetcher {
277+
async fn get_sequence(
278+
&self,
279+
ctx: &QueryContext,
280+
catalog: &Arc<dyn Catalog>,
281+
) -> Result<(GetSequenceReply, Option<GrantObjectVisibilityChecker>)> {
282+
let visibility_checker = if ctx
283+
.get_settings()
284+
.get_enable_experimental_sequence_privilege_check()?
285+
{
286+
Some(ctx.get_visibility_checker(false, Object::Sequence).await?)
287+
} else {
288+
None
289+
};
290+
291+
let req = GetSequenceReq {
292+
ident: self.sequence_ident.clone(),
293+
};
294+
catalog
295+
.get_sequence(req, &visibility_checker)
296+
.await
297+
.map(|reply| (reply, visibility_checker))
256298
}
257299
}
258300

@@ -267,24 +309,31 @@ impl NextValFetcher for AutoIncrementNextValFetcher {
267309
ctx: &QueryContext,
268310
catalog: &Arc<dyn Catalog>,
269311
to_fetch: u64,
270-
) -> Result<(u64, u64)> {
312+
) -> Result<NextValFetchResult> {
271313
let step_size = self.expr.step as u64;
272314

273315
// Calculate batch size - take the larger of count or step_size
274316
let batch_size = to_fetch.max(step_size);
317+
let step = self.expr.step;
275318

276319
// Calculate batch size - take the larger of count or step_size
277320
let req = GetAutoIncrementNextValueReq {
278321
tenant: ctx.get_tenant(),
279322
key: self.key,
280323
expr: self.expr,
281-
// FIXME: count * step
282-
// count: batch_size,
283-
count: 1,
324+
count: batch_size,
284325
};
285326

286327
let resp = catalog.get_autoincrement_next_value(req).await?;
287-
Ok((resp.start, batch_size))
328+
Ok(NextValFetchResult {
329+
start: resp.start,
330+
batch_size,
331+
step,
332+
})
333+
}
334+
335+
async fn step(&self, _ctx: &QueryContext, _catalog: &Arc<dyn Catalog>) -> Result<i64> {
336+
Ok(self.expr.step)
288337
}
289338
}
290339

src/query/sql/src/planner/binder/ddl/table.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,14 +1714,7 @@ impl Binder {
17141714
step,
17151715
is_ordered,
17161716
} => {
1717-
if !matches!(
1718-
field.data_type().remove_nullable(),
1719-
TableDataType::Number(_) | TableDataType::Decimal(_)
1720-
) {
1721-
return Err(ErrorCode::SemanticError(
1722-
"AUTO INCREMENT only supports Decimal or Numeric (e.g. INT32) types",
1723-
));
1724-
}
1717+
Self::check_autoincrement_expr(&field, step, is_ordered)?;
17251718
field.auto_increment_expr = Some(AutoIncrementExpr {
17261719
column_id: table_schema.next_column_id(),
17271720
start: *start,
@@ -1742,6 +1735,31 @@ impl Binder {
17421735
))
17431736
}
17441737

1738+
fn check_autoincrement_expr(field: &TableField, step: &i64, is_ordered: &bool) -> Result<()> {
1739+
if !matches!(
1740+
field.data_type().remove_nullable(),
1741+
TableDataType::Number(_) | TableDataType::Decimal(_)
1742+
) {
1743+
return Err(ErrorCode::SemanticError(
1744+
"AUTOINCREMENT only supports Decimal or Numeric (e.g. INT32) types",
1745+
));
1746+
}
1747+
if !is_ordered {
1748+
return Err(ErrorCode::SemanticError(
1749+
"AUTOINCREMENT only support ORDER now",
1750+
));
1751+
}
1752+
if step == &0 {
1753+
return Err(ErrorCode::SemanticError("INCREMENT cannot be 0"));
1754+
}
1755+
if step < &0 {
1756+
return Err(ErrorCode::SemanticError(
1757+
"INCREMENT does not currently support negative numbers",
1758+
));
1759+
}
1760+
Ok(())
1761+
}
1762+
17451763
#[async_backtrace::framed]
17461764
pub async fn analyze_create_table_schema_by_columns(
17471765
&self,
@@ -1770,14 +1788,7 @@ impl Binder {
17701788
step,
17711789
is_ordered,
17721790
} => {
1773-
if !matches!(
1774-
field.data_type().remove_nullable(),
1775-
TableDataType::Number(_) | TableDataType::Decimal(_)
1776-
) {
1777-
return Err(ErrorCode::SemanticError(
1778-
"AUTO INCREMENT only supports Decimal or Numeric (e.g. INT32) types",
1779-
));
1780-
}
1791+
Self::check_autoincrement_expr(&field, step, is_ordered)?;
17811792
has_autoincrement = true;
17821793
field.auto_increment_expr = Some(AutoIncrementExpr {
17831794
column_id: 0,

tests/sqllogictests/suites/base/05_ddl/05_0036_sequence.test

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,31 @@ select * from t order by id;
222222
statement ok
223223
drop table t;
224224

225+
statement ok
226+
CREATE OR REPLACE SEQUENCE seq start = 1 increment = 2;
227+
228+
statement ok
229+
CREATE OR REPLACE table t2(id int default nextval(seq), name string);
230+
231+
statement ok
232+
INSERT INTO t2(name) values('x'),('x'),('x');
233+
234+
statement ok
235+
INSERT INTO t2(name) values('x'),('x'),('x');
236+
237+
query IT
238+
select * from t2 order by id;
239+
----
240+
1 x
241+
3 x
242+
5 x
243+
7 x
244+
9 x
245+
11 x
246+
247+
statement ok
248+
DROP TABLE t2
249+
225250
statement ok
226251
DROP SEQUENCE seq;
227252

0 commit comments

Comments
 (0)