Refactor solution to improve extensibility

This commit is contained in:
ltrk2 2023-02-02 10:17:24 -08:00
parent 748c7fe04e
commit b5cef61ef3
3 changed files with 285 additions and 33 deletions

View File

@ -1,5 +1,7 @@
#include "SerializationInterval.h"
#include "SerializationCustomSimpleText.h"
#include <Columns/IColumn.h>
#include <DataTypes/DataTypeFactory.h>
#include <DataTypes/DataTypeInterval.h>
@ -9,47 +11,263 @@
#include <magic_enum.hpp>
#include <concepts>
#include <span>
namespace DB
{
using ColumnInterval = DataTypeInterval::ColumnType;
namespace ErrorCodes
{
extern const int ILLEGAL_COLUMN;
extern const int NOT_IMPLEMENTED;
extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE;
}
}
using ColumnInterval = DataTypeInterval::ColumnType;
SerializationInterval::SerializationInterval(IntervalKind kind_)
: SerializationCustomSimpleText(DataTypeFactory::instance().get("Int64")->getDefaultSerialization()), kind(std::move(kind_))
namespace
{
}
void SerializationInterval::serializeText(
const IColumn & column, const size_t row_num, WriteBuffer & ostr, const FormatSettings & format_settings) const
class SerializationKQLInterval : public DB::SerializationCustomSimpleText
{
const auto * interval_column = checkAndGetColumn<ColumnInterval>(column);
public:
explicit SerializationKQLInterval(DB::IntervalKind kind_) : SerializationCustomSimpleText(nullptr), kind(kind_) { }
void serializeText(const DB::IColumn & column, size_t row, DB::WriteBuffer & ostr, const DB::FormatSettings & settings) const override;
void deserializeText(DB::IColumn & column, DB::ReadBuffer & istr, const DB::FormatSettings & settings, bool whole) const override;
private:
DB::IntervalKind kind;
};
void SerializationKQLInterval::serializeText(
const DB::IColumn & column, const size_t row, DB::WriteBuffer & ostr, const DB::FormatSettings &) const
{
const auto * interval_column = checkAndGetColumn<DB::ColumnInterval>(column);
if (!interval_column)
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Expected column of underlying type of Interval");
throw DB::Exception(DB::ErrorCodes::ILLEGAL_COLUMN, "Expected column of underlying type of Interval");
if (const auto & format = format_settings.interval.format; format == FormatSettings::IntervalFormat::Numeric)
nested_serialization->serializeText(column, row_num, ostr, format_settings);
else if (format == FormatSettings::IntervalFormat::KQL)
{
const auto & value = interval_column->getData()[row_num];
const auto ticks = kind.toAvgNanoseconds() * value / 100;
const auto interval_as_string = ParserKQLTimespan::compose(ticks);
ostr.write(interval_as_string.c_str(), interval_as_string.length());
}
else
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Option {} is not implemented", magic_enum::enum_name(format));
const auto & value = interval_column->getData()[row];
const auto ticks = kind.toAvgNanoseconds() * value / 100;
const auto interval_as_string = DB::ParserKQLTimespan::compose(ticks);
ostr.write(interval_as_string.c_str(), interval_as_string.length());
}
void SerializationInterval::deserializeText(
[[maybe_unused]] IColumn & column,
[[maybe_unused]] ReadBuffer & istr,
[[maybe_unused]] const FormatSettings & format_settings,
void SerializationKQLInterval::deserializeText(
[[maybe_unused]] DB::IColumn & column,
[[maybe_unused]] DB::ReadBuffer & istr,
[[maybe_unused]] const DB::FormatSettings & settings,
[[maybe_unused]] const bool whole) const
{
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Deserialization is not implemented for {}", kind.toNameOfFunctionToIntervalDataType());
throw DB::Exception(
DB::ErrorCodes::NOT_IMPLEMENTED, "Deserialization is not implemented for {}", kind.toNameOfFunctionToIntervalDataType());
}
template <typename... Args, std::invocable<const DB::ISerialization *, Args...> Method>
void dispatch(
std::span<const std::unique_ptr<const DB::ISerialization>> serializations,
const Method method,
const DB::FormatSettings::IntervalFormat format,
Args &&... args)
{
const auto format_index = magic_enum::enum_index(format);
if (!format_index)
throw DB::Exception(DB::ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, "No such format exists");
const auto & serialization = serializations[*format_index];
if (!serialization)
throw DB::Exception(DB::ErrorCodes::NOT_IMPLEMENTED, "Option {} is not implemented", magic_enum::enum_name(format));
(serialization.get()->*method)(std::forward<Args>(args)...);
}
}
namespace DB
{
SerializationInterval::SerializationInterval(IntervalKind kind_)
{
serializations.at(magic_enum::enum_index(FormatSettings::IntervalFormat::KQL).value())
= std::make_unique<SerializationKQLInterval>(std::move(kind_));
serializations.at(magic_enum::enum_index(FormatSettings::IntervalFormat::Numeric).value())
= std::make_unique<SerializationNumber<typename DataTypeInterval::FieldType>>();
}
void SerializationInterval::deserializeBinary(Field & field, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(
serializations,
static_cast<void (ISerialization::*)(Field &, ReadBuffer &, const FormatSettings &) const>(&ISerialization::deserializeBinary),
settings.interval.format,
field,
istr,
settings);
}
void SerializationInterval::deserializeBinary(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(
serializations,
static_cast<void (ISerialization::*)(IColumn &, ReadBuffer &, const FormatSettings &) const>(&ISerialization::deserializeBinary),
settings.interval.format,
column,
istr,
settings);
}
void SerializationInterval::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
{
dispatch(
serializations,
&ISerialization::deserializeBinaryBulk,
FormatSettings::IntervalFormat::Numeric,
column,
istr,
limit,
avg_value_size_hint);
}
void SerializationInterval::deserializeBinaryBulkStatePrefix(
DeserializeBinaryBulkSettings & settings, DeserializeBinaryBulkStatePtr & state) const
{
dispatch(serializations, &ISerialization::deserializeBinaryBulkStatePrefix, FormatSettings::IntervalFormat::Numeric, settings, state);
}
void SerializationInterval::deserializeBinaryBulkWithMultipleStreams(
ColumnPtr & column,
size_t limit,
DeserializeBinaryBulkSettings & settings,
DeserializeBinaryBulkStatePtr & state,
SubstreamsCache * cache) const
{
dispatch(
serializations,
&ISerialization::deserializeBinaryBulkWithMultipleStreams,
FormatSettings::IntervalFormat::Numeric,
column,
limit,
settings,
state,
cache);
}
void SerializationInterval::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeTextCSV, settings.interval.format, column, istr, settings);
}
void SerializationInterval::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeTextEscaped, settings.interval.format, column, istr, settings);
}
void SerializationInterval::deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeTextJSON, settings.interval.format, column, istr, settings);
}
void SerializationInterval::deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeTextQuoted, settings.interval.format, column, istr, settings);
}
void SerializationInterval::deserializeTextRaw(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeTextRaw, settings.interval.format, column, istr, settings);
}
void SerializationInterval::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::deserializeWholeText, settings.interval.format, column, istr, settings);
}
void SerializationInterval::serializeBinary(const Field & field, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(
serializations,
static_cast<void (ISerialization::*)(const Field &, WriteBuffer &, const FormatSettings &) const>(&ISerialization::serializeBinary),
settings.interval.format,
field,
ostr,
settings);
}
void SerializationInterval::serializeBinary(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(
serializations,
static_cast<void (ISerialization::*)(const IColumn &, size_t, WriteBuffer &, const FormatSettings &) const>(
&ISerialization::serializeBinary),
settings.interval.format,
column,
row,
ostr,
settings);
}
void SerializationInterval::serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
{
dispatch(serializations, &ISerialization::serializeBinaryBulk, FormatSettings::IntervalFormat::Numeric, column, ostr, offset, limit);
}
void SerializationInterval::serializeBinaryBulkStatePrefix(
const IColumn & column, SerializeBinaryBulkSettings & settings, SerializeBinaryBulkStatePtr & state) const
{
dispatch(
serializations, &ISerialization::serializeBinaryBulkStatePrefix, FormatSettings::IntervalFormat::Numeric, column, settings, state);
}
void SerializationInterval::serializeBinaryBulkStateSuffix(
SerializeBinaryBulkSettings & settings, SerializeBinaryBulkStatePtr & state) const
{
dispatch(serializations, &ISerialization::serializeBinaryBulkStateSuffix, FormatSettings::IntervalFormat::Numeric, settings, state);
}
void SerializationInterval::serializeBinaryBulkWithMultipleStreams(
const IColumn & column, size_t offset, size_t limit, SerializeBinaryBulkSettings & settings, SerializeBinaryBulkStatePtr & state) const
{
dispatch(
serializations,
&ISerialization::serializeBinaryBulkWithMultipleStreams,
FormatSettings::IntervalFormat::Numeric,
column,
offset,
limit,
settings,
state);
}
void SerializationInterval::serializeText(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeText, settings.interval.format, column, row, ostr, settings);
}
void SerializationInterval::serializeTextCSV(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeTextCSV, settings.interval.format, column, row, ostr, settings);
}
void SerializationInterval::serializeTextEscaped(
const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeTextEscaped, settings.interval.format, column, row, ostr, settings);
}
void SerializationInterval::serializeTextJSON(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeTextJSON, settings.interval.format, column, row, ostr, settings);
}
void SerializationInterval::serializeTextQuoted(
const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeTextQuoted, settings.interval.format, column, row, ostr, settings);
}
void SerializationInterval::serializeTextRaw(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const
{
dispatch(serializations, &ISerialization::serializeTextRaw, settings.interval.format, column, row, ostr, settings);
}
}

