OmniSciDB  a5dc49c757
 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 >, const Executor *executor=nullptr)
 

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 696 of file ParserNode.h.

Constructor & Destructor Documentation

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

Definition at line 698 of file ParserNode.h.

References CHECK, and when_then_list_.

698  : else_expr_(e) {
699  CHECK(w);
700  for (const auto e : *w) {
701  when_then_list_.emplace_back(e);
702  }
703  delete w;
704  }
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:718
#define CHECK(condition)
Definition: Logger.h:291
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:717

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 1058 of file ParserNode.cpp.

References kBOOLEAN.

1061  {
1062  SQLTypeInfo ti;
1063  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1064  expr_pair_list;
1065  for (auto& p : when_then_list_) {
1066  auto e1 = p->get_expr1()->analyze(catalog, query, allow_tlist_ref);
1067  if (e1->get_type_info().get_type() != kBOOLEAN) {
1068  throw std::runtime_error("Only boolean expressions can be used after WHEN.");
1069  }
1070  auto e2 = p->get_expr2()->analyze(catalog, query, allow_tlist_ref);
1071  expr_pair_list.emplace_back(e1, e2);
1072  }
1073  auto else_e =
1074  else_expr_ ? else_expr_->analyze(catalog, query, allow_tlist_ref) : nullptr;
1075  return normalize(expr_pair_list, else_e);
1076 }
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 >, const Executor *executor=nullptr)
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:718
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:717
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,
const Executor executor = nullptr 
)
static

Definition at line 1664 of file ParserNode.cpp.

References CHECK, Analyzer::BinOper::common_numeric_type(), Parser::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, kTEXT, SQLTypeInfo::set_notnull(), and TRANSIENT_DICT_ID.

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

