Skip to content

Commit

Permalink
Add DATE_TRUNC function to system
Browse files Browse the repository at this point in the history
  • Loading branch information
dwayneberry authored and asuhan committed Dec 7, 2015
1 parent ade2410 commit 4cda304
Show file tree
Hide file tree
Showing 17 changed files with 550 additions and 36 deletions.
67 changes: 67 additions & 0 deletions Analyzer/Analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ std::shared_ptr<Analyzer::Expr> ExtractExpr::deep_copy() const {
return makeExpr<ExtractExpr>(type_info, contains_agg, field, from_expr->deep_copy());
}

std::shared_ptr<Analyzer::Expr> DatetruncExpr::deep_copy() const {
return makeExpr<DatetruncExpr>(type_info, contains_agg, field, from_expr->deep_copy());
}

SQLTypeInfo BinOper::analyze_type_info(SQLOps op,
const SQLTypeInfo& left_type,
const SQLTypeInfo& right_type,
Expand Down Expand Up @@ -1039,6 +1043,19 @@ void ExtractExpr::group_predicates(std::list<const Expr*>& scan_predicates,
const_predicates.push_back(this);
}

void DatetruncExpr::group_predicates(std::list<const Expr*>& scan_predicates,
std::list<const Expr*>& join_predicates,
std::list<const Expr*>& const_predicates) const {
std::set<int> rte_idx_set;
from_expr->collect_rte_idx(rte_idx_set);
if (rte_idx_set.size() > 1)
join_predicates.push_back(this);
else if (rte_idx_set.size() == 1)
scan_predicates.push_back(this);
else
const_predicates.push_back(this);
}

std::shared_ptr<Analyzer::Expr> ColumnVar::rewrite_with_targetlist(const std::vector<TargetEntry*>& tlist) const {
for (auto tle : tlist) {
const Expr* e = tle->get_expr();
Expand Down Expand Up @@ -1169,6 +1186,10 @@ std::shared_ptr<Analyzer::Expr> ExtractExpr::rewrite_with_targetlist(const std::
return makeExpr<ExtractExpr>(type_info, contains_agg, field, from_expr->rewrite_with_targetlist(tlist));
}

std::shared_ptr<Analyzer::Expr> DatetruncExpr::rewrite_with_targetlist(const std::vector<TargetEntry*>& tlist) const {
return makeExpr<DatetruncExpr>(type_info, contains_agg, field, from_expr->rewrite_with_targetlist(tlist));
}

std::shared_ptr<Analyzer::Expr> CaseExpr::rewrite_with_child_targetlist(const std::vector<TargetEntry*>& tlist) const {
std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>> epair_list;
for (auto p : expr_pair_list) {
Expand All @@ -1184,6 +1205,11 @@ std::shared_ptr<Analyzer::Expr> ExtractExpr::rewrite_with_child_targetlist(
return makeExpr<ExtractExpr>(type_info, contains_agg, field, from_expr->rewrite_with_child_targetlist(tlist));
}

std::shared_ptr<Analyzer::Expr> DatetruncExpr::rewrite_with_child_targetlist(
const std::vector<TargetEntry*>& tlist) const {
return makeExpr<DatetruncExpr>(type_info, contains_agg, field, from_expr->rewrite_with_child_targetlist(tlist));
}

std::shared_ptr<Analyzer::Expr> CaseExpr::rewrite_agg_to_var(const std::vector<TargetEntry*>& tlist) const {
std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>> epair_list;
for (auto p : expr_pair_list) {
Expand All @@ -1197,6 +1223,10 @@ std::shared_ptr<Analyzer::Expr> ExtractExpr::rewrite_agg_to_var(const std::vecto
return makeExpr<ExtractExpr>(type_info, contains_agg, field, from_expr->rewrite_agg_to_var(tlist));
}

std::shared_ptr<Analyzer::Expr> DatetruncExpr::rewrite_agg_to_var(const std::vector<TargetEntry*>& tlist) const {
return makeExpr<DatetruncExpr>(type_info, contains_agg, field, from_expr->rewrite_agg_to_var(tlist));
}

bool ColumnVar::operator==(const Expr& rhs) const {
if (typeid(rhs) != typeid(ColumnVar) && typeid(rhs) != typeid(Var))
return false;
Expand Down Expand Up @@ -1344,6 +1374,13 @@ bool ExtractExpr::operator==(const Expr& rhs) const {
return field == rhs_ee.get_field() && *from_expr == *rhs_ee.get_from_expr();
}

bool DatetruncExpr::operator==(const Expr& rhs) const {
if (typeid(rhs) != typeid(DatetruncExpr))
return false;
const DatetruncExpr& rhs_ee = dynamic_cast<const DatetruncExpr&>(rhs);
return field == rhs_ee.get_field() && *from_expr == *rhs_ee.get_from_expr();
}

void ColumnVar::print() const {
std::cout << "(ColumnVar table: " << table_id << " column: " << column_id << " rte: " << rte_idx << ") ";
}
Expand Down Expand Up @@ -1533,6 +1570,14 @@ void ExtractExpr::print() const {
std::cout << ") ";
}

void DatetruncExpr::print() const {
std::cout << "DATE_TRUNC(";
std::cout << field;
std::cout << " , ";
from_expr->print();
std::cout << ") ";
}

void TargetEntry::print() const {
std::cout << "(" << resname << " ";
expr->print();
Expand Down Expand Up @@ -1634,6 +1679,14 @@ void ExtractExpr::find_expr(bool (*f)(const Expr*), std::list<const Expr*>& expr
from_expr->find_expr(f, expr_list);
}

void DatetruncExpr::find_expr(bool (*f)(const Expr*), std::list<const Expr*>& expr_list) const {
if (f(this)) {
add_unique(expr_list);
return;
}
from_expr->find_expr(f, expr_list);
}

void CaseExpr::collect_rte_idx(std::set<int>& rte_idx_set) const {
for (auto p : expr_pair_list) {
p.first->collect_rte_idx(rte_idx_set);
Expand All @@ -1647,6 +1700,10 @@ void ExtractExpr::collect_rte_idx(std::set<int>& rte_idx_set) const {
from_expr->collect_rte_idx(rte_idx_set);
}

void DatetruncExpr::collect_rte_idx(std::set<int>& rte_idx_set) const {
from_expr->collect_rte_idx(rte_idx_set);
}

void CaseExpr::collect_column_var(std::set<const ColumnVar*, bool (*)(const ColumnVar*, const ColumnVar*)>& colvar_set,
bool include_agg) const {
for (auto p : expr_pair_list) {
Expand All @@ -1663,6 +1720,12 @@ void ExtractExpr::collect_column_var(
from_expr->collect_column_var(colvar_set, include_agg);
}

void DatetruncExpr::collect_column_var(
std::set<const ColumnVar*, bool (*)(const ColumnVar*, const ColumnVar*)>& colvar_set,
bool include_agg) const {
from_expr->collect_column_var(colvar_set, include_agg);
}

void CaseExpr::check_group_by(const std::list<std::shared_ptr<Analyzer::Expr>>& groupby) const {
for (auto p : expr_pair_list) {
p.first->check_group_by(groupby);
Expand All @@ -1676,6 +1739,10 @@ void ExtractExpr::check_group_by(const std::list<std::shared_ptr<Analyzer::Expr>
from_expr->check_group_by(groupby);
}

void DatetruncExpr::check_group_by(const std::list<std::shared_ptr<Analyzer::Expr>>& groupby) const {
from_expr->check_group_by(groupby);
}

void CaseExpr::get_domain(DomainSet& domain_set) const {
for (const auto& p : expr_pair_list) {
const auto c = std::dynamic_pointer_cast<const Constant>(p.second);
Expand Down
30 changes: 30 additions & 0 deletions Analyzer/Analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,36 @@ class ExtractExpr : public Expr {
std::shared_ptr<Analyzer::Expr> from_expr;
};

/*
* @type DatetruncExpr
* @brief the DATE_TRUNC expression
*/
class DatetruncExpr : public Expr {
public:
DatetruncExpr(const SQLTypeInfo& ti, bool has_agg, DatetruncField f, std::shared_ptr<Analyzer::Expr> e)
: Expr(ti, has_agg), field(f), from_expr(e) {}
DatetruncField get_field() const { return field; }
const Expr* get_from_expr() const { return from_expr.get(); }
virtual std::shared_ptr<Analyzer::Expr> deep_copy() const;
virtual void check_group_by(const std::list<std::shared_ptr<Analyzer::Expr>>& groupby) const;
virtual void group_predicates(std::list<const Expr*>& scan_predicates,
std::list<const Expr*>& join_predicates,
std::list<const Expr*>& const_predicates) const;
virtual void collect_rte_idx(std::set<int>& rte_idx_set) const;
virtual void collect_column_var(std::set<const ColumnVar*, bool (*)(const ColumnVar*, const ColumnVar*)>& colvar_set,
bool include_agg) const;
virtual std::shared_ptr<Analyzer::Expr> rewrite_with_targetlist(const std::vector<TargetEntry*>& tlist) const;
virtual std::shared_ptr<Analyzer::Expr> rewrite_with_child_targetlist(const std::vector<TargetEntry*>& tlist) const;
virtual std::shared_ptr<Analyzer::Expr> rewrite_agg_to_var(const std::vector<TargetEntry*>& tlist) const;
virtual bool operator==(const Expr& rhs) const;
virtual void print() const;
virtual void find_expr(bool (*f)(const Expr*), std::list<const Expr*>& expr_list) const;

private:
DatetruncField field;
std::shared_ptr<Analyzer::Expr> from_expr;
};

/*
* @type TargetEntry
* @brief Target list defines a relational projection. It is a list of TargetEntry's.
Expand Down
1 change: 1 addition & 0 deletions Parser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ SET (parser_source_files
ParserNode.cpp
ParserNode.h
${CMAKE_CURRENT_SOURCE_DIR}/../QueryEngine/ExtractFromTime.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../QueryEngine/DateTruncate.cpp
)

ADD_LIBRARY (Parser ${BisonppOutput} ${FlexppOutput} ${CMAKE_CURRENT_BINARY_DIR}/parser.h ${parser_source_files})
Expand Down
74 changes: 73 additions & 1 deletion Parser/ParserNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,6 @@ std::string CaseExpr::to_string() const {
str += " END";
return str;
}

std::shared_ptr<Analyzer::Expr> ExtractExpr::analyze(const Catalog_Namespace::Catalog& catalog,
Analyzer::Query& query,
TlistRefType allow_tlist_ref) const {
Expand Down Expand Up @@ -599,6 +598,79 @@ std::string ExtractExpr::to_string() const {
str += *field + " FROM " + from_arg->to_string() + ")";
return str;
}
/*
* year
* month
* day
* hour
* minute
* second
*
* millennium
* century
* decade
* milliseconds
* microseconds
* week
*/
std::shared_ptr<Analyzer::Expr> DatetruncExpr::analyze(const Catalog_Namespace::Catalog& catalog,
Analyzer::Query& query,
TlistRefType allow_tlist_ref) const {
DatetruncField fieldno;
if (boost::iequals(*field, "year"))
fieldno = dtYEAR;
else if (boost::iequals(*field, "month"))
fieldno = dtMONTH;
else if (boost::iequals(*field, "day"))
fieldno = dtDAY;
else if (boost::iequals(*field, "hour"))
fieldno = dtHOUR;
else if (boost::iequals(*field, "minute"))
fieldno = dtMINUTE;
else if (boost::iequals(*field, "second"))
fieldno = dtSECOND;
else if (boost::iequals(*field, "millennium"))
fieldno = dtMILLENNIUM;
else if (boost::iequals(*field, "century"))
fieldno = dtCENTURY;
else if (boost::iequals(*field, "decade"))
fieldno = dtDECADE;
else if (boost::iequals(*field, "millisecond"))
fieldno = dtMILLISECOND;
else if (boost::iequals(*field, "microsecond"))
fieldno = dtMICROSECOND;
else if (boost::iequals(*field, "week"))
fieldno = dtWEEK;
else
throw std::runtime_error("Invalid field in DATE_TRUNC function " + *field);
auto from_expr = from_arg->analyze(catalog, query, allow_tlist_ref);
if (!from_expr->get_type_info().is_time())
throw std::runtime_error("Only TIME, TIMESTAMP and DATE types can be in DATE_TRUNC function.");
switch (from_expr->get_type_info().get_type()) {
case kTIME:
if (fieldno != dtHOUR && fieldno != dtMINUTE && fieldno != dtSECOND)
throw std::runtime_error("Cannot DATE_TRUNC " + *field + " from TIME.");
break;
default:
break;
}
SQLTypeInfo ti(kTIMESTAMP, 0, 0, from_expr->get_type_info().get_notnull());
auto c = std::dynamic_pointer_cast<Analyzer::Constant>(from_expr);
if (c != nullptr) {
c->set_type_info(ti);
Datum d;
d.bigintval = DateTruncate(fieldno, c->get_constval().timeval);
c->set_constval(d);
return c;
}
return makeExpr<Analyzer::DatetruncExpr>(ti, from_expr->get_contains_agg(), fieldno, from_expr->decompress());
}

std::string DatetruncExpr::to_string() const {
std::string str("DATE_TRUNC(");
str += *field + " , " + from_arg->to_string() + ")";
return str;
}

void UnionQuery::analyze(const Catalog_Namespace::Catalog& catalog, Analyzer::Query& query) const {
left->analyze(catalog, query);
Expand Down
16 changes: 16 additions & 0 deletions Parser/ParserNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,22 @@ class ExtractExpr : public Expr {
std::unique_ptr<Expr> from_arg;
};

/*
* DATE_TRUNC node
*/
class DatetruncExpr : public Expr {
public:
DatetruncExpr(std::string* f, Expr* a) : field(f), from_arg(a) {}
virtual std::shared_ptr<Analyzer::Expr> analyze(const Catalog_Namespace::Catalog& catalog,
Analyzer::Query& query,
TlistRefType allow_tlist_ref = TLIST_NONE) const;
virtual std::string to_string() const;

private:
std::unique_ptr<std::string> field;
std::unique_ptr<Expr> from_arg;
};

/*
* @type TableRef
* @brief table reference in FROM clause
Expand Down
9 changes: 8 additions & 1 deletion Parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ using namespace Parser;

%token ALL ALTER AMMSC ANY AS ASC AUTHORIZATION BETWEEN BIGINT BOOLEAN BY
%token CASE CAST CHAR_LENGTH CHARACTER CHECK CLOSE COLUMN COMMIT CONTINUE COPY CREATE CURRENT
%token DATABASE DATE CURSOR DECIMAL DECLARE DEFAULT DELETE DESC DISTINCT DOUBLE DROP
%token DATABASE DATE CURSOR DATE_TRUNC DECIMAL DECLARE DEFAULT DELETE DESC DISTINCT DOUBLE DROP
%token ELSE END EXISTS EXPLAIN EXTRACT FETCH FIRST FLOAT FOR FOREIGN FOUND FROM
%token GRANT GROUP HAVING IF ILIKE IN INSERT INTEGER INTO
%token IS LANGUAGE LAST LENGTH LIKE LIMIT NULLX NUMERIC OF OFFSET ON OPEN OPTION
Expand Down Expand Up @@ -857,6 +857,12 @@ extract_exp: EXTRACT '(' NAME FROM scalar_exp ')'
}
;

datetrunc_exp: DATE_TRUNC '(' NAME ',' scalar_exp ')'
{
$<nodeval>$ = new DatetruncExpr($<stringval>3, dynamic_cast<Expr*>($<nodeval>5));
}
;

charlength_exp:
CHAR_LENGTH '(' scalar_exp ')' { $<nodeval>$ = new CharLengthExpr(dynamic_cast<Expr*>($<nodeval>3),true); }
| LENGTH '(' scalar_exp ')' { $<nodeval>$ = new CharLengthExpr(dynamic_cast<Expr*>($<nodeval>3),false); }
Expand Down Expand Up @@ -888,6 +894,7 @@ scalar_exp:
{ $<nodeval>$ = new CastExpr(dynamic_cast<Expr*>($<nodeval>3), dynamic_cast<SQLType*>($<nodeval>5)); }
| case_exp { $<nodeval>$ = $<nodeval>1; }
| extract_exp { $<nodeval>$ = $<nodeval>1; }
| datetrunc_exp { $<nodeval>$ = $<nodeval>1; }
| charlength_exp { $<nodeval>$ = $<nodeval>1; }
| array_at_exp { $<nodeval>$ = $<nodeval>1; }
;
Expand Down
1 change: 1 addition & 0 deletions Parser/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ CURRENT TOK(CURRENT)
CURSOR TOK(CURSOR)
DATABASE TOK(DATABASE)
DATE TOK(DATE)
DATE_TRUNC TOK(DATE_TRUNC)
DECIMAL TOK(DECIMAL)
DECLARE TOK(DECLARE)
DEFAULT TOK(DEFAULT)
Expand Down
2 changes: 1 addition & 1 deletion QueryEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ add_custom_command(
ARGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS ${MAPD_DEFINITIONS} -arch sm_30 -lib ${CMAKE_CURRENT_BINARY_DIR}/cuda_mapd_rt.o -o ${CMAKE_CURRENT_BINARY_DIR}/cuda_mapd_rt.a)

add_custom_command(
DEPENDS cuda_mapd_rt.cu GpuInitGroups.cu GroupByRuntime.cpp ExtractFromTime.cpp ArrayOps.cpp StringFunctions.cpp ${CMAKE_SOURCE_DIR}/Utils/ChunkIter.cpp ${CMAKE_SOURCE_DIR}/Utils/StringLike.cpp
DEPENDS cuda_mapd_rt.cu GpuInitGroups.cu GroupByRuntime.cpp DateTruncate.cpp ExtractFromTime.cpp ArrayOps.cpp StringFunctions.cpp ${CMAKE_SOURCE_DIR}/Utils/ChunkIter.cpp ${CMAKE_SOURCE_DIR}/Utils/StringLike.cpp
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cuda_mapd_rt.o
COMMAND nvcc
ARGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS ${MAPD_DEFINITIONS} --device-link -arch sm_30 -c ${CMAKE_CURRENT_SOURCE_DIR}/cuda_mapd_rt.cu)
Expand Down
Loading

0 comments on commit 4cda304

Please sign in to comment.