Skip to content

Commit 66feb7c

Browse files
wszhdshysNANASE
andauthored
feat: add function Lower & Upper (#231)
* feat: add function Lower & Upper * chore: codefmt --------- Co-authored-by: NANASE <wszhds@gmail.com>
1 parent d584167 commit 66feb7c

File tree

5 files changed

+175
-9
lines changed

5 files changed

+175
-9
lines changed

src/db.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use crate::expression::function::scala::ScalarFunctionImpl;
66
use crate::expression::function::table::TableFunctionImpl;
77
use crate::expression::function::FunctionSummary;
88
use crate::function::current_date::CurrentDate;
9+
use crate::function::lower::Lower;
910
use crate::function::numbers::Numbers;
11+
use crate::function::upper::Upper;
1012
use crate::optimizer::heuristic::batch::HepBatchStrategy;
1113
use crate::optimizer::heuristic::optimizer::HepOptimizer;
1214
use crate::optimizer::rule::implementation::ImplementationRuleImpl;
@@ -49,6 +51,8 @@ impl DataBaseBuilder {
4951
table_functions: Default::default(),
5052
};
5153
builder = builder.register_scala_function(CurrentDate::new());
54+
builder = builder.register_scala_function(Lower::new());
55+
builder = builder.register_scala_function(Upper::new());
5256
builder = builder.register_table_function(Numbers::new());
5357
builder
5458
}

src/function/lower.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use crate::catalog::ColumnRef;
2+
use crate::errors::DatabaseError;
3+
use crate::expression::function::scala::FuncMonotonicity;
4+
use crate::expression::function::scala::ScalarFunctionImpl;
5+
use crate::expression::function::FunctionSummary;
6+
use crate::expression::ScalarExpression;
7+
use crate::types::tuple::Tuple;
8+
use crate::types::value::DataValue;
9+
use crate::types::LogicalType;
10+
use serde::Deserialize;
11+
use serde::Serialize;
12+
use sqlparser::ast::CharLengthUnits;
13+
use std::sync::Arc;
14+
15+
#[derive(Debug, Serialize, Deserialize)]
16+
pub(crate) struct Lower {
17+
summary: FunctionSummary,
18+
}
19+
20+
impl Lower {
21+
#[allow(unused_mut)]
22+
pub(crate) fn new() -> Arc<Self> {
23+
let function_name = "lower".to_lowercase();
24+
let arg_types = vec![LogicalType::Varchar(None, CharLengthUnits::Characters)];
25+
Arc::new(Self {
26+
summary: FunctionSummary {
27+
name: function_name,
28+
arg_types,
29+
},
30+
})
31+
}
32+
}
33+
34+
#[typetag::serde]
35+
impl ScalarFunctionImpl for Lower {
36+
#[allow(unused_variables, clippy::redundant_closure_call)]
37+
fn eval(
38+
&self,
39+
exprs: &[ScalarExpression],
40+
tuples: &Tuple,
41+
columns: &[ColumnRef],
42+
) -> Result<DataValue, DatabaseError> {
43+
let value = exprs[0].eval(tuples, columns)?;
44+
let mut value = DataValue::clone(&value);
45+
if !matches!(value.logical_type(), LogicalType::Varchar(_, _)) {
46+
value = DataValue::clone(&value)
47+
.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
48+
}
49+
if let DataValue::Utf8 {
50+
value: Some(value),
51+
ty,
52+
unit,
53+
} = &mut value
54+
{
55+
*value = value.to_lowercase();
56+
}
57+
Ok(value)
58+
}
59+
60+
fn monotonicity(&self) -> Option<FuncMonotonicity> {
61+
todo!()
62+
}
63+
64+
fn return_type(&self) -> &LogicalType {
65+
&LogicalType::Varchar(None, CharLengthUnits::Characters)
66+
}
67+
68+
fn summary(&self) -> &FunctionSummary {
69+
&self.summary
70+
}
71+
}

