OmniSciDB  340b00dbf6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ParserWrapper.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 /*
18  * File: ParserWrapper.cpp
19  * Author: michael
20  *
21  * Created on Feb 23, 2016, 9:33 AM
22  */
23 
24 #include "ParserWrapper.h"
25 #include "Shared/measure.h"
26 
27 #include <boost/algorithm/string.hpp>
28 
29 using namespace std;
30 
31 const std::vector<std::string> ParserWrapper::ddl_cmd = {"ARCHIVE",
32  "ALTER",
33  "COPY",
34  "GRANT",
35  "CREATE",
36  "DROP",
37  "DUMP",
38  "OPTIMIZE",
39  "REFRESH",
40  "RESTORE",
41  "REVOKE",
42  "SHOW",
43  "TRUNCATE",
44  "KILL"};
45 
46 const std::vector<std::string> ParserWrapper::update_dml_cmd = {
47  "INSERT",
48  "DELETE",
49  "UPDATE",
50  "UPSERT",
51 };
52 
53 const std::string ParserWrapper::explain_str = {"explain"};
54 const std::string ParserWrapper::calcite_explain_str = {"explain calcite"};
55 const std::string ParserWrapper::optimized_explain_str = {"explain optimized"};
56 const std::string ParserWrapper::plan_explain_str = {"explain plan"};
57 const std::string ParserWrapper::optimize_str = {"optimize"};
58 const std::string ParserWrapper::validate_str = {"validate"};
59 
60 extern bool g_enable_fsi;
61 extern bool g_enable_calcite_ddl_parser;
62 
63 ParserWrapper::ParserWrapper(std::string query_string) {
64  query_type_ = QueryType::SchemaRead;
65  if (boost::istarts_with(query_string, calcite_explain_str)) {
66  actual_query = boost::trim_copy(query_string.substr(calcite_explain_str.size()));
67  ParserWrapper inner{actual_query};
68  if (inner.is_ddl || inner.is_update_dml) {
69  explain_type_ = ExplainType::Other;
70  return;
71  } else {
72  explain_type_ = ExplainType::Calcite;
73  return;
74  }
75  }
76 
77  if (boost::istarts_with(query_string, optimized_explain_str)) {
78  actual_query = boost::trim_copy(query_string.substr(optimized_explain_str.size()));
79  ParserWrapper inner{actual_query};
80  if (inner.is_ddl || inner.is_update_dml) {
81  explain_type_ = ExplainType::Other;
82  return;
83  } else {
84  explain_type_ = ExplainType::OptimizedIR;
85  return;
86  }
87  }
88 
89  if (boost::istarts_with(query_string, plan_explain_str)) {
90  actual_query = boost::trim_copy(query_string.substr(plan_explain_str.size()));
91  ParserWrapper inner{actual_query};
92  if (inner.is_ddl || inner.is_update_dml) {
93  explain_type_ = ExplainType::Other;
94  return;
95  } else {
96  explain_type_ = ExplainType::ExecutionPlan;
97  return;
98  }
99  }
100 
101  if (boost::istarts_with(query_string, explain_str)) {
102  actual_query = boost::trim_copy(query_string.substr(explain_str.size()));
103  ParserWrapper inner{actual_query};
104  if (inner.is_ddl || inner.is_update_dml) {
105  explain_type_ = ExplainType::Other;
106  return;
107  } else {
108  explain_type_ = ExplainType::IR;
109  return;
110  }
111  }
112 
113  if (boost::istarts_with(query_string, optimize_str)) {
114  query_type_ = QueryType::SchemaWrite;
115  is_optimize = true;
116  return;
117  }
118 
119  if (boost::istarts_with(query_string, validate_str)) {
120  is_validate = true;
121  return;
122  }
123  query_type_ = QueryType::Read;
124  for (std::string ddl : ddl_cmd) {
125  is_ddl = boost::istarts_with(query_string, ddl);
126  if (is_ddl) {
127  query_type_ = QueryType::SchemaWrite;
128  if (g_enable_fsi) {
129  std::string fsi_regex_pattern{
130  R"((CREATE|DROP|ALTER)\s+(SERVER|FOREIGN\s+TABLE).*)"};
131 
132  boost::regex fsi_regex{fsi_regex_pattern,
133  boost::regex::extended | boost::regex::icase};
134  boost::regex refresh_regex{R"(REFRESH\s+FOREIGN\s+TABLES.*)",
135  boost::regex::extended | boost::regex::icase};
136 
137  if (boost::regex_match(query_string, fsi_regex) ||
138  boost::regex_match(query_string, refresh_regex)) {
139  is_calcite_ddl_ = true;
140  is_legacy_ddl_ = false;
141  return;
142  }
143  }
144  if (ddl == "CREATE") {
145  boost::regex ctas_regex{R"(CREATE\s+TABLE.*AS.*SELECT.*)",
146  boost::regex::extended | boost::regex::icase};
147  if (boost::regex_match(query_string, ctas_regex)) {
148  is_ctas = true;
149  } else {
150  boost::regex create_table_regex{R"(CREATE\s+TABLE.*)",
151  boost::regex::extended | boost::regex::icase};
152  boost::regex create_view_regex{R"(CREATE\s+VIEW.*)",
153  boost::regex::extended | boost::regex::icase};
155  (boost::regex_match(query_string, create_table_regex) ||
156  boost::regex_match(query_string, create_view_regex))) {
157  is_calcite_ddl_ = true;
158  is_legacy_ddl_ = false;
159  is_distributed_calcite_ddl_ = true;
160  return;
161  }
162  }
163  } else if (ddl == "COPY") {
164  is_copy = true;
165  // now check if it is COPY TO
166  boost::regex copy_to{R"(COPY\s*\(([^#])(.+)\)\s+TO\s+.*)",
167  boost::regex::extended | boost::regex::icase};
168  if (boost::regex_match(query_string, copy_to)) {
169  query_type_ = QueryType::Read;
170  is_copy_to = true;
171  } else {
172  query_type_ = QueryType::Write;
173  }
174  } else if (ddl == "SHOW") {
175  query_type_ = QueryType::SchemaRead;
176  boost::regex show_create_table_regex{
177  R"(SHOW\s+CREATE\s+TABLE\s+.*)",
178  boost::regex::extended | boost::regex::icase};
179  if (!boost::regex_match(query_string, show_create_table_regex)) {
180  is_calcite_ddl_ = true;
181  is_legacy_ddl_ = false;
182  return;
183  }
184  } else if (ddl == "KILL") {
185  query_type_ = QueryType::Unknown;
186  is_calcite_ddl_ = true;
187  is_legacy_ddl_ = false;
188  return;
189  }
190  is_legacy_ddl_ = !is_calcite_ddl_;
191  return;
192  }
193  }
194 
195  for (int i = 0; i < update_dml_cmd.size(); i++) {
196  is_update_dml = boost::istarts_with(query_string, ParserWrapper::update_dml_cmd[i]);
197  if (is_update_dml) {
198  query_type_ = QueryType::Write;
199  dml_type_ = (DMLType)(i);
200  break;
201  }
202  }
203 
204  if (dml_type_ == DMLType::Insert) {
205  boost::regex insert_regex{R"(INSERT\s+INTO.*VALUES\s*\(.*)",
206  boost::regex::extended | boost::regex::icase};
207  if (!boost::regex_match(query_string, insert_regex)) {
208  boost::regex itas_regex{R"(INSERT\s+INTO.*SELECT.*)",
209  boost::regex::extended | boost::regex::icase};
210  if (boost::regex_match(query_string, itas_regex)) {
211  is_itas = true;
212  }
213  }
214  }
215 }
216 
218 
220  return {explain_type_ == ExplainType::IR,
221  explain_type_ == ExplainType::OptimizedIR,
222  explain_type_ == ExplainType::ExecutionPlan,
223  explain_type_ == ExplainType::Calcite};
224 }
Classes used to wrap parser calls for calcite redirection.
static const std::string optimize_str
virtual ~ParserWrapper()
static const std::string optimized_explain_str
ExplainInfo getExplainInfo() const
static const std::string calcite_explain_str
static const std::vector< std::string > ddl_cmd
bool g_enable_calcite_ddl_parser
Definition: ParserNode.cpp:72
static const std::string validate_str
static const std::string explain_str
static const std::vector< std::string > update_dml_cmd
static const std::string plan_explain_str
ParserWrapper(std::string query_string)
bool g_enable_fsi
Definition: Catalog.cpp:91