Skip to content

Commit 5f498c0

Browse files
authored
Test: add many e2e test (#88)
* test: add many e2e test - insert.slt - join_left_inner.slt - limit.slt - where.slt tips: fix `limit` operator * upgrade rust-toolchain version * fix: `insert.slt` create table use multi types * config: ci e2e test * config: fix ci e2e test
1 parent b6700ac commit 5f498c0

File tree

14 files changed

+327
-41
lines changed

14 files changed

+327
-41
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,25 @@ jobs:
6161
uses: actions-rs/cargo@v1
6262
with:
6363
command: fmt
64-
args: -- --check
64+
args: -- --check
65+
# 3
66+
e2e:
67+
name: Rust e2e sqllogictest
68+
runs-on: ubuntu-latest
69+
steps:
70+
- uses: actions/checkout@v2
71+
- name: Install latest nightly
72+
uses: actions-rs/toolchain@v1
73+
with:
74+
toolchain: nightly
75+
override: true
76+
components: rustfmt, clippy
77+
78+
# `cargo check` command here will use installed `nightly`
79+
# as it is set as an "override" for current directory
80+
81+
- name: Run cargo run sqllogictest-test
82+
uses: actions-rs/cargo@v1
83+
with:
84+
command: run
85+
args: --bin sqllogictest-test --manifest-path ./tests/sqllogictest/Cargo.toml

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ tokio = { version = "1.28.2", features = ["full"] }
2626
serde = { version = "1", features = ["derive", "rc"] }
2727
serde_json = "1"
2828
bincode = "1.3.3"
29-
async-trait = "0.1.68"
3029
integer-encoding = "3.0.4"
3130
strum_macros = "0.24"
3231
ordered-float = "3.0"

rust-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2023-09-29
1+
nightly-2023-10-13

src/binder/select.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::planner::operator::join::JoinCondition;
2626
use crate::planner::operator::sort::{SortField, SortOperator};
2727
use crate::planner::LogicalPlan;
2828
use crate::storage::Transaction;
29+
use crate::types::errors::TypeError;
2930
use crate::types::LogicalType;
3031
use itertools::Itertools;
3132
use sqlparser::ast;
@@ -178,7 +179,6 @@ impl<'a, T: Transaction> Binder<'a, T> {
178179
if tables.len() > 1 {
179180
todo!("Implement virtual tables for multiple table aliases");
180181
}
181-
// FIXME
182182
self.context
183183
.add_table_alias(alias.to_string(), tables.remove(0))?;
184184

@@ -366,19 +366,15 @@ impl<'a, T: Transaction> Binder<'a, T> {
366366
limit_expr: &Option<Expr>,
367367
offset_expr: &Option<Offset>,
368368
) -> Result<LogicalPlan, BindError> {
369-
let mut limit = 0;
370-
let mut offset = 0;
369+
let mut limit = None;
370+
let mut offset = None;
371371
if let Some(expr) = limit_expr {
372372
let expr = self.bind_expr(expr)?;
373373
match expr {
374374
ScalarExpression::Constant(dv) => match dv.as_ref() {
375-
DataValue::Int32(Some(v)) if *v > 0 => limit = *v as usize,
376-
DataValue::Int64(Some(v)) if *v > 0 => limit = *v as usize,
377-
_ => {
378-
return Err(BindError::InvalidColumn(
379-
"invalid limit expression.".to_owned(),
380-
))
381-
}
375+
DataValue::Int32(Some(v)) if *v >= 0 => limit = Some(*v as usize),
376+
DataValue::Int64(Some(v)) if *v >= 0 => limit = Some(*v as usize),
377+
_ => return Err(BindError::from(TypeError::InvalidType)),
382378
},
383379
_ => {
384380
return Err(BindError::InvalidColumn(
@@ -392,13 +388,9 @@ impl<'a, T: Transaction> Binder<'a, T> {
392388
let expr = self.bind_expr(&expr.value)?;
393389
match expr {
394390
ScalarExpression::Constant(dv) => match dv.as_ref() {
395-
DataValue::Int32(Some(v)) if *v > 0 => offset = *v as usize,
396-
DataValue::Int64(Some(v)) if *v > 0 => offset = *v as usize,
397-
_ => {
398-
return Err(BindError::InvalidColumn(
399-
"invalid limit expression.".to_owned(),
400-
))
401-
}
391+
DataValue::Int32(Some(v)) if *v > 0 => offset = Some(*v as usize),
392+
DataValue::Int64(Some(v)) if *v > 0 => offset = Some(*v as usize),
393+
_ => return Err(BindError::from(TypeError::InvalidType)),
402394
},
403395
_ => {
404396
return Err(BindError::InvalidColumn(

src/execution/executor/dql/limit.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub struct Limit {
1616
impl From<(LimitOperator, BoxedExecutor)> for Limit {
1717
fn from((LimitOperator { offset, limit }, input): (LimitOperator, BoxedExecutor)) -> Self {
1818
Limit {
19-
offset: Some(offset),
20-
limit: Some(limit),
19+
offset,
20+
limit,
2121
input,
2222
}
2323
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![feature(iterator_try_collect)]
66
#![feature(slice_pattern)]
77
#![feature(bound_map)]
8+
#![feature(async_fn_in_trait)]
89
extern crate core;
910
pub mod binder;
1011
pub mod catalog;

src/optimizer/rule/pushdown_limit.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ impl Rule for EliminateLimits {
7575
if let Operator::Limit(op) = graph.operator(node_id) {
7676
let child_id = graph.children_at(node_id)[0];
7777
if let Operator::Limit(child_op) = graph.operator(child_id) {
78-
let new_limit_op = LimitOperator {
79-
offset: op.offset + child_op.offset,
80-
limit: cmp::min(op.limit, child_op.limit),
81-
};
78+
let offset = Self::binary_options(op.offset, child_op.offset, |a, b| a + b);
79+
let limit = Self::binary_options(op.limit, child_op.limit, |a, b| cmp::min(a, b));
80+
81+
let new_limit_op = LimitOperator { offset, limit };
8282

8383
graph.remove_node(child_id, false);
8484
graph.replace_node(
@@ -92,6 +92,21 @@ impl Rule for EliminateLimits {
9292
}
9393
}
9494

95+
impl EliminateLimits {
96+
fn binary_options<F: Fn(usize, usize) -> usize>(
97+
a: Option<usize>,
98+
b: Option<usize>,
99+
_fn: F,
100+
) -> Option<usize> {
101+
match (a, b) {
102+
(Some(a), Some(b)) => Some(_fn(a, b)),
103+
(Some(a), None) => Some(a),
104+
(None, Some(b)) => Some(b),
105+
(None, None) => None,
106+
}
107+
}
108+
}
109+
95110
/// Add extra limits below JOIN:
96111
/// 1. For LEFT OUTER and RIGHT OUTER JOIN, we push limits to the left and right sides,
97112
/// respectively.
@@ -147,7 +162,7 @@ impl Rule for PushLimitIntoScan {
147162
if let Operator::Scan(scan_op) = graph.operator(child_index) {
148163
let mut new_scan_op = scan_op.clone();
149164

150-
new_scan_op.limit = (Some(limit_op.offset), Some(limit_op.limit));
165+
new_scan_op.limit = (limit_op.offset, limit_op.limit);
151166

152167
graph.remove_node(node_id, false);
153168
graph.replace_node(
@@ -208,8 +223,8 @@ mod tests {
208223
);
209224

210225
let new_limit_op = LimitOperator {
211-
offset: 2,
212-
limit: 1,
226+
offset: Some(2),
227+
limit: Some(1),
213228
};
214229

215230
optimizer
@@ -219,8 +234,8 @@ mod tests {
219234
let best_plan = optimizer.find_best()?;
220235

221236
if let Operator::Limit(op) = &best_plan.operator {
222-
assert_eq!(op.limit, 1);
223-
assert_eq!(op.offset, 3);
237+
assert_eq!(op.limit, Some(1));
238+
assert_eq!(op.offset, Some(3));
224239
} else {
225240
unreachable!("Should be a project operator")
226241
}
@@ -253,7 +268,7 @@ mod tests {
253268
}
254269

255270
if let Operator::Limit(op) = &best_plan.childrens[0].childrens[0].childrens[0].operator {
256-
assert_eq!(op.limit, 1);
271+
assert_eq!(op.limit, Some(1));
257272
} else {
258273
unreachable!("Should be a limit operator")
259274
}

src/planner/operator/limit.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use super::Operator;
44

55
#[derive(Debug, PartialEq, Clone)]
66
pub struct LimitOperator {
7-
pub offset: usize,
8-
pub limit: usize,
7+
pub offset: Option<usize>,
8+
pub limit: Option<usize>,
99
}
1010

1111
impl LimitOperator {
12-
pub fn new(offset: usize, limit: usize, children: LogicalPlan) -> LogicalPlan {
12+
pub fn new(offset: Option<usize>, limit: Option<usize>, children: LogicalPlan) -> LogicalPlan {
1313
LogicalPlan {
1414
operator: Operator::Limit(LimitOperator { offset, limit }),
1515
childrens: vec![children],

src/storage/kip.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::types::errors::TypeError;
88
use crate::types::index::{Index, IndexMeta, IndexMetaRef};
99
use crate::types::tuple::{Tuple, TupleId};
1010
use crate::types::value::ValueRef;
11-
use async_trait::async_trait;
1211
use kip_db::kernel::lsm::iterator::Iter as KipDBIter;
1312
use kip_db::kernel::lsm::mvcc::TransactionIter;
1413
use kip_db::kernel::lsm::storage::Config;
@@ -37,7 +36,6 @@ impl KipStorage {
3736
}
3837
}
3938

40-
#[async_trait]
4139
impl Storage for KipStorage {
4240
type TransactionType = KipTransaction;
4341

@@ -56,7 +54,6 @@ pub struct KipTransaction {
5654
cache: ShardingLruCache<String, TableCatalog>,
5755
}
5856

59-
#[async_trait]
6057
impl Transaction for KipTransaction {
6158
type IterType<'a> = KipIter<'a>;
6259

src/storage/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,23 @@ use crate::storage::table_codec::TableCodec;
88
use crate::types::errors::TypeError;
99
use crate::types::index::{Index, IndexMetaRef};
1010
use crate::types::tuple::{Tuple, TupleId};
11-
use async_trait::async_trait;
1211
use kip_db::error::CacheError;
1312
use kip_db::kernel::lsm::mvcc;
1413
use kip_db::KernelError;
1514
use std::collections::VecDeque;
1615
use std::ops::SubAssign;
1716

18-
#[async_trait]
1917
pub trait Storage: Sync + Send + Clone + 'static {
2018
type TransactionType: Transaction;
2119

20+
#[allow(async_fn_in_trait)]
2221
async fn transaction(&self) -> Result<Self::TransactionType, StorageError>;
2322
}
2423

2524
/// Optional bounds of the reader, of the form (offset, limit).
2625
pub(crate) type Bounds = (Option<usize>, Option<usize>);
2726
type Projections = Vec<ScalarExpression>;
2827

29-
#[async_trait]
3028
pub trait Transaction: Sync + Send + 'static {
3129
type IterType<'a>: Iter;
3230

@@ -80,6 +78,7 @@ pub trait Transaction: Sync + Send + 'static {
8078

8179
fn show_tables(&self) -> Result<Vec<String>, StorageError>;
8280

81+
#[allow(async_fn_in_trait)]
8382
async fn commit(self) -> Result<(), StorageError>;
8483
}
8584

0 commit comments

Comments
 (0)