OmniSciDB  c1a53651b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExtensionFunction.java
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.mapd.parser.server;
18 
19 import org.apache.calcite.sql.type.SqlTypeFamily;
20 import org.apache.calcite.sql.type.SqlTypeName;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 
24 import java.util.ArrayList;
25 import java.util.EnumSet;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 public class ExtensionFunction {
32  final static Logger HEAVYDBLOGGER = LoggerFactory.getLogger(ExtensionFunction.class);
33 
34  public enum ExtArgumentType {
103  }
104  ;
105 
106  ExtensionFunction(final List<ExtArgumentType> args,
107  final ExtArgumentType ret,
108  final List<Map<String, String>> annotations) {
109  this.args = args;
110  this.ret = ret;
111  this.annotations = annotations;
112  this.outs = null;
113  this.names = null;
114  this.isRowUdf = true;
115  this.options = null;
116  this.cursor_field_types = null;
117  }
118 
119  ExtensionFunction(final List<ExtArgumentType> args,
120  final List<ExtArgumentType> outs,
121  final List<String> names,
122  final Map<String, String> options,
123  final Map<String, List<ExtArgumentType>> cursor_field_types) {
124  this.args = args;
125  this.ret = null;
126  this.outs = outs;
127  this.names = names;
128  this.isRowUdf = false;
129  this.annotations = null;
130  this.options = options;
131  this.cursor_field_types = cursor_field_types;
132  }
133 
134  public Map<String, List<ExtArgumentType>> getCursorFieldTypes() {
135  assert (this.isTableUdf());
136  return this.cursor_field_types;
137  }
138 
139  public List<ExtArgumentType> getArgs() {
140  return this.args;
141  }
142 
143  public List<ExtArgumentType> getOuts() {
144  return this.outs;
145  }
146 
147  public List<String> getArgNames() {
148  if (this.names != null) {
149  return this.names.subList(0, this.args.size());
150  }
151  return null;
152  }
153 
154  public List<String> getPrettyArgNames() {
155  if (this.names != null) {
156  List<String> pretty_names = new ArrayList<String>();
157  for (int arg_idx = 0; arg_idx < this.args.size(); ++arg_idx) {
158  // Split on first array opening bracket and take everything preceding
159  // For names without array brackets this will just be the name
160  pretty_names.add(this.names.get(arg_idx).split("\\[", 2)[0]);
161  }
162  return pretty_names;
163  }
164  return null;
165  }
166 
167  public List<String> getOutNames() {
168  if (this.names != null) {
169  return this.names.subList(this.args.size(), this.names.size());
170  }
171  return null;
172  }
173 
175  return this.ret;
176  }
177 
178  public SqlTypeName getSqlRet() {
179  assert this.isRowUdf();
180  return toSqlTypeName(this.ret);
181  }
182 
183  public Map<String, String> getOptions() {
184  if (this.options != null) {
185  return new HashMap<String, String>(this.options);
186  }
187  return null;
188  }
189 
190  public boolean isRowUdf() {
191  return this.isRowUdf;
192  }
193 
194  public boolean isTableUdf() {
195  return !this.isRowUdf();
196  }
197 
198  public String toJson(final String name) {
199  HEAVYDBLOGGER.debug("Extensionfunction::toJson: " + name);
200  StringBuilder json_cons = new StringBuilder();
201  json_cons.append("{");
202  json_cons.append("\"name\":").append(dq(name)).append(",");
203  if (isRowUdf) {
204  json_cons.append("\"annotations\":");
205  List<String> anns = new ArrayList<String>();
206  for (final Map<String, String> m : this.annotations) {
207  List<String> lst = new ArrayList<String>();
208  for (final Map.Entry<String, String> kv : m.entrySet()) {
209  lst.add("\"" + kv.getKey() + "\":\"" + kv.getValue() + "\"");
210  }
211  anns.add("{" + ExtensionFunctionSignatureParser.join(lst, ",") + "}");
212  }
213  json_cons.append("[" + ExtensionFunctionSignatureParser.join(anns, ",") + "],");
214  json_cons.append("\"ret\":").append(dq(typeName(ret))).append(",");
215  } else {
216  json_cons.append("\"outs\":");
217  json_cons.append("[");
218  List<String> param_list = new ArrayList<String>();
219  for (final ExtArgumentType out : outs) {
220  param_list.add(dq(typeName(out)));
221  }
222  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
223  json_cons.append("],");
224  }
225  json_cons.append("\"args\":");
226  json_cons.append("[");
227  List<String> param_list = new ArrayList<String>();
228  for (final ExtArgumentType arg : args) {
229  param_list.add(dq(typeName(arg)));
230  }
231  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
232  json_cons.append("]");
233  json_cons.append("}");
234  return json_cons.toString();
235  }
236 
237  private static String typeName(final ExtArgumentType type) {
238  switch (type) {
239  case Bool:
240  return "i1";
241  case Int8:
242  return "i8";
243  case Int16:
244  return "i16";
245  case Int32:
246  return "i32";
247  case Int64:
248  return "i64";
249  case Float:
250  return "float";
251  case Double:
252  return "double";
253  case Void:
254  return "void";
255  case PInt8:
256  return "i8*";
257  case PInt16:
258  return "i16*";
259  case PInt32:
260  return "i32*";
261  case PInt64:
262  return "i64*";
263  case PFloat:
264  return "float*";
265  case PDouble:
266  return "double*";
267  case PBool:
268  return "i1*";
269  case ArrayInt8:
270  return "Array<i8>";
271  case ArrayInt16:
272  return "Array<i16>";
273  case ArrayInt32:
274  return "Array<i32>";
275  case ArrayInt64:
276  return "Array<i64>";
277  case ArrayFloat:
278  return "Array<float>";
279  case ArrayDouble:
280  return "Array<double>";
281  case ArrayBool:
282  return "Array<bool>";
284  return "Array<TextEncodingDict>";
285  case ColumnInt8:
286  return "Column<i8>";
287  case ColumnInt16:
288  return "Column<i16>";
289  case ColumnInt32:
290  return "Column<i32>";
291  case ColumnInt64:
292  return "Column<i64>";
293  case ColumnFloat:
294  return "Column<float>";
295  case ColumnDouble:
296  return "Column<double>";
297  case ColumnBool:
298  return "Column<bool>";
300  return "Column<TextEncodingDict>";
301  case ColumnTimestamp:
302  return "Column<timestamp>";
303  case GeoPoint:
304  return "geo_point";
305  case GeoMultiPoint:
306  return "geo_multi_point";
307  case Cursor:
308  return "cursor";
309  case GeoLineString:
310  return "geo_linestring";
311  case GeoMultiLineString:
312  return "geo_multi_linestring";
313  case GeoPolygon:
314  return "geo_polygon";
315  case GeoMultiPolygon:
316  return "geo_multi_polygon";
317  case Timestamp:
318  return "timestamp";
319  case TextEncodingNone:
320  return "TextEncodingNone";
321  case TextEncodingDict:
322  return "TextEncodingDict";
323  case ColumnListInt8:
324  return "ColumnList<i8>";
325  case ColumnListInt16:
326  return "ColumnList<i16>";
327  case ColumnListInt32:
328  return "ColumnList<i32>";
329  case ColumnListInt64:
330  return "ColumnList<i64>";
331  case ColumnListFloat:
332  return "ColumnList<float>";
333  case ColumnListDouble:
334  return "ColumnList<double>";
335  case ColumnListBool:
336  return "ColumnList<bool>";
338  return "ColumnList<TextEncodingDict>";
339  case ColumnArrayInt8:
340  return "Column<Array<i8>>";
341  case ColumnArrayInt16:
342  return "Column<Array<i16>>";
343  case ColumnArrayInt32:
344  return "Column<Array<i32>>";
345  case ColumnArrayInt64:
346  return "Column<Array<i64>>";
347  case ColumnArrayFloat:
348  return "Column<Array<float>>";
349  case ColumnArrayDouble:
350  return "Column<Array<double>>";
351  case ColumnArrayBool:
352  return "Column<Array<bool>>";
354  return "Column<Array<TextEncodingDict>>";
355  case ColumnListArrayInt8:
356  return "ColumnList<Array<i8>>";
358  return "ColumnList<Array<i16>>";
360  return "ColumnList<Array<i32>>";
362  return "ColumnList<Array<i64>>";
364  return "ColumnList<Array<float>>";
366  return "ColumnList<Array<double>>";
367  case ColumnListArrayBool:
368  return "ColumnList<Array<bool>>";
370  return "ColumnList<Array<TextEncodingDict>>";
371  case DayTimeInterval:
372  return "DayTimeInterval";
374  return "YearMonthTimeInterval";
375  }
376  HEAVYDBLOGGER.info("Extensionfunction::typeName: unknown type=`" + type + "`");
377  assert false;
378  return null;
379  }
380 
381  private static String dq(final String str) {
382  return "\"" + str + "\"";
383  }
384 
385  private final List<ExtArgumentType> args;
386  private final List<ExtArgumentType> outs; // only used by UDTFs
387  private final List<String> names;
388  private final ExtArgumentType ret; // only used by UDFs
389  private final boolean isRowUdf;
390  private final List<Map<String, String>> annotations; // only used by UDFs atm
391  private final Map<String, String> options;
392  private final Map<String, List<ExtArgumentType>>
393  cursor_field_types; // only used by UDTFs
394 
395  public final java.util.List<SqlTypeFamily> toSqlSignature() {
396  java.util.List<SqlTypeFamily> sql_sig = new java.util.ArrayList<SqlTypeFamily>();
397  boolean isRowUdf = this.isRowUdf();
398  for (int arg_idx = 0; arg_idx < this.getArgs().size(); ++arg_idx) {
399  final ExtArgumentType arg_type = this.getArgs().get(arg_idx);
400  if (isRowUdf) {
401  sql_sig.add(toSqlTypeName(arg_type).getFamily());
402  if (isPointerType(arg_type)) {
403  ++arg_idx;
404  }
405  } else {
406  sql_sig.add(toSqlTypeName(arg_type).getFamily());
407  }
408  }
409  return sql_sig;
410  }
411 
412  public static boolean isPointerType(final ExtArgumentType type) {
413  return type == ExtArgumentType.PInt8 || type == ExtArgumentType.PInt16
414  || type == ExtArgumentType.PInt32 || type == ExtArgumentType.PInt64
415  || type == ExtArgumentType.PFloat || type == ExtArgumentType.PDouble
416  || type == ExtArgumentType.PBool;
417  }
418 
419  public static boolean isColumnArrayType(final ExtArgumentType type) {
420  return type == ExtArgumentType.ColumnArrayInt8
421  || type == ExtArgumentType.ColumnArrayInt16
422  || type == ExtArgumentType.ColumnArrayInt32
423  || type == ExtArgumentType.ColumnArrayInt64
424  || type == ExtArgumentType.ColumnArrayFloat
425  || type == ExtArgumentType.ColumnArrayDouble
426  || type == ExtArgumentType.ColumnArrayBool
428  }
429 
430  public static boolean isArrayType(final ExtArgumentType type) {
431  return type == ExtArgumentType.ArrayInt8 || type == ExtArgumentType.ArrayInt16
432  || type == ExtArgumentType.ArrayInt32 || type == ExtArgumentType.ArrayInt64
433  || type == ExtArgumentType.ArrayFloat || type == ExtArgumentType.ArrayDouble
434  || type == ExtArgumentType.ArrayBool
436  }
437 
438  public static boolean isColumnListArrayType(final ExtArgumentType type) {
439  return type == ExtArgumentType.ColumnListArrayInt8
440  || type == ExtArgumentType.ColumnListArrayInt16
441  || type == ExtArgumentType.ColumnListArrayInt32
442  || type == ExtArgumentType.ColumnListArrayInt64
443  || type == ExtArgumentType.ColumnListArrayFloat
444  || type == ExtArgumentType.ColumnListArrayDouble
445  || type == ExtArgumentType.ColumnListArrayBool
447  }
448 
449  public static boolean isColumnType(final ExtArgumentType type) {
450  return type == ExtArgumentType.ColumnInt8 || type == ExtArgumentType.ColumnInt16
451  || type == ExtArgumentType.ColumnInt32 || type == ExtArgumentType.ColumnInt64
452  || type == ExtArgumentType.ColumnFloat || type == ExtArgumentType.ColumnDouble
453  || type == ExtArgumentType.ColumnBool
454  || type == ExtArgumentType.ColumnTextEncodingDict
455  || type == ExtArgumentType.ColumnTimestamp || isColumnArrayType(type);
456  }
457 
458  public static boolean isColumnListType(final ExtArgumentType type) {
459  return type == ExtArgumentType.ColumnListInt8
460  || type == ExtArgumentType.ColumnListInt16
461  || type == ExtArgumentType.ColumnListInt32
462  || type == ExtArgumentType.ColumnListInt64
463  || type == ExtArgumentType.ColumnListFloat
464  || type == ExtArgumentType.ColumnListDouble
465  || type == ExtArgumentType.ColumnListBool
466  || type == ExtArgumentType.ColumnListTextEncodingDict
467  || isColumnListArrayType(type);
468  }
469 
471  switch (type) {
472  case PInt8:
473  case ArrayInt8:
474  case ColumnInt8:
475  case ColumnListInt8:
476  case Int8:
477  return ExtArgumentType.Int8;
478  case ArrayInt16:
479  case PInt16:
480  case ColumnInt16:
481  case ColumnListInt16:
482  case Int16:
483  return ExtArgumentType.Int16;
484  case ArrayInt32:
485  case PInt32:
486  case ColumnInt32:
487  case ColumnListInt32:
488  case Int32:
489  return ExtArgumentType.Int32;
490  case ArrayInt64:
491  case PInt64:
492  case ColumnInt64:
493  case ColumnListInt64:
494  case Int64:
495  return ExtArgumentType.Int64;
496  case ArrayFloat:
497  case PFloat:
498  case ColumnFloat:
499  case ColumnListFloat:
500  case Float:
501  return ExtArgumentType.Float;
502  case ArrayDouble:
503  case PDouble:
504  case ColumnDouble:
505  case ColumnListDouble:
506  case Double:
507  return ExtArgumentType.Double;
508  case ArrayBool:
509  case PBool:
510  case ColumnBool:
511  case ColumnListBool:
512  case Bool:
513  return ExtArgumentType.Bool;
514  case TextEncodingDict:
522  case ColumnTimestamp:
524  case ColumnArrayInt8:
526  case ColumnArrayInt16:
528  case ColumnArrayInt32:
530  case ColumnArrayInt64:
532  case ColumnArrayFloat:
534  case ColumnArrayDouble:
536  case ColumnArrayBool:
538  case ColumnListArrayInt8:
550  case ColumnListArrayBool:
552  }
553  HEAVYDBLOGGER.error("getValueType: no value for type " + type);
554  assert false;
555  return null;
556  }
557 
558  public static ExtArgumentType toSqlTypeName(final String type) {
559  return ExtArgumentType.valueOf(type);
560  }
561 
562  public static SqlTypeName toSqlTypeName(final ExtArgumentType type) {
563  switch (type) {
564  // Column types are mapped to their underlying type for CURSOR typechecking
565  case Bool:
566  case ColumnBool:
567  return SqlTypeName.BOOLEAN;
568  case ColumnInt8:
569  case Int8:
570  return SqlTypeName.TINYINT;
571  case ColumnInt16:
572  case Int16:
573  return SqlTypeName.SMALLINT;
574  case Int32:
575  case ColumnInt32:
576  return SqlTypeName.INTEGER;
577  case Int64:
578  case ColumnInt64:
579  return SqlTypeName.BIGINT;
580  case Float:
581  case ColumnFloat:
582  return SqlTypeName.FLOAT;
583  case Double:
584  case ColumnDouble:
585  return SqlTypeName.DOUBLE;
586  case PInt8:
587  case PInt16:
588  case PInt32:
589  case PInt64:
590  case PFloat:
591  case PDouble:
592  case PBool:
593  case ArrayInt8:
594  case ArrayInt16:
595  case ArrayInt32:
596  case ArrayInt64:
597  case ArrayFloat:
598  case ArrayDouble:
599  case ArrayBool:
601  return SqlTypeName.ARRAY;
602  case ColumnArrayInt8:
603  case ColumnArrayInt16:
604  case ColumnArrayInt32:
605  case ColumnArrayInt64:
606  case ColumnArrayFloat:
607  case ColumnArrayDouble:
608  case ColumnArrayBool:
610  return SqlTypeName.ARRAY;
611  case GeoPoint:
612  case GeoMultiPoint:
613  case GeoLineString:
614  case GeoMultiLineString:
615  case GeoPolygon:
616  case GeoMultiPolygon:
617  return SqlTypeName.GEOMETRY;
618  case Cursor:
619  return SqlTypeName.CURSOR;
620  case TextEncodingNone:
621  case TextEncodingDict:
623  return SqlTypeName.VARCHAR;
624  case Timestamp:
625  case ColumnTimestamp:
626  return SqlTypeName.TIMESTAMP;
627  case ColumnListInt8:
628  case ColumnListInt16:
629  case ColumnListInt32:
630  case ColumnListInt64:
631  case ColumnListFloat:
632  case ColumnListDouble:
633  case ColumnListBool:
634  case ColumnListArrayInt8:
640  case ColumnListArrayBool:
643  return SqlTypeName.COLUMN_LIST;
644  case DayTimeInterval:
645  return SqlTypeName.INTERVAL_DAY_HOUR;
647  return SqlTypeName.INTERVAL_YEAR_MONTH;
648  case Void:
649  // some extension functions return void. these functions should be defined in
650  // HeavyDBSqlOperatorTable and never have their definition set from the AST file
651  return null;
652  }
653  Set<SqlTypeName> allSqlTypeNames = EnumSet.allOf(SqlTypeName.class);
654  HEAVYDBLOGGER.error("toSqlTypeName: unknown type " + type + " to be mapped to {"
655  + allSqlTypeNames + "}");
656  assert false;
657  return null;
658  }
659 }
final java.util.List< SqlTypeFamily > toSqlSignature()
size_t append(FILE *f, const size_t size, const int8_t *buf)
Appends the specified number of bytes to the end of the file f from buf.
Definition: File.cpp:178
static SqlTypeName toSqlTypeName(final ExtArgumentType type)
Map< String, List< ExtArgumentType > > getCursorFieldTypes()
Simplified core of GeoJSON Polygon coordinates definition.
Definition: heavydbTypes.h:661
ExtensionFunction(final List< ExtArgumentType > args, final List< ExtArgumentType > outs, final List< String > names, final Map< String, String > options, final Map< String, List< ExtArgumentType >> cursor_field_types)
static boolean isColumnListArrayType(final ExtArgumentType type)
std::vector< std::string > split(std::string_view str, std::string_view delim, std::optional< size_t > maxsplit)
split apart a string into a vector of substrings
Simplified core of GeoJSON MultiPolygon coordinates definition.
Definition: heavydbTypes.h:682
static boolean isColumnListType(final ExtArgumentType type)
static boolean isColumnType(final ExtArgumentType type)
static boolean isColumnArrayType(final ExtArgumentType type)
ExtensionFunction(final List< ExtArgumentType > args, final ExtArgumentType ret, final List< Map< String, String >> annotations)
static String typeName(final ExtArgumentType type)
final List< Map< String, String > > annotations
static boolean isArrayType(final ExtArgumentType type)
static ExtArgumentType toSqlTypeName(final String type)
static String dq(final String str)
string name
Definition: setup.in.py:72
final Map< String, List< ExtArgumentType > > cursor_field_types
static boolean isPointerType(final ExtArgumentType type)
static ExtArgumentType getValueType(final ExtArgumentType type)