@@ -12,8 +12,119 @@ use crate::parse::expressions;
12
12
use crate :: parse:: extensions;
13
13
use crate :: parse:: sorts;
14
14
use crate :: parse:: types;
15
+ use crate :: util;
16
+ use crate :: util:: string:: Describe ;
15
17
use std:: sync:: Arc ;
16
18
19
+ /// A function argument; either a value, a type, or an enum option.
20
+ #[ derive( Clone , Debug , PartialEq ) ]
21
+ pub enum FunctionArgument {
22
+ /// Used for value arguments or normal expressions.
23
+ Value ( expressions:: Expression ) ,
24
+
25
+ /// Used for type arguments.
26
+ Type ( Arc < data_type:: DataType > ) ,
27
+
28
+ /// Used for enum option arguments.
29
+ Enum ( Option < String > ) ,
30
+ }
31
+
32
+ impl Default for FunctionArgument {
33
+ fn default ( ) -> Self {
34
+ FunctionArgument :: Value ( expressions:: Expression :: default ( ) )
35
+ }
36
+ }
37
+
38
+ impl From < expressions:: Expression > for FunctionArgument {
39
+ fn from ( expr : expressions:: Expression ) -> Self {
40
+ FunctionArgument :: Value ( expr)
41
+ }
42
+ }
43
+
44
+ impl Describe for FunctionArgument {
45
+ fn describe (
46
+ & self ,
47
+ f : & mut std:: fmt:: Formatter < ' _ > ,
48
+ limit : util:: string:: Limit ,
49
+ ) -> std:: fmt:: Result {
50
+ match self {
51
+ FunctionArgument :: Value ( e) => e. describe ( f, limit) ,
52
+ FunctionArgument :: Type ( e) => e. describe ( f, limit) ,
53
+ FunctionArgument :: Enum ( Some ( x) ) => util:: string:: describe_identifier ( f, x, limit) ,
54
+ FunctionArgument :: Enum ( None ) => write ! ( f, "-" ) ,
55
+ }
56
+ }
57
+ }
58
+
59
+ impl std:: fmt:: Display for FunctionArgument {
60
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
61
+ self . display ( ) . fmt ( f)
62
+ }
63
+ }
64
+
65
+ /// Parse an enum option argument type.
66
+ fn parse_enum_type (
67
+ x : & substrait:: function_argument:: r#enum:: EnumKind ,
68
+ _y : & mut context:: Context ,
69
+ ) -> diagnostic:: Result < Option < String > > {
70
+ match x {
71
+ substrait:: function_argument:: r#enum:: EnumKind :: Specified ( x) => Ok ( Some ( x. clone ( ) ) ) ,
72
+ substrait:: function_argument:: r#enum:: EnumKind :: Unspecified ( _) => Ok ( None ) ,
73
+ }
74
+ }
75
+
76
+ /// Parse an enum option argument.
77
+ fn parse_enum (
78
+ x : & substrait:: function_argument:: Enum ,
79
+ y : & mut context:: Context ,
80
+ ) -> diagnostic:: Result < Option < String > > {
81
+ Ok ( proto_required_field ! ( x, y, enum_kind, parse_enum_type)
82
+ . 1
83
+ . flatten ( ) )
84
+ }
85
+
86
+ /// Parse a 0.3.0+ function argument type.
87
+ fn parse_function_argument_type (
88
+ x : & substrait:: function_argument:: ArgType ,
89
+ y : & mut context:: Context ,
90
+ ) -> diagnostic:: Result < FunctionArgument > {
91
+ match x {
92
+ substrait:: function_argument:: ArgType :: Enum ( x) => {
93
+ Ok ( FunctionArgument :: Enum ( parse_enum ( x, y) ?) )
94
+ }
95
+ substrait:: function_argument:: ArgType :: Type ( x) => {
96
+ types:: parse_type ( x, y) ?;
97
+ Ok ( FunctionArgument :: Type ( y. data_type ( ) ) )
98
+ }
99
+ substrait:: function_argument:: ArgType :: Value ( x) => Ok ( FunctionArgument :: Value (
100
+ expressions:: parse_expression ( x, y) ?,
101
+ ) ) ,
102
+ }
103
+ }
104
+
105
+ /// Parse a 0.3.0+ function argument.
106
+ fn parse_function_argument (
107
+ x : & substrait:: FunctionArgument ,
108
+ y : & mut context:: Context ,
109
+ ) -> diagnostic:: Result < FunctionArgument > {
110
+ Ok (
111
+ proto_required_field ! ( x, y, arg_type, parse_function_argument_type)
112
+ . 1
113
+ . unwrap_or_default ( ) ,
114
+ )
115
+ }
116
+
117
+ /// Parse a pre-0.3.0 function argument expression.
118
+ fn parse_legacy_function_argument (
119
+ x : & substrait:: Expression ,
120
+ y : & mut context:: Context ,
121
+ ) -> diagnostic:: Result < FunctionArgument > {
122
+ expressions:: parse_legacy_function_argument ( x, y) . map ( |x| match x {
123
+ expressions:: ExpressionOrEnum :: Value ( x) => FunctionArgument :: Value ( x) ,
124
+ expressions:: ExpressionOrEnum :: Enum ( x) => FunctionArgument :: Enum ( x) ,
125
+ } )
126
+ }
127
+
17
128
/// Matches a function call with its YAML definition, yielding its return type.
18
129
/// Yields an unresolved type if resolution fails.
19
130
pub fn check_function (
@@ -41,7 +152,8 @@ pub fn check_function(
41
152
fn parse_function (
42
153
y : & mut context:: Context ,
43
154
function : Option < Arc < extension:: Reference < extension:: Function > > > ,
44
- arguments : ( Vec < Arc < tree:: Node > > , Vec < Option < expressions:: Expression > > ) ,
155
+ arguments : ( Vec < Arc < tree:: Node > > , Vec < Option < FunctionArgument > > ) ,
156
+ legacy_arguments : ( Vec < Arc < tree:: Node > > , Vec < Option < FunctionArgument > > ) ,
45
157
return_type : Arc < data_type:: DataType > ,
46
158
) -> ( Arc < data_type:: DataType > , expressions:: Expression ) {
47
159
// Determine the name of the function.
@@ -50,6 +162,36 @@ fn parse_function(
50
162
. map ( |x| x. name . to_string ( ) )
51
163
. unwrap_or_else ( || String :: from ( "?" ) ) ;
52
164
165
+ // Reconcile v3.0.0+ vs older function argument syntax.
166
+ let arguments = if legacy_arguments. 1 . is_empty ( ) {
167
+ arguments
168
+ } else if arguments. 1 . is_empty ( ) {
169
+ diagnostic ! (
170
+ y,
171
+ Warning ,
172
+ Deprecation ,
173
+ "the args field for specifying function arguments was deprecated Substrait 0.3.0 (#161)"
174
+ ) ;
175
+ legacy_arguments
176
+ } else {
177
+ if arguments != legacy_arguments {
178
+ diagnostic ! (
179
+ y,
180
+ Error ,
181
+ IllegalValue ,
182
+ "mismatch between v0.3+ and legacy function argument specification"
183
+ ) ;
184
+ comment ! (
185
+ y,
186
+ "If both the v0.3+ and legacy syntax is used to specify function \
187
+ arguments, please make sure both map to the same arguments. If \
188
+ the argument pack is not representable using the legacy syntax, \
189
+ do not use it."
190
+ ) ;
191
+ }
192
+ arguments
193
+ } ;
194
+
53
195
// Unpack the arguments into the function's enum options and regular
54
196
// arguments.
55
197
let mut opt_values = vec ! [ ] ;
@@ -61,7 +203,7 @@ fn parse_function(
61
203
. into_iter ( )
62
204
. zip ( arguments. 1 . into_iter ( ) . map ( |x| x. unwrap_or_default ( ) ) )
63
205
{
64
- if let expressions :: Expression :: EnumVariant ( x) = & expr {
206
+ if let FunctionArgument :: Enum ( x) = & expr {
65
207
if opt_exprs. is_empty ( ) && !arg_exprs. is_empty ( ) {
66
208
diagnostic ! (
67
209
y,
@@ -122,13 +264,16 @@ pub fn parse_scalar_function(
122
264
extensions:: simple:: parse_function_reference
123
265
)
124
266
. 1 ;
125
- let arguments = proto_repeated_field ! ( x, y, args, expressions:: parse_function_argument) ;
267
+ #[ allow( deprecated) ]
268
+ let legacy_arguments = proto_repeated_field ! ( x, y, args, parse_legacy_function_argument) ;
269
+ let arguments = proto_repeated_field ! ( x, y, arguments, parse_function_argument) ;
126
270
let return_type = proto_required_field ! ( x, y, output_type, types:: parse_type)
127
271
. 0
128
272
. data_type ( ) ;
129
273
130
274
// Check function information.
131
- let ( return_type, expression) = parse_function ( y, function, arguments, return_type) ;
275
+ let ( return_type, expression) =
276
+ parse_function ( y, function, arguments, legacy_arguments, return_type) ;
132
277
133
278
// Describe node.
134
279
y. set_data_type ( return_type) ;
@@ -168,13 +313,16 @@ pub fn parse_window_function(
168
313
extensions:: simple:: parse_function_reference
169
314
)
170
315
. 1 ;
171
- let arguments = proto_repeated_field ! ( x, y, args, expressions:: parse_function_argument) ;
316
+ #[ allow( deprecated) ]
317
+ let legacy_arguments = proto_repeated_field ! ( x, y, args, parse_legacy_function_argument) ;
318
+ let arguments = proto_repeated_field ! ( x, y, arguments, parse_function_argument) ;
172
319
let return_type = proto_required_field ! ( x, y, output_type, types:: parse_type)
173
320
. 0
174
321
. data_type ( ) ;
175
322
176
323
// Check function information.
177
- let ( return_type, expression) = parse_function ( y, function, arguments, return_type) ;
324
+ let ( return_type, expression) =
325
+ parse_function ( y, function, arguments, legacy_arguments, return_type) ;
178
326
179
327
// Parse modifiers.
180
328
proto_repeated_field ! ( x, y, partitions, expressions:: parse_expression) ;
@@ -216,13 +364,16 @@ pub fn parse_aggregate_function(
216
364
extensions:: simple:: parse_function_reference
217
365
)
218
366
. 1 ;
219
- let arguments = proto_repeated_field ! ( x, y, args, expressions:: parse_function_argument) ;
367
+ #[ allow( deprecated) ]
368
+ let legacy_arguments = proto_repeated_field ! ( x, y, args, parse_legacy_function_argument) ;
369
+ let arguments = proto_repeated_field ! ( x, y, arguments, parse_function_argument) ;
220
370
let return_type = proto_required_field ! ( x, y, output_type, types:: parse_type)
221
371
. 0
222
372
. data_type ( ) ;
223
373
224
374
// Check function information.
225
- let ( return_type, expression) = parse_function ( y, function, arguments, return_type) ;
375
+ let ( return_type, expression) =
376
+ parse_function ( y, function, arguments, legacy_arguments, return_type) ;
226
377
227
378
// Parse modifiers.
228
379
proto_repeated_field ! ( x, y, sorts, sorts:: parse_sort_field) ;
0 commit comments