OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SerializeToSql.cpp
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 #include "SerializeToSql.h"
18 #include "ExternalExecutor.h"
19 
21  : ra_exe_unit_(ra_exe_unit) {}
22 
23 std::string ScalarExprToSql::visitVar(const Analyzer::Var* var) const {
24  auto it = ra_exe_unit_->groupby_exprs.begin();
25  std::advance(it, var->get_varno() - 1);
26  return visit(it->get());
27 }
28 
29 std::string ScalarExprToSql::visitColumnVar(const Analyzer::ColumnVar* col_var) const {
30  const auto& column_key = col_var->getColumnKey();
31  const auto catalog =
33  return serialize_table_ref(column_key.table_id, catalog.get()) + "." +
34  serialize_column_ref(column_key.table_id, column_key.column_id, catalog.get());
35 }
36 
37 std::string ScalarExprToSql::visitConstant(const Analyzer::Constant* constant) const {
38  if (constant->get_is_null()) {
39  return "NULL";
40  }
41  const auto& constant_ti = constant->get_type_info();
42  const auto result = DatumToString(constant->get_constval(), constant_ti);
43  if (constant_ti.is_string()) {
44  return "'" + result + "'";
45  } else {
46  return result;
47  }
48 }
49 
50 std::string ScalarExprToSql::visitUOper(const Analyzer::UOper* uoper) const {
51  const auto operand = uoper->get_operand();
52  const auto operand_str = visit(operand);
53  const auto optype = uoper->get_optype();
54  switch (optype) {
55  case kNOT: {
56  return "NOT (" + operand_str + ")";
57  }
58  case kUMINUS: {
59  return "-" + operand_str;
60  }
61  case kISNULL: {
62  return operand_str + " IS NULL";
63  }
64  case kCAST: {
65  const auto& operand_ti = operand->get_type_info();
66  const auto& target_ti = uoper->get_type_info();
68  throw std::runtime_error("Type not supported yet for extern execution: " +
69  target_ti.get_type_name());
70  }
71  if ((operand_ti.get_type() == target_ti.get_type()) ||
72  ((operand_ti.is_string() && target_ti.is_string()))) {
73  return operand_str;
74  }
75  return "CAST(" + operand_str + " AS " + target_ti.get_type_name() + ")";
76  }
77  default: {
78  throw std::runtime_error("Unary operator type: " + std::to_string(optype) +
79  " not supported");
80  }
81  }
82 }
83 
84 std::string ScalarExprToSql::visitBinOper(const Analyzer::BinOper* bin_oper) const {
85  return visit(bin_oper->get_left_operand()) + " " +
86  binOpTypeToString(bin_oper->get_optype()) + " " +
87  visit(bin_oper->get_right_operand());
88 }
89 
90 std::string ScalarExprToSql::visitInValues(const Analyzer::InValues* in_values) const {
91  const auto needle = visit(in_values->get_arg());
92  const auto haystack = visitList(in_values->get_value_list());
93  return needle + " IN (" + boost::algorithm::join(haystack, ", ") + ")";
94 }
95 
96 std::string ScalarExprToSql::visitLikeExpr(const Analyzer::LikeExpr* like) const {
97  const auto str = visit(like->get_arg());
98  const auto pattern = visit(like->get_like_expr());
99  const auto result = str + " LIKE " + pattern;
100  if (like->get_escape_expr()) {
101  const auto escape = visit(like->get_escape_expr());
102  return result + " ESCAPE " + escape;
103  }
104  return result;
105 }
106 
107 std::string ScalarExprToSql::visitCaseExpr(const Analyzer::CaseExpr* case_) const {
108  std::string case_str = "CASE ";
109  const auto& expr_pair_list = case_->get_expr_pair_list();
110  for (const auto& expr_pair : expr_pair_list) {
111  const auto when = "WHEN " + visit(expr_pair.first.get());
112  const auto then = " THEN " + visit(expr_pair.second.get());
113  case_str += when + then;
114  }
115  return case_str + " ELSE " + visit(case_->get_else_expr()) + " END";
116 }
117 
118 namespace {
119 
120 std::string agg_to_string(const Analyzer::AggExpr* agg_expr,
121  const RelAlgExecutionUnit* ra_exe_unit) {
122  ScalarExprToSql scalar_expr_to_sql(ra_exe_unit);
123  const auto agg_type = ::toString(agg_expr->get_aggtype());
124  const auto arg =
125  agg_expr->get_arg() ? scalar_expr_to_sql.visit(agg_expr->get_arg()) : "*";
126  const auto distinct = agg_expr->get_is_distinct() ? "DISTINCT " : "";
127  return agg_type + "(" + distinct + arg + ")";
128 }
129 
130 } // namespace
131 
133  const Analyzer::FunctionOper* func_oper) const {
134  std::string result = func_oper->getName();
135  if (result == "||") {
136  CHECK_EQ(func_oper->getArity(), size_t(2));
137  return visit(func_oper->getArg(0)) + "||" + visit(func_oper->getArg(1));
138  }
139  if (result == "SUBSTRING") {
140  result = "SUBSTR";
141  }
142  std::vector<std::string> arg_strs;
143  for (size_t i = 0; i < func_oper->getArity(); ++i) {
144  arg_strs.push_back(visit(func_oper->getArg(i)));
145  }
146  return result + "(" + boost::algorithm::join(arg_strs, ",") + ")";
147 }
148 
150  const Analyzer::WindowFunction* window_func) const {
151  std::string result = ::toString(window_func->getKind());
152  {
153  const auto arg_strs = visitList(window_func->getArgs());
154  result += "(" + boost::algorithm::join(arg_strs, ",") + ")";
155  }
156  result += " OVER (";
157  {
158  const auto partition_strs = visitList(window_func->getPartitionKeys());
159  if (!partition_strs.empty()) {
160  result += "PARTITION BY " + boost::algorithm::join(partition_strs, ",");
161  }
162  }
163  {
164  std::vector<std::string> order_strs;
165  const auto& order_keys = window_func->getOrderKeys();
166  const auto& collation = window_func->getCollation();
167  CHECK_EQ(order_keys.size(), collation.size());
168  for (size_t i = 0; i < order_keys.size(); ++i) {
169  std::string order_str = visit(order_keys[i].get());
170  order_str += collation[i].is_desc ? " DESC" : " ASC";
171  // TODO: handle nulls first / last
172  order_strs.push_back(order_str);
173  }
174  if (!order_strs.empty()) {
175  result += " ORDER BY " + boost::algorithm::join(order_strs, ",");
176  }
177  }
178  result += ")";
179  return result;
180 }
181 
182 std::string ScalarExprToSql::visitAggExpr(const Analyzer::AggExpr* agg) const {
183  return agg_to_string(agg, ra_exe_unit_);
184 }
185 
186 std::string ScalarExprToSql::binOpTypeToString(const SQLOps op_type) {
187  switch (op_type) {
188  case kEQ:
189  return "=";
190  case kNE:
191  return "<>";
192  case kLT:
193  return "<";
194  case kLE:
195  return "<=";
196  case kGT:
197  return ">";
198  case kGE:
199  return ">=";
200  case kAND:
201  return "AND";
202  case kOR:
203  return "OR";
204  case kMINUS:
205  return "-";
206  case kPLUS:
207  return "+";
208  case kMULTIPLY:
209  return "*";
210  case kDIVIDE:
211  return "/";
212  case kMODULO:
213  return "%";
214  case kARRAY_AT:
215  return "[]";
216  case kBBOX_INTERSECT:
217  return "BBOX_INTERSECT";
218  default:
219  LOG(FATAL) << "Invalid operator type: " << op_type;
220  return "";
221  }
222 }
223 
224 template <typename List>
225 std::vector<std::string> ScalarExprToSql::visitList(const List& expressions) const {
226  std::vector<std::string> result;
227  for (const auto& expression : expressions) {
228  result.push_back(visit(expression.get()));
229  }
230  return result;
231 }
232 
233 namespace {
234 
235 std::string where_to_string(const RelAlgExecutionUnit* ra_exe_unit) {
236  ScalarExprToSql scalar_expr_to_sql(ra_exe_unit);
237  auto qual_strings = scalar_expr_to_sql.visitList(ra_exe_unit->quals);
238  const auto simple_qual_strings =
239  scalar_expr_to_sql.visitList(ra_exe_unit->simple_quals);
240  qual_strings.insert(
241  qual_strings.end(), simple_qual_strings.begin(), simple_qual_strings.end());
242  return boost::algorithm::join(qual_strings, " AND ");
243 }
244 
245 std::string join_condition_to_string(const RelAlgExecutionUnit* ra_exe_unit) {
246  ScalarExprToSql scalar_expr_to_sql(ra_exe_unit);
247  std::vector<std::string> qual_strings;
248  for (const auto& join_level_quals : ra_exe_unit->join_quals) {
249  const auto level_qual_strings = scalar_expr_to_sql.visitList(join_level_quals.quals);
250  qual_strings.insert(
251  qual_strings.end(), level_qual_strings.begin(), level_qual_strings.end());
252  }
253  return boost::algorithm::join(qual_strings, " AND ");
254 }
255 
256 std::string targets_to_string(const RelAlgExecutionUnit* ra_exe_unit) {
257  ScalarExprToSql scalar_expr_to_sql(ra_exe_unit);
258  std::vector<std::string> target_strings;
259  for (const auto target : ra_exe_unit->target_exprs) {
260  target_strings.push_back(scalar_expr_to_sql.visit(target));
261  }
262  return boost::algorithm::join(target_strings, ", ");
263 }
264 
265 std::string group_by_to_string(const RelAlgExecutionUnit* ra_exe_unit) {
266  if (ra_exe_unit->groupby_exprs.size() == 1 || !ra_exe_unit->groupby_exprs.front()) {
267  return "";
268  }
269  ScalarExprToSql scalar_expr_to_sql(ra_exe_unit);
270  const auto group_by_strings = scalar_expr_to_sql.visitList(ra_exe_unit->groupby_exprs);
271  return boost::algorithm::join(group_by_strings, ", ");
272 }
273 
274 std::string from_to_string(const RelAlgExecutionUnit* ra_exe_unit) {
275  std::vector<std::string> from_strings;
276  for (const auto& input_desc : ra_exe_unit->input_descs) {
277  const auto& table_key = input_desc.getTableKey();
278  const auto catalog =
280  const auto table_ref = serialize_table_ref(table_key.table_id, catalog.get());
281  from_strings.push_back(table_ref);
282  }
283  return boost::algorithm::join(from_strings, ", ");
284 }
285 
286 std::string maybe(const std::string& prefix, const std::string& clause) {
287  return clause.empty() ? "" : " " + prefix + " " + clause;
288 }
289 
290 } // namespace
291 
292 std::string serialize_table_ref(const int table_id,
293  const Catalog_Namespace::Catalog* catalog) {
294  if (table_id >= 0) {
295  CHECK(catalog);
296  const auto td = catalog->getMetadataForTable(table_id);
297  CHECK(td);
298  return td->tableName;
299  }
300  return "\"#temp" + std::to_string(table_id) + "\"";
301 }
302 
303 std::string serialize_column_ref(const int table_id,
304  const int column_id,
305  const Catalog_Namespace::Catalog* catalog) {
306  if (table_id >= 0) {
307  CHECK(catalog);
308  const auto cd = catalog->getMetadataForColumn(table_id, column_id);
309  CHECK(cd);
310  return cd->columnName;
311  }
312  return "col" + std::to_string(column_id);
313 }
314 
316  const auto targets = targets_to_string(ra_exe_unit);
317  const auto from = from_to_string(ra_exe_unit);
318  const auto join_on = join_condition_to_string(ra_exe_unit);
319  const auto where = where_to_string(ra_exe_unit);
320  const auto group = group_by_to_string(ra_exe_unit);
321  return {"SELECT " + targets + " FROM " + from + maybe("ON", join_on) +
322  maybe("WHERE", where) + maybe("GROUP BY", group),
323  from};
324 }
bool is_supported_type_for_extern_execution(const SQLTypeInfo &ti)
std::vector< Analyzer::Expr * > target_exprs
#define CHECK_EQ(x, y)
Definition: Logger.h:301
SqlWindowFunctionKind getKind() const
Definition: Analyzer.h:2794
std::string join_condition_to_string(const RelAlgExecutionUnit *ra_exe_unit)
std::string group_by_to_string(const RelAlgExecutionUnit *ra_exe_unit)
std::string visitColumnVar(const Analyzer::ColumnVar *col_var) const override
const Expr * get_else_expr() const
Definition: Analyzer.h:1387
std::string DatumToString(Datum d, const SQLTypeInfo &ti)
Definition: Datum.cpp:460
const Expr * get_escape_expr() const
Definition: Analyzer.h:1064
size_t getArity() const
Definition: Analyzer.h:2615
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:143
#define LOG(tag)
Definition: Logger.h:285
const Expr * get_right_operand() const
Definition: Analyzer.h:456
SQLOps
Definition: sqldefs.h:28
Definition: sqldefs.h:34
std::string maybe(const std::string &prefix, const std::string &clause)
Definition: sqldefs.h:35
std::string join(T const &container, std::string const &delim)
bool get_is_null() const
Definition: Analyzer.h:347
Definition: sqldefs.h:37
std::vector< InputDescriptor > input_descs
std::string visitWindowFunction(const Analyzer::WindowFunction *window_func) const override
Definition: sqldefs.h:48
Definition: sqldefs.h:29
std::string targets_to_string(const RelAlgExecutionUnit *ra_exe_unit)
Expr * get_arg() const
Definition: Analyzer.h:1330
Definition: sqldefs.h:40
std::string toString(const QueryDescriptionType &type)
Definition: Types.h:64
ScalarExprToSql(const RelAlgExecutionUnit *ra_exe_unit)
std::string visit(const Analyzer::Expr *expr) const
const std::list< std::shared_ptr< Analyzer::Expr > > groupby_exprs
const std::vector< std::shared_ptr< Analyzer::Expr > > & getOrderKeys() const
Definition: Analyzer.h:2802
std::string visitBinOper(const Analyzer::BinOper *bin_oper) const override
const std::vector< OrderEntry > & getCollation() const
Definition: Analyzer.h:2820
const Expr * get_arg() const
Definition: Analyzer.h:1061
std::vector< std::string > visitList(const List &expressions) const
std::string visitConstant(const Analyzer::Constant *constant) const override
std::string to_string(char const *&&v)
std::string serialize_column_ref(const int table_id, const int column_id, const Catalog_Namespace::Catalog *catalog)
std::string visitAggExpr(const Analyzer::AggExpr *agg) const override
SQLOps get_optype() const
Definition: Analyzer.h:452
static SysCatalog & instance()
Definition: SysCatalog.h:343
const std::vector< std::shared_ptr< Analyzer::Expr > > & getArgs() const
Definition: Analyzer.h:2796
const JoinQualsPerNestingLevel join_quals
std::string visitCaseExpr(const Analyzer::CaseExpr *case_) const override
const ColumnDescriptor * getMetadataForColumn(int tableId, const std::string &colName) const
Definition: sqldefs.h:36
int32_t get_varno() const
Definition: Analyzer.h:288
bool get_is_distinct() const
Definition: Analyzer.h:1332
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::string visitVar(const Analyzer::Var *) const override
Definition: sqldefs.h:33
std::string visitLikeExpr(const Analyzer::LikeExpr *like) const override
std::shared_ptr< Catalog > getCatalog(const std::string &dbName)
Definition: sqldefs.h:39
const shared::ColumnKey & getColumnKey() const
Definition: Analyzer.h:198
static std::string binOpTypeToString(const SQLOps op_type)
const Expr * get_like_expr() const
Definition: Analyzer.h:1063
const Analyzer::Expr * getArg(const size_t i) const
Definition: Analyzer.h:2617
const Expr * get_operand() const
Definition: Analyzer.h:384
Datum get_constval() const
Definition: Analyzer.h:348
Definition: sqldefs.h:31
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:646
ExecutionUnitSql serialize_to_sql(const RelAlgExecutionUnit *ra_exe_unit)
std::string get_type_name() const
Definition: sqltypes.h:482
const RelAlgExecutionUnit * ra_exe_unit_
std::string from_to_string(const RelAlgExecutionUnit *ra_exe_unit)
SQLAgg get_aggtype() const
Definition: Analyzer.h:1329
std::list< std::shared_ptr< Analyzer::Expr > > quals
std::string agg_to_string(const Analyzer::AggExpr *agg_expr, const RelAlgExecutionUnit *ra_exe_unit)
std::string visitFunctionOper(const Analyzer::FunctionOper *func_oper) const override
#define CHECK(condition)
Definition: Logger.h:291
std::string visitUOper(const Analyzer::UOper *uoper) const override
Definition: sqldefs.h:32
const Expr * get_left_operand() const
Definition: Analyzer.h:455
std::string where_to_string(const RelAlgExecutionUnit *ra_exe_unit)
const TableDescriptor * getMetadataForTable(const std::string &tableName, const bool populateFragmenter=true) const
Returns a pointer to a const TableDescriptor struct matching the provided tableName.
std::string getName() const
Definition: Analyzer.h:2613
std::string visitInValues(const Analyzer::InValues *in_values) const override
const std::vector< std::shared_ptr< Analyzer::Expr > > & getPartitionKeys() const
Definition: Analyzer.h:2798
std::string serialize_table_ref(const int table_id, const Catalog_Namespace::Catalog *catalog)
Definition: sqldefs.h:38
const Expr * get_arg() const
Definition: Analyzer.h:644
SQLOps get_optype() const
Definition: Analyzer.h:383
const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr > > > & get_expr_pair_list() const
Definition: Analyzer.h:1384
std::list< std::shared_ptr< Analyzer::Expr > > simple_quals