Skip to content

Commit c441a0d

Browse files
committed
Conditional compilation
1 parent 4b5acd1 commit c441a0d

File tree

6 files changed

+192
-109
lines changed

6 files changed

+192
-109
lines changed

datafusion/functions/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ authors = { workspace = true }
1212
rust-version = { workspace = true }
1313

1414
[features]
15-
default = ["encoding_expressions"]
16-
# enable the encoding expressions
15+
default= []
16+
# enable the encode/decode functions
1717
encoding_expressions = ["base64", "hex"]
1818

1919

datafusion/functions/src/encoding/inner.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ enum Encoding {
3737
Base64,
3838
Hex,
3939
}
40-
4140
fn encode_process(value: &ColumnarValue, encoding: Encoding) -> Result<ColumnarValue> {
4241
match value {
4342
ColumnarValue::Array(a) => match a.data_type() {
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//! Metadata information for "encode" and "decode" functions
19+
use datafusion_common::arrow::datatypes::DataType;
20+
use datafusion_common::{plan_err, DataFusionError, Result};
21+
use datafusion_expr::TypeSignature::*;
22+
use datafusion_expr::{ColumnarValue, FunctionImplementation, Signature, Volatility};
23+
use std::sync::OnceLock;
24+
use DataType::*;
25+
26+
pub(super) struct EncodeFunc {}
27+
28+
static ENCODE_SIGNATURE: OnceLock<Signature> = OnceLock::new();
29+
30+
impl FunctionImplementation for EncodeFunc {
31+
fn name(&self) -> &str {
32+
"encode"
33+
}
34+
35+
fn signature(&self) -> &Signature {
36+
ENCODE_SIGNATURE.get_or_init(|| {
37+
Signature::one_of(
38+
vec![
39+
Exact(vec![Utf8, Utf8]),
40+
Exact(vec![LargeUtf8, Utf8]),
41+
Exact(vec![Binary, Utf8]),
42+
Exact(vec![LargeBinary, Utf8]),
43+
],
44+
Volatility::Immutable,
45+
)
46+
})
47+
}
48+
49+
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
50+
Ok(match arg_types[0] {
51+
Utf8 => Utf8,
52+
LargeUtf8 => LargeUtf8,
53+
Binary => Utf8,
54+
LargeBinary => LargeUtf8,
55+
Null => Null,
56+
_ => {
57+
return plan_err!("The encode function can only accept utf8 or binary.");
58+
}
59+
})
60+
}
61+
62+
fn invoke(&self, args: &[ColumnarValue]) -> Result<ColumnarValue> {
63+
// Put a feature flag here to make sure this is only compiled when the feature is activated
64+
super::inner::encode(args)
65+
}
66+
}
67+
68+
pub(super) struct DecodeFunc {}
69+
70+
static DECODE_SIGNATURE: OnceLock<Signature> = OnceLock::new();
71+
72+
impl FunctionImplementation for DecodeFunc {
73+
fn name(&self) -> &str {
74+
"decode"
75+
}
76+
77+
fn signature(&self) -> &Signature {
78+
DECODE_SIGNATURE.get_or_init(|| {
79+
Signature::one_of(
80+
vec![
81+
Exact(vec![Utf8, Utf8]),
82+
Exact(vec![LargeUtf8, Utf8]),
83+
Exact(vec![Binary, Utf8]),
84+
Exact(vec![LargeBinary, Utf8]),
85+
],
86+
Volatility::Immutable,
87+
)
88+
})
89+
}
90+
91+
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
92+
Ok(match arg_types[0] {
93+
Utf8 => Binary,
94+
LargeUtf8 => LargeBinary,
95+
Binary => Binary,
96+
LargeBinary => LargeBinary,
97+
Null => Null,
98+
_ => {
99+
return plan_err!("The decode function can only accept utf8 or binary.");
100+
}
101+
})
102+
}
103+
104+
fn invoke(&self, args: &[ColumnarValue]) -> Result<ColumnarValue> {
105+
// Put a feature flag here to make sure this is only compiled when the feature is activated
106+
super::inner::decode(args)
107+
}
108+
}

datafusion/functions/src/encoding/mod.rs

Lines changed: 15 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -15,120 +15,29 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
#[cfg(feature = "encoding_expressions")]
1819
mod inner;
20+
#[cfg(feature = "encoding_expressions")]
21+
mod meta;
1922

20-
use datafusion_common::arrow::datatypes::DataType;
21-
use datafusion_common::{plan_err, DataFusionError, Result};
22-
use datafusion_expr::TypeSignature::*;
23-
use datafusion_expr::{
24-
ColumnarValue, FunctionImplementation, ScalarUDF, Signature, Volatility,
25-
};
23+
use crate::utils::insert;
24+
use datafusion_expr::ScalarUDF;
2625
use std::collections::HashMap;
27-
use std::sync::{Arc, OnceLock};
28-
use DataType::*;
29-
30-
// TODO make stub implementations when feature is not activated
31-
//#[cfg(feature = "encoding_expressions")]
32-
//pub mod encoding_expressions;
33-
34-
pub fn encode_udf() -> ScalarUDF {
35-
ScalarUDF::new_from_impl(Arc::new(EncodeFunc {}))
36-
}
37-
38-
pub fn decode_udf() -> ScalarUDF {
39-
ScalarUDF::new_from_impl(Arc::new(DecodeFunc {}))
40-
}
41-
42-
fn insert(registry: &mut HashMap<String, Arc<ScalarUDF>>, udf: ScalarUDF) {
43-
registry.insert(udf.name().to_string(), Arc::new(udf));
44-
}
26+
use std::sync::Arc;
4527

4628
/// Registers the `encode` and `decode` functions with the function registry
29+
#[cfg(feature = "encoding_expressions")]
4730
pub fn register(registry: &mut HashMap<String, Arc<ScalarUDF>>) {
48-
insert(registry, encode_udf());
49-
insert(registry, decode_udf());
50-
}
51-
52-
struct EncodeFunc {}
53-
54-
static ENCODE_SIGNATURE: OnceLock<Signature> = OnceLock::new();
55-
56-
impl FunctionImplementation for EncodeFunc {
57-
fn name(&self) -> &str {
58-
"encode"
59-
}
60-
61-
fn signature(&self) -> &Signature {
62-
ENCODE_SIGNATURE.get_or_init(|| {
63-
Signature::one_of(
64-
vec![
65-
Exact(vec![Utf8, Utf8]),
66-
Exact(vec![LargeUtf8, Utf8]),
67-
Exact(vec![Binary, Utf8]),
68-
Exact(vec![LargeBinary, Utf8]),
69-
],
70-
Volatility::Immutable,
71-
)
72-
})
73-
}
74-
75-
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
76-
Ok(match arg_types[0] {
77-
Utf8 => Utf8,
78-
LargeUtf8 => LargeUtf8,
79-
Binary => Utf8,
80-
LargeBinary => LargeUtf8,
81-
Null => Null,
82-
_ => {
83-
return plan_err!("The encode function can only accept utf8 or binary.");
84-
}
85-
})
86-
}
87-
88-
fn invoke(&self, args: &[ColumnarValue]) -> Result<ColumnarValue> {
89-
// Put a feature flag here to make sure this is only compiled when the feature is activated
90-
inner::encode(args)
91-
}
31+
insert(registry, meta::EncodeFunc {});
32+
insert(registry, meta::DecodeFunc {});
9233
}
9334

