OmniSciDB  c0231cc57d
 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 {
101  }
102  ;
103 
104  ExtensionFunction(final List<ExtArgumentType> args, final ExtArgumentType ret) {
105  this.args = args;
106  this.ret = ret;
107  this.outs = null;
108  this.names = null;
109  this.isRowUdf = true;
110  this.options = null;
111  this.cursor_field_types = null;
112  }
113 
114  ExtensionFunction(final List<ExtArgumentType> args,
115  final List<ExtArgumentType> outs,
116  final List<String> names,
117  final Map<String, String> options,
118  final Map<String, List<ExtArgumentType>> cursor_field_types) {
119  this.args = args;
120  this.ret = null;
121  this.outs = outs;
122  this.names = names;
123  this.isRowUdf = false;
124  this.options = options;
125  this.cursor_field_types = cursor_field_types;
126  }
127 
128  public Map<String, List<ExtArgumentType>> getCursorFieldTypes() {
129  assert (this.isTableUdf());
130  return this.cursor_field_types;
131  }
132 
133  public List<ExtArgumentType> getArgs() {
134  return this.args;
135  }
136 
137  public List<ExtArgumentType> getOuts() {
138  return this.outs;
139  }
140 
141  public List<String> getArgNames() {
142  if (this.names != null) {
143  return this.names.subList(0, this.args.size());
144  }
145  return null;
146  }
147 
148  public List<String> getPrettyArgNames() {
149  if (this.names != null) {
150  List<String> pretty_names = new ArrayList<String>();
151  for (int arg_idx = 0; arg_idx < this.args.size(); ++arg_idx) {
152  // Split on first array opening bracket and take everything preceding
153  // For names without array brackets this will just be the name
154  pretty_names.add(this.names.get(arg_idx).split("\\[", 2)[0]);
155  }
156  return pretty_names;
157  }
158  return null;
159  }
160 
161  public List<String> getOutNames() {
162  if (this.names != null) {
163  return this.names.subList(this.args.size(), this.names.size());
164  }
165  return null;
166  }
167 
169  return this.ret;
170  }
171 
172  public SqlTypeName getSqlRet() {
173  assert this.isRowUdf();
174  return toSqlTypeName(this.ret);
175  }
176 
177  public List<SqlTypeName> getSqlOuts() {
178  assert this.isTableUdf();
179  List<SqlTypeName> sql_outs = new ArrayList<SqlTypeName>();
180  for (final ExtArgumentType otype : this.getOuts()) {
181  sql_outs.add(toSqlTypeName(getValueType(otype)));
182  }
183  return sql_outs;
184  }
185 
186  public Map<String, String> getOptions() {
187  if (this.options != null) {
188  return new HashMap<String, String>(this.options);
189  }
190  return null;
191  }
192 
193  public boolean isRowUdf() {
194  return this.isRowUdf;
195  }
196 
197  public boolean isTableUdf() {
198  return !this.isRowUdf();
199  }
200 
201  public String toJson(final String name) {
202  HEAVYDBLOGGER.debug("Extensionfunction::toJson: " + name);
203  StringBuilder json_cons = new StringBuilder();
204  json_cons.append("{");
205  json_cons.append("\"name\":").append(dq(name)).append(",");
206  if (isRowUdf) {
207  json_cons.append("\"ret\":").append(dq(typeName(ret))).append(",");
208  } else {
209  json_cons.append("\"outs\":");
210  json_cons.append("[");
211  List<String> param_list = new ArrayList<String>();
212  for (final ExtArgumentType out : outs) {
213  param_list.add(dq(typeName(out)));
214  }
215  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
216  json_cons.append("],");
217  }
218  json_cons.append("\"args\":");
219  json_cons.append("[");
220  List<String> param_list = new ArrayList<String>();
221  for (final ExtArgumentType arg : args) {
222  param_list.add(dq(typeName(arg)));
223  }
224  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
225  json_cons.append("]");
226  json_cons.append("}");
227  return json_cons.toString();
228  }
229 
230  private static String typeName(final ExtArgumentType type) {
231  switch (type) {
232  case Bool:
233  return "i1";
234  case Int8:
235  return "i8";
236  case Int16:
237  return "i16";
238  case Int32:
239  return "i32";
240  case Int64:
241  return "i64";
242  case Float:
243  return "float";
244  case Double:
245  return "double";
246  case Void:
247  return "void";
248  case PInt8:
249  return "i8*";
250  case PInt16:
251  return "i16*";
252  case PInt32:
253  return "i32*";
254  case PInt64:
255  return "i64*";
256  case PFloat:
257  return "float*";
258  case PDouble:
259  return "double*";
260  case PBool:
261  return "i1*";
262  case ArrayInt8:
263  return "Array<i8>";
264  case ArrayInt16:
265  return "Array<i16>";
266  case ArrayInt32:
267  return "Array<i32>";
268  case ArrayInt64:
269  return "Array<i64>";
270  case ArrayFloat:
271  return "Array<float>";
272  case ArrayDouble:
273  return "Array<double>";
274  case ArrayBool:
275  return "Array<bool>";
277  return "Array<TextEncodingDict>";
278  case ColumnInt8:
279  return "Column<i8>";
280  case ColumnInt16:
281  return "Column<i16>";
282  case ColumnInt32:
283  return "Column<i32>";
284  case ColumnInt64:
285  return "Column<i64>";
286  case ColumnFloat:
287  return "Column<float>";
288  case ColumnDouble:
289  return "Column<double>";
290  case ColumnBool:
291  return "Column<bool>";
293  return "Column<TextEncodingDict>";
294  case ColumnTimestamp:
295  return "Column<timestamp>";
296  case GeoPoint:
297  return "geo_point";
298  case GeoMultiPoint:
299  return "geo_multi_point";
300  case Cursor:
301  return "cursor";
302  case GeoLineString:
303  return "geo_linestring";
304  case GeoMultiLineString:
305  return "geo_multi_linestring";
306  case GeoPolygon:
307  return "geo_polygon";
308  case GeoMultiPolygon:
309  return "geo_multi_polygon";
310  case Timestamp:
311  return "timestamp";
312  case TextEncodingNone:
313  return "TextEncodingNone";
314  case TextEncodingDict:
315  return "TextEncodingDict";
316  case ColumnListInt8:
317  return "ColumnList<i8>";
318  case ColumnListInt16:
319  return "ColumnList<i16>";
320  case ColumnListInt32:
321  return "ColumnList<i32>";
322  case ColumnListInt64:
323  return "ColumnList<i64>";
324  case ColumnListFloat:
325  return "ColumnList<float>";
326  case ColumnListDouble:
327  return "ColumnList<double>";
328  case ColumnListBool:
329  return "ColumnList<bool>";
331  return "ColumnList<TextEncodingDict>";
332  case ColumnArrayInt8:
333  return "Column<Array<i8>>";
334  case ColumnArrayInt16:
335  return "Column<Array<i16>>";
336  case ColumnArrayInt32:
337  return "Column<Array<i32>>";
338  case ColumnArrayInt64:
339  return "Column<Array<i64>>";
340  case ColumnArrayFloat:
341  return "Column<Array<float>>";
342  case ColumnArrayDouble:
343  return "Column<Array<double>>";
344  case ColumnArrayBool:
345  return "Column<Array<bool>>";
347  return "Column<Array<TextEncodingDict>>";
348  case ColumnListArrayInt8:
349  return "ColumnList<Array<i8>>";
351  return "ColumnList<Array<i16>>";
353  return "ColumnList<Array<i32>>";
355  return "ColumnList<Array<i64>>";
357  return "ColumnList<Array<float>>";
359  return "ColumnList<Array<double>>";
360  case ColumnListArrayBool:
361  return "ColumnList<Array<bool>>";
363  return "ColumnList<Array<TextEncodingDict>>";
364  }
365  HEAVYDBLOGGER.info("Extensionfunction::typeName: unknown type=`" + type + "`");
366  assert false;
367  return null;
368  }
369 
370  private static String dq(final String str) {
371  return "\"" + str + "\"";
372  }
373 
374  private final List<ExtArgumentType> args;
375  private final List<ExtArgumentType> outs; // only used by UDTFs
376  private final List<String> names;
377  private final ExtArgumentType ret; // only used by UDFs
378  private final boolean isRowUdf;
379  private final Map<String, String> options;
380  private final Map<String, List<ExtArgumentType>>
381  cursor_field_types; // only used by UDTFs
382 
383  public final java.util.List<SqlTypeFamily> toSqlSignature() {
384  java.util.List<SqlTypeFamily> sql_sig = new java.util.ArrayList<SqlTypeFamily>();
385  boolean isRowUdf = this.isRowUdf();
386  for (int arg_idx = 0; arg_idx < this.getArgs().size(); ++arg_idx) {
387  final ExtArgumentType arg_type = this.getArgs().get(arg_idx);
388  if (isRowUdf) {
389  sql_sig.add(toSqlTypeName(arg_type).getFamily());
390  if (isPointerType(arg_type)) {
391  ++arg_idx;
392  }
393  } else {
394  sql_sig.add(toSqlTypeName(arg_type).getFamily());
395  }
396  }
397  return sql_sig;
398  }
399 
400  public static boolean isPointerType(final ExtArgumentType type) {
401  return type == ExtArgumentType.PInt8 || type == ExtArgumentType.PInt16
402  || type == ExtArgumentType.PInt32 || type == ExtArgumentType.PInt64
403  || type == ExtArgumentType.PFloat || type == ExtArgumentType.PDouble
404  || type == ExtArgumentType.PBool;
405  }
406 
407  public static boolean isColumnArrayType(final ExtArgumentType type) {
408  return type == ExtArgumentType.ColumnArrayInt8
409  || type == ExtArgumentType.ColumnArrayInt16
410  || type == ExtArgumentType.ColumnArrayInt32
411  || type == ExtArgumentType.ColumnArrayInt64
412  || type == ExtArgumentType.ColumnArrayFloat
413  || type == ExtArgumentType.ColumnArrayDouble
414  || type == ExtArgumentType.ColumnArrayBool
416  }
417 
418  public static boolean isColumnListArrayType(final ExtArgumentType type) {
419  return type == ExtArgumentType.ColumnListArrayInt8
420  || type == ExtArgumentType.ColumnListArrayInt16
421  || type == ExtArgumentType.ColumnListArrayInt32
422  || type == ExtArgumentType.ColumnListArrayInt64
423  || type == ExtArgumentType.ColumnListArrayFloat
424  || type == ExtArgumentType.ColumnListArrayDouble
425  || type == ExtArgumentType.ColumnListArrayBool
427  }
428 
429  public static boolean isColumnType(final ExtArgumentType type) {
430  return type == ExtArgumentType.ColumnInt8 || type == ExtArgumentType.ColumnInt16
431  || type == ExtArgumentType.ColumnInt32 || type == ExtArgumentType.ColumnInt64
432  || type == ExtArgumentType.ColumnFloat || type == ExtArgumentType.ColumnDouble
433  || type == ExtArgumentType.ColumnBool
434  || type == ExtArgumentType.ColumnTextEncodingDict
435  || type == ExtArgumentType.ColumnTimestamp || isColumnArrayType(type);
436  }
437 
438  public static boolean isColumnListType(final ExtArgumentType type) {
439  return type == ExtArgumentType.ColumnListInt8
440  || type == ExtArgumentType.ColumnListInt16
441  || type == ExtArgumentType.ColumnListInt32
442  || type == ExtArgumentType.ColumnListInt64
443  || type == ExtArgumentType.ColumnListFloat
444  || type == ExtArgumentType.ColumnListDouble
445  || type == ExtArgumentType.ColumnListBool
446  || type == ExtArgumentType.ColumnListTextEncodingDict
447  || isColumnListArrayType(type);
448  }
449 
451  switch (type) {
452  case PInt8:
453  case ArrayInt8:
454  case ColumnInt8:
455  case ColumnListInt8:
456  case Int8:
457  return ExtArgumentType.Int8;
458  case ArrayInt16:
459  case PInt16:
460  case ColumnInt16:
461  case ColumnListInt16:
462  case Int16:
463  return ExtArgumentType.Int16;
464  case ArrayInt32:
465  case PInt32:
466  case ColumnInt32:
467  case ColumnListInt32:
468  case Int32:
469  return ExtArgumentType.Int32;
470  case ArrayInt64:
471  case PInt64:
472  case ColumnInt64:
473  case ColumnListInt64:
474  case Int64:
475  return ExtArgumentType.Int64;
476  case ArrayFloat:
477  case PFloat:
478  case ColumnFloat:
479  case ColumnListFloat:
480  case Float:
481  return ExtArgumentType.Float;
482  case ArrayDouble:
483  case PDouble:
484  case ColumnDouble:
485  case ColumnListDouble:
486  case Double:
487  return ExtArgumentType.Double;
488  case ArrayBool:
489  case PBool:
490  case ColumnBool:
491  case ColumnListBool:
492  case Bool:
493  return ExtArgumentType.Bool;
494  case TextEncodingDict:
500  case ColumnTimestamp:
502  case ColumnArrayInt8:
503  return ExtArgumentType.Int8;
504  case ColumnArrayInt16:
505  return ExtArgumentType.Int16;
506  case ColumnArrayInt32:
507  return ExtArgumentType.Int32;
508  case ColumnArrayInt64:
509  return ExtArgumentType.Int64;
510  case ColumnArrayFloat:
511  return ExtArgumentType.Float;
512  case ColumnArrayDouble:
513  return ExtArgumentType.Double;
514  case ColumnArrayBool:
515  return ExtArgumentType.Bool;
516  case ColumnListArrayInt8:
528  case ColumnListArrayBool:
530  }
531  HEAVYDBLOGGER.error("getValueType: no value for type " + type);
532  assert false;
533  return null;
534  }
535 
536  public static ExtArgumentType toSqlTypeName(final String type) {
537  return ExtArgumentType.valueOf(type);
538  }
539 
540  public static SqlTypeName toSqlTypeName(final ExtArgumentType type) {
541  switch (type) {
542  // Column types are mapped to their underlying type for CURSOR typechecking
543  case Bool:
544  case ColumnBool:
545  return SqlTypeName.BOOLEAN;
546  case ColumnInt8:
547  case Int8:
548  return SqlTypeName.TINYINT;
549  case ColumnInt16:
550  case Int16:
551  return SqlTypeName.SMALLINT;
552  case Int32:
553  case ColumnInt32:
554  return SqlTypeName.INTEGER;
555  case Int64:
556  case ColumnInt64:
557  return SqlTypeName.BIGINT;
558  case Float:
559  case ColumnFloat:
560  return SqlTypeName.FLOAT;
561  case Double:
562  case ColumnDouble:
563  return SqlTypeName.DOUBLE;
564  case PInt8:
565  case PInt16:
566  case PInt32:
567  case PInt64:
568  case PFloat:
569  case PDouble:
570  case PBool:
571  case ArrayInt8:
572  case ArrayInt16:
573  case ArrayInt32:
574  case ArrayInt64:
575  case ArrayFloat:
576  case ArrayDouble:
577  case ArrayBool:
579  return SqlTypeName.ARRAY;
580  case ColumnArrayInt8:
581  case ColumnArrayInt16:
582  case ColumnArrayInt32:
583  case ColumnArrayInt64:
584  case ColumnArrayFloat:
585  case ColumnArrayDouble:
586  case ColumnArrayBool:
588  return SqlTypeName.ARRAY;
589  case GeoPoint:
590  case GeoMultiPoint:
591  case GeoLineString:
592  case GeoMultiLineString:
593  case GeoPolygon:
594  case GeoMultiPolygon:
595  return SqlTypeName.GEOMETRY;
596  case Cursor:
597  return SqlTypeName.CURSOR;
598  case TextEncodingNone:
599  case TextEncodingDict:
601  return SqlTypeName.VARCHAR;
602  case Timestamp:
603  case ColumnTimestamp:
604  return SqlTypeName.TIMESTAMP;
605  case ColumnListInt8:
606  case ColumnListInt16:
607  case ColumnListInt32:
608  case ColumnListInt64:
609  case ColumnListFloat:
610  case ColumnListDouble:
611  case ColumnListBool:
612  case ColumnListArrayInt8:
618  case ColumnListArrayBool:
621  return SqlTypeName.COLUMN_LIST;
622  case Void:
623  // some extension functions return void. these functions should be defined in
624  // HeavyDBSqlOperatorTable and never have their definition set from the AST file
625  return null;
626  }
627  Set<SqlTypeName> allSqlTypeNames = EnumSet.allOf(SqlTypeName.class);
628  HEAVYDBLOGGER.error("toSqlTypeName: unknown type " + type + " to be mapped to {"
629  + allSqlTypeNames + "}");
630  assert false;
631  return null;
632  }
633 }
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:168
static SqlTypeName toSqlTypeName(final ExtArgumentType type)
Map< String, List< ExtArgumentType > > getCursorFieldTypes()
Simplified core of GeoJSON Polygon coordinates definition.
Definition: heavydbTypes.h:502
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:523
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)
static String typeName(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)