1668  {
1669  SQLTypeInfo ti;
1670  bool has_agg = false;
1671  // We need to keep track of whether there was at
1672  // least one none-encoded string literal expression
1673  // type among any of the case sub-expressions separately
1674  // from rest of type determination logic, as it will
1675  // be casted to the output dictionary type if all output
1676  // types are either dictionary encoded or none-encoded
1677  // literals, or a transient encoded dictionary if all
1678  // types are none-encoded (column or literal)
1679  SQLTypeInfo none_encoded_literal_ti;
1680 
1681  for (auto& p : expr_pair_list) {
1682  auto e1 = p.first;
1683  CHECK(e1->get_type_info().is_boolean());
1684  auto e2 = p.second;
1685  if (e2->get_contains_agg()) {
1686  has_agg = true;
1687  }
1688  const auto& e2_ti = e2->get_type_info();
1689  const auto col_var = std::dynamic_pointer_cast<const Analyzer::ColumnVar>(e2);
1690  if (e2_ti.is_string() && !e2_ti.is_dict_encoded_string() && !col_var) {
1691  CHECK(e2_ti.is_none_encoded_string());
1692  none_encoded_literal_ti =
1693  none_encoded_literal_ti.get_type() == kNULLT
1694  ? e2_ti
1695  : common_string_type(none_encoded_literal_ti, e2_ti, executor);
1696  continue;
1697  }
1698  if (ti.get_type() == kNULLT) {
1699  if (!expr_is_null(e2.get())) {
1700  ti = e2_ti;
1701  }
1702  } else if (expr_is_null(e2.get())) {
1703  ti.set_notnull(false);
1704  e2->set_type_info(ti);
1705  } else if (ti != e2_ti) {
1706  if (ti.is_string() && e2_ti.is_string()) {
1707  // Executor is needed to determine which dictionary is the largest
1708  // in case of two dictionary types with different encodings
1709  ti = common_string_type(ti, e2_ti, executor);
1710  } else if (ti.is_number() && e2_ti.is_number()) {
1712  } else if (ti.is_boolean() && e2_ti.is_boolean()) {
1714  } else {
1715  throw std::runtime_error(
1716  "Expressions in THEN clause must be of the same or compatible types.");
1717  }
1718  }
1719  }
1720  auto else_e = else_e_in;
1721  const auto& else_ti = else_e->get_type_info();
1722  if (else_e) {
1723  const auto col_var = std::dynamic_pointer_cast<const Analyzer::ColumnVar>(else_e);
1724  if (else_e->get_contains_agg()) {
1725  has_agg = true;
1726  }
1727  if (else_ti.is_string() && !else_ti.is_dict_encoded_string() && !col_var) {
1728  CHECK(else_ti.is_none_encoded_string());
1729  none_encoded_literal_ti =
1730  none_encoded_literal_ti.get_type() == kNULLT
1731  ? else_ti
1732  : common_string_type(none_encoded_literal_ti, else_ti, executor);
1733  } else {
1734  if (ti.get_type() == kNULLT) {
1735  ti = else_ti;
1736  } else if (expr_is_null(else_e.get())) {
1737  ti.set_notnull(false);
1738  else_e->set_type_info(ti);
1739  } else if (ti != else_ti) {
1740  ti.set_notnull(false);
1741  if (ti.is_string() && else_ti.is_string()) {
1742  // Executor is needed to determine which dictionary is the largest
1743  // in case of two dictionary types with different encodings
1744  ti = common_string_type(ti, else_ti, executor);
1745  } else if (ti.is_number() && else_ti.is_number()) {
1746  ti = Analyzer::BinOper::common_numeric_type(ti, else_ti);
1747  } else if (ti.is_boolean() && else_ti.is_boolean()) {
1748  ti = Analyzer::BinOper::common_numeric_type(ti, else_ti);
1749  } else if (get_logical_type_info(ti) != get_logical_type_info(else_ti)) {
1750  throw std::runtime_error(
1751  // types differing by encoding will be resolved at decode
1752  "Expressions in ELSE clause must be of the same or compatible types as "
1753  "those in the THEN clauses.");
1754  }
1755  }
1756  }
1757  }
1758 
1759  if (ti.get_type() == kNULLT && none_encoded_literal_ti.get_type() != kNULLT) {
1760  // If we haven't set a type so far it's because
1761  // every case sub-expression has a none-encoded
1762  // literal output. Output a transient-encoded dictionary
1763  // so we can use the output downstream
1765  }
1766 
1767  std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1768  cast_expr_pair_list;
1769  for (auto p : expr_pair_list) {
1770  ti.set_notnull(false);
1771  cast_expr_pair_list.emplace_back(p.first, p.second->add_cast(ti));
1772  }
1773  if (else_e != nullptr) {
1774  else_e = else_e->add_cast(ti);
1775  } else {
1776  Datum d;
1777  // always create an else expr so that executor doesn't need to worry about it
1778  ti.set_notnull(false);
1779  else_e = makeExpr<Analyzer::Constant>(ti, true, d);
1780  }
1781  if (ti.get_type() == kNULLT) {
1782  throw std::runtime_error(
1783  "Cannot deduce the type for case expressions, all branches null");
1784  }
1785 
1786  auto case_expr = makeExpr<Analyzer::CaseExpr>(ti, has_agg, cast_expr_pair_list, else_e);
1787  return case_expr;
1788 }
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1472
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:391
SQLTypeInfo common_string_type(const SQLTypeInfo &lhs_type_info, const SQLTypeInfo &rhs_type_info, const Executor *executor)
Definition: ParserNode.cpp:355
#define TRANSIENT_DICT_ID
Definition: DbObjectKeys.h:24
bool is_number() const
Definition: sqltypes.h:576
static SQLTypeInfo common_numeric_type(const SQLTypeInfo &type1, const SQLTypeInfo &type2)
Definition: Analyzer.cpp:500
bool is_boolean() const
Definition: sqltypes.h:582
bool expr_is_null(const Analyzer::Expr *expr)
Definition: sqltypes.h:79
void set_notnull(bool n)
Definition: sqltypes.h:477
#define CHECK(condition)
Definition: Logger.h:291
bool is_string() const
Definition: sqltypes.h:561
Definition: Datum.h:71

+ 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 1790 of file ParserNode.cpp.

1790  {
1791  std::string str("CASE ");
1792  for (auto& p : when_then_list_) {
1793  str += "WHEN " + p->get_expr1()->to_string() + " THEN " +
1794  p->get_expr2()->to_string() + " ";
1795  }
1796  if (else_expr_ != nullptr) {
1797  str += "ELSE " + else_expr_->to_string();
1798  }
1799  str += " END";
1800  return str;
1801 }
std::unique_ptr< Expr > else_expr_
Definition: ParserNode.h:718
std::list< std::unique_ptr< ExprPair > > when_then_list_
Definition: ParserNode.h:717

Member Data Documentation

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

Definition at line 718 of file ParserNode.h.

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

Definition at line 717 of file ParserNode.h.

Referenced by CaseExpr().


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