Skip to content

Commit 0b9dd84

Browse files
committed
FunctionFactoryHelper
Signed-off-by: coldWater <forsaken628@gmail.com>
1 parent 070eedc commit 0b9dd84

File tree

7 files changed

+110
-51
lines changed

7 files changed

+110
-51
lines changed

src/query/expression/src/function.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
use std::borrow::Cow;
1616
use std::collections::HashMap;
17+
use std::fmt::Debug;
1718
use std::ops::BitAnd;
1819
use std::ops::BitOr;
1920
use std::ops::Not;
@@ -53,14 +54,62 @@ pub type AutoCastRules<'a> = &'a [(DataType, DataType)];
5354
pub trait FunctionFactoryClosure =
5455
Fn(&[Scalar], &[DataType]) -> Option<Arc<Function>> + Send + Sync + 'static;
5556

57+
pub struct FunctionFactoryHelper {
58+
fixed_arg_count: Option<usize>,
59+
passthrough_nullable: bool,
60+
create: Box<dyn FunctionFactoryClosure>,
61+
}
62+
63+
impl Debug for FunctionFactoryHelper {
64+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65+
f.debug_struct("FunctionFactoryHelper")
66+
.field("fixed_arg_count", &self.fixed_arg_count)
67+
.field("passthrough_nullable", &self.passthrough_nullable)
68+
.finish()
69+
}
70+
}
71+
72+
impl FunctionFactoryHelper {
73+
pub fn create_1_arg_core(
74+
create: fn(&[Scalar], &DataType) -> Option<Function>,
75+
) -> FunctionFactory {
76+
FunctionFactory::Helper(Self {
77+
fixed_arg_count: Some(1),
78+
passthrough_nullable: false,
79+
create: Box::new(move |params, args: &[DataType]| match args {
80+
[arg0] => create(params, arg0).map(Arc::new),
81+
_ => None,
82+
}),
83+
})
84+
}
85+
86+
pub fn create_1_arg_passthrough_nullable(
87+
create: fn(&[Scalar], &DataType) -> Option<Function>,
88+
) -> FunctionFactory {
89+
FunctionFactory::Helper(Self {
90+
fixed_arg_count: Some(1),
91+
passthrough_nullable: true,
92+
create: Box::new(move |params, args: &[DataType]| match args {
93+
[DataType::Nullable(box arg0)] => {
94+
create(params, arg0).map(|func| Arc::new(func.passthrough_nullable()))
95+
}
96+
[arg0] => create(params, arg0).map(Arc::new),
97+
_ => None,
98+
}),
99+
})
100+
}
101+
}
102+
56103
pub enum FunctionFactory {
57104
Closure(Box<dyn FunctionFactoryClosure>),
105+
Helper(FunctionFactoryHelper),
58106
}
59107

60108
impl FunctionFactory {
61109
fn create(&self, params: &[Scalar], args: &[DataType]) -> Option<Arc<Function>> {
62110
match self {
63111
FunctionFactory::Closure(closure) => closure(params, args),
112+
FunctionFactory::Helper(factory) => (factory.create)(params, args),
64113
}
65114
}
66115
}

src/query/functions/src/scalars/decimal/src/uuid.rs

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,81 +12,68 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::sync::Arc;
16-
1715
use databend_common_base::base::uuid::Uuid;
16+
use databend_common_expression::types::string::StringColumnBuilder;
1817
use databend_common_expression::types::DataType;
1918
use databend_common_expression::types::Decimal128Type;
2019
use databend_common_expression::types::Decimal256As128Type;
2120
use databend_common_expression::types::DecimalDataType;
22-
use databend_common_expression::types::DecimalSize;
2321
use databend_common_expression::types::StringType;
2422
use databend_common_expression::vectorize_with_builder_1_arg;
23+
use databend_common_expression::EvalContext;
2524
use databend_common_expression::Function;
2625
use databend_common_expression::FunctionDomain;
2726
use databend_common_expression::FunctionEval;
28-
use databend_common_expression::FunctionFactory;
27+
use databend_common_expression::FunctionFactoryHelper;
2928
use databend_common_expression::FunctionRegistry;
3029
use databend_common_expression::FunctionSignature;
3130

