2020import org .elasticsearch .xpack .sql .expression .function .aggregate .Sum ;
2121import org .elasticsearch .xpack .sql .expression .function .aggregate .SumOfSquares ;
2222import org .elasticsearch .xpack .sql .expression .function .aggregate .VarPop ;
23+ import org .elasticsearch .xpack .sql .expression .function .scalar .Cast ;
2324import org .elasticsearch .xpack .sql .expression .function .scalar .datetime .DayName ;
2425import org .elasticsearch .xpack .sql .expression .function .scalar .datetime .DayOfMonth ;
2526import org .elasticsearch .xpack .sql .expression .function .scalar .datetime .DayOfWeek ;
8485import org .elasticsearch .xpack .sql .expression .predicate .operator .arithmetic .Mod ;
8586import org .elasticsearch .xpack .sql .parser .ParsingException ;
8687import org .elasticsearch .xpack .sql .tree .Location ;
88+ import org .elasticsearch .xpack .sql .type .DataType ;
8789import org .elasticsearch .xpack .sql .util .StringUtils ;
8890
8991import java .util .Arrays ;
@@ -116,14 +118,14 @@ public class FunctionRegistry {
116118 public FunctionRegistry () {
117119 defineDefaultFunctions ();
118120 }
119-
121+
120122 /**
121123 * Constructor specifying alternate functions for testing.
122124 */
123125 FunctionRegistry (FunctionDefinition ... functions ) {
124126 addToMap (functions );
125127 }
126-
128+
127129 private void defineDefaultFunctions () {
128130 // Aggregate functions
129131 addToMap (def (Avg .class , Avg ::new ),
@@ -206,11 +208,13 @@ private void defineDefaultFunctions() {
206208 def (Space .class , Space ::new ),
207209 def (Substring .class , Substring ::new ),
208210 def (UCase .class , UCase ::new ));
211+ // DataType conversion
212+ addToMap (def (Cast .class , Cast ::new , "CONVERT" ));
209213 // Special
210214 addToMap (def (Score .class , Score ::new ));
211215 }
212-
213- protected void addToMap (FunctionDefinition ...functions ) {
216+
217+ void addToMap (FunctionDefinition ...functions ) {
214218 // temporary map to hold [function_name/alias_name : function instance]
215219 Map <String , FunctionDefinition > batchMap = new HashMap <>();
216220 for (FunctionDefinition f : functions ) {
@@ -227,7 +231,7 @@ protected void addToMap(FunctionDefinition...functions) {
227231 // sort the temporary map by key name and add it to the global map of functions
228232 defs .putAll (batchMap .entrySet ().stream ()
229233 .sorted (Map .Entry .comparingByKey ())
230- .collect (Collectors .<Entry <String , FunctionDefinition >, String ,
234+ .collect (Collectors .<Entry <String , FunctionDefinition >, String ,
231235 FunctionDefinition , LinkedHashMap <String , FunctionDefinition >> toMap (Map .Entry ::getKey , Map .Entry ::getValue ,
232236 (oldValue , newValue ) -> oldValue , LinkedHashMap ::new )));
233237 }
@@ -390,7 +394,7 @@ private static FunctionDefinition def(Class<? extends Function> function, Functi
390394 private interface FunctionBuilder {
391395 Function build (Location location , List <Expression > children , boolean distinct , TimeZone tz );
392396 }
393-
397+
394398 @ SuppressWarnings ("overloads" ) // These are ambiguous if you aren't using ctor references but we always do
395399 static <T extends Function > FunctionDefinition def (Class <T > function ,
396400 ThreeParametersFunctionBuilder <T > ctorRef , String ... aliases ) {
@@ -408,11 +412,11 @@ static <T extends Function> FunctionDefinition def(Class<T> function,
408412 };
409413 return def (function , builder , false , aliases );
410414 }
411-
415+
412416 interface ThreeParametersFunctionBuilder <T > {
413417 T build (Location location , Expression source , Expression exp1 , Expression exp2 );
414418 }
415-
419+
416420 @ SuppressWarnings ("overloads" ) // These are ambiguous if you aren't using ctor references but we always do
417421 static <T extends Function > FunctionDefinition def (Class <T > function ,
418422 FourParametersFunctionBuilder <T > ctorRef , String ... aliases ) {
@@ -427,11 +431,29 @@ static <T extends Function> FunctionDefinition def(Class<T> function,
427431 };
428432 return def (function , builder , false , aliases );
429433 }
430-
434+
431435 interface FourParametersFunctionBuilder <T > {
432436 T build (Location location , Expression source , Expression exp1 , Expression exp2 , Expression exp3 );
433437 }
434438
439+ /**
440+ * Special method to create function definition for {@link Cast} as its
441+ * signature is not compatible with {@link UnresolvedFunction}
442+ *
443+ * @return Cast function definition
444+ */
445+ @ SuppressWarnings ("overloads" ) // These are ambiguous if you aren't using ctor references but we always do
446+ private static <T extends Function > FunctionDefinition def (Class <T > function ,
447+ CastFunctionBuilder <T > ctorRef ,
448+ String ... aliases ) {
449+ FunctionBuilder builder = (location , children , distinct , tz ) ->
450+ ctorRef .build (location , children .get (0 ), children .get (0 ).dataType ());
451+ return def (function , builder , false , aliases );
452+ }
453+ private interface CastFunctionBuilder <T > {
454+ T build (Location location , Expression expression , DataType dataType );
455+ }
456+
435457 private static String normalize (String name ) {
436458 // translate CamelCase to camel_case
437459 return StringUtils .camelCaseToUnderscore (name );
0 commit comments