able to insert DateTime64 objects into the table

This commit is contained in:
Martijn Bakker 2019-04-01 17:18:13 +01:00
parent a602a6c79c
commit 23b53ee2f9
4 changed files with 99 additions and 8 deletions

View File

@ -16,6 +16,7 @@
#include <Parsers/ASTLiteral.h>
#include <iomanip>
namespace DB
{
@ -47,6 +48,23 @@ DataTypeDateTimeBase<NumberBase>::DataTypeDateTimeBase(const std::string & time_
{
}
DataTypeDateTime64::Precision parsePrecision(const std::string & precision_name)
{
if (precision_name == "MILLI")
return DataTypeDateTime64::Precision::Millis;
else if (precision_name == "MICRO")
return DataTypeDateTime64::Precision::Micros;
return DataTypeDateTime64::Precision::Nanos;
}
DataTypeDateTime64::DataTypeDateTime64(const std::string & time_zone_name, const std::string & precision_name)
: DataTypeDateTimeBase(time_zone_name),
precision(parsePrecision(precision_name))
{
}
template<typename NumberBase>
const char * DataTypeDateTimeBase<NumberBase>::getFamilyName() const
{
@ -76,6 +94,43 @@ void DataTypeDateTimeBase<NumberBase>::serializeText(const IColumn & column, siz
writeDateTimeText(static_cast<const typename TypeGetter<NumberBase>::Column &>(column).getData()[row_num], ostr, time_zone);
}
void DataTypeDateTime64::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
{
time_t base_time;
auto full_time = static_cast<const ColumnUInt64 &>(column).getData()[row_num];
UInt32 time_fraction;
int pad_length = 0;
switch(precision) {
case DataTypeDateTime64::Precision::Millis: {
base_time = full_time / MILLIS_PER_SECOND;
time_fraction = full_time % MILLIS_PER_SECOND;
pad_length = 3;
break;
}
case DataTypeDateTime64::Precision::Micros: {
base_time = full_time / MICROS_PER_SECOND;
time_fraction = full_time % MICROS_PER_SECOND;
pad_length = 6;
break;
}
case DataTypeDateTime64::Precision::Nanos: {
base_time = full_time / NANOS_PER_SECOND;
time_fraction = full_time % NANOS_PER_SECOND;
pad_length = 9;
break;
}
}
writeDateTimeText(base_time, ostr, time_zone);
writeText(".", 1, ostr);
/// TODO make this efficient
std::stringstream ss;
ss << std::setfill('0') << std::setw(pad_length) << time_fraction;
writeText(ss.str(), ostr);
}
template<typename NumberBase>
void DataTypeDateTimeBase<NumberBase>::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
{
@ -258,14 +313,18 @@ static DataTypePtr create64(const ASTPtr & arguments)
if (!arguments)
return std::make_shared<DataTypeDateTime64>();
if (arguments->children.size() != 1)
throw Exception("DateTime64 data type can optionally have only one argument - time zone name", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
if (arguments->children.size() != 2)
throw Exception("DateTime64 data type can optionally have 2 arguments - precision and time zone name", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
const auto * arg = arguments->children[0]->as<ASTLiteral>();
if (!arg || arg->value.getType() != Field::Types::String)
throw Exception("Parameter for DateTime64 data type must be string literal", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
const auto * timezone_arg = arguments->children[0]->as<ASTLiteral>();
if (!timezone_arg || timezone_arg->value.getType() != Field::Types::String)
throw Exception("Timezone parameter for DateTime64 data type must be string literal", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
return std::make_shared<DataTypeDateTime>(arg->value.get<String>());
const auto * precision_arg = arguments->children[1]->as<ASTLiteral>();
if (!precision_arg || precision_arg->value.getType() != Field::Types::String)
throw Exception("Precision parameter for DateTime64 data type must be string literal", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
return std::make_shared<DataTypeDateTime64>(timezone_arg->value.get<String>(), precision_arg->value.get<String>());
}
void registerDataTypeDateTime(DataTypeFactory & factory)

View File

@ -57,7 +57,7 @@ public:
const DateLUTImpl & getTimeZone() const { return time_zone; }
private:
protected:
bool has_explicit_time_zone;
const DateLUTImpl & time_zone;
const DateLUTImpl & utc_time_zone;
@ -68,7 +68,21 @@ struct DataTypeDateTime : DataTypeDateTimeBase<UInt32> {
};
struct DataTypeDateTime64 : DataTypeDateTimeBase<UInt64> {
using DataTypeDateTimeBase::DataTypeDateTimeBase;
enum class Precision {
Millis,
Micros,
Nanos,
};
static constexpr UInt32 MILLIS_PER_SECOND = 1000;
static constexpr UInt32 MICROS_PER_SECOND = 1000 * 1000;
static constexpr UInt32 NANOS_PER_SECOND = 1000 * 1000 * 1000;
DataTypeDateTime64(const std::string & time_zone_name = "", const std::string & precision_name = "");
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override;
private:
const Precision precision;
};
}

View File

@ -0,0 +1,3 @@
2 1970-01-01 01:00:01.000000001 1 0
2 1970-01-01 01:00:01.000000003 3 3
2 1970-01-01 01:00:01.000000005 5 3

View File

@ -0,0 +1,15 @@
USE test;
DROP TABLE IF EXISTS A;
DROP TABLE IF EXISTS B;
CREATE TABLE A(k UInt32, t DateTime64, a Float64) ENGINE = MergeTree() ORDER BY (k, t);
INSERT INTO A(k,t,a) VALUES (2,1000000001,1),(2,1000000003,3),(2,1000000005,5);
CREATE TABLE B(k UInt32, t DateTime64, b Float64) ENGINE = MergeTree() ORDER BY (k, t);
INSERT INTO B(k,t,b) VALUES (2,1000000003,3);
SELECT k, t, a, b FROM A ASOF LEFT JOIN B USING(k,t) ORDER BY (k,t);
DROP TABLE B;
DROP TABLE A;