3231
pub fn register_decimal_to_uuid(registry: &mut FunctionRegistry) {
33-
let factory = FunctionFactory::Closure(Box::new(|_, args_type: &[DataType]| {
34-
let (size, has_nullable) = match args_type {
35-
[DataType::Decimal(size)] => (*size, false),
36-
[DataType::Nullable(box DataType::Decimal(size))] => (*size, true),
37-
[DataType::Null] => (DecimalSize::default_128(), true),
38-
_ => return None,
39-
};
32+
let factory = FunctionFactoryHelper::create_1_arg_passthrough_nullable(|_, arg| {
33+
let size = arg.as_decimal()?;
4034

4135
if !size.can_carried_by_128() {
4236
return None;
4337
}
4438

45-
let function = Function {
39+
fn to_uuid(arg: i128, output: &mut StringColumnBuilder, _: &mut EvalContext<'_>) {
40+
let uuid = Uuid::from_u128(arg as u128);
41+
let str = uuid.as_simple().to_string();
42+
output.put_str(str.as_str());
43+
output.commit_row();
44+
}
45+
46+
Some(Function {
4647
signature: FunctionSignature {
4748
name: "to_uuid".to_string(),
48-
args_type: [DataType::Decimal(size)].into(),
49+
args_type: [DataType::Decimal(*size)].into(),
4950
return_type: DataType::String,
5051
},
5152
eval: FunctionEval::Scalar {
5253
calc_domain: Box::new(move |_, _| FunctionDomain::Full),
53-
eval: Box::new(move |args, ctx| {
54+
eval: Box::new(|args, ctx| {
5455
let arg = args[0].clone();
5556
let (decimal_type, _) = DecimalDataType::from_value(&arg).unwrap();
5657
match decimal_type {
5758
DecimalDataType::Decimal128(_) => {
5859
let arg = arg.try_downcast::<Decimal128Type>().unwrap();
59-
vectorize_with_builder_1_arg::<Decimal128Type, StringType>(
60-
|arg, output, _| {
61-
let uuid = Uuid::from_u128(arg as u128);
62-
let str = uuid.as_simple().to_string();
63-
output.put_str(str.as_str());
64-
output.commit_row();
65-
},
66-
)(arg, ctx)
60+
vectorize_with_builder_1_arg::<Decimal128Type, StringType>(to_uuid)(
61+
arg, ctx,
62+
)
6763
.upcast()
6864
}
6965
DecimalDataType::Decimal256(_) => {
7066
let arg = arg.try_downcast::<Decimal256As128Type>().unwrap();
7167
vectorize_with_builder_1_arg::<Decimal256As128Type, StringType>(
72-
|arg, output, _| {
73-
let uuid = Uuid::from_u128(arg as u128);
74-
let str = uuid.as_simple().to_string();
75-
output.put_str(str.as_str());
76-
output.commit_row();
77-
},
68+
to_uuid,
7869
)(arg, ctx)
7970
.upcast()
8071
}
8172
}
8273
}),
8374
},
84-
};
85-
if has_nullable {
86-
Some(Arc::new(function.passthrough_nullable()))
87-
} else {
88-
Some(Arc::new(function))
89-
}
90-
}));
75+
})
76+
});
77+
9178
registry.register_function_factory("to_uuid", factory);
9279
}

src/query/functions/tests/it/scalars/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use databend_common_expression::ConstantFolder;
2424
use databend_common_expression::DataBlock;
2525
use databend_common_expression::Evaluator;
2626
use databend_common_expression::FunctionContext;
27+
use databend_common_expression::FunctionFactory;
2728
use databend_common_expression::Value;
2829
use databend_common_functions::BUILTIN_FUNCTIONS;
2930
use goldenfile::Mint;
@@ -259,9 +260,15 @@ fn list_all_builtin_functions() {
259260
.factories
260261
.iter()
261262
.flat_map(|(name, funcs)| {
262-
funcs
263-
.iter()
264-
.map(|(_, id)| ((name.clone(), *id), format!("{} FACTORY", name.clone())))
263+
funcs.iter().map(move |(factor, id)| {
264+
let display = match factor {
265+
FunctionFactory::Closure(_) => format!("{name} FACTORY"),
266+
FunctionFactory::Helper(helper) => {
267+
format!("{name} {helper:?}")
268+
}
269+
};
270+
((name.clone(), *id), display)
271+
})
265272
})
266273
.collect_into(&mut funcs);
267274
funcs.sort_by_key(|(key, _)| key.clone());

src/query/functions/tests/it/scalars/string.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,6 @@ fn test_split(file: &mut impl Write) {
770770

771771
fn test_to_uuid(file: &mut impl Write) {
772772
run_ast(file, "to_uuid(5::decimal(1,0))", &[]);
773-
run_ast(file, "to_uuid(null)", &[]);
774773

775774
let size = DecimalSize::new(10, 0).unwrap();
776775
run_ast(file, "to_uuid(a)", &[(
@@ -785,6 +784,11 @@ fn test_to_uuid(file: &mut impl Write) {
785784
"a",
786785
Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size),
787786
)]);
787+
run_ast(file, "to_uuid(a)", &[(
788+
"a",
789+
Decimal256Type::from_data_with_size([i256::from(0), i256::from(20)], size)
790+
.wrap_nullable(None),
791+
)]);
788792
run_ast(file, "to_uuid(a)", &[(
789793
"a",
790794
Decimal256Type::from_data_with_size(

src/query/functions/tests/it/scalars/testdata/function_list.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4135,7 +4135,7 @@ Functions overloads:
41354135
25 to_uint8(Boolean NULL) :: UInt8 NULL
41364136
0 to_unix_timestamp(Timestamp) :: Int64
41374137
1 to_unix_timestamp(Timestamp NULL) :: Int64 NULL
4138-
0 to_uuid FACTORY
4138+
0 to_uuid FunctionFactoryHelper { fixed_arg_count: Some(1), passthrough_nullable: true }
41394139
0 to_variant FACTORY
41404140
0 to_week_of_year(Date) :: UInt32
41414141
1 to_week_of_year(Date NULL) :: UInt32 NULL

src/query/functions/tests/it/scalars/testdata/string.txt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3703,15 +3703,6 @@ output domain : {"00000000000000000000000000000005"..="000000000000000000000000
37033703
output : '00000000000000000000000000000005'
37043704

37053705

3706-
ast : to_uuid(null)
3707-
raw expr : to_uuid(NULL)
3708-
checked expr : to_uuid<Decimal(38, 0) NULL>(CAST<NULL>(NULL AS Decimal(38, 0) NULL))
3709-
optimized expr : NULL
3710-
output type : String NULL
3711-
output domain : {NULL}
3712-
output : NULL
3713-
3714-
37153706
ast : to_uuid(a)
37163707
raw expr : to_uuid(a::Decimal(10, 0))
37173708
checked expr : to_uuid<Decimal(10, 0)>(a)
@@ -3777,6 +3768,27 @@ evaluation (internal):
37773768
+--------+----------------------------------------------------------------------------------+
37783769

37793770

3771+
ast : to_uuid(a)
3772+
raw expr : to_uuid(a::Decimal(10, 0) NULL)
3773+
checked expr : to_uuid<Decimal(10, 0) NULL>(a)
3774+
evaluation:
3775+
+--------+---------------------+------------------------------------+
3776+
| | a | Output |
3777+
+--------+---------------------+------------------------------------+
3778+
| Type | Decimal(10, 0) NULL | String NULL |
3779+
| Domain | {0..=20} | {""..} ∪ {NULL} |
3780+
| Row 0 | 0 | '00000000000000000000000000000000' |
3781+
| Row 1 | 20 | '00000000000000000000000000000014' |
3782+
+--------+---------------------+------------------------------------+
3783+
evaluation (internal):
3784+
+--------+-------------------------------------------------------------------------------------------------------------------------------------+
3785+
| Column | Data |
3786+
+--------+-------------------------------------------------------------------------------------------------------------------------------------+
3787+
| a | NullableColumn { column: Decimal256([0, 20]), validity: [0b______11] } |
3788+
| Output | NullableColumn { column: StringColumn[00000000000000000000000000000000, 00000000000000000000000000000014], validity: [0b______11] } |
3789+
+--------+-------------------------------------------------------------------------------------------------------------------------------------+
3790+
3791+
37803792
error:
37813793
--> SQL:1:1
37823794
|

tests/sqllogictests/suites/query/functions/02_0009_function_hashes.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ SELECT SIPHASH(1)
1111
query I
1212
SELECT SIPHASH(1.2)
1313
----
14-
2854037594257667269
14+
17113433499147459995
1515

1616
query I
1717
SELECT SIPHASH([1,2,3]), SIPHASH([1,3,null])
@@ -31,7 +31,7 @@ SELECT SIPHASH64(1)
3131
query I
3232
SELECT SIPHASH64(1.2)
3333
----
34-
2854037594257667269
34+
17113433499147459995
3535

3636
query T
3737
SELECT BLAKE3('1234567890')

0 commit comments

Comments
 (0)