1
1
package io .substrait .isthmus ;
2
2
3
3
import static org .junit .jupiter .api .Assertions .assertEquals ;
4
+ import static org .junit .jupiter .api .Assertions .assertInstanceOf ;
5
+ import static org .junit .jupiter .api .Assertions .assertTrue ;
4
6
5
7
import io .substrait .dsl .SubstraitBuilder ;
8
+ import io .substrait .expression .Expression ;
6
9
import io .substrait .isthmus .expression .ExpressionRexConverter ;
7
- import io .substrait .isthmus .expression .ScalarFunctionConverter ;
8
- import io .substrait .isthmus .expression .WindowFunctionConverter ;
9
10
import io .substrait .relation .Rel ;
11
+ import io .substrait .relation .Rel .Remap ;
10
12
import io .substrait .type .Type ;
11
13
import io .substrait .type .TypeCreator ;
12
14
import java .util .List ;
15
+ import org .apache .calcite .rel .RelNode ;
13
16
import org .apache .calcite .rel .type .RelDataType ;
17
+ import org .apache .calcite .rex .RexNode ;
18
+ import org .apache .calcite .rex .RexSubQuery ;
19
+ import org .apache .calcite .sql .SqlKind ;
14
20
import org .junit .jupiter .api .Test ;
15
21
16
22
public class SubstraitExpressionConverterTest extends PlanTestBase {
@@ -20,17 +26,19 @@ public class SubstraitExpressionConverterTest extends PlanTestBase {
20
26
21
27
final SubstraitBuilder b = new SubstraitBuilder (extensions );
22
28
23
- final ExpressionRexConverter converter =
24
- new ExpressionRexConverter (
25
- typeFactory ,
26
- new ScalarFunctionConverter (extensions .scalarFunctions (), typeFactory ),
27
- new WindowFunctionConverter (extensions .windowFunctions (), typeFactory ),
28
- TypeConverter .DEFAULT );
29
+ final ExpressionRexConverter converter ;
29
30
30
31
final List <Type > commonTableType = List .of (R .I32 , R .FP32 , N .STRING , N .BOOLEAN );
31
32
final Rel commonTable =
32
33
b .namedScan (List .of ("example" ), List .of ("a" , "b" , "c" , "d" ), commonTableType );
33
34
35
+ final SubstraitRelNodeConverter relNodeConverter =
36
+ new SubstraitRelNodeConverter (extensions , typeFactory , builder );
37
+
38
+ public SubstraitExpressionConverterTest () {
39
+ converter = relNodeConverter .expressionRexConverter ;
40
+ }
41
+
34
42
@ Test
35
43
public void switchExpression () {
36
44
var expr =
@@ -43,6 +51,54 @@ public void switchExpression() {
43
51
assertTypeMatch (calciteExpr .getType (), N .BOOLEAN );
44
52
}
45
53
54
+ @ Test
55
+ public void scalarSubQuery () {
56
+ /*
57
+ * equivalent to:
58
+ *
59
+ * select
60
+ * r_regionkey
61
+ * from
62
+ * region
63
+ * where
64
+ * r_name = 'EUROPE'
65
+ */
66
+ Rel subQueryRel =
67
+ b .project (
68
+ input -> {
69
+ return List .of (b .fieldReference (input , 0 ));
70
+ },
71
+ // currently, all columns of the input are emitted first and then the expressions of
72
+ // this project unless remap is configured
73
+ Remap .of (List .of (3 )),
74
+ b .filter (
75
+ input -> {
76
+ return b .equal (
77
+ b .fieldReference (input , 1 ),
78
+ Expression .StrLiteral .builder ().nullable (false ).value ("EUROPE" ).build ());
79
+ },
80
+ b .namedScan (
81
+ List .of ("REGION" ),
82
+ List .of ("r_regionkey" , "r_name" , "r_comment" ),
83
+ List .of (
84
+ TypeCreator .REQUIRED .I64 ,
85
+ TypeCreator .NULLABLE .fixedChar (25 ),
86
+ TypeCreator .NULLABLE .varChar (152 )))));
87
+
88
+ Expression .ScalarSubquery expr =
89
+ Expression .ScalarSubquery .builder ()
90
+ .type (TypeCreator .REQUIRED .I64 )
91
+ .input (subQueryRel )
92
+ .build ();
93
+
94
+ RexNode calciteExpr = expr .accept (converter );
95
+ assertEquals (SqlKind .SCALAR_QUERY , calciteExpr .getKind ());
96
+ assertInstanceOf (RexSubQuery .class , calciteExpr );
97
+
98
+ RelNode subQueryRelNode = subQueryRel .accept (relNodeConverter );
99
+ assertTrue (subQueryRelNode .deepEquals (((RexSubQuery ) calciteExpr ).rel ));
100
+ }
101
+
46
102
void assertTypeMatch (RelDataType actual , Type expected ) {
47
103
Type type = TypeConverter .DEFAULT .toSubstrait (actual );
48
104
assertEquals (expected , type );
0 commit comments