mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
Add DateTime64 support
This commit is contained in:
parent
8483d1c701
commit
4f4640ec90
@ -46,6 +46,8 @@ public class PreparedStatementsTest {
|
||||
testDecimalTypes(conn);
|
||||
testMiscTypes(conn);
|
||||
testDateTypes(conn);
|
||||
testUnusualDateTime64Scales(conn);
|
||||
testDateTimeTimezones(conn);
|
||||
conn.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -59,21 +61,21 @@ public class PreparedStatementsTest {
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "i8"), rs.getInt("i8"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "i16"), rs.getInt("i16"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "i32"), rs.getInt("i32"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "i64"), rs.getLong("i64"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "i128"), rs.getString("i128"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "i256"), rs.getString("i256"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "ui8"), rs.getInt("ui8"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "ui16"), rs.getInt("ui16"));
|
||||
System.out.printf("Type: %s, value: %d\n", getMysqlType(rs, "ui32"), rs.getLong("ui32"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "ui64"), rs.getString("ui64"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "ui128"), rs.getString("ui128"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "ui256"), rs.getString("ui256"));
|
||||
System.out.printf("Type: %s, value: %f\n", getMysqlType(rs, "f32"), rs.getFloat("f32"));
|
||||
System.out.printf("Type: %s, value: %f\n", getMysqlType(rs, "f64"), rs.getFloat("f64"));
|
||||
System.out.printf("Type: %s, value: %b\n", getMysqlType(rs, "b"), rs.getBoolean("b"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "i8"), rs.getInt("i8"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "i16"), rs.getInt("i16"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "i32"), rs.getInt("i32"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "i64"), rs.getLong("i64"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "i128"), rs.getString("i128"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "i256"), rs.getString("i256"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "ui8"), rs.getInt("ui8"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "ui16"), rs.getInt("ui16"));
|
||||
System.out.printf("%s, value: %d\n", getMysqlType(rs, "ui32"), rs.getLong("ui32"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "ui64"), rs.getString("ui64"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "ui128"), rs.getString("ui128"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "ui256"), rs.getString("ui256"));
|
||||
System.out.printf("%s, value: %f\n", getMysqlType(rs, "f32"), rs.getFloat("f32"));
|
||||
System.out.printf("%s, value: %f\n", getMysqlType(rs, "f64"), rs.getFloat("f64"));
|
||||
System.out.printf("%s, value: %b\n", getMysqlType(rs, "b"), rs.getBoolean("b"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
@ -84,10 +86,10 @@ public class PreparedStatementsTest {
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "s"), rs.getString("s"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "sn"), rs.getString("sn"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "lc"), rs.getString("lc"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "nlc"), rs.getString("nlc"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "s"), rs.getString("s"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "sn"), rs.getString("sn"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "lc"), rs.getString("lc"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "nlc"), rs.getString("nlc"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
@ -98,16 +100,12 @@ public class PreparedStatementsTest {
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d32"),
|
||||
rs.getBigDecimal("d32").toPlainString());
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d64"),
|
||||
rs.getBigDecimal("d64").toPlainString());
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d128_native"),
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d32"), rs.getBigDecimal("d32").toPlainString());
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d64"), rs.getBigDecimal("d64").toPlainString());
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d128_native"),
|
||||
rs.getBigDecimal("d128_native").toPlainString());
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d128_text"),
|
||||
rs.getString("d128_text"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d256"),
|
||||
rs.getString("d256"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d128_text"), rs.getString("d128_text"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d256"), rs.getString("d256"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
@ -118,12 +116,41 @@ public class PreparedStatementsTest {
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d"), rs.getDate("d"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "d32"), rs.getDate("d32"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "dt"), rs.getTimestamp("dt"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "dt64_3"), rs.getString("dt64_3"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "dt64_6"), rs.getString("dt64_6"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "dt64_9"), rs.getString("dt64_9"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d"), rs.getDate("d"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "d32"), rs.getDate("d32"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt"), rs.getTimestamp("dt"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_3"), rs.getTimestamp("dt64_3"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_6"), rs.getTimestamp("dt64_6"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_9"), rs.getTimestamp("dt64_9"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static void testUnusualDateTime64Scales(Connection conn) throws SQLException {
|
||||
System.out.println("### testUnusualDateTime64Scales");
|
||||
ResultSet rs = conn.prepareStatement("SELECT * FROM ps_unusual_datetime64_scales").executeQuery();
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_0"), rs.getTimestamp("dt64_0"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_1"), rs.getTimestamp("dt64_1"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_2"), rs.getTimestamp("dt64_2"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_4"), rs.getTimestamp("dt64_4"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_5"), rs.getTimestamp("dt64_5"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_7"), rs.getTimestamp("dt64_7"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_8"), rs.getTimestamp("dt64_8"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static void testDateTimeTimezones(Connection conn) throws SQLException {
|
||||
System.out.println("### testDateTimeTimezones");
|
||||
ResultSet rs = conn.prepareStatement("SELECT * FROM ps_datetime_timezones").executeQuery();
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt"), rs.getTimestamp("dt"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "dt64_3"), rs.getTimestamp("dt64_3"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
@ -134,16 +161,17 @@ public class PreparedStatementsTest {
|
||||
int rowNum = 1;
|
||||
while (rs.next()) {
|
||||
System.out.printf("Row #%d\n", rowNum++);
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "a"), rs.getString("a"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "u"), rs.getString("u"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "t"), rs.getString("t"));
|
||||
System.out.printf("Type: %s, value: %s\n", getMysqlType(rs, "m"), rs.getString("m"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "a"), rs.getString("a"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "u"), rs.getString("u"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "t"), rs.getString("t"));
|
||||
System.out.printf("%s, value: %s\n", getMysqlType(rs, "m"), rs.getString("m"));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static MysqlType getMysqlType(ResultSet rs, String columnLabel) throws SQLException {
|
||||
private static String getMysqlType(ResultSet rs, String columnLabel) throws SQLException {
|
||||
ResultSetMetaData meta = rs.getMetaData();
|
||||
return MysqlType.getByJdbcType(meta.getColumnType(rs.findColumn(columnLabel)));
|
||||
return String.format("%s type is %s", columnLabel,
|
||||
MysqlType.getByJdbcType(meta.getColumnType(rs.findColumn(columnLabel))));
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "Columns/ColumnLowCardinality.h"
|
||||
#include "Columns/ColumnVector.h"
|
||||
#include "Columns/ColumnsDateTime.h"
|
||||
#include "Core/DecimalFunctions.h"
|
||||
#include "DataTypes/DataTypeDateTime64.h"
|
||||
#include "DataTypes/DataTypeLowCardinality.h"
|
||||
#include "DataTypes/DataTypeNullable.h"
|
||||
#include "DataTypes/DataTypesNumber.h"
|
||||
@ -74,46 +76,66 @@ namespace MySQLProtocol
|
||||
payload_size += 8;
|
||||
break;
|
||||
case TypeIndex::Date: {
|
||||
UInt16 value = assert_cast<const ColumnVector<UInt16> &>(*col).getData()[row_num];
|
||||
if (value == 0)
|
||||
{
|
||||
payload_size += 1; // length only, no other fields
|
||||
}
|
||||
else
|
||||
{
|
||||
payload_size += 5;
|
||||
}
|
||||
payload_size += 5;
|
||||
break;
|
||||
}
|
||||
case TypeIndex::Date32: {
|
||||
Int32 value = assert_cast<const ColumnVector<Int32> &>(*col).getData()[row_num];
|
||||
if (value == 0)
|
||||
{
|
||||
payload_size += 1; // length only, no other fields
|
||||
}
|
||||
else
|
||||
{
|
||||
payload_size += 5;
|
||||
}
|
||||
payload_size += 5;
|
||||
break;
|
||||
}
|
||||
case TypeIndex::DateTime: {
|
||||
UInt32 value = assert_cast<const ColumnVector<UInt32> &>(*col).getData()[row_num];
|
||||
if (value == 0)
|
||||
LocalDateTime ldt = LocalDateTime(value, DateLUT::instance(getDateTimeTimezone(*data_type)));
|
||||
|
||||
bool has_time = !(ldt.hour() == 0 && ldt.minute() == 0 && ldt.second() == 0);
|
||||
if (has_time)
|
||||
{
|
||||
payload_size += 1; // length only, no other fields
|
||||
payload_size += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalDateTime ldt = LocalDateTime(value, DateLUT::instance(getDateTimeTimezone(*data_type)));
|
||||
if (ldt.second() == 0 && ldt.minute() == 0 && ldt.hour() == 0)
|
||||
{
|
||||
payload_size += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
payload_size += 8;
|
||||
}
|
||||
payload_size += 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeIndex::DateTime64: {
|
||||
const auto * date_time_type = typeid_cast<const DataTypeDateTime64 *>(data_type.get());
|
||||
UInt32 scale = date_time_type->getScale();
|
||||
|
||||
static constexpr UInt32 MaxScale = DecimalUtils::max_precision<DateTime64>;
|
||||
scale = scale > MaxScale ? MaxScale : scale;
|
||||
|
||||
const auto dt64 = assert_cast<const ColumnDateTime64 &>(*col).getData()[row_num];
|
||||
auto components = DecimalUtils::split(dt64, scale);
|
||||
|
||||
using T = typename DateTime64::NativeType;
|
||||
if (dt64.value < 0 && components.fractional)
|
||||
{
|
||||
components.fractional
|
||||
= DecimalUtils::scaleMultiplier<T>(scale) + (components.whole ? T(-1) : T(1)) * components.fractional;
|
||||
--components.whole;
|
||||
}
|
||||
if (scale > 6)
|
||||
{
|
||||
// MySQL Timestamp has max scale of 6
|
||||
components.fractional /= static_cast<int>(pow(10, scale - 6));
|
||||
}
|
||||
|
||||
LocalDateTime ldt = LocalDateTime(components.whole, DateLUT::instance(getDateTimeTimezone(*data_type)));
|
||||
|
||||
bool has_microseconds = components.fractional != 0;
|
||||
bool has_time = !(ldt.hour() == 0 && ldt.minute() == 0 && ldt.second() == 0);
|
||||
if (has_microseconds)
|
||||
{
|
||||
payload_size += 12;
|
||||
}
|
||||
else if (has_time)
|
||||
{
|
||||
payload_size += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
payload_size += 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -199,73 +221,133 @@ namespace MySQLProtocol
|
||||
}
|
||||
case TypeIndex::Date: {
|
||||
UInt16 value = assert_cast<const ColumnVector<UInt16> &>(*col).getData()[row_num];
|
||||
if (value != 0)
|
||||
{
|
||||
LocalDate ld = LocalDate(DayNum(value));
|
||||
buffer.write(static_cast<char>(4)); // bytes_following
|
||||
auto year = ld.year();
|
||||
auto month = ld.month();
|
||||
auto day = ld.day();
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write(static_cast<char>(0));
|
||||
}
|
||||
LocalDate ld = LocalDate(DayNum(value));
|
||||
buffer.write(static_cast<char>(4)); // bytes_following
|
||||
auto year = ld.year();
|
||||
auto month = ld.month();
|
||||
auto day = ld.day();
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
break;
|
||||
}
|
||||
case TypeIndex::Date32: {
|
||||
Int32 value = assert_cast<const ColumnVector<Int32> &>(*col).getData()[row_num];
|
||||
if (value != 0)
|
||||
{
|
||||
LocalDate ld = LocalDate(ExtendedDayNum(value));
|
||||
buffer.write(static_cast<char>(4)); // bytes_following
|
||||
auto year = ld.year();
|
||||
auto month = ld.month();
|
||||
auto day = ld.day();
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write(static_cast<char>(0));
|
||||
}
|
||||
LocalDate ld = LocalDate(ExtendedDayNum(value));
|
||||
buffer.write(static_cast<char>(4)); // bytes_following
|
||||
auto year = ld.year();
|
||||
auto month = ld.month();
|
||||
auto day = ld.day();
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
break;
|
||||
}
|
||||
case TypeIndex::DateTime: {
|
||||
UInt32 value = assert_cast<const ColumnVector<UInt32> &>(*col).getData()[row_num];
|
||||
if (value != 0)
|
||||
String timezone = getDateTimeTimezone(*data_type);
|
||||
LocalDateTime ldt = LocalDateTime(value, DateLUT::instance(timezone));
|
||||
int year = ldt.year();
|
||||
int month = ldt.month();
|
||||
int day = ldt.day();
|
||||
int hour = ldt.hour();
|
||||
int minute = ldt.minute();
|
||||
int second = ldt.second();
|
||||
bool has_time = !(hour == 0 && minute == 0 && second == 0);
|
||||
size_t bytes_following = has_time ? 7 : 4;
|
||||
buffer.write(reinterpret_cast<const char *>(&bytes_following), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
if (has_time)
|
||||
{
|
||||
LocalDateTime ldt = LocalDateTime(value, DateLUT::instance(getDateTimeTimezone(*data_type)));
|
||||
int year = ldt.year();
|
||||
int month = ldt.month();
|
||||
int day = ldt.day();
|
||||
int hour = ldt.hour();
|
||||
int minute = ldt.minute();
|
||||
int second = ldt.second();
|
||||
bool has_time = !(hour == 0 && minute == 0 && second == 0);
|
||||
size_t bytes_following = has_time ? 7 : 4;
|
||||
buffer.write(reinterpret_cast<const char *>(&bytes_following), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
if (has_time)
|
||||
{
|
||||
buffer.write(reinterpret_cast<const char *>(&hour), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&minute), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&second), 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write(static_cast<char>(0));
|
||||
buffer.write(reinterpret_cast<const char *>(&hour), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&minute), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&second), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeIndex::DateTime64: {
|
||||
const auto * date_time_type = typeid_cast<const DataTypeDateTime64 *>(data_type.get());
|
||||
UInt32 scale = date_time_type->getScale();
|
||||
|
||||
static constexpr UInt32 MaxScale = DecimalUtils::max_precision<DateTime64>;
|
||||
scale = scale > MaxScale ? MaxScale : scale;
|
||||
|
||||
const auto dt64 = assert_cast<const ColumnDateTime64 &>(*col).getData()[row_num];
|
||||
auto components = DecimalUtils::split(dt64, scale);
|
||||
|
||||
using T = typename DateTime64::NativeType;
|
||||
if (dt64.value < 0 && components.fractional)
|
||||
{
|
||||
components.fractional
|
||||
= DecimalUtils::scaleMultiplier<T>(scale) + (components.whole ? T(-1) : T(1)) * components.fractional;
|
||||
--components.whole;
|
||||
}
|
||||
|
||||
if (components.fractional != 0)
|
||||
{
|
||||
if (scale > 6)
|
||||
{
|
||||
// MySQL Timestamp has max scale of 6
|
||||
components.fractional /= static_cast<int>(pow(10, scale - 6));
|
||||
}
|
||||
else
|
||||
{
|
||||
// fractional == 1 is a different microsecond value depending on the scale
|
||||
// Scale 1 = 100 000
|
||||
// Scale 2 = 010 000
|
||||
// Scale 3 = 001 000
|
||||
// Scale 4 = 000 100
|
||||
// Scale 5 = 000 010
|
||||
// Scale 6 = 000 001
|
||||
components.fractional *= static_cast<int>(pow(10, 6 - scale));
|
||||
}
|
||||
}
|
||||
|
||||
String timezone = getDateTimeTimezone(*data_type);
|
||||
std::cout << "Timezone is " << timezone << std::endl;
|
||||
LocalDateTime ldt = LocalDateTime(components.whole, DateLUT::instance(timezone));
|
||||
auto year = ldt.year();
|
||||
auto month = ldt.month();
|
||||
auto day = ldt.day();
|
||||
auto hour = ldt.hour();
|
||||
auto minute = ldt.minute();
|
||||
auto second = ldt.second();
|
||||
|
||||
bool has_time = !(hour == 0 && minute == 0 && second == 0);
|
||||
bool has_microseconds = components.fractional != 0;
|
||||
|
||||
if (has_microseconds)
|
||||
{
|
||||
buffer.write(static_cast<char>(11)); // bytes_following
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&hour), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&minute), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&second), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&components.fractional), 4);
|
||||
}
|
||||
else if (has_time)
|
||||
{
|
||||
buffer.write(static_cast<char>(7)); // bytes_following
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&hour), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&minute), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&second), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write(static_cast<char>(4)); // bytes_following
|
||||
buffer.write(reinterpret_cast<const char *>(&year), 2);
|
||||
buffer.write(reinterpret_cast<const char *>(&month), 1);
|
||||
buffer.write(reinterpret_cast<const char *>(&day), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
writeLengthEncodedString(serialized[i], buffer);
|
||||
break;
|
||||
|
@ -211,6 +211,10 @@ namespace MySQLProtocol
|
||||
column_type = ColumnType::MYSQL_TYPE_DATETIME;
|
||||
flags = ColumnDefinitionFlags::BINARY_FLAG;
|
||||
break;
|
||||
case TypeIndex::DateTime64:
|
||||
column_type = ColumnType::MYSQL_TYPE_DATETIME;
|
||||
flags = ColumnDefinitionFlags::BINARY_FLAG;
|
||||
break;
|
||||
case TypeIndex::Decimal32:
|
||||
case TypeIndex::Decimal64:
|
||||
column_type = ColumnType::MYSQL_TYPE_DECIMAL;
|
||||
|
@ -1,81 +1,114 @@
|
||||
### testSimpleDataTypes
|
||||
Row #1
|
||||
Type: TINYINT, value: -128
|
||||
Type: SMALLINT, value: -32768
|
||||
Type: INT, value: -2147483648
|
||||
Type: BIGINT, value: -9223372036854775808
|
||||
Type: CHAR, value: -170141183460469231731687303715884105728
|
||||
Type: CHAR, value: -57896044618658097711785492504343953926634992332820282019728792003956564819968
|
||||
Type: TINYINT, value: 120
|
||||
Type: SMALLINT, value: 1234
|
||||
Type: INT, value: 51234
|
||||
Type: BIGINT, value: 421342
|
||||
Type: CHAR, value: 15324355
|
||||
Type: CHAR, value: 41345135123432
|
||||
Type: FLOAT, value: -0.796896
|
||||
Type: DOUBLE, value: -0.113259
|
||||
Type: BIT, value: true
|
||||
i8 type is TINYINT, value: -128
|
||||
i16 type is SMALLINT, value: -32768
|
||||
i32 type is INT, value: -2147483648
|
||||
i64 type is BIGINT, value: -9223372036854775808
|
||||
i128 type is CHAR, value: -170141183460469231731687303715884105728
|
||||
i256 type is CHAR, value: -57896044618658097711785492504343953926634992332820282019728792003956564819968
|
||||
ui8 type is TINYINT, value: 120
|
||||
ui16 type is SMALLINT, value: 1234
|
||||
ui32 type is INT, value: 51234
|
||||
ui64 type is BIGINT, value: 421342
|
||||
ui128 type is CHAR, value: 15324355
|
||||
ui256 type is CHAR, value: 41345135123432
|
||||
f32 type is FLOAT, value: -0.796896
|
||||
f64 type is DOUBLE, value: -0.113259
|
||||
b type is BIT, value: true
|
||||
Row #2
|
||||
Type: TINYINT, value: 127
|
||||
Type: SMALLINT, value: 32767
|
||||
Type: INT, value: 2147483647
|
||||
Type: BIGINT, value: 9223372036854775807
|
||||
Type: CHAR, value: 170141183460469231731687303715884105727
|
||||
Type: CHAR, value: 57896044618658097711785492504343953926634992332820282019728792003956564819967
|
||||
Type: TINYINT, value: 255
|
||||
Type: SMALLINT, value: 65535
|
||||
Type: INT, value: 4294967295
|
||||
Type: BIGINT, value: 18446744073709551615
|
||||
Type: CHAR, value: 340282366920938463463374607431768211455
|
||||
Type: CHAR, value: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
Type: FLOAT, value: 1.234000
|
||||
Type: DOUBLE, value: 3.352451
|
||||
Type: BIT, value: false
|
||||
i8 type is TINYINT, value: 127
|
||||
i16 type is SMALLINT, value: 32767
|
||||
i32 type is INT, value: 2147483647
|
||||
i64 type is BIGINT, value: 9223372036854775807
|
||||
i128 type is CHAR, value: 170141183460469231731687303715884105727
|
||||
i256 type is CHAR, value: 57896044618658097711785492504343953926634992332820282019728792003956564819967
|
||||
ui8 type is TINYINT, value: 255
|
||||
ui16 type is SMALLINT, value: 65535
|
||||
ui32 type is INT, value: 4294967295
|
||||
ui64 type is BIGINT, value: 18446744073709551615
|
||||
ui128 type is CHAR, value: 340282366920938463463374607431768211455
|
||||
ui256 type is CHAR, value: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
f32 type is FLOAT, value: 1.234000
|
||||
f64 type is DOUBLE, value: 3.352451
|
||||
b type is BIT, value: false
|
||||
|
||||
### testStringTypes
|
||||
Row #1
|
||||
Type: CHAR, value: 42
|
||||
Type: CHAR, value: null
|
||||
Type: CHAR, value: test
|
||||
Type: CHAR, value: null
|
||||
s type is CHAR, value: 42
|
||||
sn type is CHAR, value: null
|
||||
lc type is CHAR, value: test
|
||||
nlc type is CHAR, value: null
|
||||
Row #2
|
||||
Type: CHAR, value: foo
|
||||
Type: CHAR, value: bar
|
||||
Type: CHAR, value: qaz
|
||||
Type: CHAR, value: qux
|
||||
s type is CHAR, value: foo
|
||||
sn type is CHAR, value: bar
|
||||
lc type is CHAR, value: qaz
|
||||
nlc type is CHAR, value: qux
|
||||
|
||||
### testDecimalTypes
|
||||
Row #1
|
||||
Type: DECIMAL, value: -1.55
|
||||
Type: DECIMAL, value: 6.03
|
||||
Type: DECIMAL, value: 5
|
||||
Type: CHAR, value: -1224124.23423
|
||||
Type: CHAR, value: -54342.3
|
||||
d32 type is DECIMAL, value: -1.55
|
||||
d64 type is DECIMAL, value: 6.03
|
||||
d128_native type is DECIMAL, value: 5
|
||||
d128_text type is CHAR, value: -1224124.23423
|
||||
d256 type is CHAR, value: -54342.3
|
||||
Row #2
|
||||
Type: DECIMAL, value: 1234567.89
|
||||
Type: DECIMAL, value: 123456789123456.789
|
||||
Type: DECIMAL, value: 12345678912345678912.1234567891
|
||||
Type: CHAR, value: 1234567.8912345678912345678911234567891
|
||||
Type: CHAR, value: 12345678912345678912345678911234567891234567891234567891.12345678911234567891
|
||||
d32 type is DECIMAL, value: 1234567.89
|
||||
d64 type is DECIMAL, value: 123456789123456.789
|
||||
d128_native type is DECIMAL, value: 12345678912345678912.1234567891
|
||||
d128_text type is CHAR, value: 1234567.8912345678912345678911234567891
|
||||
d256 type is CHAR, value: 12345678912345678912345678911234567891234567891234567891.12345678911234567891
|
||||
|
||||
### testMiscTypes
|
||||
Row #1
|
||||
Type: CHAR, value: []
|
||||
Type: CHAR, value: 9a0ccc06-2578-4861-8534-631c9d40f3f7
|
||||
Type: CHAR, value: (0,'')
|
||||
Type: CHAR, value: {}
|
||||
a type is CHAR, value: []
|
||||
u type is CHAR, value: 9a0ccc06-2578-4861-8534-631c9d40f3f7
|
||||
t type is CHAR, value: (0,'')
|
||||
m type is CHAR, value: {}
|
||||
Row #2
|
||||
Type: CHAR, value: ['foo','bar']
|
||||
Type: CHAR, value: 5da5038d-788f-48c6-b510-babb41c538d3
|
||||
Type: CHAR, value: (42,'qaz')
|
||||
Type: CHAR, value: {'qux':144,'text':255}
|
||||
a type is CHAR, value: ['foo','bar']
|
||||
u type is CHAR, value: 5da5038d-788f-48c6-b510-babb41c538d3
|
||||
t type is CHAR, value: (42,'qaz')
|
||||
m type is CHAR, value: {'qux':144,'text':255}
|
||||
|
||||
### testDateTypes
|
||||
Row #1
|
||||
Type: DATE, value: 2149-06-06
|
||||
Type: DATE, value: 2178-04-16
|
||||
Type: TIMESTAMP, value: 2106-02-07 06:28:15.0
|
||||
Type: CHAR, value: 2106-02-07 06:28:15.123
|
||||
Type: CHAR, value: 2106-02-07 06:28:15.123456
|
||||
Type: CHAR, value: 2106-02-07 06:28:15.123456789
|
||||
d type is DATE, value: 1970-01-01
|
||||
d32 type is DATE, value: 1900-01-01
|
||||
dt type is TIMESTAMP, value: 1970-01-01 01:00:00.0
|
||||
dt64_3 type is TIMESTAMP, value: 1900-01-01 00:00:00.0
|
||||
dt64_6 type is TIMESTAMP, value: 1900-01-01 00:00:00.000001
|
||||
dt64_9 type is TIMESTAMP, value: 1900-01-01 00:00:00.0
|
||||
Row #2
|
||||
d type is DATE, value: 2149-06-06
|
||||
d32 type is DATE, value: 2178-04-16
|
||||
dt type is TIMESTAMP, value: 2106-02-07 06:28:15.0
|
||||
dt64_3 type is TIMESTAMP, value: 2106-02-07 06:28:15.123
|
||||
dt64_6 type is TIMESTAMP, value: 2106-02-07 06:28:15.123456
|
||||
dt64_9 type is TIMESTAMP, value: 2106-02-07 06:28:15.123456
|
||||
|
||||
### testUnusualDateTime64Scales
|
||||
Row #1
|
||||
dt64_0 type is TIMESTAMP, value: 2022-04-13 03:17:45.0
|
||||
dt64_1 type is TIMESTAMP, value: 2022-04-13 03:17:45.1
|
||||
dt64_2 type is TIMESTAMP, value: 2022-04-13 03:17:45.12
|
||||
dt64_4 type is TIMESTAMP, value: 2022-04-13 03:17:45.1234
|
||||
dt64_5 type is TIMESTAMP, value: 2022-04-13 03:17:45.12345
|
||||
dt64_7 type is TIMESTAMP, value: 2022-04-13 03:17:45.123456
|
||||
dt64_8 type is TIMESTAMP, value: 2022-04-13 03:17:45.123456
|
||||
Row #2
|
||||
dt64_0 type is TIMESTAMP, value: 2022-04-13 03:17:45.0
|
||||
dt64_1 type is TIMESTAMP, value: 2022-04-13 03:17:45.1
|
||||
dt64_2 type is TIMESTAMP, value: 2022-04-13 03:17:45.01
|
||||
dt64_4 type is TIMESTAMP, value: 2022-04-13 03:17:45.0001
|
||||
dt64_5 type is TIMESTAMP, value: 2022-04-13 03:17:45.00001
|
||||
dt64_7 type is TIMESTAMP, value: 2022-04-13 03:17:45.0
|
||||
dt64_8 type is TIMESTAMP, value: 2022-04-13 03:17:45.0
|
||||
|
||||
### testDateTimeTimezones
|
||||
Row #1
|
||||
dt type is TIMESTAMP, value: 1970-01-01 01:00:00.0
|
||||
dt64_3 type is TIMESTAMP, value: 1969-12-31 16:00:00.0
|
||||
Row #2
|
||||
dt type is TIMESTAMP, value: 2022-09-04 20:31:05.0
|
||||
dt64_3 type is TIMESTAMP, value: 2022-09-04 20:31:05.022
|
||||
|
||||
|
@ -83,4 +83,35 @@ INSERT INTO ps_date_types
|
||||
VALUES ('2149-06-06', '2178-04-16', '2106-02-07 06:28:15',
|
||||
'2106-02-07 06:28:15.123',
|
||||
'2106-02-07 06:28:15.123456',
|
||||
'2106-02-07 06:28:15.123456789');
|
||||
'2106-02-07 06:28:15.123456789'),
|
||||
('1970-01-01', '1900-01-01', '1970-01-01 00:00:00',
|
||||
'1900-01-01 00:00:00.001',
|
||||
'1900-01-01 00:00:00.000001',
|
||||
'1900-01-01 00:00:00.000000001');;
|
||||
|
||||
CREATE TABLE ps_unusual_datetime64_scales
|
||||
(
|
||||
dt64_0 DateTime64(0, 'UTC'),
|
||||
dt64_1 DateTime64(1, 'UTC'),
|
||||
dt64_2 DateTime64(2, 'UTC'),
|
||||
dt64_4 DateTime64(4, 'UTC'),
|
||||
dt64_5 DateTime64(5, 'UTC'),
|
||||
dt64_7 DateTime64(7, 'UTC'),
|
||||
dt64_8 DateTime64(8, 'UTC')
|
||||
) ENGINE MergeTree ORDER BY dt64_0;
|
||||
|
||||
INSERT INTO ps_unusual_datetime64_scales
|
||||
VALUES ('2022-04-13 03:17:45',
|
||||
'2022-04-13 03:17:45.1',
|
||||
'2022-04-13 03:17:45.12',
|
||||
'2022-04-13 03:17:45.1234',
|
||||
'2022-04-13 03:17:45.12345',
|
||||
'2022-04-13 03:17:45.1234567',
|
||||
'2022-04-13 03:17:45.12345678'),
|
||||
('2022-04-13 03:17:45',
|
||||
'2022-04-13 03:17:45.1',
|
||||
'2022-04-13 03:17:45.01',
|
||||
'2022-04-13 03:17:45.0001',
|
||||
'2022-04-13 03:17:45.00001',
|
||||
'2022-04-13 03:17:45.0000001',
|
||||
'2022-04-13 03:17:45.00000001');
|
||||
|
Loading…
Reference in New Issue
Block a user