View File

@ -1,20 +1,54 @@
#pragma once
#include "SerializationCustomSimpleText.h"
#include "ISerialization.h"
#include <Formats/FormatSettings.h>
#include <Common/IntervalKind.h>
namespace DB
{
class SerializationInterval : public SerializationCustomSimpleText
class SerializationInterval : public ISerialization
{
public:
explicit SerializationInterval(IntervalKind kind_);
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override;
void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings &, bool whole) const override;
void deserializeBinary(Field & field, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeBinary(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const override;
void deserializeBinaryBulkStatePrefix(DeserializeBinaryBulkSettings & settings, DeserializeBinaryBulkStatePtr & state) const override;
void deserializeBinaryBulkWithMultipleStreams(
ColumnPtr & column,
size_t limit,
DeserializeBinaryBulkSettings & settings,
DeserializeBinaryBulkStatePtr & state,
SubstreamsCache * cache) const override;
void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeTextRaw(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override;
void serializeBinary(const Field & field, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeBinary(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const override;
void serializeBinaryBulkStatePrefix(
const IColumn & column, SerializeBinaryBulkSettings & settings, SerializeBinaryBulkStatePtr & state) const override;
void serializeBinaryBulkStateSuffix(SerializeBinaryBulkSettings & settings, SerializeBinaryBulkStatePtr & state) const override;
void serializeBinaryBulkWithMultipleStreams(
const IColumn & column,
size_t offset,
size_t limit,
SerializeBinaryBulkSettings & settings,
SerializeBinaryBulkStatePtr & state) const override;
void serializeText(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeTextCSV(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeTextEscaped(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeTextJSON(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeTextQuoted(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
void serializeTextRaw(const IColumn & column, size_t row, WriteBuffer & ostr, const FormatSettings & settings) const override;
private:
IntervalKind kind;
std::array<std::unique_ptr<const ISerialization>, magic_enum::enum_count<FormatSettings::IntervalFormat>()> serializations;
};
}

View File

@ -9,7 +9,7 @@ kql
5.00:00:00
7.00:00:00
14.00:00:00
('00:01:12', '21.00:00:00', '00:00:00.0000002')
('00:01:12','21.00:00:00','00:00:00.0000002')
numeric
99
100
@ -20,4 +20,4 @@ numeric
5
1
2
('72', '3', '200')
(72,3,200)