94-
struct DecodeFunc {}
95-
96-
static DECODE_SIGNATURE: OnceLock<Signature> = OnceLock::new();
97-
98-
impl FunctionImplementation for DecodeFunc {
99-
fn name(&self) -> &str {
100-
"decode"
101-
}
102-
103-
fn signature(&self) -> &Signature {
104-
DECODE_SIGNATURE.get_or_init(|| {
105-
Signature::one_of(
106-
vec![
107-
Exact(vec![Utf8, Utf8]),
108-
Exact(vec![LargeUtf8, Utf8]),
109-
Exact(vec![Binary, Utf8]),
110-
Exact(vec![LargeBinary, Utf8]),
111-
],
112-
Volatility::Immutable,
113-
)
114-
})
115-
}
116-
117-
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
118-
Ok(match arg_types[0] {
119-
Utf8 => Binary,
120-
LargeUtf8 => LargeBinary,
121-
Binary => Binary,
122-
LargeBinary => LargeBinary,
123-
Null => Null,
124-
_ => {
125-
return plan_err!("The decode function can only accept utf8 or binary.");
126-
}
127-
})
128-
}
35+
/// Registers the `encode` and `decode` stubs with the function registry
36+
#[cfg(not(feature = "encoding_expressions"))]
37+
pub fn register(registry: &mut HashMap<String, Arc<ScalarUDF>>) {
38+
let hint = "Requires compilation with feature flag: encoding_expressions.";
12939

130-
fn invoke(&self, args: &[ColumnarValue]) -> Result<ColumnarValue> {
131-
// Put a feature flag here to make sure this is only compiled when the feature is activated
132-
inner::decode(args)
40+
for function_name in ["encode", "decode"] {
41+
insert(registry, crate::utils::StubFunc::new(function_name, hint));
13342
}
13443
}

datafusion/functions/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::collections::HashMap;
2222
use std::sync::Arc;
2323

2424
pub mod encoding;
25+
pub mod utils;
2526

2627
/// Registers all "built in" functions from this crate with the provided registry
2728
pub fn register_all(registry: &mut HashMap<String, Arc<ScalarUDF>>) {

datafusion/functions/src/utils.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use arrow::datatypes::DataType;
19+
use datafusion_common::{exec_err, plan_err, DataFusionError, Result};
20+
use datafusion_expr::{
21+
ColumnarValue, FunctionImplementation, ScalarUDF, Signature, Volatility,
22+
};
23+
use std::collections::HashMap;
24+
use std::sync::{Arc, OnceLock};
25+
26+
/// Insert a function into the registry
27+
pub(crate) fn insert(
28+
registry: &mut HashMap<String, Arc<ScalarUDF>>,
29+
udf: impl FunctionImplementation + Send + Sync + 'static,
30+
) {
31+
let udf = ScalarUDF::new_from_impl(Arc::new(udf));
32+
registry.insert(udf.name().to_string(), Arc::new(udf));
33+
}
34+
35+
/// A scalar function that always errors with a hint. This is used to stub out
36+
/// functions that are not enabled with the current set of crate features.
37+
pub struct StubFunc {
38+
name: &'static str,
39+
hint: &'static str,
40+
}
41+
42+
impl StubFunc {
43+
/// Create a new stub function
44+
pub fn new(name: &'static str, hint: &'static str) -> Self {
45+
Self { name, hint }
46+
}
47+
}
48+
49+
static STUB_SIGNATURE: OnceLock<Signature> = OnceLock::new();
50+
51+
impl FunctionImplementation for StubFunc {
52+
fn name(&self) -> &str {
53+
self.name
54+
}
55+
56+
fn signature(&self) -> &Signature {
57+
STUB_SIGNATURE.get_or_init(|| Signature::variadic_any(Volatility::Volatile))
58+
}
59+
60+
fn return_type(&self, _args: &[DataType]) -> Result<DataType> {
61+
plan_err!("function {} not available. {}", self.name, self.hint)
62+
}
63+
fn invoke(&self, _args: &[ColumnarValue]) -> Result<ColumnarValue> {
64+
exec_err!("function {} not available. {}", self.name, self.hint)
65+
}
66+
}

0 commit comments

Comments
 (0)