88import static org .apache .calcite .sql .type .SqlTypeUtil .createArrayType ;
99import static org .opensearch .sql .calcite .utils .OpenSearchTypeFactory .*;
1010import static org .opensearch .sql .calcite .utils .OpenSearchTypeFactory .ExprUDT .*;
11- import static org .opensearch .sql .utils .DateTimeFormatters .DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL ;
1211
1312import java .time .Instant ;
14- import java .time .LocalDate ;
15- import java .time .LocalDateTime ;
1613import java .time .ZoneId ;
17- import java .time .format .DateTimeFormatter ;
18- import java .time .format .DateTimeParseException ;
1914import java .util .ArrayList ;
20- import java .util .Arrays ;
2115import java .util .Collections ;
2216import java .util .List ;
23- import java .util .Locale ;
24- import java .util .Objects ;
2517import java .util .TimeZone ;
2618import javax .annotation .Nullable ;
2719import org .apache .calcite .DataContext ;
4739import org .opensearch .sql .calcite .udf .UserDefinedAggFunction ;
4840import org .opensearch .sql .data .model .ExprValueUtils ;
4941import org .opensearch .sql .data .type .ExprType ;
50- import org .opensearch .sql .exception .SemanticCheckException ;
5142import org .opensearch .sql .executor .QueryType ;
5243import org .opensearch .sql .expression .function .FunctionProperties ;
5344import org .opensearch .sql .expression .function .ImplementorUDF ;
@@ -100,133 +91,6 @@ static SqlReturnTypeInference getReturnTypeInferenceForArray() {
10091 };
10192 }
10293
103- static List <Integer > transferStringExprToDateValue (String timeExpr ) {
104- try {
105- if (timeExpr .contains (":" )) {
106- // A timestamp
107- LocalDateTime localDateTime =
108- LocalDateTime .parse (timeExpr , DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL );
109- return List .of (
110- localDateTime .getYear (), localDateTime .getMonthValue (), localDateTime .getDayOfMonth ());
111- } else {
112- LocalDate localDate =
113- LocalDate .parse (timeExpr , DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL );
114- return List .of (localDate .getYear (), localDate .getMonthValue (), localDate .getDayOfMonth ());
115- }
116- } catch (DateTimeParseException e ) {
117- throw new SemanticCheckException (
118- String .format ("date:%s in unsupported format, please use 'yyyy-MM-dd'" , timeExpr ));
119- }
120- }
121-
122- /**
123- * Check whether a function gets enough arguments.
124- *
125- * @param funcName the name of the function
126- * @param expectedArguments the number of expected arguments
127- * @param actualArguments the number of actual arguments
128- * @param exactMatch whether the number of actual arguments should precisely match the number of
129- * expected arguments. If false, it suffices as long as the number of actual number of
130- * arguments is not smaller that the number of expected arguments.
131- * @throws IllegalArgumentException if the argument length does not match the expected one
132- */
133- public static void validateArgumentCount (
134- String funcName , int expectedArguments , int actualArguments , boolean exactMatch ) {
135- if (exactMatch ) {
136- if (actualArguments != expectedArguments ) {
137- throw new IllegalArgumentException (
138- String .format (
139- "Mismatch arguments: function %s expects %d arguments, but got %d" ,
140- funcName , expectedArguments , actualArguments ));
141- }
142- } else {
143- if (actualArguments < expectedArguments ) {
144- throw new IllegalArgumentException (
145- String .format (
146- "Mismatch arguments: function %s expects at least %d arguments, but got %d" ,
147- funcName , expectedArguments , actualArguments ));
148- }
149- }
150- }
151-
152- /**
153- * Validates that the given list of objects matches the given list of types.
154- *
155- * <p>This function first checks if the sizes of the two lists match. If not, it throws an {@code
156- * IllegalArgumentException}. Then, it iterates through the lists and checks if each object is an
157- * instance of the corresponding type. If any object is not of the expected type, it throws an
158- * {@code IllegalArgumentException} with a descriptive message.
159- *
160- * @param objects the list of objects to validate
161- * @param types the list of expected types
162- * @throws IllegalArgumentException if the sizes of the lists do not match or if any object is not
163- * an instance of the corresponding type
164- */
165- public static void validateArgumentTypes (List <Object > objects , List <Class <?>> types ) {
166- validateArgumentTypes (objects , types , Collections .nCopies (types .size (), false ));
167- }
168-
169- public static void validateArgumentTypes (
170- List <Object > objects , List <Class <?>> types , boolean nullable ) {
171- validateArgumentTypes (objects , types , Collections .nCopies (types .size (), nullable ));
172- }
173-
174- public static void validateArgumentTypes (
175- List <Object > objects , List <Class <?>> types , List <Boolean > nullables ) {
176- if (objects .size () < types .size ()) {
177- throw new IllegalArgumentException (
178- String .format (
179- "Mismatch in the number of objects and types. Got %d objects and %d types" ,
180- objects .size (), types .size ()));
181- }
182- for (int i = 0 ; i < types .size (); i ++) {
183- if (objects .get (i ) == null && nullables .get (i )) {
184- continue ;
185- }
186- if (!types .get (i ).isInstance (objects .get (i ))) {
187- throw new IllegalArgumentException (
188- String .format (
189- "Object at index %d is not of type %s (Got %s)" ,
190- i ,
191- types .get (i ).getName (),
192- objects .get (i ) == null ? "null" : objects .get (i ).getClass ().getName ()));
193- }
194- }
195- }
196-
197- /** Check whether the given array contains null values. */
198- public static boolean containsNull (Object [] objects ) {
199- return Arrays .stream (objects ).anyMatch (Objects ::isNull );
200- }
201-
202- public static String formatTimestampWithoutUnnecessaryNanos (LocalDateTime localDateTime ) {
203- String base = localDateTime .format (DateTimeFormatter .ofPattern ("yyyy-MM-dd HH:mm:ss" ));
204- int nano = localDateTime .getNano ();
205- if (nano == 0 ) return base ;
206-
207- String nanoStr = String .format (Locale .ENGLISH , "%09d" , nano );
208- nanoStr = nanoStr .replaceFirst ("0+$" , "" );
209- if (!nanoStr .isEmpty ()) {
210- return base + "." + nanoStr ;
211- }
212- return base ;
213- }
214-
215- public static SqlTypeName transferDateRelatedTimeName (RexNode candidate ) {
216- RelDataType type = candidate .getType ();
217- if (type instanceof ExprSqlType ) {
218- ExprUDT exprUDT = ((ExprSqlType ) type ).getUdt ();
219- if (exprUDT == EXPR_TIME ) {
220- return SqlTypeName .TIME ;
221- } else if (exprUDT == EXPR_TIMESTAMP ) {
222- return SqlTypeName .TIMESTAMP ;
223- } else if (exprUDT == EXPR_DATE ) {
224- return SqlTypeName .DATE ;
225- }
226- }
227- return type .getSqlTypeName ();
228- }
229-
23094 public static SqlTypeName convertRelDataTypeToSqlTypeName (RelDataType type ) {
23195 if (type instanceof ExprSqlType exprSqlType ) {
23296 return switch (exprSqlType .getUdt ()) {
@@ -239,7 +103,6 @@ public static SqlTypeName convertRelDataTypeToSqlTypeName(RelDataType type) {
239103 return type .getSqlTypeName ();
240104 }
241105
242- // TODO: pass the function properties directly to the UDF instead of string
243106 public static FunctionProperties restoreFunctionProperties (DataContext dataContext ) {
244107 long currentTimeInNanos = DataContext .Variable .UTC_TIMESTAMP .get (dataContext );
245108 Instant instant =
0 commit comments