OmniSciDB  fe05a0c208
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TableFunctionsFactory.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, 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 
18 
19 #include <boost/algorithm/string.hpp>
20 #include <mutex>
21 
22 extern bool g_enable_table_functions;
23 
24 namespace table_functions {
25 
26 namespace {
27 
29  switch (ext_arg_type) {
31  return SQLTypeInfo(kTINYINT, false);
33  return SQLTypeInfo(kSMALLINT, false);
35  return SQLTypeInfo(kINT, false);
37  return SQLTypeInfo(kBIGINT, false);
39  return SQLTypeInfo(kFLOAT, false);
41  return SQLTypeInfo(kDOUBLE, false);
43  return SQLTypeInfo(kBOOLEAN, false);
49  return generate_column_type(kINT);
72  default:
73  LOG(WARNING) << "ext_arg_pointer_type_to_type_info: ExtArgumentType `"
75  << "` conversion to SQLTypeInfo not implemented.";
76  UNREACHABLE();
77  }
78  UNREACHABLE();
79  return SQLTypeInfo(kNULLT, false);
80 }
81 
83  switch (ext_arg_type) {
88  return SQLTypeInfo(kTINYINT, false);
93  return SQLTypeInfo(kSMALLINT, false);
98  return SQLTypeInfo(kINT, false);
103  return SQLTypeInfo(kBIGINT, false);
108  return SQLTypeInfo(kFLOAT, false);
113  return SQLTypeInfo(kDOUBLE, false);
118  return SQLTypeInfo(kBOOLEAN, false);
119  default:
120  LOG(WARNING) << "ext_arg_pointer_type_to_type_info: ExtArgumentType `"
122  << "` conversion to SQLTypeInfo not implemented.";
123  UNREACHABLE();
124  }
125  UNREACHABLE();
126  return SQLTypeInfo(kNULLT, false);
127 }
128 
129 } // namespace
130 
132  CHECK_LT(idx, input_args_.size());
134 }
135 
137  CHECK_LT(idx, output_args_.size());
138  // TODO(adb): conditionally handle nulls
140 }
141 
143  int32_t scalar_args = 0;
144  for (const auto& ext_arg : input_args_) {
145  if (is_ext_arg_type_scalar(ext_arg)) {
146  scalar_args += 1;
147  }
148  }
149  return scalar_args;
150 }
151 
153  /*
154  This function differs from getOutputRowSizeParameter() since it returns the correct
155  index for the sizer in the sql_args list. For instance, consider the example below:
156 
157  RowMultiplier=4
158  input_args=[{i32*, i64}, {i32*, i64}, {i32*, i64}, i32, {i32*, i64}, {i32*, i64},
159  i32] sql_args=[cursor, i32, cursor, i32]
160 
161  Non-scalar args are aggregated in a cursor inside the sql_args list and the new
162  sizer index is 2 rather than 4 originally specified.
163  */
164 
166  size_t sizer = getOutputRowSizeParameter(); // lookup until reach the sizer arg
167  int32_t ext_arg_index = 0, sql_arg_index = 0;
168 
169  auto same_kind = [&](const ExtArgumentType& ext_arg, const ExtArgumentType& sql_arg) {
170  return ((is_ext_arg_type_scalar(ext_arg) && is_ext_arg_type_scalar(sql_arg)) ||
172  };
173 
174  while ((size_t)ext_arg_index < sizer) {
175  if ((size_t)ext_arg_index == sizer - 1)
176  return sql_arg_index;
177 
178  const auto& ext_arg = input_args_[ext_arg_index];
179  const auto& sql_arg = sql_args_[sql_arg_index];
180 
181  if (same_kind(ext_arg, sql_arg)) {
182  ++ext_arg_index;
183  ++sql_arg_index;
184  } else {
185  CHECK(same_kind(ext_arg, sql_args_[sql_arg_index - 1]));
186  ext_arg_index += 1;
187  }
188  }
189 
190  CHECK(false);
191  }
192 
193  return getOutputRowSizeParameter();
194 }
195 
196 void TableFunctionsFactory::add(const std::string& name,
198  const std::vector<ExtArgumentType>& input_args,
199  const std::vector<ExtArgumentType>& output_args,
200  const std::vector<ExtArgumentType>& sql_args,
201  bool is_runtime) {
202  auto tf = TableFunction(name, sizer, input_args, output_args, sql_args, is_runtime);
203  auto sig = tf.getSignature();
204  for (auto it = functions_.begin(); it != functions_.end();) {
205  if (it->second.getName() == name) {
206  if (it->second.isRuntime()) {
207  LOG(WARNING)
208  << "Overriding existing run-time table function (reset not called?): "
209  << name;
210  it = functions_.erase(it);
211  } else {
212  throw std::runtime_error("Will not override existing load-time table function: " +
213  name);
214  }
215  } else {
216  if (sig == it->second.getSignature() &&
217  ((tf.isCPU() && it->second.isCPU()) || (tf.isGPU() && it->second.isGPU()))) {
218  LOG(WARNING)
219  << "The existing (1) and added (2) table functions have the same signature `"
220  << sig << "`:\n"
221  << " 1: " << it->second.toString() << "\n 2: " << tf.toString() << "\n";
222  }
223  ++it;
224  }
225  }
226 
227  functions_.emplace(name, tf);
229  auto input_args2 = input_args;
230  input_args2.erase(input_args2.begin() + sizer.val - 1);
231 
232  auto sql_args2 = sql_args;
233  auto sql_sizer_pos = tf.getSqlOutputRowSizeParameter();
234  sql_args2.erase(sql_args2.begin() + sql_sizer_pos);
235 
237  sizer,
238  input_args2,
239  output_args,
240  sql_args2,
241  is_runtime);
242  auto sig = tf2.getSignature();
243  for (auto it = functions_.begin(); it != functions_.end();) {
244  if (sig == it->second.getSignature() &&
245  ((tf2.isCPU() && it->second.isCPU()) || (tf2.isGPU() && it->second.isGPU()))) {
246  LOG(WARNING)
247  << "The existing (1) and added (2) table functions have the same signature `"
248  << sig << "`:\n"
249  << " 1: " << it->second.toString() << "\n 2: " << tf2.toString() << "\n";
250  }
251  ++it;
252  }
253  functions_.emplace(name + DEFAULT_ROW_MULTIPLIER_SUFFIX, tf2);
254  }
255 }
256 
257 /*
258  The implementation for `void TableFunctionsFactory::init()` is
259  generated by QueryEngine/scripts/generate_TableFunctionsFactory_init.py
260 */
261 
262 // removes existing runtime table functions
265  return;
266  }
267  for (auto it = functions_.begin(); it != functions_.end();) {
268  if (it->second.isRuntime()) {
269  it = functions_.erase(it);
270  } else {
271  ++it;
272  }
273  }
274 }
275 
276 namespace {
277 
278 std::string drop_suffix_impl(const std::string& str) {
279  const auto idx = str.find("__");
280  if (idx == std::string::npos) {
281  return str;
282  }
283  CHECK_GT(idx, std::string::size_type(0));
284  return str.substr(0, idx);
285 }
286 
287 } // namespace
288 
289 std::string TableFunction::getName(const bool drop_suffix, const bool lower) const {
290  std::string result = name_;
291  if (drop_suffix) {
292  result = drop_suffix_impl(result);
293  }
294  if (lower) {
296  }
297  return result;
298 }
299 
300 std::vector<TableFunction> TableFunctionsFactory::get_table_funcs(const std::string& name,
301  const bool is_gpu) {
302  std::vector<TableFunction> table_funcs;
303  auto table_func_name = name;
304  boost::algorithm::to_lower(table_func_name);
305  for (const auto& pair : functions_) {
306  auto fname = drop_suffix_impl(pair.first);
307  if (fname == table_func_name &&
308  (is_gpu ? pair.second.isGPU() : pair.second.isCPU())) {
309  table_funcs.push_back(pair.second);
310  }
311  }
312  return table_funcs;
313 }
314 
315 std::vector<TableFunction> TableFunctionsFactory::get_table_funcs(const bool is_runtime) {
316  std::vector<TableFunction> table_funcs;
317  for (const auto& pair : functions_) {
318  if (pair.second.isRuntime() == is_runtime) {
319  table_funcs.push_back(pair.second);
320  }
321  }
322  return table_funcs;
323 }
324 
325 std::unordered_map<std::string, TableFunction> TableFunctionsFactory::functions_;
326 
327 } // namespace table_functions
SQLTypeInfo getOutputSQLType(const size_t idx) const
std::string to_lower(const std::string &str)
bool is_ext_arg_type_scalar(const ExtArgumentType ext_arg_type)
#define LOG(tag)
Definition: Logger.h:194
auto generate_column_type(const SQLTypes subtype)
Definition: sqltypes.h:981
string name
Definition: setup.in.py:72
SQLTypeInfo ext_arg_pointer_type_to_type_info(const ExtArgumentType ext_arg_type)
#define UNREACHABLE()
Definition: Logger.h:247
SQLTypeInfo ext_arg_type_to_type_info_output(const ExtArgumentType ext_arg_type)
const std::vector< ExtArgumentType > output_args_
#define DEFAULT_ROW_MULTIPLIER_SUFFIX
#define CHECK_GT(x, y)
Definition: Logger.h:215
bool is_ext_arg_type_nonscalar(const ExtArgumentType ext_arg_type)
const std::vector< ExtArgumentType > sql_args_
SQLTypeInfo getInputSQLType(const size_t idx) const
auto generate_column_list_type(const SQLTypes subtype)
Definition: sqltypes.h:987
std::string getName(const bool drop_suffix=false, const bool lower=false) const
#define CHECK_LT(x, y)
Definition: Logger.h:213
static void add(const std::string &name, const TableFunctionOutputRowSizer sizer, const std::vector< ExtArgumentType > &input_args, const std::vector< ExtArgumentType > &output_args, const std::vector< ExtArgumentType > &sql_args, bool is_runtime=false)
static std::string toString(const std::vector< ExtensionFunction > &ext_funcs, std::string tab="")
#define CHECK(condition)
Definition: Logger.h:203
static std::vector< TableFunction > get_table_funcs(const std::string &name, const bool is_gpu)
static std::unordered_map< std::string, TableFunction > functions_
Definition: sqltypes.h:44
const std::vector< ExtArgumentType > input_args_
bool g_enable_table_functions
Definition: Execute.cpp:104