OmniSciDB  cde582ebc3
 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 {
82  }
83  ;
84 
85  ExtensionFunction(final List<ExtArgumentType> args, final ExtArgumentType ret) {
86  this.args = args;
87  this.ret = ret;
88  this.outs = null;
89  this.names = null;
90  this.isRowUdf = true;
91  this.options = null;
92  }
93 
94  ExtensionFunction(final List<ExtArgumentType> args,
95  final List<ExtArgumentType> outs,
96  final List<String> names,
97  final Map<String, String> options) {
98  this.args = args;
99  this.ret = null;
100  this.outs = outs;
101  this.names = names;
102  this.isRowUdf = false;
103  this.options = options;
104  }
105 
106  public List<ExtArgumentType> getArgs() {
107  return this.args;
108  }
109 
110  public List<ExtArgumentType> getOuts() {
111  return this.outs;
112  }
113 
114  public List<String> getArgNames() {
115  if (this.names != null) {
116  return this.names.subList(0, this.args.size());
117  }
118  return null;
119  }
120 
121  public List<String> getPrettyArgNames() {
122  if (this.names != null) {
123  List<String> pretty_names = new ArrayList<String>();
124  for (int arg_idx = 0; arg_idx < this.args.size(); ++arg_idx) {
125  // Split on first array opening bracket and take everything preceding
126  // For names without array brackets this will just be the name
127  pretty_names.add(this.names.get(arg_idx).split("\\[", 2)[0]);
128  }
129  return pretty_names;
130  }
131  return null;
132  }
133 
134  public List<String> getOutNames() {
135  if (this.names != null) {
136  return this.names.subList(this.args.size(), this.names.size());
137  }
138  return null;
139  }
140 
142  return this.ret;
143  }
144 
145  public SqlTypeName getSqlRet() {
146  assert this.isRowUdf();
147  return toSqlTypeName(this.ret);
148  }
149 
150  public List<SqlTypeName> getSqlOuts() {
151  assert this.isTableUdf();
152  List<SqlTypeName> sql_outs = new ArrayList<SqlTypeName>();
153  for (final ExtArgumentType otype : this.getOuts()) {
154  sql_outs.add(toSqlTypeName(getValueType(otype)));
155  }
156  return sql_outs;
157  }
158 
159  public Map<String, String> getOptions() {
160  if (this.options != null) {
161  return new HashMap<String, String>(this.options);
162  }
163  return null;
164  }
165 
166  public boolean isRowUdf() {
167  return this.isRowUdf;
168  }
169 
170  public boolean isTableUdf() {
171  return !this.isRowUdf();
172  }
173 
174  public String toJson(final String name) {
175  HEAVYDBLOGGER.debug("Extensionfunction::toJson: " + name);
176  StringBuilder json_cons = new StringBuilder();
177  json_cons.append("{");
178  json_cons.append("\"name\":").append(dq(name)).append(",");
179  if (isRowUdf) {
180  json_cons.append("\"ret\":").append(dq(typeName(ret))).append(",");
181  } else {
182  json_cons.append("\"outs\":");
183  json_cons.append("[");
184  List<String> param_list = new ArrayList<String>();
185  for (final ExtArgumentType out : outs) {
186  param_list.add(dq(typeName(out)));
187  }
188  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
189  json_cons.append("],");
190  }
191  json_cons.append("\"args\":");
192  json_cons.append("[");
193  List<String> param_list = new ArrayList<String>();
194  for (final ExtArgumentType arg : args) {
195  param_list.add(dq(typeName(arg)));
196  }
197  json_cons.append(ExtensionFunctionSignatureParser.join(param_list, ","));
198  json_cons.append("]");
199  json_cons.append("}");
200  return json_cons.toString();
201  }
202 
203  private static String typeName(final ExtArgumentType type) {
204  switch (type) {
205  case Bool:
206  return "i1";
207  case Int8:
208  return "i8";
209  case Int16:
210  return "i16";
211  case Int32:
212  return "i32";
213  case Int64:
214  return "i64";
215  case Float:
216  return "float";
217  case Double:
218  return "double";
219  case Void:
220  return "void";
221  case PInt8:
222  return "i8*";
223  case PInt16:
224  return "i16*";
225  case PInt32:
226  return "i32*";
227  case PInt64:
228  return "i64*";
229  case PFloat:
230  return "float*";
231  case PDouble:
232  return "double*";
233  case PBool:
234  return "i1*";
235  case ArrayInt8:
236  return "Array<i8>";
237  case ArrayInt16:
238  return "Array<i16>";
239  case ArrayInt32:
240  return "Array<i32>";
241  case ArrayInt64:
242  return "Array<i64>";
243  case ArrayFloat:
244  return "Array<float>";
245  case ArrayDouble:
246  return "Array<double>";
247  case ArrayBool:
248  return "Array<bool>";
249  case ColumnInt8:
250  return "Column<i8>";
251  case ColumnInt16:
252  return "Column<i16>";
253  case ColumnInt32:
254  return "Column<i32>";
255  case ColumnInt64:
256  return "Column<i64>";
257  case ColumnFloat:
258  return "Column<float>";
259  case ColumnDouble:
260  return "Column<double>";
261  case ColumnBool:
262  return "Column<bool>";
264  return "Column<TextEncodingDict>";
265  case ColumnTimestamp:
266  return "Column<timestamp>";
267  case GeoPoint:
268  return "geo_point";
269  case Cursor:
270  return "cursor";
271  case GeoLineString:
272  return "geo_linestring";
273  case GeoPolygon:
274  return "geo_polygon";
275  case GeoMultiPolygon:
276  return "geo_multi_polygon";
277  case Timestamp:
278  return "timestamp";
279  case TextEncodingNone:
280  return "TextEncodingNone";
281  case TextEncodingDict:
282  return "TextEncodingDict";
283  case ColumnListInt8:
284  return "ColumnList<i8>";
285  case ColumnListInt16:
286  return "ColumnList<i16>";
287  case ColumnListInt32:
288  return "ColumnList<i32>";
289  case ColumnListInt64:
290  return "ColumnList<i64>";
291  case ColumnListFloat:
292  return "ColumnList<float>";
293  case ColumnListDouble:
294  return "ColumnList<double>";
295  case ColumnListBool:
296  return "ColumnList<bool>";
298  return "ColumnList<TextEncodingDict>";
299  }
300  HEAVYDBLOGGER.info("Extensionfunction::typeName: unknown type=`" + type + "`");
301  assert false;
302  return null;
303  }
304 
305  private static String dq(final String str) {
306  return "\"" + str + "\"";
307  }
308 
309  private final List<ExtArgumentType> args;
310  private final List<ExtArgumentType> outs; // only used by UDTFs
311  private final List<String> names;
312  private final ExtArgumentType ret; // only used by UDFs
313  private final boolean isRowUdf;
314  private final Map<String, String> options;
315 
316  public final java.util.List<SqlTypeFamily> toSqlSignature() {
317  java.util.List<SqlTypeFamily> sql_sig = new java.util.ArrayList<SqlTypeFamily>();
318  boolean isRowUdf = this.isRowUdf();
319  for (int arg_idx = 0; arg_idx < this.getArgs().size(); ++arg_idx) {
320  final ExtArgumentType arg_type = this.getArgs().get(arg_idx);
321  if (isRowUdf) {
322  sql_sig.add(toSqlTypeName(arg_type).getFamily());
323  if (isPointerType(arg_type)) {
324  ++arg_idx;
325  }
326  } else {
327  sql_sig.add(toSqlTypeName(arg_type).getFamily());
328  }
329  }
330  return sql_sig;
331  }
332 
333  private static boolean isPointerType(final ExtArgumentType type) {
334  return type == ExtArgumentType.PInt8 || type == ExtArgumentType.PInt16
335  || type == ExtArgumentType.PInt32 || type == ExtArgumentType.PInt64
336  || type == ExtArgumentType.PFloat || type == ExtArgumentType.PDouble
337  || type == ExtArgumentType.PBool;
338  }
339 
340  private static boolean isColumnType(final ExtArgumentType type) {
341  return type == ExtArgumentType.ColumnInt8 || type == ExtArgumentType.ColumnInt16
342  || type == ExtArgumentType.ColumnInt32 || type == ExtArgumentType.ColumnInt64
343  || type == ExtArgumentType.ColumnFloat || type == ExtArgumentType.ColumnDouble
344  || type == ExtArgumentType.ColumnBool
345  || type == ExtArgumentType.ColumnTextEncodingDict
347  }
348 
349  private static boolean isColumnListType(final ExtArgumentType type) {
350  return type == ExtArgumentType.ColumnListInt8
351  || type == ExtArgumentType.ColumnListInt16
352  || type == ExtArgumentType.ColumnListInt32
353  || type == ExtArgumentType.ColumnListInt64
354  || type == ExtArgumentType.ColumnListFloat
355  || type == ExtArgumentType.ColumnListDouble
356  || type == ExtArgumentType.ColumnListBool
358  }
359 
361  switch (type) {
362  case PInt8:
363  case ColumnInt8:
364  case ColumnListInt8:
365  case Int8:
366  return ExtArgumentType.Int8;
367  case PInt16:
368  case ColumnInt16:
369  case ColumnListInt16:
370  case Int16:
371  return ExtArgumentType.Int16;
372  case PInt32:
373  case ColumnInt32:
374  case ColumnListInt32:
375  case Int32:
376  return ExtArgumentType.Int32;
377  case PInt64:
378  case ColumnInt64:
379  case ColumnListInt64:
380  case Int64:
381  return ExtArgumentType.Int64;
382  case PFloat:
383  case ColumnFloat:
384  case ColumnListFloat:
385  case Float:
386  return ExtArgumentType.Float;
387  case PDouble:
388  case ColumnDouble:
389  case ColumnListDouble:
390  case Double:
391  return ExtArgumentType.Double;
392  case PBool:
393  case ColumnBool:
394  case ColumnListBool:
395  case Bool:
396  return ExtArgumentType.Bool;
397  case TextEncodingDict:
401  case ColumnTimestamp:
403  }
404  HEAVYDBLOGGER.error("getValueType: no value for type " + type);
405  assert false;
406  return null;
407  }
408 
409  private static SqlTypeName toSqlTypeName(final ExtArgumentType type) {
410  switch (type) {
411  case Bool:
412  return SqlTypeName.BOOLEAN;
413  case Int8:
414  return SqlTypeName.TINYINT;
415  case Int16:
416  return SqlTypeName.SMALLINT;
417  case Int32:
418  return SqlTypeName.INTEGER;
419  case Int64:
420  return SqlTypeName.BIGINT;
421  case Float:
422  return SqlTypeName.FLOAT;
423  case Double:
424  return SqlTypeName.DOUBLE;
425  case PInt8:
426  case PInt16:
427  case PInt32:
428  case PInt64:
429  case PFloat:
430  case PDouble:
431  case PBool:
432  case ArrayInt8:
433  case ArrayInt16:
434  case ArrayInt32:
435  case ArrayInt64:
436  case ArrayFloat:
437  case ArrayDouble:
438  case ArrayBool:
439  return SqlTypeName.ARRAY;
440  case GeoPoint:
441  case GeoLineString:
442  case GeoPolygon:
443  case GeoMultiPolygon:
444  return SqlTypeName.GEOMETRY;
445  case Cursor:
446  return SqlTypeName.CURSOR;
447  case TextEncodingNone:
448  case TextEncodingDict:
449  return SqlTypeName.VARCHAR;
450  case Timestamp:
451  return SqlTypeName.TIMESTAMP;
452  case ColumnListInt8:
453  case ColumnListInt16:
454  case ColumnListInt32:
455  case ColumnListInt64:
456  case ColumnListFloat:
457  case ColumnListDouble:
458  case ColumnListBool:
460  return SqlTypeName.COLUMN_LIST;
461  case Void:
462  // some extension functions return void. these functions should be defined in
463  // HeavyDBSqlOperatorTable and never have their definition set from the AST file
464  return null;
465  }
466  Set<SqlTypeName> allSqlTypeNames = EnumSet.allOf(SqlTypeName.class);
467  HEAVYDBLOGGER.error("toSqlTypeName: unknown type " + type + " to be mapped to {"
468  + allSqlTypeNames + "}");
469  assert false;
470  return null;
471  }
472 }
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)
Simplified core of GeoJSON Polygon coordinates definition.
Definition: heavydbTypes.h:390
ExtensionFunction(final List< ExtArgumentType > args, final List< ExtArgumentType > outs, final List< String > names, final Map< String, String > options)
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:411
static boolean isColumnListType(final ExtArgumentType type)
static boolean isColumnType(final ExtArgumentType type)
ExtensionFunction(final List< ExtArgumentType > args, final ExtArgumentType ret)
static String typeName(final ExtArgumentType type)
static String dq(final String str)
string name
Definition: setup.in.py:72
static boolean isPointerType(final ExtArgumentType type)
static ExtArgumentType getValueType(final ExtArgumentType type)