Skip to content

Commit f39c63b

Browse files
author
Arttu Voutilainen
committed
Add a test for using "not:bool"
1 parent cd549d8 commit f39c63b

File tree

6 files changed

+154
-9
lines changed

6 files changed

+154
-9
lines changed

datafusion/substrait/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ chrono = { workspace = true }
3737
datafusion = { workspace = true, default-features = true }
3838
itertools = { workspace = true }
3939
object_store = { workspace = true }
40+
pbjson-types = "0.6"
4041
prost = "0.12"
4142
prost-types = "0.12"
42-
substrait = "0.34.0"
43+
substrait = { version = "0.34.0", features = ["serde"] }
4344

4445
[dev-dependencies]
46+
serde_json = "1.0"
4547
tokio = { workspace = true }
4648

4749
[features]

datafusion/substrait/src/logical_plan/consumer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,7 @@ pub(crate) fn from_substrait_literal(lit: &Literal) -> Result<ScalarValue> {
14221422
return substrait_err!("Interval year month value is empty");
14231423
};
14241424
let value_slice: [u8; 4] =
1425-
raw_val.value.clone().try_into().map_err(|_| {
1425+
(*raw_val.value).try_into().map_err(|_| {
14261426
substrait_datafusion_err!(
14271427
"Failed to parse interval year month value"
14281428
)
@@ -1434,7 +1434,7 @@ pub(crate) fn from_substrait_literal(lit: &Literal) -> Result<ScalarValue> {
14341434
return substrait_err!("Interval day time value is empty");
14351435
};
14361436
let value_slice: [u8; 8] =
1437-
raw_val.value.clone().try_into().map_err(|_| {
1437+
(*raw_val.value).try_into().map_err(|_| {
14381438
substrait_datafusion_err!(
14391439
"Failed to parse interval day time value"
14401440
)
@@ -1446,7 +1446,7 @@ pub(crate) fn from_substrait_literal(lit: &Literal) -> Result<ScalarValue> {
14461446
return substrait_err!("Interval month day nano value is empty");
14471447
};
14481448
let value_slice: [u8; 16] =
1449-
raw_val.value.clone().try_into().map_err(|_| {
1449+
(*raw_val.value).try_into().map_err(|_| {
14501450
substrait_datafusion_err!(
14511451
"Failed to parse interval month day nano value"
14521452
)

datafusion/substrait/src/logical_plan/producer.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use datafusion::logical_expr::expr::{
4242
};
4343
use datafusion::logical_expr::{expr, Between, JoinConstraint, LogicalPlan, Operator};
4444
use datafusion::prelude::Expr;
45-
use prost_types::Any as ProtoAny;
45+
use pbjson_types::Any as ProtoAny;
4646
use substrait::proto::exchange_rel::{ExchangeKind, RoundRobin, ScatterFields};
4747
use substrait::proto::expression::literal::user_defined::Val;
4848
use substrait::proto::expression::literal::UserDefined;
@@ -487,7 +487,7 @@ pub fn to_substrait_rel(
487487
.serialize_logical_plan(extension_plan.node.as_ref())?;
488488
let detail = ProtoAny {
489489
type_url: extension_plan.node.name().to_string(),
490-
value: extension_bytes,
490+
value: extension_bytes.into(),
491491
};
492492
let mut inputs_rel = extension_plan
493493
.node
@@ -1802,7 +1802,7 @@ fn to_substrait_literal(value: &ScalarValue) -> Result<Literal> {
18021802
}],
18031803
val: Some(Val::Value(ProtoAny {
18041804
type_url: INTERVAL_YEAR_MONTH_TYPE_URL.to_string(),
1805-
value: bytes.to_vec(),
1805+
value: bytes.to_vec().into(),
18061806
})),
18071807
}),
18081808
INTERVAL_YEAR_MONTH_TYPE_REF,
@@ -1825,7 +1825,7 @@ fn to_substrait_literal(value: &ScalarValue) -> Result<Literal> {
18251825
type_parameters: vec![i64_param.clone(), i64_param],
18261826
val: Some(Val::Value(ProtoAny {
18271827
type_url: INTERVAL_MONTH_DAY_NANO_TYPE_URL.to_string(),
1828-
value: bytes.to_vec(),
1828+
value: bytes.to_vec().into(),
18291829
})),
18301830
}),
18311831
INTERVAL_MONTH_DAY_NANO_TYPE_REF,
@@ -1848,7 +1848,7 @@ fn to_substrait_literal(value: &ScalarValue) -> Result<Literal> {
18481848
}],
18491849
val: Some(Val::Value(ProtoAny {
18501850
type_url: INTERVAL_DAY_TIME_TYPE_URL.to_string(),
1851-
value: bytes.to_vec(),
1851+
value: bytes.to_vec().into(),
18521852
})),
18531853
}),
18541854
INTERVAL_DAY_TIME_TYPE_REF,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use datafusion::common::Result;
4+
use datafusion::prelude::{CsvReadOptions, SessionContext};
5+
use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
6+
use std::fs::File;
7+
use std::io::BufReader;
8+
use substrait::proto::Plan;
9+
10+
#[tokio::test]
11+
async fn function_compound_signature() -> Result<()> {
12+
// DataFusion currently produces Substrait that refers to functions only by their name.
13+
// However, the Substrait spec requires that functions be identified by their compound signature.
14+
// This test confirms that DataFusion is able to consume plans following the spec, even though
15+
// we don't yet produce such plans.
16+
// Once we start producing plans with compound signatures, this test can be replaced by the roundtrip tests.
17+
18+
let ctx = create_context().await?;
19+
20+
// File generated with substrait-java's Isthmus:
21+
// ./isthmus-cli/build/graal/isthmus "select not d from data" -c "create table data (d boolean)"
22+
let path = "tests/testdata/select_not_bool.substrait.json";
23+
let proto = serde_json::from_reader::<_, Plan>(BufReader::new(
24+
File::open(path).expect("file not found"),
25+
))
26+
.expect("failed to parse json");
27+
28+
let plan = from_substrait_plan(&ctx, &proto).await?;
29+
30+
assert_eq!(
31+
format!("{:?}", plan),
32+
"Projection: NOT DATA.a\
33+
\n TableScan: DATA projection=[a, b, c, d, e, f]"
34+
);
35+
Ok(())
36+
}
37+
38+
async fn create_context() -> datafusion::common::Result<SessionContext> {
39+
let ctx = SessionContext::new();
40+
ctx.register_csv("DATA", "tests/testdata/data.csv", CsvReadOptions::new())
41+
.await?;
42+
Ok(ctx)
43+
}
44+
}

datafusion/substrait/tests/cases/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
mod logical_plans;
1819
mod roundtrip_logical_plan;
1920
mod roundtrip_physical_plan;
2021
mod serialize;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"extensionUris": [
3+
{
4+
"extensionUriAnchor": 1,
5+
"uri": "/functions_boolean.yaml"
6+
}
7+
],
8+
"extensions": [
9+
{
10+
"extensionFunction": {
11+
"extensionUriReference": 1,
12+
"functionAnchor": 0,
13+
"name": "not:bool"
14+
}
15+
}
16+
],
17+
"relations": [
18+
{
19+
"root": {
20+
"input": {
21+
"project": {
22+
"common": {
23+
"emit": {
24+
"outputMapping": [
25+
1
26+
]
27+
}
28+
},
29+
"input": {
30+
"read": {
31+
"common": {
32+
"direct": {
33+
}
34+
},
35+
"baseSchema": {
36+
"names": [
37+
"D"
38+
],
39+
"struct": {
40+
"types": [
41+
{
42+
"bool": {
43+
"typeVariationReference": 0,
44+
"nullability": "NULLABILITY_NULLABLE"
45+
}
46+
}
47+
],
48+
"typeVariationReference": 0,
49+
"nullability": "NULLABILITY_REQUIRED"
50+
}
51+
},
52+
"namedTable": {
53+
"names": [
54+
"DATA"
55+
]
56+
}
57+
}
58+
},
59+
"expressions": [
60+
{
61+
"scalarFunction": {
62+
"functionReference": 0,
63+
"args": [],
64+
"outputType": {
65+
"bool": {
66+
"typeVariationReference": 0,
67+
"nullability": "NULLABILITY_NULLABLE"
68+
}
69+
},
70+
"arguments": [
71+
{
72+
"value": {
73+
"selection": {
74+
"directReference": {
75+
"structField": {
76+
"field": 0
77+
}
78+
},
79+
"rootReference": {
80+
}
81+
}
82+
}
83+
}
84+
],
85+
"options": []
86+
}
87+
}
88+
]
89+
}
90+
},
91+
"names": [
92+
"EXPR$0"
93+
]
94+
}
95+
}
96+
],
97+
"expectedTypeUrls": []
98+
}

0 commit comments

Comments
 (0)