src/function/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
pub(crate) mod current_date;
2+
pub(crate) mod lower;
23
pub(crate) mod numbers;
4+
pub(crate) mod upper;

src/function/upper.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use crate::catalog::ColumnRef;
2+
use crate::errors::DatabaseError;
3+
use crate::expression::function::scala::FuncMonotonicity;
4+
use crate::expression::function::scala::ScalarFunctionImpl;
5+
use crate::expression::function::FunctionSummary;
6+
use crate::expression::ScalarExpression;
7+
use crate::types::tuple::Tuple;
8+
use crate::types::value::DataValue;
9+
use crate::types::LogicalType;
10+
use serde::Deserialize;
11+
use serde::Serialize;
12+
use sqlparser::ast::CharLengthUnits;
13+
use std::sync::Arc;
14+
15+
#[derive(Debug, Serialize, Deserialize)]
16+
pub(crate) struct Upper {
17+
summary: FunctionSummary,
18+
}
19+
20+
impl Upper {
21+
#[allow(unused_mut)]
22+
pub(crate) fn new() -> Arc<Self> {
23+
let function_name = "upper".to_lowercase();
24+
let arg_types = vec![LogicalType::Varchar(None, CharLengthUnits::Characters)];
25+
Arc::new(Self {
26+
summary: FunctionSummary {
27+
name: function_name,
28+
arg_types,
29+
},
30+
})
31+
}
32+
}
33+
34+
#[typetag::serde]
35+
impl ScalarFunctionImpl for Upper {
36+
#[allow(unused_variables, clippy::redundant_closure_call)]
37+
fn eval(
38+
&self,
39+
exprs: &[ScalarExpression],
40+
tuples: &Tuple,
41+
columns: &[ColumnRef],
42+
) -> Result<DataValue, DatabaseError> {
43+
let value = exprs[0].eval(tuples, columns)?;
44+
let mut value = DataValue::clone(&value);
45+
if !matches!(value.logical_type(), LogicalType::Varchar(_, _)) {
46+
value = DataValue::clone(&value)
47+
.cast(&LogicalType::Varchar(None, CharLengthUnits::Characters))?;
48+
}
49+
if let DataValue::Utf8 {
50+
value: Some(value),
51+
ty,
52+
unit,
53+
} = &mut value
54+
{
55+
*value = value.to_uppercase();
56+
}
57+
Ok(value)
58+
}
59+
60+
fn monotonicity(&self) -> Option<FuncMonotonicity> {
61+
todo!()
62+
}
63+
64+
fn return_type(&self) -> &LogicalType {
65+
&LogicalType::Varchar(None, CharLengthUnits::Characters)
66+
}
67+
68+
fn summary(&self) -> &FunctionSummary {
69+
&self.summary
70+
}
71+
}

tests/slt/sql_2016/E021_08.slt

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,31 @@
11
# E021-08: UPPER and LOWER functions
22

3-
# TODO: LOWER()/UPPER()
3+
query T
4+
SELECT LOWER ( 'FOO' )
5+
----
6+
foo
47

5-
# query T
6-
# SELECT LOWER ( 'foo' )
7-
# ----
8-
# 'foo'
8+
query T
9+
SELECT LOWER ( 'foo' )
10+
----
11+
foo
912

10-
# query T
11-
# SELECT UPPER ( 'foo' )
12-
# ----
13-
# 'FOO'
13+
query T
14+
SELECT UPPER ( 'foo' )
15+
----
16+
FOO
17+
18+
query T
19+
SELECT UPPER ( 'FOO' )
20+
----
21+
FOO
22+
23+
query T
24+
SELECT UPPER ( LOWER ( 'FOO' ) )
25+
----
26+
FOO
27+
28+
query T
29+
SELECT LOWER ( UPPER ( 'foo' ) )
30+
----
31+
foo

0 commit comments

Comments
 (0)