Skip to content
This repository was archived by the owner on Jan 7, 2025. It is now read-only.

Commit 79c4664

Browse files
authored
feat: support more integer types (#57)
* feat: support more int types * test: add int constant predicate test * misc
1 parent d041762 commit 79c4664

File tree

8 files changed

+231
-37
lines changed

8 files changed

+231
-37
lines changed

Diff for: optd-core/src/rel_node.rs

+66-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ pub trait RelNodeTyp:
2727

2828
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2929
pub enum Value {
30-
Int(i64),
30+
UInt8(u8),
31+
UInt16(u16),
32+
UInt32(u32),
33+
UInt64(u64),
34+
Int8(i8),
35+
Int16(i16),
36+
Int32(i32),
37+
Int64(i64),
3138
Float(OrderedFloat<f64>),
3239
String(Arc<str>),
3340
Bool(bool),
@@ -37,7 +44,14 @@ pub enum Value {
3744
impl std::fmt::Display for Value {
3845
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3946
match self {
40-
Self::Int(x) => write!(f, "{x}"),
47+
Self::UInt8(x) => write!(f, "{x}"),
48+
Self::UInt16(x) => write!(f, "{x}"),
49+
Self::UInt32(x) => write!(f, "{x}"),
50+
Self::UInt64(x) => write!(f, "{x}"),
51+
Self::Int8(x) => write!(f, "{x}"),
52+
Self::Int16(x) => write!(f, "{x}"),
53+
Self::Int32(x) => write!(f, "{x}"),
54+
Self::Int64(x) => write!(f, "{x}"),
4155
Self::Float(x) => write!(f, "{x}"),
4256
Self::String(x) => write!(f, "\"{x}\""),
4357
Self::Bool(x) => write!(f, "{x}"),
@@ -47,9 +61,58 @@ impl std::fmt::Display for Value {
4761
}
4862

4963
impl Value {
64+
pub fn as_u8(&self) -> u8 {
65+
match self {
66+
Value::UInt8(i) => *i,
67+
_ => panic!("Value is not an u8"),
68+
}
69+
}
70+
71+
pub fn as_u16(&self) -> u16 {
72+
match self {
73+
Value::UInt16(i) => *i,
74+
_ => panic!("Value is not an u16"),
75+
}
76+
}
77+
78+
pub fn as_u32(&self) -> u32 {
79+
match self {
80+
Value::UInt32(i) => *i,
81+
_ => panic!("Value is not an u32"),
82+
}
83+
}
84+
85+
pub fn as_u64(&self) -> u64 {
86+
match self {
87+
Value::UInt64(i) => *i,
88+
_ => panic!("Value is not an u64"),
89+
}
90+
}
91+
92+
pub fn as_i8(&self) -> i8 {
93+
match self {
94+
Value::Int8(i) => *i,
95+
_ => panic!("Value is not an i8"),
96+
}
97+
}
98+
99+
pub fn as_i16(&self) -> i16 {
100+
match self {
101+
Value::Int16(i) => *i,
102+
_ => panic!("Value is not an i16"),
103+
}
104+
}
105+
106+
pub fn as_i32(&self) -> i32 {
107+
match self {
108+
Value::Int32(i) => *i,
109+
_ => panic!("Value is not an i32"),
110+
}
111+
}
112+
50113
pub fn as_i64(&self) -> i64 {
51114
match self {
52-
Value::Int(i) => *i,
115+
Value::Int64(i) => *i,
53116
_ => panic!("Value is not an i64"),
54117
}
55118
}

Diff for: optd-datafusion-bridge/src/from_optd.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@ fn from_optd_schema(optd_schema: &OptdSchema) -> Schema {
4040
let match_type = |typ: &ConstantType| match typ {
4141
ConstantType::Any => unimplemented!(),
4242
ConstantType::Bool => DataType::Boolean,
43-
ConstantType::Int => DataType::Int64,
43+
ConstantType::UInt8 => DataType::UInt8,
44+
ConstantType::UInt16 => DataType::UInt16,
45+
ConstantType::UInt32 => DataType::UInt32,
46+
ConstantType::UInt64 => DataType::UInt64,
47+
ConstantType::Int8 => DataType::Int8,
48+
ConstantType::Int16 => DataType::Int16,
49+
ConstantType::Int32 => DataType::Int32,
50+
ConstantType::Int64 => DataType::Int64,
4451
ConstantType::Date => DataType::Date32,
4552
ConstantType::Decimal => DataType::Float64,
4653
ConstantType::Utf8String => DataType::Utf8,
@@ -127,7 +134,14 @@ impl OptdPlanContext<'_> {
127134
let value = expr.value();
128135
let value = match typ {
129136
ConstantType::Bool => ScalarValue::Boolean(Some(value.as_bool())),
130-
ConstantType::Int => ScalarValue::Int64(Some(value.as_i64())),
137+
ConstantType::UInt8 => ScalarValue::UInt8(Some(value.as_u8())),
138+
ConstantType::UInt16 => ScalarValue::UInt16(Some(value.as_u16())),
139+
ConstantType::UInt32 => ScalarValue::UInt32(Some(value.as_u32())),
140+
ConstantType::UInt64 => ScalarValue::UInt64(Some(value.as_u64())),
141+
ConstantType::Int8 => ScalarValue::Int8(Some(value.as_i8())),
142+
ConstantType::Int16 => ScalarValue::Int16(Some(value.as_i16())),
143+
ConstantType::Int32 => ScalarValue::Int32(Some(value.as_i32())),
144+
ConstantType::Int64 => ScalarValue::Int64(Some(value.as_i64())),
131145
ConstantType::Decimal => {
132146
ScalarValue::Decimal128(Some(value.as_f64() as i128), 20, 0)
133147
// TODO(chi): no hard code decimal

Diff for: optd-datafusion-bridge/src/into_optd.rs

+49-23
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ impl OptdPlanContext<'_> {
3737
Ok(scan.into_plan_node())
3838
}
3939

40-
fn conv_into_optd_expr(&mut self, expr: &logical_expr::Expr, context: &DFSchema) -> Result<Expr> {
40+
fn conv_into_optd_expr(
41+
&mut self,
42+
expr: &logical_expr::Expr,
43+
context: &DFSchema,
44+
) -> Result<Expr> {
4145
use logical_expr::Expr;
4246
match expr {
4347
Expr::BinaryExpr(node) => {
@@ -64,15 +68,39 @@ impl OptdPlanContext<'_> {
6468
Expr::Literal(x) => match x {
6569
ScalarValue::UInt8(x) => {
6670
let x = x.as_ref().unwrap();
67-
Ok(ConstantExpr::int(*x as i64).into_expr())
71+
Ok(ConstantExpr::uint8(*x).into_expr())
6872
}
69-
ScalarValue::Utf8(x) => {
73+
ScalarValue::UInt16(x) => {
7074
let x = x.as_ref().unwrap();
71-
Ok(ConstantExpr::string(x).into_expr())
75+
Ok(ConstantExpr::uint16(*x).into_expr())
76+
}
77+
ScalarValue::UInt32(x) => {
78+
let x = x.as_ref().unwrap();
79+
Ok(ConstantExpr::uint32(*x).into_expr())
80+
}
81+
ScalarValue::UInt64(x) => {
82+
let x = x.as_ref().unwrap();
83+
Ok(ConstantExpr::uint64(*x).into_expr())
84+
}
85+
ScalarValue::Int8(x) => {
86+
let x = x.as_ref().unwrap();
87+
Ok(ConstantExpr::int8(*x).into_expr())
88+
}
89+
ScalarValue::Int16(x) => {
90+
let x = x.as_ref().unwrap();
91+
Ok(ConstantExpr::int16(*x).into_expr())
92+
}
93+
ScalarValue::Int32(x) => {
94+
let x = x.as_ref().unwrap();
95+
Ok(ConstantExpr::int32(*x).into_expr())
7296
}
7397
ScalarValue::Int64(x) => {
7498
let x = x.as_ref().unwrap();
75-
Ok(ConstantExpr::int(*x).into_expr())
99+
Ok(ConstantExpr::int64(*x).into_expr())
100+
}
101+
ScalarValue::Utf8(x) => {
102+
let x = x.as_ref().unwrap();
103+
Ok(ConstantExpr::string(x).into_expr())
76104
}
77105
ScalarValue::Date32(x) => {
78106
let x = x.as_ref().unwrap();
@@ -118,7 +146,7 @@ impl OptdPlanContext<'_> {
118146
expr,
119147
)
120148
.into_expr())
121-
}
149+
}
122150
_ => bail!("Unsupported expression: {:?}", expr),
123151
}
124152
}
@@ -224,22 +252,18 @@ impl OptdPlanContext<'_> {
224252
// instead of converting them to a join on true, we bail out
225253

226254
match node.filter {
227-
Some(DFExpr::Literal(ScalarValue::Boolean(Some(val)))) => {
228-
Ok(LogicalJoin::new(
229-
left,
230-
right,
231-
ConstantExpr::bool(val).into_expr(),
232-
join_type,
233-
))
234-
}
235-
None => {
236-
Ok(LogicalJoin::new(
237-
left,
238-
right,
239-
ConstantExpr::bool(true).into_expr(),
240-
join_type,
241-
))
242-
}
255+
Some(DFExpr::Literal(ScalarValue::Boolean(Some(val)))) => Ok(LogicalJoin::new(
256+
left,
257+
right,
258+
ConstantExpr::bool(val).into_expr(),
259+
join_type,
260+
)),
261+
None => Ok(LogicalJoin::new(
262+
left,
263+
right,
264+
ConstantExpr::bool(true).into_expr(),
265+
join_type,
266+
)),
243267
_ => bail!("unsupported join filter: {:?}", node.filter),
244268
}
245269
} else if log_ops.len() == 1 {
@@ -279,7 +303,9 @@ impl OptdPlanContext<'_> {
279303
LogicalPlan::Projection(node) => self.conv_into_optd_projection(node)?.into_plan_node(),
280304
LogicalPlan::Sort(node) => self.conv_into_optd_sort(node)?.into_plan_node(),
281305
LogicalPlan::Aggregate(node) => self.conv_into_optd_agg(node)?.into_plan_node(),
282-
LogicalPlan::SubqueryAlias(node) => self.conv_into_optd_plan_node(node.input.as_ref())?,
306+
LogicalPlan::SubqueryAlias(node) => {
307+
self.conv_into_optd_plan_node(node.input.as_ref())?
308+
}
283309
LogicalPlan::Join(node) => self.conv_into_optd_join(node)?.into_plan_node(),
284310
LogicalPlan::Filter(node) => self.conv_into_optd_filter(node)?.into_plan_node(),
285311
LogicalPlan::CrossJoin(node) => self.conv_into_optd_cross_join(node)?.into_plan_node(),

Diff for: optd-datafusion-bridge/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ impl Catalog for DatafusionCatalog {
6666
for field in fields.fields() {
6767
let dt = match field.data_type() {
6868
DataType::Date32 => ConstantType::Date,
69-
DataType::Int32 => ConstantType::Int,
70-
DataType::Int64 => ConstantType::Int,
69+
DataType::Int32 => ConstantType::Int32,
70+
DataType::Int64 => ConstantType::Int64,
7171
DataType::Float64 => ConstantType::Decimal,
7272
DataType::Utf8 => ConstantType::Utf8String,
7373
DataType::Decimal128(_, _) => ConstantType::Decimal,

Diff for: optd-datafusion-repr/src/bin/test_optimize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn main() {
4646
let scan1 = LogicalScan::new("t1".into());
4747
let filter_cond = BinOpExpr::new(
4848
ColumnRefExpr::new(1).0,
49-
ConstantExpr::new(Value::Int(2)).0,
49+
ConstantExpr::new(Value::Int64(2)).0,
5050
BinOpType::Eq,
5151
);
5252
let filter1 = LogicalFilter::new(scan1.0, filter_cond.0);

Diff for: optd-datafusion-repr/src/plan_nodes/expr.rs

+48-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ impl OptRelNode for ExprList {
6464
pub enum ConstantType {
6565
Bool,
6666
Utf8String,
67-
Int,
67+
UInt8,
68+
UInt16,
69+
UInt32,
70+
UInt64,
71+
Int8,
72+
Int16,
73+
Int32,
74+
Int64,
6875
Date,
6976
Decimal,
7077
Any,
@@ -78,7 +85,14 @@ impl ConstantExpr {
7885
let typ = match &value {
7986
Value::Bool(_) => ConstantType::Bool,
8087
Value::String(_) => ConstantType::Utf8String,
81-
Value::Int(_) => ConstantType::Int,
88+
Value::UInt8(_) => ConstantType::UInt8,
89+
Value::UInt16(_) => ConstantType::UInt16,
90+
Value::UInt32(_) => ConstantType::UInt32,
91+
Value::UInt64(_) => ConstantType::UInt64,
92+
Value::Int8(_) => ConstantType::Int8,
93+
Value::Int16(_) => ConstantType::Int16,
94+
Value::Int32(_) => ConstantType::Int32,
95+
Value::Int64(_) => ConstantType::Int64,
8296
Value::Float(_) => ConstantType::Decimal,
8397
_ => unimplemented!(),
8498
};
@@ -107,12 +121,40 @@ impl ConstantExpr {
107121
)
108122
}
109123

110-
pub fn int(value: i64) -> Self {
111-
Self::new_with_type(Value::Int(value), ConstantType::Int)
124+
pub fn uint8(value: u8) -> Self {
125+
Self::new_with_type(Value::UInt8(value), ConstantType::UInt8)
126+
}
127+
128+
pub fn uint16(value: u16) -> Self {
129+
Self::new_with_type(Value::UInt16(value), ConstantType::UInt16)
130+
}
131+
132+
pub fn uint32(value: u32) -> Self {
133+
Self::new_with_type(Value::UInt32(value), ConstantType::UInt32)
134+
}
135+
136+
pub fn uint64(value: u64) -> Self {
137+
Self::new_with_type(Value::UInt64(value), ConstantType::UInt64)
138+
}
139+
140+
pub fn int8(value: i8) -> Self {
141+
Self::new_with_type(Value::Int8(value), ConstantType::Int8)
142+
}
143+
144+
pub fn int16(value: i16) -> Self {
145+
Self::new_with_type(Value::Int16(value), ConstantType::Int16)
146+
}
147+
148+
pub fn int32(value: i32) -> Self {
149+
Self::new_with_type(Value::Int32(value), ConstantType::Int32)
150+
}
151+
152+
pub fn int64(value: i64) -> Self {
153+
Self::new_with_type(Value::Int64(value), ConstantType::Int64)
112154
}
113155

114156
pub fn date(value: i64) -> Self {
115-
Self::new_with_type(Value::Int(value), ConstantType::Date)
157+
Self::new_with_type(Value::Int64(value), ConstantType::Date)
116158
}
117159

118160
pub fn decimal(value: f64) -> Self {
@@ -152,7 +194,7 @@ impl ColumnRefExpr {
152194
RelNode {
153195
typ: OptRelNodeTyp::ColumnRef,
154196
children: vec![],
155-
data: Some(Value::Int(column_idx as i64)),
197+
data: Some(Value::Int64(column_idx as i64)),
156198
}
157199
.into(),
158200
))
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-- (no id or description)
2+
create table t1(t1v1 int, t1v2 int);
3+
insert into t1 values (0, 0), (1, 1), (2, 2);
4+
5+
/*
6+
3
7+
*/
8+
9+
-- Test whether the optimizer handles integer equality predicates correctly.
10+
select * from t1 where t1v1 = 0;
11+
12+
/*
13+
0 0
14+
*/
15+
16+
-- Test whether the optimizer handles multiple integer equality predicates correctly.
17+
select * from t1 where t1v1 = 0 and t1v2 = 1;
18+
19+
/*
20+
21+
*/
22+
23+
-- Test whether the optimizer handles multiple integer inequality predicates correctly.
24+
select * from t1 where t1v1 = 0 and t1v2 != 1;
25+
26+
/*
27+
0 0
28+
*/
29+

Diff for: optd-sqlplannertest/tests/constant_predicate.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
- sql: |
2+
create table t1(t1v1 int, t1v2 int);
3+
insert into t1 values (0, 0), (1, 1), (2, 2);
4+
tasks:
5+
- execute_with_logical
6+
- sql: |
7+
select * from t1 where t1v1 = 0;
8+
desc: Test whether the optimizer handles integer equality predicates correctly.
9+
tasks:
10+
- execute_with_logical
11+
- sql: |
12+
select * from t1 where t1v1 = 0 and t1v2 = 1;
13+
desc: Test whether the optimizer handles multiple integer equality predicates correctly.
14+
tasks:
15+
- execute_with_logical
16+
- sql: |
17+
select * from t1 where t1v1 = 0 and t1v2 != 1;
18+
desc: Test whether the optimizer handles multiple integer inequality predicates correctly.
19+
tasks:
20+
- execute_with_logical

0 commit comments

Comments
 (0)