@@ -397,5 +397,213 @@ void TransitiveClosureConstantTransform::Transform(std::shared_ptr<AbsExpr_Expre
397397 transformed.push_back (abs_expr);
398398}
399399
400+ // ===========================================================
401+ //
402+ // Boolean short-circuit related functions
403+ //
404+ // ===========================================================
405+ AndShortCircuit::AndShortCircuit () {
406+ type_ = RuleType::AND_SHORT_CIRCUIT;
407+
408+ // (FALSE AND <any expression>)
409+ match_pattern = std::make_shared<Pattern<ExpressionType>>(ExpressionType::CONJUNCTION_AND);
410+ auto left_child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::VALUE_CONSTANT);
411+ auto right_child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::GROUP_MARKER);
412+
413+ match_pattern->AddChild (left_child);
414+ match_pattern->AddChild (right_child);
415+ }
416+
417+ int AndShortCircuit::Promise (GroupExprTemplate *group_expr, OptimizeContextTemplate *context) const {
418+ (void )group_expr;
419+ (void )context;
420+ return static_cast <int >(RulePriority::HIGH);
421+ }
422+
423+ bool AndShortCircuit::Check (std::shared_ptr<AbsExpr_Expression> plan, OptimizeContextTemplate *context) const {
424+ (void )plan;
425+ (void )context;
426+ return true ;
427+ }
428+
429+ void AndShortCircuit::Transform (std::shared_ptr<AbsExpr_Expression> input,
430+ std::vector<std::shared_ptr<AbsExpr_Expression>> &transformed,
431+ OptimizeContextTemplate *context) const {
432+ (void )context;
433+ (void )transformed;
434+
435+ // Asserting guarantees provided by the GroupExprBindingIterator
436+ // Structure: (FALSE AND <any expression>)
437+ PELOTON_ASSERT (input->Children ().size () == 2 );
438+ PELOTON_ASSERT (input->Op ().GetType () == ExpressionType::CONJUNCTION_AND);
439+
440+ std::shared_ptr<AbsExpr_Expression> left = input->Children ()[0 ];
441+ PELOTON_ASSERT (left->Children ().size () == 0 );
442+ PELOTON_ASSERT (left->Op ().GetType () == ExpressionType::VALUE_CONSTANT);
443+
444+ std::shared_ptr<expression::ConstantValueExpression> left_cv_expr = std::dynamic_pointer_cast<expression::ConstantValueExpression>(left->Op ().GetExpr ());
445+ type::Value left_value = left_cv_expr->GetValue ();
446+
447+ // Only transform the expression if we're ANDing a FALSE boolean value
448+ if (left_value.GetTypeId () == type::TypeId::BOOLEAN && left_value.IsFalse ()) {
449+ type::Value val_false = type::ValueFactory::GetBooleanValue (false );
450+ std::shared_ptr<expression::ConstantValueExpression> false_expr = std::make_shared<expression::ConstantValueExpression>(val_false);
451+ std::shared_ptr<AbsExpr_Expression> false_container = std::make_shared<AbsExpr_Expression>(AbsExpr_Container (false_expr));
452+ transformed.push_back (false_container);
453+ }
454+ }
455+
456+
457+ OrShortCircuit::OrShortCircuit () {
458+ type_ = RuleType::OR_SHORT_CIRCUIT;
459+
460+ // (FALSE AND <any expression>)
461+ match_pattern = std::make_shared<Pattern<ExpressionType>>(ExpressionType::CONJUNCTION_OR);
462+ auto left_child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::VALUE_CONSTANT);
463+ auto right_child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::GROUP_MARKER);
464+
465+ match_pattern->AddChild (left_child);
466+ match_pattern->AddChild (right_child);
467+ }
468+
469+ int OrShortCircuit::Promise (GroupExprTemplate *group_expr, OptimizeContextTemplate *context) const {
470+ (void )group_expr;
471+ (void )context;
472+ return static_cast <int >(RulePriority::HIGH);
473+ }
474+
475+ bool OrShortCircuit::Check (std::shared_ptr<AbsExpr_Expression> plan, OptimizeContextTemplate *context) const {
476+ (void )plan;
477+ (void )context;
478+ return true ;
479+ }
480+
481+ void OrShortCircuit::Transform (std::shared_ptr<AbsExpr_Expression> input,
482+ std::vector<std::shared_ptr<AbsExpr_Expression>> &transformed,
483+ OptimizeContextTemplate *context) const {
484+ (void )context;
485+ (void )transformed;
486+
487+ // Asserting guarantees provided by the GroupExprBindingIterator
488+ // Structure: (TRUE OR <any expression>)
489+ PELOTON_ASSERT (input->Children ().size () == 2 );
490+ PELOTON_ASSERT (input->Op ().GetType () == ExpressionType::CONJUNCTION_OR);
491+
492+ std::shared_ptr<AbsExpr_Expression> left = input->Children ()[0 ];
493+ PELOTON_ASSERT (left->Children ().size () == 0 );
494+ PELOTON_ASSERT (left->Op ().GetType () == ExpressionType::VALUE_CONSTANT);
495+
496+ std::shared_ptr<expression::ConstantValueExpression> left_cv_expr = std::dynamic_pointer_cast<expression::ConstantValueExpression>(left->Op ().GetExpr ());
497+ type::Value left_value = left_cv_expr->GetValue ();
498+
499+ // Only transform the expression if we're ANDing a TRUE boolean value
500+ if (left_value.GetTypeId () == type::TypeId::BOOLEAN && left_value.IsTrue ()) {
501+ type::Value val_true = type::ValueFactory::GetBooleanValue (true );
502+ std::shared_ptr<expression::ConstantValueExpression> true_expr = std::make_shared<expression::ConstantValueExpression>(val_true);
503+ std::shared_ptr<AbsExpr_Expression> true_container = std::make_shared<AbsExpr_Expression>(AbsExpr_Container (true_expr));
504+ transformed.push_back (true_container);
505+ }
506+ }
507+
508+
509+ NullLookupOnNotNullColumn::NullLookupOnNotNullColumn () {
510+ type_ = RuleType::NULL_LOOKUP_ON_NOT_NULL_COLUMN;
511+
512+ // Structure: [T.X IS NULL]
513+ match_pattern = std::make_shared<Pattern<ExpressionType>>(ExpressionType::OPERATOR_IS_NULL);
514+ auto child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::VALUE_TUPLE);
515+
516+ match_pattern->AddChild (child);
517+ }
518+
519+ int NullLookupOnNotNullColumn::Promise (GroupExprTemplate *group_expr, OptimizeContextTemplate *context) const {
520+ (void )group_expr;
521+ (void )context;
522+ return static_cast <int >(RulePriority::HIGH);
523+ }
524+
525+ bool NullLookupOnNotNullColumn::Check (std::shared_ptr<AbsExpr_Expression> plan, OptimizeContextTemplate *context) const {
526+ (void )plan;
527+ (void )context;
528+ return true ;
529+ }
530+
531+ void NullLookupOnNotNullColumn::Transform (std::shared_ptr<AbsExpr_Expression> input,
532+ std::vector<std::shared_ptr<AbsExpr_Expression>> &transformed,
533+ OptimizeContextTemplate *context) const {
534+ (void )context;
535+ (void )transformed;
536+
537+ // Asserting guarantees provided by the GroupExprBindingIterator
538+ // Structure: (TRUE OR <any expression>)
539+ PELOTON_ASSERT (input->Children ().size () == 1 );
540+ PELOTON_ASSERT (input->Op ().GetType () == ExpressionType::OPERATOR_IS_NULL);
541+
542+ std::shared_ptr<AbsExpr_Expression> child = input->Children ()[0 ];
543+ PELOTON_ASSERT (child->Children ().size () == 0 );
544+ PELOTON_ASSERT (child->Op ().GetType () == ExpressionType::VALUE_TUPLE);
545+
546+ std::shared_ptr<expression::TupleValueExpression> tuple_expr = std::dynamic_pointer_cast<expression::TupleValueExpression>(child->Op ().GetExpr ());
547+
548+ // Only transform into [FALSE] if the tuple value expression is specifically non-NULL,
549+ // otherwise do nothing
550+ if (tuple_expr->GetIsNotNull ()) {
551+ type::Value val_false = type::ValueFactory::GetBooleanValue (false );
552+ std::shared_ptr<expression::ConstantValueExpression> false_expr = std::make_shared<expression::ConstantValueExpression>(val_false);
553+ std::shared_ptr<AbsExpr_Expression> false_container = std::make_shared<AbsExpr_Expression>(AbsExpr_Container (false_expr));
554+ transformed.push_back (false_container);
555+ }
556+ }
557+
558+
559+ NotNullLookupOnNotNullColumn::NotNullLookupOnNotNullColumn () {
560+ type_ = RuleType::NOT_NULL_LOOKUP_ON_NOT_NULL_COLUMN;
561+
562+ // Structure: [T.X IS NOT NULL]
563+ match_pattern = std::make_shared<Pattern<ExpressionType>>(ExpressionType::OPERATOR_IS_NOT_NULL);
564+ auto child = std::make_shared<Pattern<ExpressionType>>(ExpressionType::VALUE_TUPLE);
565+
566+ match_pattern->AddChild (child);
567+ }
568+
569+ int NotNullLookupOnNotNullColumn::Promise (GroupExprTemplate *group_expr, OptimizeContextTemplate *context) const {
570+ (void )group_expr;
571+ (void )context;
572+ return static_cast <int >(RulePriority::HIGH);
573+ }
574+
575+ bool NotNullLookupOnNotNullColumn::Check (std::shared_ptr<AbsExpr_Expression> plan, OptimizeContextTemplate *context) const {
576+ (void )plan;
577+ (void )context;
578+ return true ;
579+ }
580+
581+ void NotNullLookupOnNotNullColumn::Transform (std::shared_ptr<AbsExpr_Expression> input,
582+ std::vector<std::shared_ptr<AbsExpr_Expression>> &transformed,
583+ OptimizeContextTemplate *context) const {
584+ (void )context;
585+ (void )transformed;
586+
587+ // Asserting guarantees provided by the GroupExprBindingIterator
588+ // Structure: (TRUE OR <any expression>)
589+ PELOTON_ASSERT (input->Children ().size () == 1 );
590+ PELOTON_ASSERT (input->Op ().GetType () == ExpressionType::OPERATOR_IS_NOT_NULL);
591+
592+ std::shared_ptr<AbsExpr_Expression> child = input->Children ()[0 ];
593+ PELOTON_ASSERT (child->Children ().size () == 0 );
594+ PELOTON_ASSERT (child->Op ().GetType () == ExpressionType::VALUE_TUPLE);
595+
596+ std::shared_ptr<expression::TupleValueExpression> tuple_expr = std::dynamic_pointer_cast<expression::TupleValueExpression>(child->Op ().GetExpr ());
597+
598+ // Only transform into [TRUE] if the tuple value expression is specifically non-NULL,
599+ // otherwise do nothing
600+ if (tuple_expr->GetIsNotNull ()) {
601+ type::Value val_true = type::ValueFactory::GetBooleanValue (true );
602+ std::shared_ptr<expression::ConstantValueExpression> true_expr = std::make_shared<expression::ConstantValueExpression>(val_true);
603+ std::shared_ptr<AbsExpr_Expression> true_container = std::make_shared<AbsExpr_Expression>(AbsExpr_Container (true_expr));
604+ transformed.push_back (true_container);
605+ }
606+ }
607+
400608} // namespace optimizer
401609} // namespace peloton
0 commit comments