1+ /*
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+ package org .apache .wayang .api .sql .calcite .converter .functions ;
19+
20+ import java .io .Serializable ;
21+ import java .util .List ;
22+ import java .util .stream .Collectors ;
23+
24+ import org .apache .calcite .rex .RexCall ;
25+ import org .apache .calcite .rex .RexInputRef ;
26+ import org .apache .calcite .rex .RexLiteral ;
27+ import org .apache .calcite .rex .RexNode ;
28+ import org .apache .calcite .sql .SqlKind ;
29+
30+ import org .apache .wayang .basic .data .Record ;
31+ import org .apache .wayang .core .function .FunctionDescriptor .SerializableFunction ;
32+
33+ /**
34+ * AST of the {@link RexCall} arithmetic, composed into serializable nodes;
35+ * {@link Call}, {@link InputRef}, {@link Literal}
36+ */
37+ interface CallTreeFactory <Input , Output > extends Serializable {
38+ public default Node <Output > fromRexNode (final RexNode node ) {
39+ if (node instanceof RexCall ) {
40+ return new Call <>((RexCall ) node , this );
41+ } else if (node instanceof RexInputRef ) {
42+ return new InputRef <>((RexInputRef ) node );
43+ } else if (node instanceof RexLiteral ) {
44+ return new Literal <>((RexLiteral ) node );
45+ } else {
46+ throw new UnsupportedOperationException ("Unsupported RexNode in filter condition: " + node );
47+ }
48+ }
49+
50+ /**
51+ * Derives the java operator for a given {@link SqlKind}, and turns it into a
52+ * serializable function
53+ *
54+ * @param kind {@link SqlKind} from {@link RexCall} SqlOperator
55+ * @return a serializable function of +, -, * or /
56+ * @throws UnsupportedOperationException on unrecognized {@link SqlKind}
57+ */
58+ public SerializableFunction <List <Output >, Output > deriveOperation (SqlKind kind );
59+ }
60+
61+ interface Node <Output > extends Serializable {
62+ public Output evaluate (final Record record );
63+ }
64+
65+ class Call <Input , Output > implements Node <Output > {
66+ final List <Node <Output >> operands ;
67+ final SerializableFunction <List <Output >, Output > operation ;
68+
69+ protected Call (final RexCall call , final CallTreeFactory <Input , Output > tree ) {
70+ operands = call .getOperands ().stream ().map (tree ::fromRexNode ).collect (Collectors .toList ());
71+ operation = tree .deriveOperation (call .getKind ());
72+ }
73+
74+ @ Override
75+ public Output evaluate (final Record record ) {
76+ return operation .apply (operands .stream ().map (op -> op .evaluate (record )).collect (Collectors .toList ()));
77+ }
78+ }
79+
80+ class Literal <Output > implements Node <Output > {
81+ final Output value ;
82+
83+ Literal (final RexLiteral literal ) {
84+ value = (Output ) literal .getValue2 ();
85+ }
86+
87+ @ Override
88+ public Output evaluate (final Record record ) {
89+ return value ;
90+ }
91+ }
92+
93+ class InputRef <Output > implements Node <Output > {
94+ private final int key ;
95+
96+ InputRef (final RexInputRef inputRef ) {
97+ this .key = inputRef .getIndex ();
98+ }
99+
100+ @ Override
101+ public Output evaluate (final Record record ) {
102+ return (Output ) record .getField (key );
103+ }
104+ }
0 commit comments