OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CalciteAdapter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 "CalciteAdapter.h"
19 #include "DateTimeTranslator.h"
20 
21 #include "../Parser/ParserNode.h"
22 #include "../Shared/StringTransform.h"
23 
24 #include <rapidjson/document.h>
25 #include <boost/algorithm/string/predicate.hpp>
26 #include <boost/algorithm/string/replace.hpp>
27 #include <boost/regex.hpp>
28 
29 #include <set>
30 #include <unordered_map>
31 #include <unordered_set>
32 
33 namespace {
34 
35 ssize_t get_agg_operand_idx(const rapidjson::Value& expr) {
36  CHECK(expr.IsObject());
37  CHECK(expr.HasMember("agg"));
38  const auto& agg_operands = expr["operands"];
39  CHECK(agg_operands.IsArray());
40  CHECK(agg_operands.Size() <= 2);
41  return agg_operands.Empty() ? -1 : agg_operands[0].GetInt();
42 }
43 
44 std::tuple<const rapidjson::Value*, SQLTypeInfo, SQLTypeInfo> parse_literal(
45  const rapidjson::Value& expr) {
46  CHECK(expr.IsObject());
47  auto val_it = expr.FindMember("literal");
48  CHECK(val_it != expr.MemberEnd());
49  auto type_it = expr.FindMember("type");
50  CHECK(type_it != expr.MemberEnd());
51  CHECK(type_it->value.IsString());
52  const auto type_name = std::string(type_it->value.GetString());
53  auto target_type_it = expr.FindMember("target_type");
54  CHECK(target_type_it != expr.MemberEnd());
55  CHECK(target_type_it->value.IsString());
56  const auto target_type_name = std::string(target_type_it->value.GetString());
57  auto scale_it = expr.FindMember("scale");
58  CHECK(scale_it != expr.MemberEnd());
59  CHECK(scale_it->value.IsInt());
60  const int scale = scale_it->value.GetInt();
61  auto type_scale_it = expr.FindMember("type_scale");
62  CHECK(type_scale_it != expr.MemberEnd());
63  CHECK(type_scale_it->value.IsInt());
64  const int type_scale = type_scale_it->value.GetInt();
65  auto precision_it = expr.FindMember("precision");
66  CHECK(precision_it != expr.MemberEnd());
67  CHECK(precision_it->value.IsInt());
68  const int precision = precision_it->value.GetInt();
69  auto type_precision_it = expr.FindMember("type_precision");
70  CHECK(type_precision_it != expr.MemberEnd());
71  CHECK(type_precision_it->value.IsInt());
72  const int type_precision = type_precision_it->value.GetInt();
73  SQLTypeInfo ti(to_sql_type(type_name), precision, scale, false);
74  SQLTypeInfo target_ti(to_sql_type(target_type_name), type_precision, type_scale, false);
75  return std::make_tuple(&(val_it->value), ti, target_ti);
76 }
77 
78 std::shared_ptr<Analyzer::Expr> set_transient_dict(
79  const std::shared_ptr<Analyzer::Expr> expr) {
80  const auto& ti = expr->get_type_info();
81  if (!ti.is_string() || ti.get_compression() != kENCODING_NONE) {
82  return expr;
83  }
84  auto transient_dict_ti = ti;
85  transient_dict_ti.set_compression(kENCODING_DICT);
86  transient_dict_ti.set_comp_param(TRANSIENT_DICT_ID);
87  transient_dict_ti.set_fixed_size();
88  return expr->add_cast(transient_dict_ti);
89 }
90 
92  public:
93  CalciteAdapter(const Catalog_Namespace::Catalog& cat, const rapidjson::Value& rels)
94  : cat_(cat) {
95  time(&now_);
96  CHECK(rels.IsArray());
97  for (auto rels_it = rels.Begin(); rels_it != rels.End(); ++rels_it) {
98  const auto& scan_ra = *rels_it;
99  CHECK(scan_ra.IsObject());
100  if (scan_ra["relOp"].GetString() != std::string("EnumerableTableScan")) {
101  break;
102  }
103  col_names_.emplace_back(
104  ColNames{getColNames(scan_ra), getTableFromScanNode(scan_ra)});
105  }
106  }
107 
108  CalciteAdapter(const CalciteAdapter&) = delete;
109 
110  CalciteAdapter& operator=(const CalciteAdapter&) = delete;
111 
112  std::shared_ptr<Analyzer::Expr> getExprFromNode(
113  const rapidjson::Value& expr,
114  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
115  if (expr.IsObject() && expr.HasMember("op")) {
116  return translateOp(expr, scan_targets);
117  }
118  if (expr.IsObject() && expr.HasMember("input")) {
119  return translateColRef(expr, scan_targets);
120  }
121  if (expr.IsObject() && expr.HasMember("agg")) {
122  return translateAggregate(expr, scan_targets);
123  }
124  if (expr.IsObject() && expr.HasMember("literal")) {
125  return translateTypedLiteral(expr);
126  }
127  throw std::runtime_error("Unsupported node type");
128  }
129 
130  std::pair<std::shared_ptr<Analyzer::Expr>, SQLQualifier> getQuantifiedRhs(
131  const rapidjson::Value& rhs_op,
132  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
133  std::shared_ptr<Analyzer::Expr> rhs;
134  SQLQualifier sql_qual{kONE};
135  const auto rhs_op_it = rhs_op.FindMember("op");
136  if (rhs_op_it == rhs_op.MemberEnd()) {
137  return std::make_pair(rhs, sql_qual);
138  }
139  CHECK(rhs_op_it->value.IsString());
140  const auto& qual_str = rhs_op_it->value.GetString();
141  const auto rhs_op_operands_it = rhs_op.FindMember("operands");
142  CHECK(rhs_op_operands_it != rhs_op.MemberEnd());
143  const auto& rhs_op_operands = rhs_op_operands_it->value;
144  CHECK(rhs_op_operands.IsArray());
145  if (qual_str == std::string("PG_ANY") || qual_str == std::string("PG_ALL")) {
146  CHECK_EQ(unsigned(1), rhs_op_operands.Size());
147  rhs = getExprFromNode(rhs_op_operands[0], scan_targets);
148  sql_qual = qual_str == std::string("PG_ANY") ? kANY : kALL;
149  }
150  if (!rhs && qual_str == std::string("CAST")) {
151  CHECK_EQ(unsigned(1), rhs_op_operands.Size());
152  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op_operands[0], scan_targets);
153  }
154  return std::make_pair(rhs, sql_qual);
155  }
156 
157  std::shared_ptr<Analyzer::Expr> translateOp(
158  const rapidjson::Value& expr,
159  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
160  const auto op_str = expr["op"].GetString();
161  if (op_str == std::string("LIKE") || op_str == std::string("PG_ILIKE")) {
162  return translateLike(expr, scan_targets, op_str == std::string("PG_ILIKE"));
163  }
164  if (op_str == std::string("REGEXP_LIKE")) {
165  return translateRegexp(expr, scan_targets);
166  }
167  if (op_str == std::string("LIKELY")) {
168  return translateLikely(expr, scan_targets);
169  }
170  if (op_str == std::string("UNLIKELY")) {
171  return translateUnlikely(expr, scan_targets);
172  }
173  if (op_str == std::string("CASE")) {
174  return translateCase(expr, scan_targets);
175  }
176  if (op_str == std::string("ITEM")) {
177  return translateItem(expr, scan_targets);
178  }
179  const auto& operands = expr["operands"];
180  CHECK(operands.IsArray());
181  if (op_str == std::string("NOW")) {
182  CHECK_EQ(unsigned(0), operands.Size());
183  return translateNow();
184  }
185  if (op_str == std::string("DATETIME")) {
186  CHECK_EQ(unsigned(1), operands.Size());
187  const auto& now_lit = operands[0];
188  const std::string datetime_err{R"(Only DATETIME('NOW') supported for now.)"};
189  if (!now_lit.IsObject() || !now_lit.HasMember("literal")) {
190  throw std::runtime_error(datetime_err);
191  }
192  const auto now_lit_expr = std::dynamic_pointer_cast<const Analyzer::Constant>(
193  translateTypedLiteral(now_lit));
194  CHECK(now_lit_expr);
195  CHECK(now_lit_expr->get_type_info().is_string());
196  if (*now_lit_expr->get_constval().stringval != std::string("NOW")) {
197  throw std::runtime_error(datetime_err);
198  }
199  return translateNow();
200  }
201  if (op_str == std::string("PG_EXTRACT") || op_str == std::string("PG_DATE_TRUNC")) {
202  return translateExtract(
203  operands, scan_targets, op_str == std::string("PG_DATE_TRUNC"));
204  }
205  if (op_str == std::string("DATEADD")) {
206  return translateDateadd(operands, scan_targets);
207  }
208  if (op_str == std::string("DATEDIFF")) {
209  return translateDatediff(operands, scan_targets);
210  }
211  if (op_str == std::string("DATEPART")) {
212  return translateDatepart(operands, scan_targets);
213  }
214  if (op_str == std::string("LENGTH") || op_str == std::string("CHAR_LENGTH")) {
215  CHECK_EQ(unsigned(1), operands.Size());
216  auto str_arg = getExprFromNode(operands[0], scan_targets);
217  return makeExpr<Analyzer::CharLengthExpr>(str_arg->decompress(),
218  op_str == std::string("CHAR_LENGTH"));
219  }
220  if (op_str == std::string("KEY_FOR_STRING")) {
221  CHECK_EQ(unsigned(1), operands.Size());
222  auto str_arg = getExprFromNode(operands[0], scan_targets);
223  return makeExpr<Analyzer::KeyForStringExpr>(str_arg);
224  }
225  if (op_str == std::string("CARDINALITY") || op_str == std::string("ARRAY_LENGTH")) {
226  CHECK_EQ(unsigned(1), operands.Size());
227  auto str_arg = getExprFromNode(operands[0], scan_targets);
228  return makeExpr<Analyzer::CardinalityExpr>(str_arg->decompress());
229  }
230  if (op_str == std::string("$SCALAR_QUERY")) {
231  throw std::runtime_error("Subqueries not supported");
232  }
233  if (operands.Size() == 1) {
234  return translateUnaryOp(expr, scan_targets);
235  }
236  CHECK_GE(operands.Size(), unsigned(2));
237  auto lhs = getExprFromNode(operands[0], scan_targets);
238  for (size_t i = 1; i < operands.Size(); ++i) {
239  std::shared_ptr<Analyzer::Expr> rhs;
240  SQLQualifier sql_qual{kONE};
241  const auto& rhs_op = operands[i];
242  std::tie(rhs, sql_qual) = getQuantifiedRhs(rhs_op, scan_targets);
243  if (!rhs) {
244  rhs = getExprFromNode(rhs_op, scan_targets);
245  }
246  CHECK(rhs);
247  const auto sql_op = to_sql_op(op_str);
248  if (sql_op == kFUNCTION) {
249  throw std::runtime_error(std::string("Unsupported operator: ") + op_str);
250  }
251  lhs = Parser::OperExpr::normalize(sql_op, sql_qual, lhs, rhs);
252  }
253  return lhs;
254  }
255 
256  std::shared_ptr<Analyzer::Expr> translateUnaryOp(
257  const rapidjson::Value& expr,
258  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
259  const auto& operands = expr["operands"];
260  CHECK_EQ(unsigned(1), operands.Size());
261  const auto operand_expr = getExprFromNode(operands[0], scan_targets);
262  const auto op_str = expr["op"].GetString();
263  const auto sql_op = to_sql_op(op_str);
264  switch (sql_op) {
265  case kCAST: {
266  const auto& expr_type = expr["type"];
267  SQLTypeInfo target_ti(to_sql_type(expr_type["type"].GetString()),
268  !expr_type["nullable"].GetBool());
269  const auto& operand_ti = operand_expr->get_type_info();
270  if (target_ti.is_time() ||
271  operand_ti
272  .is_string()) { // TODO(alex): check and unify with the rest of the cases
273  return operand_expr->add_cast(target_ti);
274  }
275  return makeExpr<Analyzer::UOper>(target_ti, false, sql_op, operand_expr);
276  }
277  case kNOT:
278  case kISNULL: {
279  return makeExpr<Analyzer::UOper>(kBOOLEAN, sql_op, operand_expr);
280  }
281  case kISNOTNULL: {
282  auto is_null = makeExpr<Analyzer::UOper>(kBOOLEAN, kISNULL, operand_expr);
283  return makeExpr<Analyzer::UOper>(kBOOLEAN, kNOT, is_null);
284  }
285  case kMINUS: {
286  const auto& ti = operand_expr->get_type_info();
287  return makeExpr<Analyzer::UOper>(ti, false, kUMINUS, operand_expr);
288  }
289  case kUNNEST: {
290  const auto& ti = operand_expr->get_type_info();
291  CHECK(ti.is_array());
292  return makeExpr<Analyzer::UOper>(
293  ti.get_elem_type(), false, kUNNEST, operand_expr);
294  }
295  default: {
296  CHECK(sql_op == kFUNCTION || sql_op == kIN);
297  throw std::runtime_error(std::string("Unsupported unary operator: ") + op_str);
298  }
299  }
300  return nullptr;
301  }
302 
303  std::shared_ptr<Analyzer::Expr> translateLike(
304  const rapidjson::Value& expr,
305  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets,
306  const bool is_ilike) {
307  const auto& operands = expr["operands"];
308  CHECK_GE(operands.Size(), unsigned(2));
309  auto lhs = getExprFromNode(operands[0], scan_targets);
310  auto rhs = getExprFromNode(operands[1], scan_targets);
311  auto esc = operands.Size() > 2 ? getExprFromNode(operands[2], scan_targets) : nullptr;
312  return Parser::LikeExpr::get(lhs, rhs, esc, is_ilike, false);
313  }
314 
315  std::shared_ptr<Analyzer::Expr> translateRegexp(
316  const rapidjson::Value& expr,
317  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
318  const auto& operands = expr["operands"];
319  CHECK_GE(operands.Size(), unsigned(2));
320  auto lhs = getExprFromNode(operands[0], scan_targets);
321  auto rhs = getExprFromNode(operands[1], scan_targets);
322  auto esc = operands.Size() > 2 ? getExprFromNode(operands[2], scan_targets) : nullptr;
323  return Parser::RegexpExpr::get(lhs, rhs, esc, false);
324  }
325 
326  std::shared_ptr<Analyzer::Expr> translateLikely(
327  const rapidjson::Value& expr,
328  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
329  const auto& operands = expr["operands"];
330  CHECK_GE(operands.Size(), unsigned(1));
331  auto arg = getExprFromNode(operands[0], scan_targets);
332  return Parser::LikelihoodExpr::get(arg, 0.9375, false);
333  }
334 
335  std::shared_ptr<Analyzer::Expr> translateUnlikely(
336  const rapidjson::Value& expr,
337  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
338  const auto& operands = expr["operands"];
339  CHECK_GE(operands.Size(), unsigned(1));
340  auto arg = getExprFromNode(operands[0], scan_targets);
341  return Parser::LikelihoodExpr::get(arg, 0.0625, false);
342  }
343 
344  std::shared_ptr<Analyzer::Expr> translateCase(
345  const rapidjson::Value& expr,
346  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
347  const auto& operands = expr["operands"];
348  CHECK_GE(operands.Size(), unsigned(2));
349  std::shared_ptr<Analyzer::Expr> else_expr;
350  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
351  expr_list;
352  for (auto operands_it = operands.Begin(); operands_it != operands.End();) {
353  const auto when_expr = getExprFromNode(*operands_it++, scan_targets);
354  if (operands_it == operands.End()) {
355  else_expr = when_expr;
356  break;
357  }
358  const auto then_expr = getExprFromNode(*operands_it++, scan_targets);
359  expr_list.emplace_back(when_expr, then_expr);
360  }
361  return Parser::CaseExpr::normalize(expr_list, else_expr);
362  }
363 
364  std::shared_ptr<Analyzer::Expr> translateItem(
365  const rapidjson::Value& expr,
366  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
367  const auto& operands = expr["operands"];
368  CHECK(operands.IsArray());
369  CHECK_EQ(operands.Size(), unsigned(2));
370  auto base = getExprFromNode(operands[0], scan_targets);
371  auto index = getExprFromNode(operands[1], scan_targets);
372  return makeExpr<Analyzer::BinOper>(
373  base->get_type_info().get_elem_type(), false, kARRAY_AT, kONE, base, index);
374  }
375 
376  std::shared_ptr<Analyzer::Expr> translateNow() {
377  return Parser::TimestampLiteral::get(now_);
378  }
379 
380  std::shared_ptr<Analyzer::Expr> translateExtract(
381  const rapidjson::Value& operands,
382  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets,
383  const bool is_date_trunc) {
384  CHECK(operands.IsArray());
385  CHECK_EQ(unsigned(2), operands.Size());
386  const auto& timeunit_lit = operands[0];
387  if (!timeunit_lit.IsObject() || !timeunit_lit.HasMember("literal")) {
388  throw std::runtime_error("The time unit parameter must be a literal.");
389  }
390  const auto timeunit_lit_expr = std::dynamic_pointer_cast<const Analyzer::Constant>(
391  translateTypedLiteral(timeunit_lit));
392  const auto from_expr = getExprFromNode(operands[1], scan_targets);
393  if (is_date_trunc) {
394  return DateTruncExpr::generate(from_expr,
395  *timeunit_lit_expr->get_constval().stringval);
396  } else {
397  return ExtractExpr::generate(from_expr,
398  *timeunit_lit_expr->get_constval().stringval);
399  }
400  }
401 
402  std::shared_ptr<Analyzer::Expr> translateDateadd(
403  const rapidjson::Value& operands,
404  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
405  CHECK(operands.IsArray());
406  CHECK_EQ(unsigned(3), operands.Size());
407  const auto& timeunit_lit = operands[0];
408  if (!timeunit_lit.IsObject() || !timeunit_lit.HasMember("literal")) {
409  throw std::runtime_error("The time unit parameter must be a literal.");
410  }
411  const auto timeunit_lit_expr = std::dynamic_pointer_cast<const Analyzer::Constant>(
412  translateTypedLiteral(timeunit_lit));
413  const auto number_units = getExprFromNode(operands[1], scan_targets);
414  const auto datetime = getExprFromNode(operands[2], scan_targets);
415  return makeExpr<Analyzer::DateaddExpr>(
416  SQLTypeInfo(kTIMESTAMP, false),
417  to_dateadd_field(*timeunit_lit_expr->get_constval().stringval),
418  number_units,
419  datetime);
420  }
421 
422  std::shared_ptr<Analyzer::Expr> translateDatediff(
423  const rapidjson::Value& operands,
424  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
425  CHECK(operands.IsArray());
426  CHECK_EQ(unsigned(3), operands.Size());
427  const auto& timeunit_lit = operands[0];
428  if (!timeunit_lit.IsObject() || !timeunit_lit.HasMember("literal")) {
429  throw std::runtime_error("The time unit parameter must be a literal.");
430  }
431  const auto timeunit_lit_expr = std::dynamic_pointer_cast<const Analyzer::Constant>(
432  translateTypedLiteral(timeunit_lit));
433  const auto start = getExprFromNode(operands[1], scan_targets);
434  const auto end = getExprFromNode(operands[2], scan_targets);
435  return makeExpr<Analyzer::DatediffExpr>(
436  SQLTypeInfo(kBIGINT, false),
437  to_datediff_field(*timeunit_lit_expr->get_constval().stringval),
438  start,
439  end);
440  }
441 
442  std::shared_ptr<Analyzer::Expr> translateDatepart(
443  const rapidjson::Value& operands,
444  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
445  CHECK(operands.IsArray());
446  CHECK_EQ(unsigned(2), operands.Size());
447  const auto& timeunit_lit = operands[0];
448  if (!timeunit_lit.IsObject() || !timeunit_lit.HasMember("literal")) {
449  throw std::runtime_error("The time unit parameter must be a literal.");
450  }
451  const auto timeunit_lit_expr = std::dynamic_pointer_cast<const Analyzer::Constant>(
452  translateTypedLiteral(timeunit_lit));
453  const auto from_expr = getExprFromNode(operands[1], scan_targets);
454  return ExtractExpr::generate(
455  from_expr, to_datepart_field(*timeunit_lit_expr->get_constval().stringval));
456  }
457 
458  std::shared_ptr<Analyzer::Expr> translateColRef(
459  const rapidjson::Value& expr,
460  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
461  int col_name_idx = expr["input"].GetInt();
462  CHECK_GE(col_name_idx, 0);
463  if (static_cast<size_t>(col_name_idx) < scan_targets.size()) {
464  auto var_expr = std::dynamic_pointer_cast<Analyzer::Var>(
465  scan_targets[col_name_idx]->get_own_expr());
466  if (var_expr) {
467  return var_expr;
468  }
469  }
470  int rte_idx{0};
471  for (const auto& col_name_td : col_names_) {
472  if (static_cast<size_t>(col_name_idx) < col_name_td.names_.size()) {
473  const auto& col_name = col_name_td.names_[col_name_idx];
474  const auto cd = cat_.getMetadataForColumn(col_name_td.td_->tableId, col_name);
475  CHECK(cd);
476  used_columns_[col_name_td.td_->tableId].insert(cd->columnId);
477  return makeExpr<Analyzer::ColumnVar>(
478  cd->columnType, col_name_td.td_->tableId, cd->columnId, rte_idx);
479  }
480  col_name_idx -= col_name_td.names_.size();
481  ++rte_idx;
482  }
483  CHECK(false);
484  return nullptr;
485  }
486 
487  std::shared_ptr<Analyzer::Expr> translateAggregate(
488  const rapidjson::Value& expr,
489  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets) {
490  CHECK(expr.IsObject() && expr.HasMember("type"));
491  const auto& expr_type = expr["type"];
492  CHECK(expr_type.IsObject());
493  const auto agg_kind = to_agg_kind(expr["agg"].GetString());
494  const bool is_distinct = expr["distinct"].GetBool();
495  const auto operand = get_agg_operand_idx(expr);
496  const bool takes_arg{operand >= 0};
497  if (takes_arg) {
498  CHECK_LT(operand, static_cast<ssize_t>(scan_targets.size()));
499  }
500  const auto arg_expr = takes_arg ? scan_targets[operand]->get_own_expr() : nullptr;
501  const auto agg_ti = get_agg_type(agg_kind, arg_expr.get());
502  return makeExpr<Analyzer::AggExpr>(agg_ti, agg_kind, arg_expr, is_distinct, nullptr);
503  }
504 
505  std::shared_ptr<Analyzer::Expr> translateTypedLiteral(const rapidjson::Value& expr) {
506  const auto parsed_lit = parse_literal(expr);
507  const auto& lit_ti = std::get<1>(parsed_lit);
508  const auto json_val = std::get<0>(parsed_lit);
509  switch (lit_ti.get_type()) {
510  case kDECIMAL: {
511  CHECK(json_val->IsInt64());
512  const auto val = json_val->GetInt64();
513  const int precision = lit_ti.get_precision();
514  const int scale = lit_ti.get_scale();
515  const auto& target_ti = std::get<2>(parsed_lit);
516  if (target_ti.is_fp() && !scale) {
517  return make_fp_constant(val, target_ti);
518  }
519  auto lit_expr = scale
520  ? Parser::FixedPtLiteral::analyzeValue(val, scale, precision)
522  return scale && lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
523  }
524  case kINTERVAL_DAY_TIME:
525  case kINTERVAL_YEAR_MONTH: {
526  CHECK(json_val->IsInt64());
527  Datum d;
528  d.bigintval = json_val->GetInt64();
529  return makeExpr<Analyzer::Constant>(lit_ti.get_type(), false, d);
530  }
531  case kTIME:
532  case kTIMESTAMP: {
533  CHECK(json_val->IsInt64());
534  Datum d;
535  d.bigintval = json_val->GetInt64() / 1000;
536  return makeExpr<Analyzer::Constant>(lit_ti.get_type(), false, d);
537  }
538  case kDATE: {
539  CHECK(json_val->IsInt64());
540  Datum d;
541  d.bigintval = json_val->GetInt64() * 24 * 3600;
542  return makeExpr<Analyzer::Constant>(lit_ti.get_type(), false, d);
543  }
544  case kTEXT: {
545  CHECK(json_val->IsString());
546  const auto val = json_val->GetString();
548  }
549  case kBOOLEAN: {
550  CHECK(json_val->IsBool());
551  Datum d;
552  d.boolval = json_val->GetBool();
553  return makeExpr<Analyzer::Constant>(kBOOLEAN, false, d);
554  }
555  case kDOUBLE: {
556  CHECK(json_val->IsDouble());
557  Datum d;
558  d.doubleval = json_val->GetDouble();
559  const auto& target_ti = std::get<2>(parsed_lit);
560  auto lit_expr = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
561  return lit_ti != target_ti ? lit_expr->add_cast(target_ti) : lit_expr;
562  }
563  case kNULLT: {
564  const auto& target_ti = std::get<2>(parsed_lit);
565  return makeExpr<Analyzer::Constant>(target_ti.get_type(), true, Datum{0});
566  }
567  default: {
568  LOG(FATAL) << "Unexpected literal type " << lit_ti.get_type_name();
569  }
570  }
571  return nullptr;
572  }
573 
574  std::list<int> getUsedColumnList(const int32_t table_id) const {
575  std::list<int> used_column_list;
576  const auto it = used_columns_.find(table_id);
577  if (it == used_columns_.end()) {
578  return {};
579  }
580  for (const int used_col : it->second) {
581  used_column_list.push_back(used_col);
582  }
583  return used_column_list;
584  }
585 
586  std::vector<const TableDescriptor*> getTableDescriptors() const {
587  std::vector<const TableDescriptor*> tds;
588  for (const auto& col_name_td : col_names_) {
589  tds.push_back(col_name_td.td_);
590  }
591  return tds;
592  }
593 
594  private:
595  static std::vector<std::string> getColNames(const rapidjson::Value& scan_ra) {
596  CHECK(scan_ra.IsObject() && scan_ra.HasMember("fieldNames"));
597  const auto& col_names_node = scan_ra["fieldNames"];
598  CHECK(col_names_node.IsArray());
599  std::vector<std::string> result;
600  for (auto field_it = col_names_node.Begin(); field_it != col_names_node.End();
601  ++field_it) {
602  CHECK(field_it->IsString());
603  result.emplace_back(field_it->GetString());
604  }
605  return result;
606  }
607 
608  const TableDescriptor* getTableFromScanNode(const rapidjson::Value& scan_ra) const {
609  const auto& table_info = scan_ra["table"];
610  CHECK(table_info.IsArray());
611  CHECK_EQ(unsigned(3), table_info.Size());
612  const auto td = cat_.getMetadataForTable(table_info[2].GetString());
613  CHECK(td);
614  return td;
615  }
616 
617  struct ColNames {
618  std::vector<std::string> names_;
620  };
621 
622  std::unordered_map<int32_t, std::set<int>> used_columns_;
624  time_t now_;
625  std::vector<ColNames> col_names_;
626 };
627 
629  std::vector<std::shared_ptr<Analyzer::TargetEntry>>& agg_targets,
630  const std::vector<size_t>& result_proj_indices,
631  const rapidjson::Value& fields) {
632  CHECK(fields.IsArray());
633  CHECK_EQ(static_cast<size_t>(fields.Size()), result_proj_indices.size());
634  if (result_proj_indices.empty()) {
635  return;
636  }
637  std::vector<std::shared_ptr<Analyzer::TargetEntry>> agg_targets_reproj;
638  auto fields_it = fields.Begin();
639  for (const auto proj_idx : result_proj_indices) {
640  CHECK_LT(proj_idx, agg_targets.size());
641  CHECK(fields_it != fields.End());
642  CHECK(fields_it->IsString());
643  const auto te = agg_targets[proj_idx];
644  agg_targets_reproj.emplace_back(new Analyzer::TargetEntry(
645  fields_it->GetString(), te->get_own_expr(), te->get_unnest()));
646  ++fields_it;
647  }
648  agg_targets.swap(agg_targets_reproj);
649 }
650 
652  LogicalSortInfo() : limit(0), offset(0) {}
653  int64_t limit;
654  int64_t offset;
655  std::list<Analyzer::OrderEntry> order_entries;
656 };
657 
658 LogicalSortInfo get_logical_sort_info(const rapidjson::Value& rels) {
660  bool found{false};
661  for (auto rels_it = rels.Begin(); rels_it != rels.End(); ++rels_it) {
662  const auto& sort_rel = *rels_it;
663  CHECK(sort_rel.IsObject() && sort_rel.HasMember("relOp"));
664  if (std::string("LogicalSort") != sort_rel["relOp"].GetString()) {
665  continue;
666  }
667  if (!found) {
668  if (sort_rel.HasMember("fetch")) {
669  const auto& limit_lit = parse_literal(sort_rel["fetch"]);
670  CHECK(std::get<1>(limit_lit).is_decimal() &&
671  std::get<1>(limit_lit).get_scale() == 0);
672  CHECK(std::get<0>(limit_lit)->IsInt64());
673  result.limit = std::get<0>(limit_lit)->GetInt64();
674  }
675  if (sort_rel.HasMember("offset")) {
676  const auto& offset_lit = parse_literal(sort_rel["offset"]);
677  CHECK(std::get<1>(offset_lit).is_decimal() &&
678  std::get<1>(offset_lit).get_scale() == 0);
679  CHECK(std::get<0>(offset_lit)->IsInt64());
680  result.offset = std::get<0>(offset_lit)->GetInt64();
681  }
682  CHECK(sort_rel.HasMember("collation"));
683  const auto& collation = sort_rel["collation"];
684  CHECK(collation.IsArray());
685  for (auto collation_it = collation.Begin(); collation_it != collation.End();
686  ++collation_it) {
687  const auto& oe_node = *collation_it;
688  CHECK(oe_node.IsObject());
689  result.order_entries.emplace_back(
690  oe_node["field"].GetInt() + 1,
691  std::string("DESCENDING") == oe_node["direction"].GetString(),
692  std::string("FIRST") == oe_node["nulls"].GetString());
693  }
694  found = true;
695  } else {
696  // Looks like there are two structurally identical LogicalSortInfo nodes
697  // in the Calcite AST. Validation for now, but maybe they can be different?
698  if (sort_rel.HasMember("fetch")) {
699  const auto& limit_lit = parse_literal(sort_rel["fetch"]);
700  CHECK(std::get<1>(limit_lit).is_decimal() &&
701  std::get<1>(limit_lit).get_scale() == 0);
702  CHECK(std::get<0>(limit_lit)->IsInt64());
703  CHECK_EQ(result.limit, std::get<0>(limit_lit)->GetInt64());
704  }
705  if (sort_rel.HasMember("offset")) {
706  const auto& offset_lit = parse_literal(sort_rel["offset"]);
707  CHECK(std::get<1>(offset_lit).is_decimal() &&
708  std::get<1>(offset_lit).get_scale() == 0);
709  CHECK(std::get<0>(offset_lit)->IsInt64());
710  CHECK_EQ(result.offset, std::get<0>(offset_lit)->GetInt64());
711  }
712  CHECK(sort_rel.HasMember("collation"));
713  const auto& collation = sort_rel["collation"];
714  CHECK(collation.IsArray());
715  CHECK_EQ(static_cast<size_t>(collation.Size()), result.order_entries.size());
716  auto oe_it = result.order_entries.begin();
717  for (size_t i = 0; i < result.order_entries.size(); ++i, ++oe_it) {
718  const auto& oe_node = collation[i];
719  const auto& oe = *oe_it;
720  CHECK_EQ(oe.is_desc,
721  std::string("DESCENDING") == oe_node["direction"].GetString());
722  CHECK_EQ(oe.nulls_first, std::string("FIRST") == oe_node["nulls"].GetString());
723  }
724  }
725  }
726  return result;
727 }
728 
730  const TableDescriptor* td,
731  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets,
732  std::list<std::shared_ptr<Analyzer::Expr>>& q,
733  std::list<std::shared_ptr<Analyzer::Expr>>& sq,
734  CalciteAdapter& calcite_adapter) {
735  return new Planner::Scan(scan_targets,
736  q,
737  0.,
738  nullptr,
739  sq,
740  td->tableId,
741  calcite_adapter.getUsedColumnList(td->tableId));
742 }
743 
745  const TableDescriptor* td,
746  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets,
747  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& agg_targets,
748  const std::list<std::shared_ptr<Analyzer::Expr>>& groupby_exprs,
749  std::list<std::shared_ptr<Analyzer::Expr>>& q,
750  std::list<std::shared_ptr<Analyzer::Expr>>& sq,
751  CalciteAdapter& calcite_adapter) {
752  Planner::Plan* plan = get_scan_plan(td, scan_targets, q, sq, calcite_adapter);
753  if (!agg_targets.empty()) {
754  plan = new Planner::AggPlan(agg_targets, 0., plan, groupby_exprs);
755  }
756  return plan;
757 }
758 
760  Planner::Plan* plan,
761  const rapidjson::Value& rels,
762  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& scan_targets,
763  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& agg_targets) {
764  const auto logical_sort_info = get_logical_sort_info(rels);
765  if (!logical_sort_info.order_entries.empty()) {
766  const auto& sort_target_entries =
767  agg_targets.empty() ? scan_targets : agg_targets; // TODO(alex)
768  plan = new Planner::Sort(
769  sort_target_entries, 0, plan, logical_sort_info.order_entries, false);
770  }
771  return plan;
772 }
773 
774 std::vector<size_t> collect_reproject_indices(const rapidjson::Value& exprs) {
775  std::vector<size_t> result_proj_indices;
776  CHECK(exprs.IsArray());
777  for (auto exprs_it = exprs.Begin(); exprs_it != exprs.End(); ++exprs_it) {
778  CHECK(exprs_it->IsObject());
779  result_proj_indices.push_back((*exprs_it)["input"].GetInt());
780  }
781  return result_proj_indices;
782 }
783 
784 std::vector<std::shared_ptr<Analyzer::TargetEntry>> get_input_targets(
785  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets,
786  const rapidjson::Value& exprs,
787  const rapidjson::Value& fields,
788  CalciteAdapter& calcite_adapter) {
789  CHECK(exprs.IsArray());
790  CHECK(fields.IsArray());
791  CHECK_EQ(exprs.Size(), fields.Size());
792  std::vector<std::shared_ptr<Analyzer::TargetEntry>> result;
793  if (in_targets.empty()) {
794  auto fields_it = fields.Begin();
795  for (auto exprs_it = exprs.Begin(); exprs_it != exprs.End();
796  ++exprs_it, ++fields_it) {
797  const auto proj_expr = calcite_adapter.getExprFromNode(*exprs_it, in_targets);
798  CHECK(fields_it != exprs.End());
799  CHECK(fields_it->IsString());
800  result.emplace_back(
801  new Analyzer::TargetEntry(fields_it->GetString(), proj_expr, false));
802  }
803  } else {
804  result = in_targets;
805  }
806  return result;
807 }
808 
809 bool needs_result_plan(const rapidjson::Value& exprs) {
810  for (auto exprs_it = exprs.Begin(); exprs_it != exprs.End(); ++exprs_it) {
811  const auto& expr = *exprs_it;
812  CHECK(expr.IsObject());
813  if (!expr.HasMember("input")) {
814  return true;
815  }
816  }
817  return false;
818 }
819 
820 std::vector<std::shared_ptr<Analyzer::TargetEntry>> build_var_refs(
821  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets) {
822  std::vector<std::shared_ptr<Analyzer::TargetEntry>> var_refs_to_in_targets;
823  for (size_t i = 1; i <= in_targets.size(); ++i) {
824  const auto target = in_targets[i - 1];
825  var_refs_to_in_targets.emplace_back(new Analyzer::TargetEntry(
826  target->get_resname(),
827  var_ref(target->get_expr(), Analyzer::Var::kINPUT_OUTER, i),
828  false));
829  }
830  return var_refs_to_in_targets;
831 }
832 
833 std::vector<std::shared_ptr<Analyzer::TargetEntry>> build_result_plan_targets(
834  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets,
835  const rapidjson::Value& exprs,
836  const rapidjson::Value& fields,
837  CalciteAdapter& calcite_adapter) {
838  const auto var_refs_to_in_targets = build_var_refs(in_targets);
839  std::vector<std::shared_ptr<Analyzer::TargetEntry>> result;
840  CHECK(fields.IsArray());
841  CHECK_EQ(exprs.Size(), fields.Size());
842  auto fields_it = fields.Begin();
843  for (auto exprs_it = exprs.Begin(); exprs_it != exprs.End(); ++exprs_it, ++fields_it) {
844  const auto analyzer_expr =
845  calcite_adapter.getExprFromNode(*exprs_it, var_refs_to_in_targets);
846  CHECK(fields_it != exprs.End());
847  CHECK(fields_it->IsString());
848  result.emplace_back(
849  new Analyzer::TargetEntry(fields_it->GetString(), analyzer_expr, false));
850  }
851  return result;
852 }
853 
855  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets) {
856  CHECK(!in_targets.empty());
857  for (const auto target : in_targets) {
858  if (!dynamic_cast<const Analyzer::Var*>(target->get_expr())) {
859  return false;
860  }
861  }
862  return true;
863 }
864 
865 std::vector<std::shared_ptr<Analyzer::TargetEntry>> handle_logical_project(
866  std::vector<std::shared_ptr<Analyzer::TargetEntry>>& child_plan_targets,
867  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets,
868  const rapidjson::Value& logical_project,
869  CalciteAdapter& calcite_adapter) {
870  const auto exprs_mem_it = logical_project.FindMember("exprs");
871  CHECK(exprs_mem_it != logical_project.MemberEnd());
872  const auto& exprs = exprs_mem_it->value;
873  const auto fields_mem_it = logical_project.FindMember("fields");
874  CHECK(fields_mem_it != logical_project.MemberEnd());
875  const auto& fields = fields_mem_it->value;
876  auto result = get_input_targets(in_targets, exprs, fields, calcite_adapter);
877  if (in_targets.empty()) { // source scan was the table itself
878  return result;
879  }
880  // needs a re-projection or a result plan
881  if (needs_result_plan(exprs)) {
882  if (!targets_are_refs(result)) {
883  child_plan_targets = result;
884  }
885  return build_result_plan_targets(result, exprs, fields, calcite_adapter);
886  } else { // just target permutation. no need to create a result plan
887  const auto reproj_indices = collect_reproject_indices(exprs);
888  reproject_target_entries(result, reproj_indices, fields);
889  }
890  return result;
891 }
892 
893 std::vector<std::shared_ptr<Analyzer::TargetEntry>> handle_logical_aggregate(
894  const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& in_targets,
895  std::list<std::shared_ptr<Analyzer::Expr>>& groupby_exprs,
896  const rapidjson::Value& logical_aggregate,
897  CalciteAdapter& calcite_adapter) {
898  std::vector<std::shared_ptr<Analyzer::TargetEntry>> result;
899  const auto& agg_nodes = logical_aggregate["aggs"];
900  const auto& group_nodes = logical_aggregate["group"];
901  CHECK(group_nodes.IsArray());
902  for (auto group_nodes_it = group_nodes.Begin(); group_nodes_it != group_nodes.End();
903  ++group_nodes_it) {
904  CHECK(group_nodes_it->IsInt());
905  const int target_idx = group_nodes_it->GetInt();
906  groupby_exprs.push_back(set_transient_dict(in_targets[target_idx]->get_own_expr()));
907  }
908  CHECK(agg_nodes.IsArray());
909  const auto& fields = logical_aggregate["fields"];
910  CHECK(fields.IsArray());
911  auto fields_it = fields.Begin();
912  for (auto group_nodes_it = group_nodes.Begin(); group_nodes_it != group_nodes.End();
913  ++group_nodes_it, ++fields_it) {
914  CHECK(group_nodes_it->IsInt());
915  const int target_idx = group_nodes_it->GetInt();
916  const auto target = in_targets[target_idx];
917  CHECK(fields_it != fields.End());
918  CHECK(fields_it->IsString());
919  CHECK_EQ(target->get_resname(), fields_it->GetString());
920  const auto target_expr = set_transient_dict(target->get_own_expr());
921  const auto uoper_expr = dynamic_cast<const Analyzer::UOper*>(target_expr.get());
922  const bool is_unnest{uoper_expr && uoper_expr->get_optype() == kUNNEST};
923  auto group_var_ref = var_ref(target_expr.get(),
925  group_nodes_it - group_nodes.Begin() + 1);
926  result.emplace_back(
927  new Analyzer::TargetEntry(target->get_resname(), group_var_ref, is_unnest));
928  }
929  for (auto agg_nodes_it = agg_nodes.Begin(); agg_nodes_it != agg_nodes.End();
930  ++agg_nodes_it, ++fields_it) {
931  auto agg_expr = calcite_adapter.getExprFromNode(*agg_nodes_it, in_targets);
932  CHECK(fields_it != fields.End());
933  CHECK(fields_it->IsString());
934  result.emplace_back(
935  new Analyzer::TargetEntry(fields_it->GetString(), agg_expr, false));
936  }
937  return result;
938 }
939 
940 void add_quals(const std::shared_ptr<Analyzer::Expr> qual_expr,
941  std::list<std::shared_ptr<Analyzer::Expr>>& simple_quals,
942  std::list<std::shared_ptr<Analyzer::Expr>>& quals) {
943  CHECK(qual_expr);
944  const auto bin_oper = std::dynamic_pointer_cast<const Analyzer::BinOper>(qual_expr);
945  if (!bin_oper) {
946  quals.push_back(qual_expr);
947  return;
948  }
949  if (bin_oper->get_optype() == kAND) {
950  add_quals(bin_oper->get_own_left_operand(), simple_quals, quals);
951  add_quals(bin_oper->get_own_right_operand(), simple_quals, quals);
952  return;
953  }
954  int rte_idx{0};
955  const auto simple_qual = bin_oper->normalize_simple_predicate(rte_idx);
956  if (simple_qual) {
957  simple_quals.push_back(simple_qual);
958  } else {
959  quals.push_back(qual_expr);
960  }
961 }
962 
963 void collect_used_columns(std::vector<std::shared_ptr<Analyzer::ColumnVar>>& used_cols,
964  const std::shared_ptr<Analyzer::Expr> expr) {
965  const auto col_var = std::dynamic_pointer_cast<Analyzer::ColumnVar>(expr);
966  if (col_var && !std::dynamic_pointer_cast<Analyzer::Var>(col_var)) {
967  used_cols.push_back(col_var);
968  return;
969  }
970  const auto uoper = std::dynamic_pointer_cast<Analyzer::UOper>(expr);
971  if (uoper) {
972  collect_used_columns(used_cols, uoper->get_own_operand());
973  return;
974  }
975  const auto bin_oper = std::dynamic_pointer_cast<Analyzer::BinOper>(expr);
976  if (bin_oper) {
977  collect_used_columns(used_cols, bin_oper->get_own_left_operand());
978  collect_used_columns(used_cols, bin_oper->get_own_right_operand());
979  return;
980  }
981  const auto extract_expr = std::dynamic_pointer_cast<Analyzer::ExtractExpr>(expr);
982  if (extract_expr) {
983  collect_used_columns(used_cols, extract_expr->get_own_from_expr());
984  return;
985  }
986  const auto datetrunc_expr = std::dynamic_pointer_cast<Analyzer::DatetruncExpr>(expr);
987  if (datetrunc_expr) {
988  collect_used_columns(used_cols, datetrunc_expr->get_own_from_expr());
989  return;
990  }
991  const auto charlength_expr = std::dynamic_pointer_cast<Analyzer::CharLengthExpr>(expr);
992  if (charlength_expr) {
993  collect_used_columns(used_cols, charlength_expr->get_own_arg());
994  return;
995  }
996  const auto keyforstring_expr =
997  std::dynamic_pointer_cast<Analyzer::KeyForStringExpr>(expr);
998  if (keyforstring_expr) {
999  collect_used_columns(used_cols, keyforstring_expr->get_own_arg());
1000  return;
1001  }
1002  const auto cardinality_expr =
1003  std::dynamic_pointer_cast<Analyzer::CardinalityExpr>(expr);
1004  if (cardinality_expr) {
1005  collect_used_columns(used_cols, cardinality_expr->get_own_arg());
1006  return;
1007  }
1008  const auto like_expr = std::dynamic_pointer_cast<Analyzer::LikeExpr>(expr);
1009  if (like_expr) {
1010  collect_used_columns(used_cols, like_expr->get_own_arg());
1011  return;
1012  }
1013 }
1014 
1015 std::unordered_set<int> get_used_table_ids(
1016  const std::vector<std::shared_ptr<Analyzer::ColumnVar>>& used_cols) {
1017  std::unordered_set<int> result;
1018  for (const auto col_var : used_cols) {
1019  result.insert(col_var->get_table_id());
1020  }
1021  return result;
1022 }
1023 
1025  std::unordered_map<int, std::list<std::shared_ptr<Analyzer::Expr>>>& quals,
1026  std::list<std::shared_ptr<Analyzer::Expr>>& join_quals,
1027  const std::list<std::shared_ptr<Analyzer::Expr>>& all_quals) {
1028  for (auto qual_candidate : all_quals) {
1029  std::vector<std::shared_ptr<Analyzer::ColumnVar>> used_columns;
1030  collect_used_columns(used_columns, qual_candidate);
1031  const auto used_table_ids = get_used_table_ids(used_columns);
1032  if (used_table_ids.size() > 1) {
1033  CHECK_EQ(size_t(2), used_table_ids.size());
1034  join_quals.push_back(qual_candidate);
1035  } else {
1036  CHECK(!used_table_ids.empty());
1037  quals[*used_table_ids.begin()].push_back(qual_candidate);
1038  }
1039  }
1040 }
1041 
1042 const std::string get_op_name(const rapidjson::Value& obj) {
1043  CHECK(obj.IsObject());
1044  const auto field_it = obj.FindMember("relOp");
1045  CHECK(field_it != obj.MemberEnd());
1046  const auto& field = field_it->value;
1047  CHECK(field.IsString());
1048  return field.GetString();
1049 }
1050 
1051 bool match_compound_seq(rapidjson::Value::ConstValueIterator& rels_it,
1052  const rapidjson::Value::ConstValueIterator rels_end) {
1053  auto op_name = get_op_name(*rels_it);
1054  if (op_name == std::string("LogicalFilter")) {
1055  ++rels_it;
1056  }
1057  op_name = get_op_name(*rels_it++);
1058  if (op_name != std::string("LogicalProject")) {
1059  return false;
1060  }
1061  if (rels_it == rels_end) {
1062  return true;
1063  }
1064  op_name = get_op_name(*rels_it);
1065  if (op_name == std::string("LogicalAggregate")) {
1066  ++rels_it;
1067  if (rels_it == rels_end) {
1068  return true;
1069  }
1070  op_name = get_op_name(*rels_it);
1071  if (op_name == std::string("LogicalProject")) {
1072  ++rels_it;
1073  }
1074  }
1075  return true;
1076 }
1077 
1078 bool match_filter_project_seq(rapidjson::Value::ConstValueIterator& rels_it,
1079  const rapidjson::Value::ConstValueIterator rels_end) {
1080  CHECK(rels_it != rels_end);
1081  auto op_name = get_op_name(*rels_it++);
1082  if (op_name != std::string("LogicalFilter")) {
1083  return false;
1084  }
1085  if (rels_it != rels_end && get_op_name(*rels_it) == std::string("LogicalProject")) {
1086  ++rels_it;
1087  }
1088  return true;
1089 }
1090 
1091 bool match_sort_seq(rapidjson::Value::ConstValueIterator& rels_it,
1092  const rapidjson::Value::ConstValueIterator rels_end) {
1093  auto op_name = get_op_name(*rels_it++);
1094  if (op_name != std::string("LogicalSort")) {
1095  return false;
1096  }
1097  if (rels_it == rels_end) {
1098  return true;
1099  }
1100  op_name = get_op_name(*rels_it++);
1101  if (op_name != std::string("LogicalProject")) {
1102  return false;
1103  }
1104  op_name = get_op_name(*rels_it++);
1105  if (op_name != std::string("LogicalSort")) {
1106  return false;
1107  }
1108  return rels_it == rels_end;
1109 }
1110 
1111 // We don't aim to support everything Calcite allows in this adapter. Inspect
1112 // the nodes and reject queries which go beyond the legacy front-end.
1113 bool query_is_supported(const rapidjson::Value& rels) {
1114  rapidjson::Value::ConstValueIterator rels_it = rels.Begin();
1115  if (std::string("EnumerableTableScan") != get_op_name(*rels_it++)) {
1116  return false;
1117  }
1118  const auto op_name = get_op_name(*rels_it);
1119  if (op_name == std::string("EnumerableTableScan")) {
1120  ++rels_it;
1121  CHECK(rels_it != rels.End());
1122  if (get_op_name(*rels_it++) != std::string("LogicalJoin")) {
1123  return false;
1124  }
1125  }
1126  if (!match_compound_seq(rels_it, rels.End())) {
1127  return false;
1128  }
1129  if (rels_it == rels.End()) {
1130  return true;
1131  }
1132  if (get_op_name(*rels_it) == std::string("LogicalSort")) {
1133  return match_sort_seq(rels_it, rels.End());
1134  }
1135  // HAVING query
1136  if (!match_filter_project_seq(rels_it, rels.End())) {
1137  return false;
1138  }
1139  if (rels_it == rels.End()) {
1140  return true;
1141  }
1142  if (!match_sort_seq(rels_it, rels.End())) {
1143  return false;
1144  }
1145  return rels_it == rels.End();
1146 }
1147 
1148 } // namespace
1149 
1150 Planner::RootPlan* translate_query(const std::string& query,
1151  const Catalog_Namespace::Catalog& cat) {
1152  rapidjson::Document query_ast;
1153  query_ast.Parse(query.c_str());
1154  CHECK(!query_ast.HasParseError());
1155  CHECK(query_ast.IsObject());
1156  const auto& rels = query_ast["rels"];
1157  if (!query_is_supported(rels)) {
1158  throw std::runtime_error("This query is not supported yet");
1159  }
1160  CHECK(rels.IsArray());
1161  CalciteAdapter calcite_adapter(cat, rels);
1162  std::list<std::shared_ptr<Analyzer::Expr>> quals;
1163  std::list<std::shared_ptr<Analyzer::Expr>> simple_quals;
1164  std::list<std::shared_ptr<Analyzer::Expr>> result_quals;
1165  std::list<std::shared_ptr<Analyzer::Expr>> all_join_simple_quals;
1166  std::list<std::shared_ptr<Analyzer::Expr>> all_join_quals;
1167  std::vector<std::shared_ptr<Analyzer::TargetEntry>> child_res_targets;
1168  std::vector<std::shared_ptr<Analyzer::TargetEntry>> res_targets;
1169  std::list<std::shared_ptr<Analyzer::Expr>> groupby_exprs;
1170  bool is_agg_plan{false};
1171  bool is_join{false};
1172  for (auto rels_it = rels.Begin(); rels_it != rels.End(); ++rels_it) {
1173  const auto& crt_node = *rels_it;
1174  CHECK(crt_node.IsObject());
1175  const auto rel_op_it = crt_node.FindMember("relOp");
1176  CHECK(rel_op_it != crt_node.MemberEnd());
1177  CHECK(rel_op_it->value.IsString());
1178  if (rel_op_it->value.GetString() == std::string("EnumerableTableScan") ||
1179  rel_op_it->value.GetString() == std::string("LogicalSort")) {
1180  continue;
1181  }
1182  if (rel_op_it->value.GetString() == std::string("LogicalProject")) {
1183  res_targets = handle_logical_project(
1184  child_res_targets, res_targets, crt_node, calcite_adapter);
1185  } else if (rel_op_it->value.GetString() == std::string("LogicalAggregate")) {
1186  is_agg_plan = true;
1187  CHECK(!res_targets.empty());
1188  res_targets =
1189  handle_logical_aggregate(res_targets, groupby_exprs, crt_node, calcite_adapter);
1190  } else if (rel_op_it->value.GetString() == std::string("LogicalFilter")) {
1191  if (res_targets.empty()) {
1192  if (is_join) {
1193  add_quals(calcite_adapter.getExprFromNode(crt_node["condition"], {}),
1194  all_join_simple_quals,
1195  all_join_quals);
1196  } else {
1197  add_quals(calcite_adapter.getExprFromNode(crt_node["condition"], {}),
1198  simple_quals,
1199  quals);
1200  }
1201  } else {
1202  child_res_targets = res_targets;
1203  res_targets = build_var_refs(res_targets);
1204  add_quals(calcite_adapter.getExprFromNode(crt_node["condition"], res_targets),
1205  result_quals,
1206  result_quals);
1207  }
1208  } else if (rel_op_it->value.GetString() == std::string("LogicalJoin")) {
1209  const auto condition = std::dynamic_pointer_cast<Analyzer::Constant>(
1210  calcite_adapter.getExprFromNode(crt_node["condition"], {}));
1211  if (!condition) {
1212  throw std::runtime_error("Unsupported join condition");
1213  }
1214  const auto condition_ti = condition->get_type_info();
1215  CHECK(condition_ti.is_boolean());
1216  if (crt_node["joinType"].GetString() != std::string("inner")) {
1217  throw std::runtime_error("Only inner joins supported for now");
1218  }
1219  // TODO(alex): use the information in this node?
1220  is_join = true;
1221  } else {
1222  throw std::runtime_error(std::string("Node ") + rel_op_it->value.GetString() +
1223  " not supported yet");
1224  }
1225  }
1226  const auto tds = calcite_adapter.getTableDescriptors();
1227  if (is_join) {
1228  CHECK_EQ(size_t(2), tds.size());
1229  } else {
1230  CHECK_EQ(size_t(1), tds.size());
1231  }
1232  CHECK(!res_targets.empty());
1233  Planner::Plan* plan{nullptr};
1234  if (is_join) {
1235  std::unordered_map<int, std::list<std::shared_ptr<Analyzer::Expr>>> scan_quals;
1236  std::list<std::shared_ptr<Analyzer::Expr>> join_quals;
1237  separate_join_quals(scan_quals, join_quals, all_join_quals);
1238  std::unordered_map<int, std::list<std::shared_ptr<Analyzer::Expr>>> scan_simple_quals;
1239  std::list<std::shared_ptr<Analyzer::Expr>> join_simple_quals;
1240  separate_join_quals(scan_simple_quals, join_simple_quals, all_join_simple_quals);
1241  CHECK_LE(scan_quals.size(), size_t(2));
1242  CHECK_LE(scan_simple_quals.size(), size_t(2));
1243  const int outer_tid = tds[0]->tableId;
1244  const int inner_tid = tds[1]->tableId;
1245  auto outer_plan = get_agg_plan(tds[0],
1246  {},
1247  {},
1248  groupby_exprs,
1249  scan_quals[outer_tid],
1250  scan_simple_quals[outer_tid],
1251  calcite_adapter);
1252  auto inner_plan = get_agg_plan(tds[1],
1253  {},
1254  {},
1255  groupby_exprs,
1256  scan_quals[inner_tid],
1257  scan_simple_quals[inner_tid],
1258  calcite_adapter);
1259  if (child_res_targets.empty()) {
1260  if (is_agg_plan) {
1261  plan = new Planner::Join({}, join_quals, 0, outer_plan, inner_plan);
1262  plan = new Planner::AggPlan(res_targets, 0., plan, groupby_exprs);
1263  } else {
1264  plan = new Planner::Join(res_targets, join_quals, 0, outer_plan, inner_plan);
1265  }
1266  } else {
1267  if (is_agg_plan) {
1268  plan = new Planner::Join({}, join_quals, 0, outer_plan, inner_plan);
1269  plan = new Planner::AggPlan(child_res_targets, 0., plan, groupby_exprs);
1270  } else {
1271  plan =
1272  new Planner::Join(child_res_targets, join_quals, 0, outer_plan, inner_plan);
1273  }
1274  plan = new Planner::Result(res_targets, result_quals, 0, plan, {});
1275  }
1276  } else if (child_res_targets.empty()) {
1277  std::vector<std::shared_ptr<Analyzer::TargetEntry>> agg_targets{
1278  is_agg_plan ? res_targets
1279  : std::vector<std::shared_ptr<Analyzer::TargetEntry>>{}};
1280  std::vector<std::shared_ptr<Analyzer::TargetEntry>> scan_targets{
1281  is_agg_plan ? std::vector<std::shared_ptr<Analyzer::TargetEntry>>{}
1282  : res_targets};
1283  plan = get_agg_plan(tds[0],
1284  scan_targets,
1285  agg_targets,
1286  groupby_exprs,
1287  quals,
1288  simple_quals,
1289  calcite_adapter);
1290  } else {
1291  std::vector<std::shared_ptr<Analyzer::TargetEntry>> agg_targets{
1292  is_agg_plan ? child_res_targets
1293  : std::vector<std::shared_ptr<Analyzer::TargetEntry>>{}};
1294  std::vector<std::shared_ptr<Analyzer::TargetEntry>> scan_targets{
1295  is_agg_plan ? std::vector<std::shared_ptr<Analyzer::TargetEntry>>{}
1296  : child_res_targets};
1297  plan = get_agg_plan(tds[0],
1298  scan_targets,
1299  agg_targets,
1300  groupby_exprs,
1301  quals,
1302  simple_quals,
1303  calcite_adapter);
1304  plan = new Planner::Result(res_targets, result_quals, 0, plan, {});
1305  }
1306  CHECK(plan);
1307  const auto logical_sort_info = get_logical_sort_info(rels);
1308  plan = get_sort_plan(plan, rels, {}, res_targets);
1309  return new Planner::RootPlan(plan,
1310  kSELECT,
1311  tds[0]->tableId,
1312  {},
1313  cat,
1314  logical_sort_info.limit,
1315  logical_sort_info.offset);
1316 }
1317 
1318 namespace {
1319 
1320 std::string pg_shim_impl(const std::string& query) {
1321  auto result = query;
1322  {
1323  boost::regex unnest_expr{R"((\s+|,)(unnest)\s*\()",
1324  boost::regex::extended | boost::regex::icase};
1325  apply_shim(result, unnest_expr, [](std::string& result, const boost::smatch& what) {
1326  result.replace(what.position(), what.length(), what[1] + "PG_UNNEST(");
1327  });
1328  }
1329  {
1330  boost::regex cast_true_expr{R"(CAST\s*\(\s*'t'\s+AS\s+boolean\s*\))",
1331  boost::regex::extended | boost::regex::icase};
1332  apply_shim(
1333  result, cast_true_expr, [](std::string& result, const boost::smatch& what) {
1334  result.replace(what.position(), what.length(), "true");
1335  });
1336  }
1337  {
1338  boost::regex cast_false_expr{R"(CAST\s*\(\s*'f'\s+AS\s+boolean\s*\))",
1339  boost::regex::extended | boost::regex::icase};
1340  apply_shim(
1341  result, cast_false_expr, [](std::string& result, const boost::smatch& what) {
1342  result.replace(what.position(), what.length(), "false");
1343  });
1344  }
1345  {
1346  boost::regex ilike_expr{
1347  R"((\s+|\()((?!\()[^\s]+)\s+ilike\s+('(?:[^']+|'')+')(\s+escape(\s+('[^']+')))?)",
1348  boost::regex::perl | boost::regex::icase};
1349  apply_shim(result, ilike_expr, [](std::string& result, const boost::smatch& what) {
1350  std::string esc = what[6];
1351  result.replace(what.position(),
1352  what.length(),
1353  what[1] + "PG_ILIKE(" + what[2] + ", " + what[3] +
1354  (esc.empty() ? "" : ", " + esc) + ")");
1355  });
1356  }
1357  {
1358  boost::regex regexp_expr{
1359  R"((\s+)([^\s]+)\s+REGEXP\s+('(?:[^']+|'')+')(\s+escape(\s+('[^']+')))?)",
1360  boost::regex::perl | boost::regex::icase};
1361  apply_shim(result, regexp_expr, [](std::string& result, const boost::smatch& what) {
1362  std::string esc = what[6];
1363  result.replace(what.position(),
1364  what.length(),
1365  what[1] + "REGEXP_LIKE(" + what[2] + ", " + what[3] +
1366  (esc.empty() ? "" : ", " + esc) + ")");
1367  });
1368  }
1369  {
1370  boost::regex extract_expr{R"(extract\s*\(\s*(\w+)\s+from\s+(.+)\))",
1371  boost::regex::extended | boost::regex::icase};
1372  apply_shim(result, extract_expr, [](std::string& result, const boost::smatch& what) {
1373  result.replace(what.position(),
1374  what.length(),
1375  "PG_EXTRACT('" + what[1] + "', " + what[2] + ")");
1376  });
1377  }
1378  {
1379  boost::regex date_trunc_expr{R"(date_trunc\s*\(\s*(\w+)\s*,(.*)\))",
1380  boost::regex::extended | boost::regex::icase};
1381  apply_shim(
1382  result, date_trunc_expr, [](std::string& result, const boost::smatch& what) {
1383  result.replace(what.position(),
1384  what.length(),
1385  "PG_DATE_TRUNC('" + what[1] + "', " + what[2] + ")");
1386  });
1387  }
1388  {
1389  boost::regex quant_expr{R"(\s(any|all)\s+([^(\s|;)]+))",
1390  boost::regex::extended | boost::regex::icase};
1391  apply_shim(result, quant_expr, [](std::string& result, const boost::smatch& what) {
1392  std::string qual_name = what[1];
1393  std::string quant_fname{boost::iequals(qual_name, "any") ? "PG_ANY" : "PG_ALL"};
1394  result.replace(what.position(), what.length(), quant_fname + "(" + what[2] + ")");
1395  });
1396  }
1397  {
1398  boost::regex immediate_cast_expr{R"(TIMESTAMP\(([0369])\)\s+('[^']+'))",
1399  boost::regex::extended | boost::regex::icase};
1400  apply_shim(
1401  result, immediate_cast_expr, [](std::string& result, const boost::smatch& what) {
1402  result.replace(what.position(),
1403  what.length(),
1404  "CAST(" + what[2] + " AS TIMESTAMP(" + what[1] + "))");
1405  });
1406  }
1407  {
1408  boost::regex timestampadd_expr{R"(TIMESTAMPADD\s*\(\s*(\w+)\s*,)",
1409  boost::regex::extended | boost::regex::icase};
1410  apply_shim(
1411  result, timestampadd_expr, [](std::string& result, const boost::smatch& what) {
1412  result.replace(what.position(), what.length(), "DATEADD('" + what[1] + "',");
1413  });
1414  }
1415  {
1416  boost::regex us_timestamp_cast_expr{
1417  R"(CAST\s*\(\s*('[^']+')\s*AS\s*TIMESTAMP\(6\)\s*\))",
1418  boost::regex::extended | boost::regex::icase};
1420  us_timestamp_cast_expr,
1421  [](std::string& result, const boost::smatch& what) {
1422  result.replace(
1423  what.position(), what.length(), "usTIMESTAMP(" + what[1] + ")");
1424  });
1425  }
1426  {
1427  boost::regex ns_timestamp_cast_expr{
1428  R"(CAST\s*\(\s*('[^']+')\s*AS\s*TIMESTAMP\(9\)\s*\))",
1429  boost::regex::extended | boost::regex::icase};
1431  ns_timestamp_cast_expr,
1432  [](std::string& result, const boost::smatch& what) {
1433  result.replace(
1434  what.position(), what.length(), "nsTIMESTAMP(" + what[1] + ")");
1435  });
1436  }
1437  {
1438  boost::regex corr_expr{R"((\s+|,|\()(corr)\s*\()",
1439  boost::regex::extended | boost::regex::icase};
1440  apply_shim(result, corr_expr, [](std::string& result, const boost::smatch& what) {
1441  result.replace(what.position(), what.length(), what[1] + "CORRELATION(");
1442  });
1443  }
1444  {
1445  try {
1446  // the geography regex pattern is expensive and can sometimes run out of stack space
1447  // on long queries. Treat it separately from the other shims.
1448  boost::regex cast_to_geography_expr{
1449  R"(CAST\s*\(\s*(((?!geography).)+)\s+AS\s+geography\s*\))",
1450  boost::regex::perl | boost::regex::icase};
1452  cast_to_geography_expr,
1453  [](std::string& result, const boost::smatch& what) {
1454  result.replace(what.position(),
1455  what.length(),
1456  "CastToGeography(" + what[1] + ")");
1457  });
1458  } catch (const std::exception& e) {
1459  LOG(WARNING) << "Error apply geography cast shim: " << e.what()
1460  << "\nContinuing query parse...";
1461  }
1462  }
1463  return result;
1464 }
1465 
1466 } // namespace
1467 
1468 std::string pg_shim(const std::string& query) {
1469  try {
1470  return pg_shim_impl(query);
1471  } catch (const std::exception& e) {
1472  LOG(WARNING) << "Error applying shim: " << e.what() << "\nContinuing query parse...";
1473  // boost::regex throws an exception about the complexity of matching when
1474  // the wrong type of quotes are used or they're mismatched. Let the query
1475  // through unmodified, the parser will throw a much more informative error.
1476  }
1477  return query;
1478 }
SQLTypes to_sql_type(const std::string &type_name)
Definition: sqldefs.h:69
#define CHECK_EQ(x, y)
Definition: Logger.h:198
std::shared_ptr< Analyzer::Expr > translateRegexp(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
Definition: Analyzer.h:1483
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:81
Definition: sqltypes.h:52
std::shared_ptr< Analyzer::Expr > set_transient_dict(const std::shared_ptr< Analyzer::Expr > expr)
std::shared_ptr< Analyzer::Expr > getExprFromNode(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
void add_quals(const std::shared_ptr< Analyzer::Expr > qual_expr, std::list< std::shared_ptr< Analyzer::Expr >> &simple_quals, std::list< std::shared_ptr< Analyzer::Expr >> &quals)
std::shared_ptr< Analyzer::Expr > translateDatepart(const rapidjson::Value &operands, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
SQLQualifier
Definition: sqldefs.h:69
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:112
SQLAgg to_agg_kind(const std::string &agg_name)
#define LOG(tag)
Definition: Logger.h:185
bool boolval
Definition: sqltypes.h:125
std::shared_ptr< Analyzer::Expr > translateDatediff(const rapidjson::Value &operands, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
std::shared_ptr< Analyzer::Var > var_ref(const Analyzer::Expr *expr, const Analyzer::Var::WhichRow which_row, const int varno)
Definition: Analyzer.h:1585
#define CHECK_GE(x, y)
Definition: Logger.h:203
std::unordered_set< int > get_used_table_ids(const std::vector< std::shared_ptr< Analyzer::ColumnVar >> &used_cols)
Definition: sqldefs.h:49
std::vector< std::shared_ptr< Analyzer::TargetEntry > > build_var_refs(const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets)
SQLTypeInfo get_agg_type(const SQLAgg agg_kind, const Analyzer::Expr *arg_expr)
std::shared_ptr< Analyzer::Expr > translateLike(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets, const bool is_ilike)
void collect_used_columns(std::vector< std::shared_ptr< Analyzer::ColumnVar >> &used_cols, const std::shared_ptr< Analyzer::Expr > expr)
static std::shared_ptr< Analyzer::Expr > normalize(const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >)
Definition: ParserNode.cpp:905
std::shared_ptr< Analyzer::Expr > translateItem(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
std::vector< std::shared_ptr< Analyzer::TargetEntry > > handle_logical_aggregate(const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets, std::list< std::shared_ptr< Analyzer::Expr >> &groupby_exprs, const rapidjson::Value &logical_aggregate, CalciteAdapter &calcite_adapter)
std::shared_ptr< Analyzer::Expr > translateExtract(const rapidjson::Value &operands, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets, const bool is_date_trunc)
LogicalSortInfo get_logical_sort_info(const rapidjson::Value &rels)
ExtractField to_datepart_field(const std::string &field)
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
std::shared_ptr< Analyzer::Expr > translateCase(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
void reproject_target_entries(std::vector< std::shared_ptr< Analyzer::TargetEntry >> &agg_targets, const std::vector< size_t > &result_proj_indices, const rapidjson::Value &fields)
CHECK(cgen_state)
std::pair< std::shared_ptr< Analyzer::Expr >, SQLQualifier > getQuantifiedRhs(const rapidjson::Value &rhs_op, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
bool match_sort_seq(rapidjson::Value::ConstValueIterator &rels_it, const rapidjson::Value::ConstValueIterator rels_end)
bool is_time() const
Definition: sqltypes.h:483
const std::shared_ptr< Analyzer::Expr > generate() const
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, std::shared_ptr< Analyzer::Expr > pattern_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_not)
Definition: ParserNode.cpp:625
std::vector< std::shared_ptr< Analyzer::TargetEntry > > handle_logical_project(std::vector< std::shared_ptr< Analyzer::TargetEntry >> &child_plan_targets, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets, const rapidjson::Value &logical_project, CalciteAdapter &calcite_adapter)
SQLOps to_sql_op(const std::string &op_str)
std::shared_ptr< Analyzer::Expr > translateOp(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
int64_t bigintval
Definition: sqltypes.h:129
static std::vector< std::string > getColNames(const rapidjson::Value &scan_ra)
bool targets_are_refs(const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets)
std::shared_ptr< Analyzer::Expr > translateAggregate(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
Planner::Plan * get_agg_plan(const TableDescriptor *td, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &agg_targets, const std::list< std::shared_ptr< Analyzer::Expr >> &groupby_exprs, std::list< std::shared_ptr< Analyzer::Expr >> &q, std::list< std::shared_ptr< Analyzer::Expr >> &sq, CalciteAdapter &calcite_adapter)
Definition: sqldefs.h:37
Definition: sqldefs.h:69
static std::shared_ptr< Analyzer::Expr > analyzeValue(const std::string &)
Definition: ParserNode.cpp:97
std::tuple< const rapidjson::Value *, SQLTypeInfo, SQLTypeInfo > parse_literal(const rapidjson::Value &expr)
DatetruncField to_datediff_field(const std::string &field)
std::string pg_shim_impl(const std::string &query)
void separate_join_quals(std::unordered_map< int, std::list< std::shared_ptr< Analyzer::Expr >>> &quals, std::list< std::shared_ptr< Analyzer::Expr >> &join_quals, const std::list< std::shared_ptr< Analyzer::Expr >> &all_quals)
std::shared_ptr< Analyzer::Expr > translateUnaryOp(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, float likelihood, const bool is_not)
Definition: ParserNode.cpp:676
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:852
static std::shared_ptr< Analyzer::Expr > normalize(const SQLOps optype, const SQLQualifier qual, std::shared_ptr< Analyzer::Expr > left_expr, std::shared_ptr< Analyzer::Expr > right_expr)
Definition: ParserNode.cpp:261
void apply_shim(std::string &result, const boost::regex &reg_expr, const std::function< void(std::string &, const boost::smatch &)> &shim_fn)
ssize_t get_agg_operand_idx(const rapidjson::Value &expr)
Planner::RootPlan * translate_query(const std::string &query, const Catalog_Namespace::Catalog &cat)
#define CHECK_LT(x, y)
Definition: Logger.h:200
Definition: sqltypes.h:55
Definition: sqltypes.h:56
Definition: sqldefs.h:40
std::vector< std::shared_ptr< Analyzer::TargetEntry > > build_result_plan_targets(const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets, const rapidjson::Value &exprs, const rapidjson::Value &fields, CalciteAdapter &calcite_adapter)
Definition: sqldefs.h:69
#define TRANSIENT_DICT_ID
Definition: sqltypes.h:189
#define CHECK_LE(x, y)
Definition: Logger.h:201
bool is_null(const T &v, const SQLTypeInfo &t)
static std::shared_ptr< Analyzer::Expr > get(std::shared_ptr< Analyzer::Expr > arg_expr, std::shared_ptr< Analyzer::Expr > like_expr, std::shared_ptr< Analyzer::Expr > escape_expr, const bool is_ilike, const bool is_not)
Definition: ParserNode.cpp:530
std::shared_ptr< Analyzer::Expr > translateTypedLiteral(const rapidjson::Value &expr)
CalciteAdapter(const Catalog_Namespace::Catalog &cat, const rapidjson::Value &rels)
Planner::Plan * get_sort_plan(Planner::Plan *plan, const rapidjson::Value &rels, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &agg_targets)
bool query_is_supported(const rapidjson::Value &rels)
bool takes_arg(const TargetInfo &target_info)
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t numericval, const int scale, const int precision)
Definition: ParserNode.cpp:137
std::vector< const TableDescriptor * > getTableDescriptors() const
Definition: sqldefs.h:53
const std::string get_op_name(const rapidjson::Value &obj)
static std::shared_ptr< Analyzer::Expr > get(const int64_t)
Definition: ParserNode.cpp:173
std::unordered_map< int32_t, std::set< int > > used_columns_
std::shared_ptr< Analyzer::Constant > make_fp_constant(const int64_t val, const SQLTypeInfo &ti)
bool match_filter_project_seq(rapidjson::Value::ConstValueIterator &rels_it, const rapidjson::Value::ConstValueIterator rels_end)
bool needs_result_plan(const rapidjson::Value &exprs)
Planner::Scan * get_scan_plan(const TableDescriptor *td, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets, std::list< std::shared_ptr< Analyzer::Expr >> &q, std::list< std::shared_ptr< Analyzer::Expr >> &sq, CalciteAdapter &calcite_adapter)
std::shared_ptr< Analyzer::Expr > translateLikely(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
std::shared_ptr< Analyzer::Expr > translateColRef(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
std::list< int > getUsedColumnList(const int32_t table_id) const
std::vector< size_t > collect_reproject_indices(const rapidjson::Value &exprs)
std::vector< std::shared_ptr< Analyzer::TargetEntry > > get_input_targets(const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &in_targets, const rapidjson::Value &exprs, const rapidjson::Value &fields, CalciteAdapter &calcite_adapter)
bool is_unnest(const Analyzer::Expr *expr)
Definition: Execute.h:1090
specifies the content in-memory of a row in the table metadata table
std::shared_ptr< Analyzer::Expr > translateUnlikely(const rapidjson::Value &expr, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
std::shared_ptr< Analyzer::Expr > translateDateadd(const rapidjson::Value &operands, const std::vector< std::shared_ptr< Analyzer::TargetEntry >> &scan_targets)
bool is_distinct(const size_t input_idx, const RelAlgNode *node)
std::string pg_shim(const std::string &query)
Definition: sqldefs.h:39
bool match_compound_seq(rapidjson::Value::ConstValueIterator &rels_it, const rapidjson::Value::ConstValueIterator rels_end)
DateaddField to_dateadd_field(const std::string &field)
double doubleval
Definition: sqltypes.h:131
const TableDescriptor * getTableFromScanNode(const rapidjson::Value &scan_ra) const
const std::shared_ptr< Analyzer::Expr > generate() const