Skip to content

Commit 7c14309

Browse files
committed
test: add Tpcc
1 parent 9d7e0af commit 7c14309

File tree

20 files changed

+1833
-22
lines changed

20 files changed

+1833
-22
lines changed

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] }
8282
[workspace]
8383
members = [
8484
"tests/sqllogictest",
85-
"tests/macros-test"
86-
, "fnck_sql_serde_macros"]
85+
"tests/macros-test",
86+
"fnck_sql_serde_macros",
87+
"tpcc"]
8788

8889
[profile.release]
8990
lto = true

src/binder/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ impl<'a, T: Transaction> Binder<'a, '_, T> {
586586
if !args.is_empty() {
587587
ty = args[0].return_type();
588588

589-
for arg in args.iter() {
589+
for arg in args.iter_mut() {
590590
let temp_ty = arg.return_type();
591591

592592
if temp_ty == LogicalType::SqlNull {
@@ -595,7 +595,7 @@ impl<'a, T: Transaction> Binder<'a, '_, T> {
595595
if ty == LogicalType::SqlNull && temp_ty != LogicalType::SqlNull {
596596
ty = temp_ty;
597597
} else if ty != temp_ty {
598-
return Err(DatabaseError::Incomparable(ty, temp_ty));
598+
ty = LogicalType::max_logical_type(&ty, &temp_ty)?;
599599
}
600600
}
601601
}

src/execution/dql/aggregate/avg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Accumulator for AvgAccumulator {
4545
let quantity_ty = quantity.logical_type();
4646

4747
if value_ty != quantity_ty {
48-
value = DataValue::clone(&value).cast(&quantity_ty)?
48+
value = value.cast(&quantity_ty)?
4949
}
5050
let evaluator = EvaluatorFactory::binary_create(quantity_ty, BinaryOperator::Divide)?;
5151
Ok(evaluator.0.binary_eval(&value, &quantity))

src/expression/evaluator.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl ScalarExpression {
3737
pub fn eval(&self, tuple: &Tuple, schema: &[ColumnRef]) -> Result<DataValue, DatabaseError> {
3838
let check_cast = |value: DataValue, return_type: &LogicalType| {
3939
if value.logical_type() != *return_type {
40-
return DataValue::clone(&value).cast(return_type);
40+
return value.cast(return_type);
4141
}
4242
Ok(value)
4343
};
@@ -73,9 +73,7 @@ impl ScalarExpression {
7373
expr.eval(tuple, schema)
7474
}
7575
ScalarExpression::TypeCast { expr, ty, .. } => {
76-
let value = expr.eval(tuple, schema)?;
77-
78-
Ok(DataValue::clone(&value).cast(ty)?)
76+
Ok(expr.eval(tuple, schema)?.cast(ty)?)
7977
}
8078
ScalarExpression::Binary {
8179
left_expr,

src/function/char_length.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ impl ScalarFunctionImpl for CharLength {
4141
let value = exprs[0].eval(tuples, columns)?;
4242
let mut value = DataValue::clone(&value);
4343
if !matches!(value.logical_type(), LogicalType::Varchar(_, _)) {
44-
value = DataValue::clone(&value)
45-
.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
44+
value = value.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
4645
}
4746
let mut length: u64 = 0;
4847
if let DataValue::Utf8 {

src/function/lower.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ impl ScalarFunctionImpl for Lower {
4343
let value = exprs[0].eval(tuples, columns)?;
4444
let mut value = DataValue::clone(&value);
4545
if !matches!(value.logical_type(), LogicalType::Varchar(_, _)) {
46-
value = DataValue::clone(&value)
47-
.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
46+
value = value.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
4847
}
4948
if let DataValue::Utf8 {
5049
value: Some(value),

src/function/upper.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ impl ScalarFunctionImpl for Upper {
4343
let value = exprs[0].eval(tuples, columns)?;
4444
let mut value = DataValue::clone(&value);
4545
if !matches!(value.logical_type(), LogicalType::Varchar(_, _)) {
46-
value = DataValue::clone(&value)
47-
.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
46+
value = value.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
4847
}
4948
if let DataValue::Utf8 {
5049
value: Some(value),

src/macros/mod.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ macro_rules! implement_from_tuple {
3333
.enumerate()
3434
.find(|(_, col)| col.name() == field_name)?;
3535

36-
::fnck_sql::types::value::DataValue::clone(&tuple.values[idx])
37-
.cast(&ty)
38-
.ok()
36+
tuple.values[idx].cast(&ty).ok()
3937
}
4038

4139
let mut struct_instance = $struct_name::default();
@@ -103,7 +101,7 @@ macro_rules! scala_function {
103101
_index += 1;
104102

105103
if value.logical_type() != $arg_ty {
106-
value = ::fnck_sql::types::value::DataValue::clone(&value).cast(&$arg_ty)?;
104+
value = value.cast(&$arg_ty)?;
107105
}
108106
value
109107
}, )*)
@@ -197,7 +195,7 @@ macro_rules! table_function {
197195
_index += 1;
198196

199197
if value.logical_type() != $arg_ty {
200-
value = ::fnck_sql::types::value::DataValue::clone(&value).cast(&$arg_ty)?;
198+
value = value.cast(&$arg_ty)?;
201199
}
202200
value
203201
}, )*)

src/types/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ impl LogicalType {
335335
LogicalType::Float | LogicalType::Double | LogicalType::Decimal(_, _)
336336
),
337337
LogicalType::Float => matches!(to, LogicalType::Double | LogicalType::Decimal(_, _)),
338-
LogicalType::Double => false,
338+
LogicalType::Double => matches!(to, LogicalType::Decimal(_, _)),
339339
LogicalType::Char(..) => false,
340340
LogicalType::Varchar(..) => false,
341341
LogicalType::Date => matches!(

src/types/tuple_builder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ impl TupleIdBuilder {
3434
}
3535

3636
pub fn build(&mut self) -> Option<TupleId> {
37+
if self.tmp_keys.len() != self.primary_indexes.len() {
38+
self.tmp_keys.clear();
39+
return None;
40+
}
3741
(!self.tmp_keys.is_empty()).then(|| {
3842
if self.tmp_keys.len() == 1 {
3943
self.tmp_keys.pop().unwrap().unwrap()

src/types/value.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ impl DataValue {
563563
}
564564
Utf8Type::Fixed(len) => match unit {
565565
CharLengthUnits::Characters => {
566+
debug_assert!((*len as usize) >= v.len());
566567
let chars_len = *len as usize;
567568
let string_bytes =
568569
format!("{:len$}", v, len = chars_len).into_bytes();
@@ -1388,7 +1389,7 @@ impl DataValue {
13881389
LogicalType::Tuple(types) => Ok(if let Some(mut values) = values {
13891390
for (i, value) in values.iter_mut().enumerate() {
13901391
if types[i] != value.logical_type() {
1391-
*value = DataValue::clone(value).cast(&types[i])?;
1392+
*value = mem::replace(value, DataValue::Null).cast(&types[i])?;
13921393
}
13931394
}
13941395
DataValue::Tuple(Some(values))

tpcc/Cargo.toml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "tpcc"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
clap = { version = "4", features = ["derive"] }
8+
chrono = { version = "0.4" }
9+
fnck_sql = { version = "0.0.4", path = "..", package = "fnck_sql" }
10+
indicatif = { version = "0.17" }
11+
ordered-float = { version = "4" }
12+
rand = { version = "0.8" }
13+
rust_decimal = { version = "1" }
14+
tempfile = { version = "3" }
15+
thiserror = { version = "1" }

tpcc/src/delivery.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use crate::load::DIST_PER_WARE;
2+
use crate::{TpccArgs, TpccError, TpccTest, TpccTransaction};
3+
use chrono::Utc;
4+
use fnck_sql::db::DBTransaction;
5+
use fnck_sql::storage::Storage;
6+
use rand::prelude::ThreadRng;
7+
use rand::Rng;
8+
9+
#[derive(Debug)]
10+
pub(crate) struct DeliveryArgs {
11+
w_id: usize,
12+
o_carrier_id: usize,
13+
}
14+
15+
impl DeliveryArgs {
16+
pub(crate) fn new(w_id: usize, o_carrier_id: usize) -> Self {
17+
Self { w_id, o_carrier_id }
18+
}
19+
}
20+
21+
pub(crate) struct Delivery;
22+
pub(crate) struct DeliveryTest;
23+
24+
impl<S: Storage> TpccTransaction<S> for Delivery {
25+
type Args = DeliveryArgs;
26+
27+
fn run(tx: &mut DBTransaction<S>, args: &Self::Args) -> Result<(), TpccError> {
28+
let now = Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();
29+
30+
for d_id in 1..DIST_PER_WARE + 1 {
31+
// "SELECT COALESCE(MIN(no_o_id),0) FROM new_orders WHERE no_d_id = ? AND no_w_id = ?"
32+
let (_, tuple) = tx.run(format!("SELECT COALESCE(MIN(no_o_id),0) FROM new_orders WHERE no_d_id = {} AND no_w_id = {}", d_id, args.w_id))?;
33+
let no_o_id = tuple[0].values[0].i32().unwrap();
34+
35+
if no_o_id == 0 {
36+
continue;
37+
}
38+
// "DELETE FROM new_orders WHERE no_o_id = ? AND no_d_id = ? AND no_w_id = ?"
39+
let _ = tx.run(format!(
40+
"DELETE FROM new_orders WHERE no_o_id = {} AND no_d_id = {} AND no_w_id = {}",
41+
no_o_id, d_id, args.w_id
42+
))?;
43+
// "SELECT o_c_id FROM orders WHERE o_id = ? AND o_d_id = ? AND o_w_id = ?"
44+
let (_, tuple) = tx.run(format!(
45+
"SELECT o_c_id FROM orders WHERE o_id = {} AND o_d_id = {} AND o_w_id = {}",
46+
no_o_id, d_id, args.w_id
47+
))?;
48+
let c_id = tuple[0].values[0].i32().unwrap();
49+
// "UPDATE orders SET o_carrier_id = ? WHERE o_id = ? AND o_d_id = ? AND o_w_id = ?"
50+
let _ = tx.run(format!("UPDATE orders SET o_carrier_id = {} WHERE o_id = {} AND o_d_id = {} AND o_w_id = {}", args.o_carrier_id, no_o_id, d_id, args.w_id))?;
51+
// "UPDATE order_line SET ol_delivery_d = ? WHERE ol_o_id = ? AND ol_d_id = ? AND ol_w_id = ?"
52+
let _ = tx.run(format!("UPDATE order_line SET ol_delivery_d = '{}' WHERE ol_o_id = {} AND ol_d_id = {} AND ol_w_id = {}", now, no_o_id, d_id, args.w_id))?;
53+
// "SELECT SUM(ol_amount) FROM order_line WHERE ol_o_id = ? AND ol_d_id = ? AND ol_w_id = ?"
54+
let (_, tuple) = tx.run(format!("SELECT SUM(ol_amount) FROM order_line WHERE ol_o_id = {} AND ol_d_id = {} AND ol_w_id = {}", no_o_id, d_id, args.w_id))?;
55+
let ol_total = tuple[0].values[0].decimal().unwrap();
56+
// "UPDATE customer SET c_balance = c_balance + ? , c_delivery_cnt = c_delivery_cnt + 1 WHERE c_id = ? AND c_d_id = ? AND c_w_id = ?"
57+
let _ = tx.run(format!("UPDATE customer SET c_balance = c_balance + {} , c_delivery_cnt = c_delivery_cnt + 1 WHERE c_id = {} AND c_d_id = {} AND c_w_id = {}", ol_total, c_id, d_id, args.w_id))?;
58+
}
59+
60+
Ok(())
61+
}
62+
}
63+
64+
impl<S: Storage> TpccTest<S> for DeliveryTest {
65+
fn name(&self) -> &'static str {
66+
"Delivery"
67+
}
68+
69+
fn do_transaction(
70+
&self,
71+
rng: &mut ThreadRng,
72+
tx: &mut DBTransaction<S>,
73+
num_ware: usize,
74+
_: &TpccArgs,
75+
) -> Result<(), TpccError> {
76+
let w_id = rng.gen_range(0..num_ware) + 1;
77+
let o_carrier_id = rng.gen_range(1..10);
78+
79+
let args = DeliveryArgs::new(w_id, o_carrier_id);
80+
Delivery::run(tx, &args)?;
81+
82+
Ok(())
83+
}
84+
}

0 commit comments

Comments
 (0)