OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
anonymous_namespace{CalciteAdapter.cpp} Namespace Reference

Functions

std::string pg_shim_impl (const std::string &query)
 

Function Documentation

std::string anonymous_namespace{CalciteAdapter.cpp}::pg_shim_impl ( const std::string &  query)

Definition at line 28 of file CalciteAdapter.cpp.

References apply_shim(), LOG, shared::power10(), run_benchmark_import::result, to_lower(), to_string(), and logger::WARNING.

Referenced by pg_shim().

28  {
29  auto result = query;
30  {
31  static const auto& unnest_expr = *new boost::regex(
32  R"((\s+|,)(unnest)\s*\()", boost::regex::extended | boost::regex::icase);
33  static_assert(std::is_trivially_destructible_v<decltype(unnest_expr)>);
34  apply_shim(result, unnest_expr, [](std::string& result, const boost::smatch& what) {
35  result.replace(what.position(), what.length(), what[1] + "PG_UNNEST(");
36  });
37  }
38  {
39  static const auto& cast_true_expr =
40  *new boost::regex(R"(CAST\s*\(\s*'t'\s+AS\s+boolean\s*\))",
41  boost::regex::extended | boost::regex::icase);
42  static_assert(std::is_trivially_destructible_v<decltype(cast_true_expr)>);
43  apply_shim(
44  result, cast_true_expr, [](std::string& result, const boost::smatch& what) {
45  result.replace(what.position(), what.length(), "true");
46  });
47  }
48  {
49  static const auto& cast_false_expr =
50  *new boost::regex(R"(CAST\s*\(\s*'f'\s+AS\s+boolean\s*\))",
51  boost::regex::extended | boost::regex::icase);
52  static_assert(std::is_trivially_destructible_v<decltype(cast_false_expr)>);
53  apply_shim(
54  result, cast_false_expr, [](std::string& result, const boost::smatch& what) {
55  result.replace(what.position(), what.length(), "false");
56  });
57  }
58  {
59  static const auto& ilike_expr = *new boost::regex(
60  R"((\s+|\()((?!\()[^\s]+)\s+(not\s)?\s*ilike\s+('(?:[^']+|'')+')(\s+escape(\s+('[^']+')))?)",
61  boost::regex::perl | boost::regex::icase);
62  static_assert(std::is_trivially_destructible_v<decltype(ilike_expr)>);
63  apply_shim(result, ilike_expr, [](std::string& result, const boost::smatch& what) {
64  std::string esc = what[6];
65  result.replace(what.position(),
66  what.length(),
67  what[1] + what[3] + "PG_ILIKE(" + what[2] + ", " + what[4] +
68  (esc.empty() ? "" : ", " + esc) + ")");
69  });
70  }
71  {
72  static const auto& regexp_expr = *new boost::regex(
73  R"((\s+)([^\s]+)\s+REGEXP\s+('(?:[^']+|'')+')(\s+escape(\s+('[^']+')))?)",
74  boost::regex::perl | boost::regex::icase);
75  static_assert(std::is_trivially_destructible_v<decltype(regexp_expr)>);
76  apply_shim(result, regexp_expr, [](std::string& result, const boost::smatch& what) {
77  std::string esc = what[6];
78  result.replace(what.position(),
79  what.length(),
80  what[1] + "REGEXP_LIKE(" + what[2] + ", " + what[3] +
81  (esc.empty() ? "" : ", " + esc) + ")");
82  });
83  }
84  {
85  // Comparison operator needed to distinguish from other uses of ALL (e.g. UNION ALL)
86  static const auto& quant_expr =
87  *new boost::regex(R"(([<=>]\s*)(any|all)\s+([^(\s|;)]+))",
88  boost::regex::extended | boost::regex::icase);
89  static_assert(std::is_trivially_destructible_v<decltype(quant_expr)>);
90  apply_shim(result, quant_expr, [](std::string& result, const boost::smatch& what) {
91  auto const quant_fname = boost::iequals(what[2], "any") ? "PG_ANY(" : "PG_ALL(";
92  result.replace(
93  what.position(), what.length(), what[1] + quant_fname + what[3] + ')');
94  });
95  }
96  {
97  static const auto& immediate_cast_expr =
98  *new boost::regex(R"(TIMESTAMP\(([0369])\)\s+('[^']+'))",
99  boost::regex::extended | boost::regex::icase);
100  static_assert(std::is_trivially_destructible_v<decltype(immediate_cast_expr)>);
101  apply_shim(
102  result, immediate_cast_expr, [](std::string& result, const boost::smatch& what) {
103  result.replace(what.position(),
104  what.length(),
105  "CAST(" + what[2] + " AS TIMESTAMP(" + what[1] + "))");
106  });
107  }
108  {
109  static const auto& timestampadd_expr =
110  *new boost::regex(R"(DATE(ADD|DIFF|PART|_TRUNC)\s*\(\s*(\w+)\s*,)",
111  boost::regex::extended | boost::regex::icase);
112  static_assert(std::is_trivially_destructible_v<decltype(timestampadd_expr)>);
113  apply_shim(
114  result, timestampadd_expr, [](std::string& result, const boost::smatch& what) {
115  result.replace(
116  what.position(), what.length(), "DATE" + what[1] + "('" + what[2] + "',");
117  });
118  }
119 
120  {
121  static const auto& pg_extract_expr = *new boost::regex(
122  R"(PG_EXTRACT\s*\(\s*(\w+)\s*,)", boost::regex::extended | boost::regex::icase);
123  static_assert(std::is_trivially_destructible_v<decltype(pg_extract_expr)>);
124  apply_shim(
125  result, pg_extract_expr, [](std::string& result, const boost::smatch& what) {
126  result.replace(what.position(), what.length(), "PG_EXTRACT('" + what[1] + "',");
127  });
128 
129  static const auto& extract_expr_quoted =
130  *new boost::regex(R"(extract\s*\(\s*'(\w+)'\s+from\s+(.+)\))",
131  boost::regex::extended | boost::regex::icase);
132  static_assert(std::is_trivially_destructible_v<decltype(extract_expr_quoted)>);
133  apply_shim(
134  result, extract_expr_quoted, [](std::string& result, const boost::smatch& what) {
135  result.replace(what.position(),
136  what.length(),
137  "PG_EXTRACT('" + what[1] + "', " + what[2] + ")");
138  });
139 
140  static const auto& extract_expr =
141  *new boost::regex(R"(extract\s*\(\s*(\w+)\s+from\s+(.+)\))",
142  boost::regex::extended | boost::regex::icase);
143  static_assert(std::is_trivially_destructible_v<decltype(extract_expr)>);
144  apply_shim(result, extract_expr, [](std::string& result, const boost::smatch& what) {
145  result.replace(what.position(),
146  what.length(),
147  "PG_EXTRACT('" + what[1] + "', " + what[2] + ")");
148  });
149  }
150 
151  {
152  static const auto& date_trunc_expr = *new boost::regex(
153  R"(([^_])date_trunc\s*)", boost::regex::extended | boost::regex::icase);
154  static_assert(std::is_trivially_destructible_v<decltype(date_trunc_expr)>);
155  apply_shim(
156  result, date_trunc_expr, [](std::string& result, const boost::smatch& what) {
157  result.replace(what.position(), what.length(), what[1] + "PG_DATE_TRUNC");
158  });
159  }
160  {
161  static const auto& timestampadd_expr_quoted =
162  *new boost::regex(R"(TIMESTAMP(ADD|DIFF)\s*\(\s*'(\w+)'\s*,)",
163  boost::regex::extended | boost::regex::icase);
164  static_assert(std::is_trivially_destructible_v<decltype(timestampadd_expr_quoted)>);
165  apply_shim(result,
166  timestampadd_expr_quoted,
167  [](std::string& result, const boost::smatch& what) {
168  result.replace(what.position(),
169  what.length(),
170  "DATE" + what[1] + "('" + what[2] + "',");
171  });
172  static const auto& timestampadd_expr =
173  *new boost::regex(R"(TIMESTAMP(ADD|DIFF)\s*\(\s*(\w+)\s*,)",
174  boost::regex::extended | boost::regex::icase);
175  static_assert(std::is_trivially_destructible_v<decltype(timestampadd_expr)>);
176  apply_shim(
177  result, timestampadd_expr, [](std::string& result, const boost::smatch& what) {
178  result.replace(
179  what.position(), what.length(), "DATE" + what[1] + "('" + what[2] + "',");
180  });
181  }
182  {
183  static const auto& us_timestamp_cast_expr =
184  *new boost::regex(R"(CAST\s*\(\s*('[^']+')\s*AS\s*TIMESTAMP\(6\)\s*\))",
185  boost::regex::extended | boost::regex::icase);
186  static_assert(std::is_trivially_destructible_v<decltype(us_timestamp_cast_expr)>);
187  apply_shim(result,
188  us_timestamp_cast_expr,
189  [](std::string& result, const boost::smatch& what) {
190  result.replace(
191  what.position(), what.length(), "usTIMESTAMP(" + what[1] + ")");
192  });
193  }
194  {
195  static const auto& ns_timestamp_cast_expr =
196  *new boost::regex(R"(CAST\s*\(\s*('[^']+')\s*AS\s*TIMESTAMP\(9\)\s*\))",
197  boost::regex::extended | boost::regex::icase);
198  static_assert(std::is_trivially_destructible_v<decltype(ns_timestamp_cast_expr)>);
199  apply_shim(result,
200  ns_timestamp_cast_expr,
201  [](std::string& result, const boost::smatch& what) {
202  result.replace(
203  what.position(), what.length(), "nsTIMESTAMP(" + what[1] + ")");
204  });
205  }
206  {
207  static const auto& corr_expr = *new boost::regex(
208  R"((\s+|,|\()(corr)\s*\()", boost::regex::extended | boost::regex::icase);
209  static_assert(std::is_trivially_destructible_v<decltype(corr_expr)>);
210  apply_shim(result, corr_expr, [](std::string& result, const boost::smatch& what) {
211  result.replace(what.position(), what.length(), what[1] + "CORRELATION(");
212  });
213  }
214  {
215  try {
216  // the geography regex pattern is expensive and can sometimes run out of stack space
217  // on long queries. Treat it separately from the other shims.
218  static const auto& cast_to_geography_expr =
219  *new boost::regex(R"(CAST\s*\(\s*(((?!geography).)+)\s+AS\s+geography\s*\))",
220  boost::regex::perl | boost::regex::icase);
221  static_assert(std::is_trivially_destructible_v<decltype(cast_to_geography_expr)>);
222  apply_shim(result,
223  cast_to_geography_expr,
224  [](std::string& result, const boost::smatch& what) {
225  result.replace(what.position(),
226  what.length(),
227  "CastToGeography(" + what[1] + ")");
228  });
229  } catch (const std::exception& e) {
230  LOG(WARNING) << "Error apply geography cast shim: " << e.what()
231  << "\nContinuing query parse...";
232  }
233  }
234  {
235  static const auto& interval_subsecond_expr =
236  *new boost::regex(R"(interval\s+([0-9]+)\s+(millisecond|microsecond|nanosecond))",
237  boost::regex::extended | boost::regex::icase);
238  static_assert(std::is_trivially_destructible_v<decltype(interval_subsecond_expr)>);
239  apply_shim(
240  result,
241  interval_subsecond_expr,
242  [](std::string& result, const boost::smatch& what) {
243  std::string interval_str = what[1];
244  const std::string time_unit_str = to_lower(to_string(what[2]));
245  static const std::array<std::pair<std::string_view, size_t>, 3> precision_map{
246  std::make_pair("millisecond", 3),
247  std::make_pair("microsecond", 6),
248  std::make_pair("nanosecond", 9)};
249  static_assert(std::is_trivially_destructible_v<decltype(precision_map)>);
250  auto precision_it = std::find_if(
251  precision_map.cbegin(),
252  precision_map.cend(),
253  [&time_unit_str](const std::pair<std::string_view, size_t>& precision) {
254  return time_unit_str.compare(precision.first) == 0;
255  });
256  if (precision_it != precision_map.end()) {
257  std::ostringstream out;
258  const auto interval_time = std::strtod(interval_str.c_str(), nullptr);
259  double const scale = shared::power10(precision_it->second);
260  out << std::fixed << interval_time / scale;
261  interval_str = out.str();
262  result.replace(
263  what.position(), what.length(), "interval " + interval_str + " second");
264  }
265  });
266  }
267 
268  return result;
269 }
std::string to_lower(const std::string &str)
double power10(unsigned const x)
Definition: misc.h:275
#define LOG(tag)
Definition: Logger.h:285
std::string to_string(char const *&&v)
void apply_shim(std::string &result, const boost::regex &reg_expr, const std::function< void(std::string &, const boost::smatch &)> &shim_fn)

+ Here is the call graph for this function:

+ Here is the caller graph for this function: