OmniSciDB  d2f719934e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Parser::CaseExpr Class Reference

#include <ParserNode.h>

+ Inheritance diagram for Parser::CaseExpr:
+ Collaboration diagram for Parser::CaseExpr:

Public Member Functions

 CaseExpr (std::list< ExprPair * > *w, Expr *e)
 
std::shared_ptr< Analyzer::Expranalyze (const Catalog_Namespace::Catalog &catalog, Analyzer::Query &query, TlistRefType allow_tlist_ref=TLIST_NONE) const override
 
std::string to_string () const override
 
- Public Member Functions inherited from Parser::Node
virtual ~Node ()
 

Static Public Member Functions

static std::shared_ptr
< Analyzer::Expr
normalize (const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >)
 

Private Attributes

std::list< std::unique_ptr
< ExprPair > > 
when_then_list_
 
std::unique_ptr< Exprelse_expr_
 

Additional Inherited Members

- Public Types inherited from Parser::Expr
enum  TlistRefType { TLIST_NONE, TLIST_REF, TLIST_COPY }
 

Detailed Description

Definition at line 694 of file ParserNode.h.

Constructor & Destructor Documentation

Parser::CaseExpr::CaseExpr ( std::list< ExprPair * > *  w,
Expr e 
)
inline

Definition at line 696 of file ParserNode.h.

References CHECK, and when_then_list_.

696  : else_expr_(e) {
697  CHECK(w);
698  for (const auto e : *w) {
699  when_then_list_.emplace_back(e);
700  }
701  delete w;
702  }
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:715
#define CHECK(condition)
Definition: Logger.h:211
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:714

Member Function Documentation

std::shared_ptr< Analyzer::Expr > Parser::CaseExpr::analyze ( const Catalog_Namespace::Catalog catalog,
Analyzer::Query query,
TlistRefType  allow_tlist_ref = TLIST_NONE 
) const
overridevirtual

Implements Parser::Expr.

Definition at line 920 of file ParserNode.cpp.

References kBOOLEAN.

923  {
924  SQLTypeInfo ti;
925  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
926  expr_pair_list;
927  for (auto& p : when_then_list_) {
928  auto e1 = p->get_expr1()->analyze(catalog, query, allow_tlist_ref);
929  if (e1->get_type_info().get_type() != kBOOLEAN) {
930  throw std::runtime_error("Only boolean expressions can be used after WHEN.");
931  }
932  auto e2 = p->get_expr2()->analyze(catalog, query, allow_tlist_ref);
933  expr_pair_list.emplace_back(e1, e2);
934  }
935  auto else_e =
936  else_expr_ ? else_expr_->analyze(catalog, query, allow_tlist_ref) : nullptr;
937  return normalize(expr_pair_list, else_e);
938 }
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:715
static std::shared_ptr< Analyzer::Expr > normalize(const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &, const std::shared_ptr< Analyzer::Expr >)
Definition: ParserNode.cpp:963
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:714
std::shared_ptr< Analyzer::Expr > Parser::CaseExpr::normalize ( const std::list< std::pair< std::shared_ptr< Analyzer::Expr >, std::shared_ptr< Analyzer::Expr >>> &  expr_pair_list,
const std::shared_ptr< Analyzer::Expr else_e_in 
)
static

Definition at line 963 of file ParserNode.cpp.

References CHECK, Analyzer::BinOper::common_numeric_type(), Analyzer::BinOper::common_string_type(), Parser::anonymous_namespace{ParserNode.cpp}::expr_is_null(), get_logical_type_info(), SQLTypeInfo::get_type(), SQLTypeInfo::is_boolean(), SQLTypeInfo::is_number(), SQLTypeInfo::is_string(), kENCODING_DICT, kNULLT, and SQLTypeInfo::set_notnull().

Referenced by QueryRewriter::rewriteColumnarDelete(), QueryRewriter::rewriteColumnarUpdate(), and RelAlgTranslator::translateCase().

