Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Commit 52be828

Browse files
committed
Refactor query_to_operator_transformer a bit to support better error handling
1 parent ab16393 commit 52be828

File tree

7 files changed

+161
-59
lines changed

7 files changed

+161
-59
lines changed

src/common/internal_types.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,9 @@ std::string ExpressionTypeToString(ExpressionType type, bool short_str) {
929929
case ExpressionType::CAST: {
930930
return ("CAST");
931931
}
932+
case ExpressionType::OPERATOR_IS_NOT_NULL: {
933+
return ("IS_NOT_NULL");
934+
}
932935
default: {
933936
throw ConversionException(StringUtil::Format(
934937
"No string conversion for ExpressionType value '%d'",

src/include/optimizer/query_to_operator_transformer.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class QueryToOperatorTransformer : public SqlNodeVisitor {
6666
void Visit(expression::ComparisonExpression *expr) override;
6767
void Visit(expression::OperatorExpression *expr) override;
6868

69+
private:
6970
inline oid_t GetAndIncreaseGetId() { return get_id++; }
7071

7172
/**
@@ -96,14 +97,28 @@ class QueryToOperatorTransformer : public SqlNodeVisitor {
9697
* @return If the expression could be transformed into sub-query, return true,
9798
* return false otherwise
9899
*/
99-
bool GenerateSubquerytree(
100-
expression::AbstractExpression *expr,
101-
std::vector<expression::AbstractExpression *> &select_list,
102-
bool single_join = false);
100+
bool GenerateSubquerytree(expression::AbstractExpression *expr,
101+
oid_t child_id, bool single_join = false);
103102

103+
/**
104+
* @brief Decide if a conjunctive predicate is supported. We need to extract
105+
* conjunction predicate first then call this function to decide if the
106+
* predicate is supported by our system
107+
*
108+
* @param expr The conjunctive predicate provided
109+
*
110+
* @return True if supported, false otherwise
111+
*/
112+
bool IsSupportedConjunctivePredicate(expression::AbstractExpression *expr);
113+
/**
114+
* @brief Check if a sub-select statement is supported.
115+
*
116+
* @param op The select statement
117+
*
118+
* @return True if supported, false otherwise
119+
*/
120+
bool IsSupportedSubSelect(const parser::SelectStatement *op);
104121
static bool RequireAggregation(const parser::SelectStatement *op);
105-
106-
private:
107122
std::shared_ptr<OperatorExpression> output_expr_;
108123

109124
concurrency::TransactionContext *txn_;

src/include/planner/abstract_scan_plan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class AbstractScan : public AbstractPlan {
7474

7575
void SetForUpdateFlag(bool flag) { is_for_update = flag; }
7676

77+
const std::string GetPredicateInfo() const {
78+
return predicate_ != nullptr ? predicate_->GetInfo() : "";
79+
}
80+
7781
private:
7882
// Pointer to table to scan from
7983
storage::DataTable *target_table_ = nullptr;

src/include/planner/seq_scan_plan.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ class SeqScanPlan : public AbstractScan {
5353
return PlanNodeType::SEQSCAN;
5454
}
5555

56-
const std::string GetInfo() const override { return "SeqScan"; }
56+
const std::string GetInfo() const override {
57+
return "SeqScan(" + GetPredicateInfo() + ")";
58+
}
5759

5860
void SetParameterValues(std::vector<type::Value> *values) override;
5961

@@ -81,7 +83,8 @@ class SeqScanPlan : public AbstractScan {
8183
return !(*this == rhs);
8284
}
8385

84-
virtual void VisitParameters(codegen::QueryParametersMap &map,
86+
virtual void VisitParameters(
87+
codegen::QueryParametersMap &map,
8588
std::vector<peloton::type::Value> &values,
8689
const std::vector<peloton::type::Value> &values_from_user) override;
8790

src/optimizer/query_to_operator_transformer.cpp

Lines changed: 119 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -304,15 +304,9 @@ void QueryToOperatorTransformer::Visit(
304304
void QueryToOperatorTransformer::Visit(expression::ComparisonExpression *expr) {
305305
auto expr_type = expr->GetExpressionType();
306306
if (expr->GetExpressionType() == ExpressionType::COMPARE_IN) {
307-
std::vector<expression::AbstractExpression *> select_list;
308-
if (GenerateSubquerytree(expr->GetModifiableChild(1), select_list) ==
309-
true) {
310-
if (select_list.size() != 1) {
311-
throw Exception("Array in predicates not supported");
312-
}
313-
314-
// Set the right child as the output of the subquery
315-
expr->SetChild(1, select_list.at(0)->Copy());
307+
if (GenerateSubquerytree(expr, 1)) {
308+
// TODO(boweic): Should use IN to preserve the semantic, for now we do not
309+
// have semi-join so use = to transform into inner join
316310
expr->SetExpressionType(ExpressionType::COMPARE_EQUAL);
317311
}
318312

@@ -321,40 +315,25 @@ void QueryToOperatorTransformer::Visit(expression::ComparisonExpression *expr) {
321315
expr_type == ExpressionType::COMPARE_GREATERTHANOREQUALTO ||
322316
expr_type == ExpressionType::COMPARE_LESSTHAN ||
323317
expr_type == ExpressionType::COMPARE_LESSTHANOREQUALTO) {
324-
std::vector<expression::AbstractExpression *> select_list;
325-
if (GenerateSubquerytree(expr->GetModifiableChild(0), select_list, true) ==
326-
true) {
327-
if (select_list.size() != 1) {
328-
throw Exception("Array in predicates not supported");
329-
}
330-
331-
// Set the left child as the output of the subquery
332-
expr->SetChild(0, select_list.at(0)->Copy());
333-
}
334-
select_list.clear();
335-
if (GenerateSubquerytree(expr->GetModifiableChild(1), select_list, true) ==
336-
true) {
337-
if (select_list.size() != 1) {
338-
throw Exception("Array in predicates not supported");
339-
}
340-
341-
// Set the right child as the output of the subquery
342-
expr->SetChild(1, select_list.at(0)->Copy());
318+
if (expr->GetChild(0)->GetExpressionType() ==
319+
ExpressionType::ROW_SUBQUERY &&
320+
expr->GetChild(1)->GetExpressionType() ==
321+
ExpressionType::ROW_SUBQUERY) {
322+
throw Exception("Do not support comparison between sub-select");
343323
}
324+
// Transform if either child is sub-query
325+
GenerateSubquerytree(expr, 0, true) || GenerateSubquerytree(expr, 1, true);
344326
}
345327
expr->AcceptChildren(this);
346328
}
347329

348330
void QueryToOperatorTransformer::Visit(expression::OperatorExpression *expr) {
331+
// TODO(boweic): We may want to do the rewrite (exist -> in) in the binder
349332
if (expr->GetExpressionType() == ExpressionType::OPERATOR_EXISTS) {
350-
std::vector<expression::AbstractExpression *> select_list;
351-
if (GenerateSubquerytree(expr->GetModifiableChild(0), select_list) ==
352-
true) {
353-
PL_ASSERT(!select_list.empty());
354-
355-
// Set the right child as the output of the subquery
333+
if (GenerateSubquerytree(expr, 0)) {
334+
// Already reset the child to column, we need to transform exist to
335+
// not-null to preserve semantic
356336
expr->SetExpressionType(ExpressionType::OPERATOR_IS_NOT_NULL);
357-
expr->SetChild(0, select_list.at(0)->Copy());
358337
}
359338
}
360339

@@ -391,24 +370,117 @@ bool QueryToOperatorTransformer::RequireAggregation(
391370

392371
void QueryToOperatorTransformer::CollectPredicates(
393372
expression::AbstractExpression *expr) {
373+
// First check if all conjunctive predicates are supported before
374+
// transfoming
375+
// predicate with sub-select into regular predicates
376+
std::vector<expression::AbstractExpression *> predicates;
377+
util::SplitPredicates(expr, predicates);
378+
for (const auto &pred : predicates) {
379+
if (!IsSupportedConjunctivePredicate(pred)) {
380+
throw Exception("Predicate type not supported yet");
381+
}
382+
}
383+
// Accept will change the expression, e.g. (a in (select b from test)) into
384+
// (a IN test.b), after the rewrite, we can extract the table aliases
385+
// information correctly
394386
expr->Accept(this);
395387
util::ExtractPredicates(expr, predicates_);
396388
}
397389

398-
bool QueryToOperatorTransformer::GenerateSubquerytree(
399-
expression::AbstractExpression *expr,
400-
std::vector<expression::AbstractExpression *> &select_list,
401-
bool single_join) {
402-
if (expr->GetExpressionType() != ExpressionType::ROW_SUBQUERY) {
403-
return false;
390+
bool QueryToOperatorTransformer::IsSupportedConjunctivePredicate(
391+
expression::AbstractExpression *expr) {
392+
// Currently support : 1. expr without subquery
393+
// 2. subquery without disjunction. Since the expr is already one of the
394+
// conjunctive exprs, we'll only need to check if the root level is an
395+
// operator with subquery
396+
if (!expr->HasSubquery()) {
397+
return true;
398+
}
399+
auto expr_type = expr->GetExpressionType();
400+
// Subquery with IN
401+
if (expr_type == ExpressionType::COMPARE_IN &&
402+
expr->GetChild(1)->GetExpressionType() == ExpressionType::ROW_SUBQUERY) {
403+
return true;
404+
}
405+
// Subquery with EXIST
406+
if (expr_type == ExpressionType::OPERATOR_EXISTS &&
407+
expr->GetChild(0)->GetExpressionType() == ExpressionType::ROW_SUBQUERY) {
408+
return true;
409+
}
410+
// Subquery with other operator
411+
if (expr_type == ExpressionType::COMPARE_EQUAL ||
412+
expr_type == ExpressionType::COMPARE_GREATERTHAN ||
413+
expr_type == ExpressionType::COMPARE_GREATERTHANOREQUALTO ||
414+
expr_type == ExpressionType::COMPARE_LESSTHAN ||
415+
expr_type == ExpressionType::COMPARE_LESSTHANOREQUALTO) {
416+
// Supported is one child is subquery and the other is not
417+
if ((!expr->GetChild(0)->HasSubquery() &&
418+
expr->GetChild(1)->GetExpressionType() ==
419+
ExpressionType::ROW_SUBQUERY) ||
420+
(!expr->GetChild(1)->HasSubquery() &&
421+
expr->GetChild(0)->GetExpressionType() ==
422+
ExpressionType::ROW_SUBQUERY)) {
423+
return true;
424+
}
404425
}
405-
auto subquery_expr = dynamic_cast<expression::SubqueryExpression *>(expr);
406-
auto sub_select = subquery_expr->GetSubSelect();
426+
return false;
427+
}
407428

408-
for (auto &ele : sub_select->select_list) {
409-
select_list.push_back(ele.get());
429+
bool QueryToOperatorTransformer::IsSupportedSubSelect(
430+
const parser::SelectStatement *op) {
431+
// Supported if 1. No aggregation. 2. With aggregation and WHERE clause only
432+
// have correlated columns in conjunctive predicates in the form of
433+
// "outer_relation.a = ..."
434+
// TODO(boweic): Add support for arbitary expressions, this would require
435+
// the
436+
// support for mark join & some special operators, see Hyper's unnesting
437+
// arbitary query slides
438+
if (!RequireAggregation(op)) {
439+
return true;
440+
}
441+
442+
std::vector<expression::AbstractExpression *> predicates;
443+
util::SplitPredicates(op->where_clause.get(), predicates);
444+
for (const auto &pred : predicates) {
445+
// If correlated predicate
446+
if (pred->GetDepth() < op->depth) {
447+
if (pred->GetExpressionType() != ExpressionType::COMPARE_EQUAL) {
448+
return false;
449+
}
450+
// Check if in the form of
451+
// "outer_relation.a = (expr only columns in inner relation)"
452+
if (!((pred->GetChild(0)->GetDepth() == op->depth &&
453+
pred->GetChild(0)->GetExpressionType() ==
454+
ExpressionType::VALUE_TUPLE) ||
455+
(pred->GetChild(1)->GetDepth() == op->depth &&
456+
pred->GetChild(1)->GetExpressionType() ==
457+
ExpressionType::VALUE_TUPLE))) {
458+
return false;
459+
}
460+
}
410461
}
462+
return true;
463+
}
411464

465+
bool QueryToOperatorTransformer::GenerateSubquerytree(
466+
expression::AbstractExpression *expr, oid_t child_id, bool single_join) {
467+
// Get potential subquery
468+
auto subquery_expr = expr->GetChild(child_id);
469+
if (subquery_expr->GetExpressionType() != ExpressionType::ROW_SUBQUERY) {
470+
return false;
471+
}
472+
auto sub_select =
473+
static_cast<const expression::SubqueryExpression *>(subquery_expr)
474+
->GetSubSelect()
475+
.get();
476+
if (!IsSupportedSubSelect(sub_select)) {
477+
throw Exception("Sub-select not supported");
478+
}
479+
// We only support subselect with single row
480+
if (sub_select->select_list.size() != 1) {
481+
throw Exception("Array in predicates not supported");
482+
}
483+
std::vector<expression::AbstractExpression *> select_list;
412484
// Construct join
413485
std::shared_ptr<OperatorExpression> op_expr;
414486
if (single_join) {
@@ -426,6 +498,8 @@ bool QueryToOperatorTransformer::GenerateSubquerytree(
426498
op_expr->PushChild(output_expr_);
427499

428500
output_expr_ = op_expr;
501+
// Convert subquery to the selected column in the sub-select
502+
expr->SetChild(child_id, sub_select->select_list.at(0)->Copy());
429503
return true;
430504
}
431505

src/optimizer/rule_impls.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,9 @@ void GetToIndexScan::Transform(
261261
->GetValue());
262262
LOG_TRACE("Value Type: %d",
263263
static_cast<int>(
264-
reinterpret_cast<expression::ConstantValueExpression *>(
265-
expr->GetModifiableChild(1))
266-
->GetValueType()));
264+
reinterpret_cast<expression::ConstantValueExpression *>(
265+
expr->GetModifiableChild(1))
266+
->GetValueType()));
267267
} else {
268268
value_list.push_back(
269269
type::ValueFactory::GetParameterOffsetValue(
@@ -748,12 +748,14 @@ void PushFilterThroughJoin::Transform(
748748
// E.g. An expression (test.a = test1.b and test.a = 5) would become
749749
// {test.a = test1.b, test.a = 5}
750750
for (auto &predicate : predicates) {
751-
if (util::IsSubset(left_group_aliases_set, predicate.table_alias_set))
751+
if (util::IsSubset(left_group_aliases_set, predicate.table_alias_set)) {
752752
left_predicates.emplace_back(predicate);
753-
else if (util::IsSubset(right_group_aliases_set, predicate.table_alias_set))
753+
} else if (util::IsSubset(right_group_aliases_set,
754+
predicate.table_alias_set)) {
754755
right_predicates.emplace_back(predicate);
755-
else
756+
} else {
756757
join_predicates.emplace_back(predicate);
758+
}
757759
}
758760

759761
// Construct join operator

test/sql/testing_sql_util.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ ResultType TestingSQLUtil::ExecuteSQLQueryWithOptimizer(
132132
return status.m_result;
133133
} catch (Exception &e) {
134134
error_message = e.what();
135+
LOG_DEBUG("Testing SQL Util Caught Exception : %s", e.what());
135136
return ResultType::FAILURE;
136137
}
137138
}

0 commit comments

Comments
 (0)