Permalink
Browse files

Change the first input type from Integer to Varchar and fix the inter…

…preted engine.
  • Loading branch information...
malin1993ml authored and hzxa21 committed Dec 5, 2017
1 parent 601fb33 commit 8ac0edd07c50f9954b3cf23e733a4e2fc5e6722d
@@ -199,34 +199,6 @@ void BindNodeVisitor::Visit(expression::FunctionExpression *expr) {
// Visit the subtree first
SqlNodeVisitor::Visit(expr);
// Specialize the first argument (DatePartType) for date functions, otherwise
// we have to do the string comparison to find out the corresponding
// DatePartType when scanning every tuple.
auto func_name = expr->GetFuncName();
auto func_operator_id =
function::BuiltInFunctions::GetFuncBySQLName(func_name).op_id;
if (func_operator_id == OperatorId::DateTrunc ||
func_operator_id == OperatorId::Extract) {
// Check the type of the first argument. Should be VARCHAR
auto date_part = expr->GetChild(0);
if (date_part->GetValueType() != type::TypeId::VARCHAR) {
throw Exception(EXCEPTION_TYPE_EXPRESSION,
"Incorrect argument type to function: " + func_name +
". Argument 0 expected type VARCHAR but found " +
TypeIdToString(date_part->GetValueType()) + ".");
}
// Convert the first argument to DatePartType
auto date_part_type = StringToDatePartType(
date_part->Evaluate(nullptr, nullptr, nullptr).ToString());
auto date_part_integer = type::ValueFactory::GetIntegerValue(
static_cast<int32_t>(date_part_type));
// Replace the first argument with an Integer expression of the DatePartType
expr->SetChild(0,
new expression::ConstantValueExpression(date_part_integer));
}
// Check catalog and bind function
std::vector<type::TypeId> argtypes;
for (size_t i = 0; i < expr->GetChildrenSize(); i++)
@@ -239,6 +211,20 @@ void BindNodeVisitor::Visit(expression::FunctionExpression *expr) {
LOG_DEBUG("Argument num: %ld", func_data.argument_types_.size());
expr->SetFunctionExpressionParameters(func_data.func_, func_data.return_type_,
func_data.argument_types_);
// Look into the OperatorId for built-in functions to check the first argument
// for timestamp functions.
// TODO(LM): The OperatorId might need to be changed to global ID after we
// rewrite the function identification logic.
auto func_operator_id = func_data.func_.op_id;
if (func_operator_id == OperatorId::DateTrunc ||
func_operator_id == OperatorId::Extract) {
auto date_part = expr->GetChild(0);
// Test whether the first argument is a correct DatePartType
StringToDatePartType(
date_part->Evaluate(nullptr, nullptr, nullptr).ToString());
}
}
} // namespace binder
View
@@ -817,7 +817,7 @@ void Catalog::AddBuiltinFunction(
txn)) {
throw CatalogException("Failed to add function " + func_name);
}
function::BuiltInFunctions::AddFunction(name, func_name, func);
function::BuiltInFunctions::AddFunction(func_name, func);
}
const FunctionData Catalog::GetFunction(
@@ -849,7 +849,7 @@ const FunctionData Catalog::GetFunction(
result.argument_types_ = argument_types;
result.func_name_ = proc_catalog_obj->GetSrc();
result.return_type_ = proc_catalog_obj->GetRetType();
result.func_ = function::BuiltInFunctions::GetFuncBySourceName(result.func_name_);
result.func_ = function::BuiltInFunctions::GetFuncByName(result.func_name_);
if (result.func_.impl == nullptr) {
txn_manager.AbortTransaction(txn);
@@ -1027,7 +1027,7 @@ void Catalog::InitializeFunctions() {
function::DateFunctions::Extract},
txn);
AddBuiltinFunction(
"date_trunc", {type::TypeId::INTEGER, type::TypeId::TIMESTAMP},
"date_trunc", {type::TypeId::VARCHAR, type::TypeId::TIMESTAMP},
type::TypeId::TIMESTAMP, internal_lang, "DateTrunc",
function::BuiltInFuncType{OperatorId::DateTrunc,
function::TimestampFunctions::_DateTrunc},
View
@@ -15,31 +15,16 @@
namespace peloton {
namespace function {
std::unordered_map<std::string, BuiltInFuncType>
BuiltInFunctions::kSourceNameFuncMap;
std::unordered_map<std::string, BuiltInFuncType>
BuiltInFunctions::kSQLNameFuncMap;
std::unordered_map<std::string, BuiltInFuncType> BuiltInFunctions::kFuncMap;
void BuiltInFunctions::AddFunction(const std::string &sql_func_name,
const std::string &source_func_name,
void BuiltInFunctions::AddFunction(const std::string &func_name,
BuiltInFuncType func) {
kSourceNameFuncMap.emplace(source_func_name, func);
kSQLNameFuncMap.emplace(sql_func_name, func);
kFuncMap.emplace(func_name, func);
}
BuiltInFuncType BuiltInFunctions::GetFuncBySourceName(
const std::string &func_name) {
auto func = kSourceNameFuncMap.find(func_name);
if (func == kSourceNameFuncMap.end()) {
return {OperatorId::Invalid, nullptr};
}
return func->second;
}
BuiltInFuncType BuiltInFunctions::GetFuncBySQLName(
const std::string &func_name) {
auto func = kSQLNameFuncMap.find(func_name);
if (func == kSQLNameFuncMap.end()) {
BuiltInFuncType BuiltInFunctions::GetFuncByName(const std::string &func_name) {
auto func = kFuncMap.find(func_name);
if (func == kFuncMap.end()) {
return {OperatorId::Invalid, nullptr};
}
return func->second;
@@ -23,9 +23,12 @@
namespace peloton {
namespace function {
uint64_t TimestampFunctions::DateTrunc(uint32_t date_part_type,
uint64_t TimestampFunctions::DateTrunc(const char *date_part_type,
uint64_t value) {
DatePartType date_part = static_cast<DatePartType>(date_part_type);
PL_ASSERT(date_part_type != nullptr);
std::string date_part_string(date_part_type);
DatePartType date_part = StringToDatePartType(date_part_string);
uint64_t timestamp = value;
uint64_t result = 0;
@@ -141,7 +144,7 @@ uint64_t TimestampFunctions::DateTrunc(uint32_t date_part_type,
type::Value TimestampFunctions::_DateTrunc(
const std::vector<type::Value> &args) {
uint32_t date_part = args[0].GetAs<uint32_t>();
char *date_part = args[0].GetAs<char *>();
uint64_t timestamp = args[1].GetAs<uint64_t>();
type::Value result;
@@ -34,22 +34,13 @@ class BuiltInFunctions {
private:
// Map the function name in C++ source (should be unique) to the actual
// function implementation
static std::unordered_map<std::string, BuiltInFuncType> kSourceNameFuncMap;
// Map the function name used in SQL to the actual function implementation.
// Different SQL names can map to the same function implementation(alias).
static std::unordered_map<std::string, BuiltInFuncType> kSQLNameFuncMap;
static std::unordered_map<std::string, BuiltInFuncType> kFuncMap;
public:
static void AddFunction(const std::string &sql_func_name,
const std::string &source_func_name,
BuiltInFuncType func);
static void AddFunction(const std::string &func_name, BuiltInFuncType func);
// Get the function from the name in C++ source code
static BuiltInFuncType GetFuncBySourceName(const std::string &func_name);
// Get the function from the name used in SQL
static BuiltInFuncType GetFuncBySQLName(const std::string &func_name);
static BuiltInFuncType GetFuncByName(const std::string &func_name);
};
} // namespace function
@@ -26,11 +26,7 @@ class TimestampFunctions {
// Truncate a timestamp to specified precision
// (1) The first argument selects to which precision to truncate the input
// value
// (2) The second argument is the length of the precision value (used to
// evaluate whether the value is NULL)
// (3) The third argument is the value expression of type timestamp
// (4) The fourth argument is the length of the timestamp value (used to
// evaluate whether the value is NULL)
// (2) The second argument is the value of the timestamp expression
// @return The Value returned is the value of type timestamp with
// all fields that are less significant than the selected one set to zero (or
// one, for day and month).
@@ -39,7 +35,7 @@ class TimestampFunctions {
// this function here to support that, but we need the parser/binder to
// support explicit type casts. For example:
// SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
static uint64_t DateTrunc(uint32_t date_part_type, uint64_t value);
static uint64_t DateTrunc(const char *date_part_type, uint64_t value);
static type::Value _DateTrunc(const std::vector<type::Value> &args);
};
View
@@ -289,8 +289,7 @@ Value::Value(TypeId type, float f) : Value(type) {
}
// VARCHAR and VARBINARY
Value::Value(TypeId type, const char *data, uint32_t len,
bool manage_data)
Value::Value(TypeId type, const char *data, uint32_t len, bool manage_data)
: Value(type) {
switch (type) {
case TypeId::VARCHAR:
@@ -379,8 +378,9 @@ bool Value::CheckComparable(const Value &o) const {
case TypeId::BOOLEAN:
case TypeId::VARCHAR:
return (true);
default:break;
} // SWITCH
default:
break;
} // SWITCH
break;
case TypeId::TINYINT:
case TypeId::SMALLINT:
@@ -397,7 +397,7 @@ bool Value::CheckComparable(const Value &o) const {
return true;
default:
break;
} // SWITCH
} // SWITCH
break;
case TypeId::VARCHAR:
// Anything can be cast to a string!
@@ -414,7 +414,7 @@ bool Value::CheckComparable(const Value &o) const {
break;
default:
break;
} // SWITCH
} // SWITCH
return false;
}
@@ -39,21 +39,22 @@ class TimestampFunctionsTests : public PelotonTest {};
*/
void DateTruncTestHelper(DatePartType part, std::string &date,
std::string &expected) {
// The first argument is an IntegerValue of the DatePartType
// The first argument is an VarcharValue of the DatePartType
// The second argument is a TimestampValue of the date
uint32_t int_date_part = *reinterpret_cast<const uint32_t *>(&part);
uint64_t int_date = type::ValueFactory::CastAsTimestamp(
type::ValueFactory::GetVarcharValue(date))
.GetAs<uint64_t>();
std::string string_date_part = DatePartTypeToString(part);
const char *char_date_part = string_date_part.c_str();
uint64_t int_date =
type::ValueFactory::CastAsTimestamp(
type::ValueFactory::GetVarcharValue(date)).GetAs<uint64_t>();
// The expected return value
uint64_t int_expected = type::ValueFactory::CastAsTimestamp(
type::ValueFactory::GetVarcharValue(expected))
.GetAs<uint64_t>();
uint64_t int_expected =
type::ValueFactory::CastAsTimestamp(
type::ValueFactory::GetVarcharValue(expected)).GetAs<uint64_t>();
// Invoke the DateTrunc method and get back the result
auto result =
function::TimestampFunctions::DateTrunc(int_date_part, int_date);
function::TimestampFunctions::DateTrunc(char_date_part, int_date);
// <PART> <EXPECTED>
// You can generate the expected value in postgres using this SQL:
@@ -70,8 +71,8 @@ void DateTruncTestHelper(DatePartType part, std::string &date,
// Invoke TimestampFunctions::DateTrunc(NULL)
TEST_F(TimestampFunctionsTests, NullDateTruncTest) {
auto result =
function::TimestampFunctions::DateTrunc(3, type::PELOTON_TIMESTAMP_NULL);
auto result = function::TimestampFunctions::DateTrunc(
"hour", type::PELOTON_TIMESTAMP_NULL);
EXPECT_EQ(result, type::PELOTON_TIMESTAMP_NULL);
}

0 comments on commit 8ac0edd

Please sign in to comment.