OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
QueryPlanDagChecker.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 "QueryPlanDagChecker.h"
18 
21 }
22 
23 void QueryPlanDagChecker::detectNonSupportedNode(const std::string& node_tag) {
25  non_supported_node_tag_ = node_tag;
26 }
27 
28 std::pair<bool, std::string> QueryPlanDagChecker::hasNonSupportedNodeInDag(
29  const RelAlgNode* rel_alg_node) {
30  QueryPlanDagChecker checker;
31  checker.check(rel_alg_node);
32  return std::make_pair(checker.getCheckResult(), checker.getNonSupportedNodeTag());
33 }
34 
35 void QueryPlanDagChecker::check(const RelAlgNode* rel_alg_node) {
36  RelRexDagVisitor::visit(rel_alg_node);
37 }
38 
39 void QueryPlanDagChecker::visit(const RelLogicalValues* rel_alg_node) {
40  detectNonSupportedNode("Detect RelLogicalValues node");
41  return;
42 }
43 
44 void QueryPlanDagChecker::visit(const RelModify* rel_alg_node) {
45  detectNonSupportedNode("Detect RelModify node");
46  return;
47 }
48 
49 void QueryPlanDagChecker::visit(const RelProject* rel_alg_node) {
50  if (rel_alg_node->isDeleteViaSelect() || rel_alg_node->isUpdateViaSelect() ||
51  rel_alg_node->isVarlenUpdateRequired()) {
52  detectNonSupportedNode("Executing UPDATE/MODIFY/DELETE query");
53  return;
54  }
55  RelRexDagVisitor::visit(rel_alg_node);
56 }
57 
58 void QueryPlanDagChecker::visit(const RelCompound* rel_alg_node) {
59  if (rel_alg_node->isDeleteViaSelect() || rel_alg_node->isUpdateViaSelect() ||
60  rel_alg_node->isVarlenUpdateRequired()) {
61  detectNonSupportedNode("Executing UPDATE/MODIFY/DELETE query");
62  return;
63  }
64  // SINGLE_VALUE / SAMPLE query
65  if (rel_alg_node->isAggregate() && rel_alg_node->size() > 0) {
66  for (size_t i = 0; i < rel_alg_node->size(); ++i) {
67  auto target_expr = rel_alg_node->getTargetExpr(i);
68  auto agg_expr = dynamic_cast<const RexAgg*>(target_expr);
69  if (agg_expr && (agg_expr->getKind() == SQLAgg::kSINGLE_VALUE ||
70  agg_expr->getKind() == SQLAgg::kSAMPLE ||
71  agg_expr->getKind() == SQLAgg::kAPPROX_QUANTILE)) {
73  "Detect non-supported aggregation function: "
74  "SINGLE_VALUE/SAMPLE/APPROX_QUANTILE");
75  return;
76  }
77  }
78  }
79  RelRexDagVisitor::visit(rel_alg_node);
80 }
81 
82 void QueryPlanDagChecker::visit(const RelLogicalUnion* rel_alg_node) {
83  detectNonSupportedNode("Detect RelLogicalUnion node");
84  return;
85 }
86 
87 void QueryPlanDagChecker::visit(const RelScan* rel_alg_node) {
88  if (rel_alg_node->getTableDescriptor()->isForeignTable()) {
89  detectNonSupportedNode("Detect foreign table");
90  return;
91  }
92  if (rel_alg_node->getTableDescriptor()->isTemporaryTable()) {
93  detectNonSupportedNode("Detect temporary table");
94  }
95 
96  if (rel_alg_node->getTableDescriptor()->is_system_table) {
97  detectNonSupportedNode("Detect system table");
98  }
99  RelRexDagVisitor::visit(rel_alg_node);
100 }
101 
103  // prevent too heavy IN clause containing more than 20 values to check
104  if (rex_node->getOperator() == SQLOps::kOR && rex_node->size() > 20) {
105  detectNonSupportedNode("Detect heavy IN-clause having more than 20 values");
106  return;
107  }
108  for (size_t i = 0; i < rex_node->size(); ++i) {
109  if (rex_node->getOperand(i)) {
110  RelRexDagVisitor::visit(rex_node->getOperand(i));
111  }
112  }
113 }
114 
116  if (non_supported_functions_.count(rex_node->getName())) {
117  detectNonSupportedNode("Detect non-supported function: " + rex_node->getName());
118  }
119  if (getCheckResult()) {
120  return;
121  }
122  for (size_t i = 0; i < rex_node->size(); ++i) {
123  if (rex_node->getOperand(i)) {
124  RelRexDagVisitor::visit(rex_node->getOperand(i));
125  }
126  }
127 }
128 
132 }
133 
136 }
std::string non_supported_node_tag_
void check(const RelAlgNode *)
const Rex * getTargetExpr(const size_t i) const
Definition: RelAlgDag.h:2102
virtual void visit(RelAlgNode const *)
size_t size() const override
Definition: RelAlgDag.h:2094
size_t size() const
Definition: RelAlgDag.h:364
const RexScalar * getOperand(const size_t idx) const
Definition: RelAlgDag.h:366
Definition: sqldefs.h:40
static std::pair< bool, std::string > hasNonSupportedNodeInDag(const RelAlgNode *rel_alg_node)
bool isForeignTable() const
std::string const & getNonSupportedNodeTag() const
SQLOps getOperator() const
Definition: RelAlgDag.h:376
void visit(const RelLogicalValues *) override
const std::unordered_set< std::string > non_supported_functions_
bool isTemporaryTable() const
void detectNonSupportedNode(const std::string &node_tag)
auto const isDeleteViaSelect() const
Definition: RelAlgDag.h:1218
bool isAggregate() const
Definition: RelAlgDag.h:2123
auto const isUpdateViaSelect() const
Definition: RelAlgDag.h:1217
const std::string & getName() const
Definition: RelAlgDag.h:506
auto const isVarlenUpdateRequired() const
Definition: RelAlgDag.h:1219
const TableDescriptor * getTableDescriptor() const
Definition: RelAlgDag.h:1117