示例#1
0
/*
 * Create an instance of an aggregator for the specified aggregate
 * type, column type, and result type. The object is constructed in
 * memory from the provided memrory pool.
 */
AbstractAttributeAggregator *GetAttributeAggregatorInstance(ExpressionType agg_type) {
  AbstractAttributeAggregator *aggregator;

  switch (agg_type) {
    case ExpressionType::AGGREGATE_COUNT:
      aggregator = new CountAggregator();
      break;
    case ExpressionType::AGGREGATE_COUNT_STAR:
      aggregator = new CountStarAggregator();
      break;
    case ExpressionType::AGGREGATE_SUM:
      aggregator = new SumAggregator();
      break;
    case ExpressionType::AGGREGATE_AVG:
      aggregator = new AvgAggregator(false);
      break;
    case ExpressionType::AGGREGATE_MIN:
      aggregator = new MinAggregator();
      break;
    case ExpressionType::AGGREGATE_MAX:
      aggregator = new MaxAggregator();
      break;
    default: {
      std::string message =
          "Unknown aggregate type " + ExpressionTypeToString(agg_type);
      throw UnknownTypeException(static_cast<int>(agg_type), message);
    }
  }

  return aggregator;
}
示例#2
0
AbstractExpression *GetMoreSpecialized(ExpressionType c, L *l, R *r) {
  assert(l);
  assert(r);
  switch (c) {
    case (EXPRESSION_TYPE_COMPARE_EQUAL):
      return new InlinedComparisonExpression<CmpEq, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
      return new InlinedComparisonExpression<CmpNe, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
      return new InlinedComparisonExpression<CmpLt, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
      return new InlinedComparisonExpression<CmpGt, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
      return new InlinedComparisonExpression<CmpLte, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
      return new InlinedComparisonExpression<CmpGte, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LIKE):
      return new InlinedComparisonExpression<CmpLike, L, R>(
          c, l, r);  // added by michael
    case (EXPRESSION_TYPE_COMPARE_IN):
      return new InlinedComparisonExpression<CmpIn, L, R>(
          c, l,
          r);  // added by michael
    default:
      char message[256];
      sprintf(message,
              "Invalid ExpressionType '%s' called for"
              " ComparisonExpression",
              ExpressionTypeToString(c).c_str());
      throw ExpressionException(message);
  }
}
示例#3
0
void AbstractExpression::DeduceExpressionName() {
  // If alias exists, it will be used in TrafficCop
  if (!alias.empty()) return;

  for (auto &child : children_) child->DeduceExpressionName();

  // Aggregate expression already has correct expr_name_
  if (ExpressionUtil::IsAggregateExpression(exp_type_)) return;

  auto op_str = ExpressionTypeToString(exp_type_, true);
  auto children_size = children_.size();
  if (exp_type_ == ExpressionType::FUNCTION) {
    auto expr = (FunctionExpression *)this;
    expr_name_ = expr->GetFuncName() + "(";
    for (size_t i = 0; i < children_size; i++) {
      if (i > 0) expr_name_.append(",");
      expr_name_.append(GetChild(i)->expr_name_);
    }
    expr_name_.append(")");
  } else {
    PL_ASSERT(children_size <= 2);
    if (children_size == 2) {
      expr_name_ = GetChild(0)->expr_name_ + " " + op_str + " " +
                   GetChild(1)->expr_name_;
    } else if (children_size == 1) {
      expr_name_ = op_str + " " + GetChild(0)->expr_name_;
    }
  }
}
示例#4
0
AbstractExpression *GetGeneral(ExpressionType c, AbstractExpression *l,
                               AbstractExpression *r) {
  PL_ASSERT(l);
  PL_ASSERT(r);
  switch (c) {
    case (EXPRESSION_TYPE_COMPARE_EQUAL):
      return new ComparisonExpression<CmpEq>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
      return new ComparisonExpression<CmpNe>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
      return new ComparisonExpression<CmpLt>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
      return new ComparisonExpression<CmpGt>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
      return new ComparisonExpression<CmpLte>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
      return new ComparisonExpression<CmpGte>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LIKE):
      return new ComparisonExpression<CmpLike>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_NOTLIKE):
      return new ComparisonExpression<CmpNotLike>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_IN):
      return new ComparisonExpression<CmpIn>(c, l, r);
    default:
      char message[256];
      snprintf(message, 256,
               "Invalid ExpressionType '%s' called"
               " for ComparisonExpression",
               ExpressionTypeToString(c).c_str());
      throw Exception(message);
  }
}
std::string AbstractExpression::Debug() const {
  if (this == nullptr) return "";
  std::ostringstream buffer;
  buffer << "Expression[" << ExpressionTypeToString(GetExpressionType()) << ", "
         << GetExpressionType() << "]";
  return (buffer.str());
}
示例#6
0
SeqScanPlan::SeqScanPlan(parser::SelectStatement *select_node) {
  LOG_DEBUG("Creating a Sequential Scan Plan");
  auto target_table = static_cast<storage::DataTable *>(
      catalog::Catalog::GetInstance()->GetTableWithName(
          select_node->from_table->GetDatabaseName(),
          select_node->from_table->GetTableName()));
  SetTargetTable(target_table);
  ColumnIds().clear();
  // Check if there is an aggregate function in query
  bool function_found = false;
  for (auto elem : *select_node->select_list) {
    if (elem->GetExpressionType() == EXPRESSION_TYPE_FUNCTION_REF) {
      function_found = true;
      break;
    }
  }
  // Pass all columns
  // TODO: This isn't efficient. Needs to be fixed
  if (function_found) {
    for (auto column : GetTable()->GetSchema()->GetColumns()) {
      oid_t col_id = SeqScanPlan::GetColumnID(column.column_name);
      SetColumnId(col_id);
    }
  }
  // Pass columns in select_list
  else {
    if (select_node->select_list->at(0)->GetExpressionType() !=
        EXPRESSION_TYPE_STAR) {
      for (auto col : *select_node->select_list) {
        LOG_TRACE("ExpressionType: %s",
                  ExpressionTypeToString(col->GetExpressionType()).c_str());
        auto col_name = col->GetName();
        oid_t col_id = SeqScanPlan::GetColumnID(std::string(col_name));
        SetColumnId(col_id);
      }
    } else {
      auto allColumns = GetTable()->GetSchema()->GetColumns();
      for (uint i = 0; i < allColumns.size(); i++) SetColumnId(i);
    }
  }

  // Check for "For Update" flag
  if(select_node->is_for_update == true){
    SetForUpdateFlag(true);
  }

  // Keep a copy of the where clause to be binded to values
  if (select_node->where_clause != NULL) {
    auto predicate = select_node->where_clause->Copy();
    // Replace COLUMN_REF expressions with TupleValue expressions
    expression::ExpressionUtil::ReplaceColumnExpressions(GetTable()->GetSchema(), predicate);
    predicate_with_params_ =
        std::unique_ptr<expression::AbstractExpression>(predicate->Copy());
    SetPredicate(predicate);
  }
}
示例#7
0
const std::string ComparisonExpression::GetInfo(int num_indent) const {
  std::ostringstream os;

  os << StringUtil::Indent(num_indent) << "Expression ::\n"
     << StringUtil::Indent(num_indent + 1) << "expression type = Comparison,\n"
     << StringUtil::Indent(num_indent + 1)
     << "comparison type = " << ExpressionTypeToString(exp_type_) << "\n";

  for (const auto &child : children_) {
    os << child.get()->GetInfo(num_indent + 2);
  }

  return os.str();
}
示例#8
0
// Produce the value that is the result of codegening the expression
codegen::Value ConjunctionTranslator::DeriveValue(CodeGen &codegen,
                                                  RowBatch::Row &row) const {
  const auto &conjunction =
      GetExpressionAs<expression::ConjunctionExpression>();
  codegen::Value left = row.DeriveValue(codegen, *conjunction.GetChild(0));
  codegen::Value right = row.DeriveValue(codegen, *conjunction.GetChild(1));

  switch (conjunction.GetExpressionType()) {
    case ExpressionType::CONJUNCTION_AND:
      return left.LogicalAnd(codegen, right);
    case ExpressionType::CONJUNCTION_OR:
      return left.LogicalOr(codegen, right);
    default:
      throw Exception{"Received a non-conjunction expression type: " +
                      ExpressionTypeToString(conjunction.GetExpressionType())};
  }
}
示例#9
0
//===--------------------------------------------------------------------===//
// Plain Aggregator
//===--------------------------------------------------------------------===//
PlainAggregator::PlainAggregator(const planner::AggregatePlan *node,
                                 storage::DataTable *output_table,
                                 executor::ExecutorContext *econtext)
    : AbstractAggregator(node, output_table, econtext) {
  // allocate aggregators
  aggregates = new Agg *[node->GetUniqueAggTerms().size()]();

  // initialize aggregators
  for (oid_t aggno = 0; aggno < node->GetUniqueAggTerms().size(); aggno++) {
	  LOG_TRACE("Aggregate term type: %s", ExpressionTypeToString(
        node->GetUniqueAggTerms()[aggno].aggtype).c_str());
    aggregates[aggno] =
        GetAggInstance(node->GetUniqueAggTerms()[aggno].aggtype);

    bool distinct = node->GetUniqueAggTerms()[aggno].distinct;
    aggregates[aggno]->SetDistinct(distinct);
  }
}
示例#10
0
TEST_F(BooleanValueTests, ComparisonTest) {
  std::vector<ExpressionType> compares = {
      ExpressionType::COMPARE_EQUAL,
      ExpressionType::COMPARE_NOTEQUAL,
      ExpressionType::COMPARE_LESSTHAN,
      ExpressionType::COMPARE_LESSTHANOREQUALTO,
      ExpressionType::COMPARE_GREATERTHAN,
      ExpressionType::COMPARE_GREATERTHANOREQUALTO};

  int values[] = {true, false, type::PELOTON_BOOLEAN_NULL};

  CmpBool result;
  type::Value val0;
  type::Value val1;

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      bool expected_null = false;

      // VALUE #0
      if (values[i] == type::PELOTON_BOOLEAN_NULL) {
        val0 = type::ValueFactory::GetNullValueByType(type::TypeId::BOOLEAN);
        expected_null = true;
      } else {
        val0 =
            type::ValueFactory::GetBooleanValue(static_cast<bool>(values[i]));
      }

      // VALUE #1
      if (values[j] == type::PELOTON_BOOLEAN_NULL) {
        val1 = type::ValueFactory::GetNullValueByType(type::TypeId::BOOLEAN);
        expected_null = true;
      } else {
        val1 =
            type::ValueFactory::GetBooleanValue(static_cast<bool>(values[j]));
      }

      for (auto etype : compares) {
        bool expected;

        switch (etype) {
          case ExpressionType::COMPARE_EQUAL:
            expected = values[i] == values[j];
            result = val0.CompareEquals(val1);
            break;
          case ExpressionType::COMPARE_NOTEQUAL:
            expected = values[i] != values[j];
            result = val0.CompareNotEquals(val1);
            break;
          case ExpressionType::COMPARE_LESSTHAN:
            expected = values[i] < values[j];
            result = val0.CompareLessThan(val1);
            break;
          case ExpressionType::COMPARE_LESSTHANOREQUALTO:
            expected = values[i] <= values[j];
            result = val0.CompareLessThanEquals(val1);
            break;
          case ExpressionType::COMPARE_GREATERTHAN:
            expected = values[i] > values[j];
            result = val0.CompareGreaterThan(val1);
            break;
          case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
            expected = values[i] >= values[j];
            result = val0.CompareGreaterThanEquals(val1);
            break;
          default:
            throw Exception("Unexpected comparison");
        }  // SWITCH
        LOG_TRACE("%s %s %s => %d | %d\n", val0.ToString().c_str(),
                  ExpressionTypeToString(etype).c_str(),
                  val1.ToString().c_str(),
                  static_cast<int>(expected),
                  static_cast<int>(result));

        if (expected_null) expected = false;

        EXPECT_EQ(expected, result == CmpBool::CmpTrue);
        EXPECT_EQ(!expected, result == CmpBool::CmpFalse);
        EXPECT_EQ(expected_null, result == CmpBool::NULL_);
      }
    }
  }
}
示例#11
0
const planner::AbstractPlan *PlanTransformer::TransformAgg(
    const AggPlanState *plan_state) {
  // Alias all I need
  const Agg *agg = plan_state->agg_plan;
  auto numphases = plan_state->numphases;
  auto numaggs = plan_state->numaggs;
  auto targetlist = plan_state->ps_targetlist;
  auto qual = plan_state->ps_qual;
  auto peragg = plan_state->peragg;
  auto tupleDesc = plan_state->result_tupleDescriptor;
  auto aggstrategy = plan_state->agg_plan->aggstrategy;

  LOG_INFO("Number of Agg phases: %d \n", numphases);

  // When we'll have >1 phases?
  if (numphases != 1) return nullptr;

  /* Get project info */
  std::unique_ptr<const planner::ProjectInfo> proj_info(
      BuildProjectInfoFromTLSkipJunk(targetlist));
  LOG_INFO("proj_info : \n%s", proj_info->Debug().c_str());

  /* Get predicate */
  std::unique_ptr<const expression::AbstractExpression> predicate(
      BuildPredicateFromQual(qual));

  /* Get Aggregate terms */
  std::vector<planner::AggregatePlan::AggTerm> unique_agg_terms;

  LOG_INFO("Number of (unique) Agg nodes: %d \n", numaggs);
  for (int aggno = 0; aggno < numaggs; aggno++) {
    auto transfn_oid = peragg[aggno].transfn_oid;

    auto itr = peloton::bridge::kPgTransitFuncMap.find(transfn_oid);
    if (kPgFuncMap.end() == itr) {
      LOG_ERROR("Unmapped Transit function Id : %u\n", transfn_oid);
      return nullptr;
    }

    // We don't check whether the mapped exprtype is a valid aggregate type
    // here.
    PltFuncMetaInfo fn_meta = itr->second;
    // We only take the first argument as input to aggregator because
    // we don't have multi-argument aggregator in Peloton at the moment.
    // WARNING: there can be no arguments (e.g., COUNT(*))
    auto arguments = peragg[aggno].aggrefstate->args;
    expression::AbstractExpression *agg_expr = nullptr;
    if (arguments) {
      GenericExprState *gstate =
          (GenericExprState *)lfirst(list_head(arguments));
      LOG_INFO("Creating Agg Expr");
      agg_expr = ExprTransformer::TransformExpr(gstate->arg);
      LOG_INFO("Done creating Agg Expr");
    }

    /*
     * AggStatePerAggData.sortColIdx along with other related attributes
     * are used to handle ORDER BY and DISTINCT *within* aggregation.
     * E.g.,
     * SELECT count(DISTINCT x) ...
     * SELECT str_agg(y ORDER BY x) ...
     * Currently, we only handle the agg(DISTINCT x) case by
     * checking whether numDistinctCols > 0.
     * Note that numDistinctCols > 0 may be a necessary but not sufficient
     * condition for agg(DISTINCT x).
     */

    bool distinct = (peragg[aggno].numDistinctCols > 0);

    unique_agg_terms.emplace_back(fn_meta.exprtype, agg_expr, distinct);

    LOG_INFO(
        "Unique Agg # : %d , transfn_oid : %u\n , aggtype = %s \n expr = %s, "
        "numDistinctCols = %d",
        aggno, transfn_oid, ExpressionTypeToString(fn_meta.exprtype).c_str(),
        agg_expr ? agg_expr->Debug().c_str() : "<NULL>",
        peragg[aggno].numDistinctCols);

    for (int i = 0; i < peragg[aggno].numDistinctCols; i++) {
      LOG_INFO("sortColIdx[%d] : %d \n", i, peragg[aggno].sortColIdx[i]);
    }

  }  // end loop aggno

  /* Get Group by columns */
  std::vector<oid_t> groupby_col_ids;
  LOG_INFO("agg.numCols = %d", agg->numCols);
  for (int i = 0; i < agg->numCols; i++) {
    LOG_INFO("agg.grpColIdx[%d] = %d \n", i, agg->grpColIdx[i]);

    auto attrno = agg->grpColIdx[i];
    if (AttributeNumberIsValid(attrno) &&
        AttrNumberIsForUserDefinedAttr(attrno)) {
      groupby_col_ids.emplace_back(AttrNumberGetAttrOffset(attrno));
    }
  }

  /* Get output schema */
  std::unique_ptr<catalog::Schema> output_schema(
      SchemaTransformer::GetSchemaFromTupleDesc(tupleDesc));

  /* Map agg stragegy */
  LOG_INFO("aggstrategy : %s\n", (AGG_HASHED == aggstrategy)
                                     ? "HASH"
                                     : (AGG_SORTED ? "SORT" : "PLAIN"));

  PelotonAggType agg_type = AGGREGATE_TYPE_INVALID;

  switch (aggstrategy) {
    case AGG_SORTED:
      agg_type = AGGREGATE_TYPE_SORTED;
      break;
    case AGG_HASHED:
      agg_type = AGGREGATE_TYPE_HASH;
      break;
    case AGG_PLAIN:
      agg_type = AGGREGATE_TYPE_PLAIN;
      break;
  }

  std::vector<oid_t> column_ids;
  for (auto agg_term : unique_agg_terms) {
    if (agg_term.expression) {
      LOG_INFO("AGG TERM :: %s", agg_term.expression->Debug().c_str());
    }
    BuildColumnListFromExpr(column_ids, agg_term.expression);
  }

  auto retval = new planner::AggregatePlan(
      proj_info.release(), predicate.release(), std::move(unique_agg_terms),
      std::move(groupby_col_ids), output_schema.release(), agg_type);

  ((planner::AggregatePlan *)retval)->SetColumnIds(column_ids);

  // Find children
  auto lchild = TransformPlan(outerAbstractPlanState(plan_state));
  retval->AddChild(lchild);

  return retval;
}
示例#12
0
TEST_F(TimestampValueTests, ComparisonTest) {
  std::vector<ExpressionType> compares = {
      ExpressionType::COMPARE_EQUAL,
      ExpressionType::COMPARE_NOTEQUAL,
      ExpressionType::COMPARE_LESSTHAN,
      ExpressionType::COMPARE_LESSTHANOREQUALTO,
      ExpressionType::COMPARE_GREATERTHAN,
      ExpressionType::COMPARE_GREATERTHANOREQUALTO};

  uint64_t values[] = {1000000000, 2000000000, type::PELOTON_TIMESTAMP_NULL};

  type::CmpBool result;
  type::Value val0;
  type::Value val1;

  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      bool expected_null = false;

      // VALUE #0
      if (values[i] == type::PELOTON_TIMESTAMP_NULL) {
        val0 = type::ValueFactory::GetNullValueByType(type::TypeId::TIMESTAMP);
        expected_null = true;
      } else {
        val0 = type::ValueFactory::GetTimestampValue(
            static_cast<uint64_t>(values[i]));
      }

      // VALUE #1
      if (values[j] == type::PELOTON_TIMESTAMP_NULL) {
        val1 = type::ValueFactory::GetNullValueByType(type::TypeId::TIMESTAMP);
        expected_null = true;
      } else {
        val1 = type::ValueFactory::GetTimestampValue(
            static_cast<uint64_t>(values[j]));
      }
      bool temp = expected_null;

      for (auto etype : compares) {
        bool expected;
        expected_null = temp;
        switch (etype) {
          case ExpressionType::COMPARE_EQUAL:
            expected = values[i] == values[j];
            result = val0.CompareEquals(val1);
            break;
          case ExpressionType::COMPARE_NOTEQUAL:
            expected = values[i] != values[j];
            result = val0.CompareNotEquals(val1);
            if (!val1.IsNull() && expected_null) {
              expected_null = false;
            }
            break;
          case ExpressionType::COMPARE_LESSTHAN:
            expected = values[i] < values[j];
            result = val0.CompareLessThan(val1);
            break;
          case ExpressionType::COMPARE_LESSTHANOREQUALTO:
            expected = values[i] <= values[j];
            result = val0.CompareLessThanEquals(val1);
            break;
          case ExpressionType::COMPARE_GREATERTHAN:
            expected = values[i] > values[j];
            result = val0.CompareGreaterThan(val1);
            break;
          case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
            expected = values[i] >= values[j];
            result = val0.CompareGreaterThanEquals(val1);
            break;
          default:
            throw Exception("Unexpected comparison");
        }  // SWITCH
        LOG_TRACE("%s %s %s => %d | %d\n", val0.ToString().c_str(),
                  ExpressionTypeToString(etype).c_str(),
                  val1.ToString().c_str(), expected, result);

        if (expected_null) {
          EXPECT_EQ(expected_null, result == type::CMP_NULL);
        } else {
          EXPECT_EQ(expected, result == type::CMP_TRUE);
          EXPECT_EQ(!expected, result == type::CMP_FALSE);
        }
      }
    }
  }
}