Skip to content

Commit

Permalink
Fix casts on timestamps
Browse files Browse the repository at this point in the history
* Fix casts on timestamps

1) Write parser to get TIMESTAMP(3) in calcite
2) make valus to pass through cast during comparisions
3) unit tests for comparisions on timestamps

* Add DATE test for timestamp precision casts

* Code cleanup; Bypass skipping fragments for timestamps with unequal types
  • Loading branch information
wamsiv authored and andrewseidl committed Oct 19, 2018
1 parent 076a9cb commit 4522c7c
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 2 deletions.
1 change: 0 additions & 1 deletion Analyzer/Analyzer.cpp
Expand Up @@ -1064,7 +1064,6 @@ void Constant::do_cast(const SQLTypeInfo& new_type_info) {
} else if (type_info.get_type() == kTIMESTAMP &&
new_type_info.get_type() == kTIMESTAMP) {
type_info = new_type_info;
constval.timeval *= static_cast<int64_t>(pow(10, type_info.get_dimension()));
} else if (new_type_info.is_array() && type_info.is_array()) {
auto new_sub_ti = new_type_info.get_elem_type();
for (auto& v : value_list) {
Expand Down
9 changes: 9 additions & 0 deletions QueryEngine/CalciteAdapter.cpp
Expand Up @@ -1375,6 +1375,15 @@ std::string pg_shim_impl(const std::string& query) {
what.position(), what.length(), "CAST(" + what[1] + " AS TIMESTAMP(0))");
});
}
{
boost::regex immediate_cast_expr{R"(TIMESTAMP\(3\)\s+('[^']+'))",
boost::regex::extended | boost::regex::icase};
apply_shim(
result, immediate_cast_expr, [](std::string& result, const boost::smatch& what) {
result.replace(
what.position(), what.length(), "CAST(" + what[1] + " AS TIMESTAMP(3))");
});
}
{
boost::regex corr_expr{R"((\s+|,|\()(corr)\s*\()",
boost::regex::extended | boost::regex::icase};
Expand Down
3 changes: 2 additions & 1 deletion QueryEngine/CastIR.cpp
Expand Up @@ -68,7 +68,8 @@ llvm::Value* Executor::codegenCast(llvm::Value* operand_lv,
return codegenCastTimestampToDate(
operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
}
if (operand_ti.get_type() == kTIMESTAMP && ti.get_type() == kTIMESTAMP) {
if ((operand_ti.get_type() == kTIMESTAMP || operand_ti.get_type() == kDATE) &&
ti.get_type() == kTIMESTAMP) {
return codegenCastBetweenTimestamps(
operand_lv, operand_ti.get_dimension(), ti.get_dimension(), !ti.get_notnull());
}
Expand Down
7 changes: 7 additions & 0 deletions QueryEngine/Execute.cpp
Expand Up @@ -3075,6 +3075,13 @@ std::pair<bool, int64_t> Executor::skipFragment(
if (!lhs->get_type_info().is_integer() && !lhs->get_type_info().is_time()) {
continue;
}
if (lhs->get_type_info().get_type() == kTIMESTAMP &&
(lhs_col->get_type_info() != rhs_const->get_type_info())) {
// Original lhs col has different precision so
// column metadata holds value in original dimension scale
// therefore skip meta value comparison check
continue;
}
const int col_id = lhs_col->get_column_id();
auto chunk_meta_it = fragment.getChunkMetadataMap().find(col_id);
int64_t chunk_min{0};
Expand Down
175 changes: 175 additions & 0 deletions Tests/ExecuteTest.cpp
Expand Up @@ -7054,6 +7054,7 @@ TEST(Select, TimestampPrecision) {
// Precisions Cast Tests
// TODO(Wamsi): Add test for microsecond and nanosecond
// once the calcite issue regarding support above milliseconds is resolved
// Timestamps
ASSERT_EQ(1418509395000,
v<int64_t>(run_simple_agg(
"SELECT CAST(m as TIMESTAMP(3)) FROM test limit 1;", dt)));
Expand All @@ -7069,6 +7070,180 @@ TEST(Select, TimestampPrecision) {
ASSERT_EQ(g_num_rows + g_num_rows,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where CAST(m_3 as TIMESTAMP(0)) = m", dt)));
ASSERT_EQ(
g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m as timestamp(0)) between "
"TIMESTAMP(0) '2014-12-13 22:23:14' and TIMESTAMP(0) '2014-12-13 22:23:15'",
dt)));
ASSERT_EQ(g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m as timestamp(3)) between "
"TIMESTAMP(3) '2014-12-12 22:23:15.320' and TIMESTAMP(3) '2014-12-13 "
"22:23:15.323'",
dt)));
ASSERT_EQ(
g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_3 as timestamp(0)) between "
"TIMESTAMP(0) '2014-12-13 22:23:14' and TIMESTAMP(3) '2014-12-13 22:23:15'",
dt)));
ASSERT_EQ(g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_6 as timestamp(3)) between "
"TIMESTAMP(3) '2014-12-13 22:23:15.870' and TIMESTAMP(3) '2014-12-13 "
"22:23:15.875'",
dt)));
ASSERT_EQ(
g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_6 as timestamp(0)) between "
"TIMESTAMP(0) '2014-12-13 22:23:14' and TIMESTAMP(3) '2014-12-13 22:23:15'",
dt)));
ASSERT_EQ(g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_9 as timestamp(3)) between "
"TIMESTAMP(3) '2014-12-13 22:23:15.607' and TIMESTAMP(3) '2014-12-13 "
"22:23:15.608'",
dt)));
ASSERT_EQ(
g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_9 as timestamp(0)) between "
"TIMESTAMP(0) '2014-12-13 22:23:14' and TIMESTAMP(0) '2014-12-13 22:23:15'",
dt)));
ASSERT_EQ(
10,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where cast(m_9 as "
"timestamp(0)) >= TIMESTAMP(0) '2014-12-13 22:23:14';",
dt)));
ASSERT_EQ(
10,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where cast(m_9 as "
"timestamp(0)) <= TIMESTAMP(0) '2014-12-13 22:23:14';",
dt)));
ASSERT_EQ(10,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_9 as timestamp(3)) > "
"TIMESTAMP(3) '2014-12-13 22:23:14.607';",
dt)));
ASSERT_EQ(10,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_9 as timestamp(3)) < "
"TIMESTAMP(3) '2014-12-13 22:23:14.607';",
dt)));
ASSERT_EQ(10,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_6 as timestamp(3)) >= "
"TIMESTAMP(3) '2014-12-13 22:23:14.607';",
dt)));
ASSERT_EQ(10,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(m_6 as timestamp(3)) <= "
"TIMESTAMP(3) '2014-12-13 22:23:14.607';",
dt)));
ASSERT_EQ(
5,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where cast(m_6 as "
"timestamp(0)) >= TIMESTAMP(0) '2014-12-14 22:23:14';",
dt)));
ASSERT_EQ(
15,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where cast(m_6 as "
"timestamp(0)) <= TIMESTAMP(0) '2014-12-14 22:23:14';",
dt)));
ASSERT_EQ(5,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where m_3 >= "
"TIMESTAMP(3) '2014-12-13 22:23:15.607';",
dt)));
ASSERT_EQ(15,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where m_3 <= "
"TIMESTAMP(3) '2014-12-13 22:23:15.607';",
dt)));
ASSERT_EQ(
20,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where m_3 >= TIMESTAMP(0) '2014-12-14 22:23:14';",
dt)));
ASSERT_EQ(
0,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where m_3 <= TIMESTAMP(0) '2014-12-14 22:23:14';",
dt)));
ASSERT_EQ(20,
v<int64_t>(run_simple_agg(
"select count(*) from test where cast(m_3 as timestamp(0)) = m;", dt)));
ASSERT_EQ(20,
v<int64_t>(run_simple_agg("select count(*) from test where m_3 > m;", dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg("select count(*) from test where m_3 = m;", dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg("select count(*) from test where m_3 < m;", dt)));
ASSERT_EQ(
5, v<int64_t>(run_simple_agg("select count(*) from test where m_6 > m_3;", dt)));
ASSERT_EQ(
15, v<int64_t>(run_simple_agg("select count(*) from test where m_6 < m_3;", dt)));
ASSERT_EQ(
0, v<int64_t>(run_simple_agg("select count(*) from test where m_6 = m_3;", dt)));
ASSERT_EQ(
0,
v<int64_t>(run_simple_agg(
"select count(*) from test where cast(m_6 as timestamp(3)) = m_3;", dt)));
ASSERT_EQ(
15, v<int64_t>(run_simple_agg("select count(*) from test where m_9 > m_6;", dt)));
ASSERT_EQ(
5, v<int64_t>(run_simple_agg("select count(*) from test where m_9 < m_6;", dt)));
ASSERT_EQ(
0, v<int64_t>(run_simple_agg("select count(*) from test where m_9 = m_6;", dt)));
ASSERT_EQ(
0,
v<int64_t>(run_simple_agg(
"select count(*) from test where cast(m_9 as timestamp(3)) = m_3;", dt)));
ASSERT_EQ(15,
v<int64_t>(run_simple_agg("SELECT count(*) FROM test where m_3 = "
"TIMESTAMP(3) '2014-12-13 22:23:15.323';",
dt)));
// Dates
ASSERT_EQ(
g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(0)) between "
"TIMESTAMP(0) '1999-09-08 22:23:14' and TIMESTAMP(0) '1999-09-09 22:23:15'",
dt)));
ASSERT_EQ(g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(3)) between "
"TIMESTAMP(3) '1999-09-08 12:12:31.500' and TIMESTAMP(3) '1999-09-09 "
"22:23:15'",
dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(0)) between "
"TIMESTAMP(3) '1999-09-09 12:12:31.500' and TIMESTAMP(3) '1999-09-09 "
"22:23:15.500'",
dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(3)) between "
"TIMESTAMP(0) '1999-09-09 12:12:31.500' and TIMESTAMP(0) '1999-09-09 "
"22:23:15.500'",
dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(3)) >= "
"TIMESTAMP(3) '1999-09-09 12:12:31.500'",
dt)));
ASSERT_EQ(g_num_rows + g_num_rows / 2,
v<int64_t>(
run_simple_agg("SELECT count(*) FROM test where cast(o as "
"timestamp(3)) < TIMESTAMP(3) '1999-09-09 12:12:31.500'",
dt)));
ASSERT_EQ(g_num_rows + g_num_rows / 2,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(3)) < m_3", dt)));
ASSERT_EQ(0,
v<int64_t>(run_simple_agg(
"SELECT count(*) FROM test where cast(o as timestamp(3)) >= m_3", dt)));
}
}

Expand Down

0 comments on commit 4522c7c

Please sign in to comment.