966  {
967  SQLTypeInfo ti;
968  bool has_agg = false;
969  std::set<int> dictionary_ids;
970  bool has_none_encoded_str_projection = false;
971 
972  for (auto& p : expr_pair_list) {
973  auto e1 = p.first;
974  CHECK(e1->get_type_info().is_boolean());
975  auto e2 = p.second;
976  if (e2->get_type_info().is_string()) {
977  if (e2->get_type_info().is_dict_encoded_string()) {
978  dictionary_ids.insert(e2->get_type_info().get_comp_param());
979  // allow literals to potentially fall down the transient path
980  } else if (std::dynamic_pointer_cast<const Analyzer::ColumnVar>(e2)) {
981  has_none_encoded_str_projection = true;
982  }
983  }
984 
985  if (ti.get_type() == kNULLT) {
986  ti = e2->get_type_info();
987  } else if (e2->get_type_info().get_type() == kNULLT) {
988  ti.set_notnull(false);
989  e2->set_type_info(ti);
990  } else if (ti != e2->get_type_info()) {
991  if (ti.is_string() && e2->get_type_info().is_string()) {
992  ti = Analyzer::BinOper::common_string_type(ti, e2->get_type_info());
993  } else if (ti.is_number() && e2->get_type_info().is_number()) {
994  ti = Analyzer::BinOper::common_numeric_type(ti, e2->get_type_info());
995  } else if (ti.is_boolean() && e2->get_type_info().is_boolean()) {
996  ti = Analyzer::BinOper::common_numeric_type(ti, e2->get_type_info());
997  } else {
998  throw std::runtime_error(
999  "expressions in THEN clause must be of the same or compatible types.");
1000  }
1001  }
1002  if (e2->get_contains_agg()) {
1003  has_agg = true;
1004  }
1005  }
1006  auto else_e = else_e_in;
1007  if (else_e) {
1008  if (else_e->get_contains_agg()) {
1009  has_agg = true;
1010  }
1011  if (expr_is_null(else_e.get())) {
1012  ti.set_notnull(false);
1013  else_e->set_type_info(ti);
1014  } else if (ti != else_e->get_type_info()) {
1015  if (else_e->get_type_info().is_string()) {
1016  if (else_e->get_type_info().is_dict_encoded_string()) {
1017  dictionary_ids.insert(else_e->get_type_info().get_comp_param());
1018  // allow literals to potentially fall down the transient path
1019  } else if (std::dynamic_pointer_cast<const Analyzer::ColumnVar>(else_e)) {
1020  has_none_encoded_str_projection = true;
1021  }
1022  }
1023  ti.set_notnull(false);
1024  if (ti.is_string() && else_e->get_type_info().is_string()) {
1025  ti = Analyzer::BinOper::common_string_type(ti, else_e->get_type_info());
1026  } else if (ti.is_number() && else_e->get_type_info().is_number()) {
1027  ti = Analyzer::BinOper::common_numeric_type(ti, else_e->get_type_info());
1028  } else if (ti.is_boolean() && else_e->get_type_info().is_boolean()) {
1029  ti = Analyzer::BinOper::common_numeric_type(ti, else_e->get_type_info());
1030  } else if (get_logical_type_info(ti) !=
1031  get_logical_type_info(else_e->get_type_info())) {
1032  throw std::runtime_error(
1033  // types differing by encoding will be resolved at decode
1034 
1035  "expressions in ELSE clause must be of the same or compatible types as those "
1036  "in the THEN clauses.");
1037  }
1038  }
1039  }
1040  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1041  cast_expr_pair_list;
1042  for (auto p : expr_pair_list) {
1043  ti.set_notnull(false);
1044  cast_expr_pair_list.emplace_back(p.first, p.second->add_cast(ti));
1045  }
1046  if (else_e != nullptr) {
1047  else_e = else_e->add_cast(ti);
1048  } else {
1049  Datum d;
1050  // always create an else expr so that executor doesn't need to worry about it
1051  ti.set_notnull(false);
1052  else_e = makeExpr<Analyzer::Constant>(ti, true, d);
1053  }
1054  if (ti.get_type() == kNULLT) {
1055  throw std::runtime_error(
1056  "Can't deduce the type for case expressions, all branches null");
1057  }
1058 
1059  auto case_expr = makeExpr<Analyzer::CaseExpr>(ti, has_agg, cast_expr_pair_list, else_e);
1060  if (ti.get_compression() != kENCODING_DICT && dictionary_ids.size() == 1 &&
1061  *(dictionary_ids.begin()) > 0 && !has_none_encoded_str_projection) {
1062  // the above logic makes two assumptions when strings are present. 1) that all types
1063  // in the case statement are either null or strings, and 2) that none-encoded strings
1064  // will always win out over dict encoding. If we only have one dictionary, and that
1065  // dictionary is not a transient dictionary, we can cast the entire case to be dict
1066  // encoded and use transient dictionaries for any literals
1067  ti.set_compression(kENCODING_DICT);
1068  ti.set_comp_param(*dictionary_ids.begin());
1069  case_expr->add_cast(ti);
1070  }
1071  return case_expr;
1072 }
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1064
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
bool is_number() const
Definition: sqltypes.h:524
static SQLTypeInfo common_string_type(const SQLTypeInfo &type1, const SQLTypeInfo &type2)
Definition: Analyzer.cpp:411
static SQLTypeInfo common_numeric_type(const SQLTypeInfo &type1, const SQLTypeInfo &type2)
Definition: Analyzer.cpp:451
bool is_boolean() const
Definition: sqltypes.h:526
bool expr_is_null(const Analyzer::Expr *expr)
Definition: ParserNode.cpp:942
void set_notnull(bool n)
Definition: sqltypes.h:436
#define CHECK(condition)
Definition: Logger.h:211
bool is_string() const
Definition: sqltypes.h:519

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::string Parser::CaseExpr::to_string ( ) const
overridevirtual

Implements Parser::Expr.

Definition at line 1074 of file ParserNode.cpp.

1074  {
1075  std::string str("CASE ");
1076  for (auto& p : when_then_list_) {
1077  str += "WHEN " + p->get_expr1()->to_string() + " THEN " +
1078  p->get_expr2()->to_string() + " ";
1079  }
1080  if (else_expr_ != nullptr) {
1081  str += "ELSE " + else_expr_->to_string();
1082  }
1083  str += " END";
1084  return str;
1085 }
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:715
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:714

Member Data Documentation

std::unique_ptr<Expr> Parser::CaseExpr::else_expr_
private

Definition at line 715 of file ParserNode.h.

std::list<std::unique_ptr<ExprPair> > Parser::CaseExpr::when_then_list_
private

Definition at line 714 of file ParserNode.h.

Referenced by CaseExpr().


The documentation for this class was generated from the following files: