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

Commit

Permalink
Ported not-null foreign keys and short-circuiting
Browse files Browse the repository at this point in the history
  • Loading branch information
17zhangw committed May 5, 2019
1 parent 5caae6d commit e3ac1ba
Show file tree
Hide file tree
Showing 8 changed files with 598 additions and 1 deletion.
17 changes: 17 additions & 0 deletions src/binder/bind_node_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "binder/bind_node_visitor.h"
#include "catalog/catalog.h"
#include "catalog/table_catalog.h"
#include "catalog/column_catalog.h"
#include "expression/expression_util.h"
#include "expression/star_expression.h"
#include "type/type_id.h"
Expand Down Expand Up @@ -250,6 +252,21 @@ void BindNodeVisitor::Visit(expression::TupleValueExpression *expr) {
expr->SetColName(col_name);
expr->SetValueType(value_type);
expr->SetBoundOid(col_pos_tuple);

// TODO(esargent): Uncommenting the following code makes AddressSanitizer get mad at me with a
// heap buffer overflow whenever I try a query that references the same non-null attribute multiple
// times (e.g. 'SELECT id FROM t WHERE id < 3 AND id > 1'). Leaving it commented out prevents the
// memory error, but then this prevents the is_not_null flag of a tuple expression from being
// populated in some cases (specifically, when the expression's table name is initially empty).

//if (table_obj == nullptr) {
// LOG_DEBUG("Extracting regular table object");
// BinderContext::GetRegularTableObj(context_, table_name, table_obj, depth);
//}

if (table_obj != nullptr) {
expr->SetIsNotNull(table_obj->GetColumnCatalogEntry(std::get<2>(col_pos_tuple), false)->IsNotNull());
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/include/common/internal_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,14 @@ enum class RuleType : uint32_t {
TV_EQUALITY_WITH_TWO_CV, // (A.B = x) AND (A.B = y) where x/y are constant
TRANSITIVE_CLOSURE_CONSTANT, // (A.B = x) AND (A.B = C.D)

// Boolean short-circuit rules
AND_SHORT_CIRCUIT, // (FALSE AND B)
OR_SHORT_CIRCUIT, // (TRUE OR B)

// Catalog-based NULL/NON-NULL rules
NULL_LOOKUP_ON_NOT_NULL_COLUMN,
NOT_NULL_LOOKUP_ON_NOT_NULL_COLUMN,

// Place holder to generate number of rules compile time
NUM_RULES

Expand Down
12 changes: 11 additions & 1 deletion src/include/expression/tuple_value_expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class TupleValueExpression : public AbstractExpression {
tuple_idx_ = tuple_idx;
}

inline void SetIsNotNull(bool is_not_null) {
is_not_null_ = is_not_null;
}

/**
* @brief Attribute binding
* @param binding_contexts
Expand Down Expand Up @@ -116,6 +120,8 @@ class TupleValueExpression : public AbstractExpression {
if ((table_name_.empty() xor other.table_name_.empty()) ||
col_name_.empty() xor other.col_name_.empty())
return false;
if (GetIsNotNull() != other.GetIsNotNull())
return false;
bool res = bound_obj_id_ == other.bound_obj_id_;
if (!table_name_.empty() && !other.table_name_.empty())
res = table_name_ == other.table_name_ && res;
Expand Down Expand Up @@ -151,6 +157,8 @@ class TupleValueExpression : public AbstractExpression {

bool GetIsBound() const { return is_bound_; }

bool GetIsNotNull() const { return is_not_null_; }

const std::tuple<oid_t, oid_t, oid_t> &GetBoundOid() const {
return bound_obj_id_;
}
Expand Down Expand Up @@ -185,7 +193,8 @@ class TupleValueExpression : public AbstractExpression {
value_idx_(other.value_idx_),
tuple_idx_(other.tuple_idx_),
table_name_(other.table_name_),
col_name_(other.col_name_) {}
col_name_(other.col_name_),
is_not_null_(other.is_not_null_) {}

// Bound flag
bool is_bound_ = false;
Expand All @@ -196,6 +205,7 @@ class TupleValueExpression : public AbstractExpression {
int tuple_idx_;
std::string table_name_;
std::string col_name_;
bool is_not_null_ = false;

const planner::AttributeInfo *ai_;
};
Expand Down
47 changes: 47 additions & 0 deletions src/include/optimizer/rule_rewrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
namespace peloton {
namespace optimizer {

using GroupExprTemplate = GroupExpression;
using OptimizeContext = OptimizeContext;

/* Rules are applied from high to low priority */
enum class RulePriority : int {
HIGH = 3,
Expand Down Expand Up @@ -71,5 +74,49 @@ class TransitiveClosureConstantTransform: public Rule {
OptimizeContext *context) const override;
};

class AndShortCircuit: public Rule {
public:
AndShortCircuit();

int Promise(GroupExprTemplate *group_expr, OptimizeContext *context) const override;
bool Check(std::shared_ptr<AbstractNodeExpression> plan, OptimizeContext *context) const override;
void Transform(std::shared_ptr<AbstractNodeExpression> input,
std::vector<std::shared_ptr<AbstractNodeExpression>> &transformed,
OptimizeContext *context) const override;
};

class OrShortCircuit: public Rule {
public:
OrShortCircuit();

int Promise(GroupExprTemplate *group_expr, OptimizeContext *context) const override;
bool Check(std::shared_ptr<AbstractNodeExpression> plan, OptimizeContext *context) const override;
void Transform(std::shared_ptr<AbstractNodeExpression> input,
std::vector<std::shared_ptr<AbstractNodeExpression>> &transformed,
OptimizeContext *context) const override;
};

class NullLookupOnNotNullColumn: public Rule {
public:
NullLookupOnNotNullColumn();

int Promise(GroupExprTemplate *group_expr, OptimizeContext *context) const override;
bool Check(std::shared_ptr<AbstractNodeExpression> plan, OptimizeContext *context) const override;
void Transform(std::shared_ptr<AbstractNodeExpression> input,
std::vector<std::shared_ptr<AbstractNodeExpression>> &transformed,
OptimizeContext *context) const override;
};

class NotNullLookupOnNotNullColumn: public Rule {
public:
NotNullLookupOnNotNullColumn();

int Promise(GroupExprTemplate *group_expr, OptimizeContext *context) const override;
bool Check(std::shared_ptr<AbstractNodeExpression> plan, OptimizeContext *context) const override;
void Transform(std::shared_ptr<AbstractNodeExpression> input,
std::vector<std::shared_ptr<AbstractNodeExpression>> &transformed,
OptimizeContext *context) const override;
};

} // namespace optimizer
} // namespace peloton
4 changes: 4 additions & 0 deletions src/optimizer/binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@

#include "optimizer/binding.h"

#include <memory>

#include "common/logger.h"
#include "optimizer/operator_visitor.h"
#include "optimizer/optimizer.h"
#include "optimizer/absexpr_expression.h"
#include "expression/group_marker_expression.h"
#include "expression/abstract_expression.h"
#include "expression/tuple_value_expression.h"

namespace peloton {
namespace optimizer {
Expand Down
9 changes: 9 additions & 0 deletions src/optimizer/rule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ RuleSet::RuleSet() {
AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new TVEqualityWithTwoCVTransform());
AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new TransitiveClosureConstantTransform());

AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new AndShortCircuit());
AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new OrShortCircuit());

AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new NullLookupOnNotNullColumn());
AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new NotNullLookupOnNotNullColumn());

AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new TVEqualityWithTwoCVTransform());
AddRewriteRule(RewriteRuleSetName::GENERIC_RULES, new TransitiveClosureConstantTransform());

// Define transformation/implementation rules
AddTransformationRule(new InnerJoinCommutativity());
AddTransformationRule(new InnerJoinAssociativity());
Expand Down
Loading

0 comments on commit e3ac1ba

Please sign in to comment.