2016-07-05 16:23:37 +00:00
|
|
|
#include <DB/DataTypes/DataTypeNullable.h>
|
|
|
|
#include <DB/Columns/ColumnNullable.h>
|
2016-07-14 12:58:30 +00:00
|
|
|
#include <DB/IO/ReadBuffer.h>
|
|
|
|
#include <DB/IO/ReadHelpers.h>
|
|
|
|
#include <DB/IO/WriteBuffer.h>
|
|
|
|
#include <DB/IO/WriteHelpers.h>
|
2016-12-30 05:13:14 +00:00
|
|
|
#include <DB/IO/ConcatReadBuffer.h>
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-07-14 12:58:30 +00:00
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
namespace DB
|
2016-08-24 16:02:34 +00:00
|
|
|
{
|
|
|
|
|
2016-07-11 16:41:57 +00:00
|
|
|
|
2016-07-07 10:33:12 +00:00
|
|
|
DataTypeNullable::DataTypeNullable(DataTypePtr nested_data_type_)
|
|
|
|
: nested_data_type{nested_data_type_}
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::serializeBinary(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
|
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
|
|
|
nested_data_type->serializeBinary(*col.getNestedColumn(), ostr, offset, limit);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
|
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
ColumnNullable & col = static_cast<ColumnNullable &>(column);
|
|
|
|
nested_data_type->deserializeBinary(*col.getNestedColumn(), istr, limit, avg_value_size_hint);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
|
2016-07-05 16:23:37 +00:00
|
|
|
void DataTypeNullable::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-12-30 05:13:14 +00:00
|
|
|
|
|
|
|
bool is_null = col.isNullAt(row_num);
|
|
|
|
writeBinary(is_null, ostr);
|
|
|
|
if (!is_null)
|
|
|
|
nested_data_type->serializeBinary(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
|
|
|
|
/// We need to insert both to nested column and to null byte map, or, in case of exception, to not insert at all.
|
|
|
|
template <typename CheckForNull, typename DeserializeNested>
|
|
|
|
static void safeDeserialize(
|
|
|
|
IColumn & column,
|
|
|
|
CheckForNull && check_for_null, DeserializeNested && deserialize_nested)
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
ColumnNullable & col = static_cast<ColumnNullable &>(column);
|
2016-12-30 05:13:14 +00:00
|
|
|
|
|
|
|
if (check_for_null())
|
|
|
|
{
|
|
|
|
col.insertDefault();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
deserialize_nested(*col.getNestedColumn());
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
col.getNullMap().push_back(0);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
col.getNestedColumn()->popBack(1);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
|
|
|
|
void DataTypeNullable::deserializeBinary(IColumn & column, ReadBuffer & istr) const
|
|
|
|
{
|
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr] { bool is_null = 0; readBinary(is_null, istr); return is_null; },
|
|
|
|
[this, &istr] (IColumn & nested) { nested_data_type->deserializeBinary(nested, istr); } );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("\\N", ostr);
|
2016-07-11 14:54:46 +00:00
|
|
|
else
|
2016-08-17 17:35:54 +00:00
|
|
|
nested_data_type->serializeTextEscaped(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-12-30 05:13:14 +00:00
|
|
|
/// Little tricky, because we cannot discriminate null from first character.
|
|
|
|
|
|
|
|
if (istr.eof())
|
|
|
|
throw Exception("Unexpected end of stream, while parsing value of Nullable type", ErrorCodes::CANNOT_READ_ALL_DATA);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
/// This is not null, surely.
|
|
|
|
if (*istr.position() != '\\')
|
|
|
|
{
|
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr] { return false; },
|
2016-12-30 05:22:45 +00:00
|
|
|
[this, &istr] (IColumn & nested) { nested_data_type->deserializeTextEscaped(nested, istr); } );
|
2016-12-30 05:13:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/// Now we know, that data in buffer starts with backslash.
|
|
|
|
++istr.position();
|
|
|
|
|
|
|
|
if (istr.eof())
|
|
|
|
throw Exception("Unexpected end of stream, while parsing value of Nullable type, after backslash", ErrorCodes::CANNOT_READ_ALL_DATA);
|
|
|
|
|
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr]
|
|
|
|
{
|
|
|
|
if (*istr.position() == 'N')
|
|
|
|
{
|
|
|
|
++istr.position();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
[this, &istr] (IColumn & nested)
|
|
|
|
{
|
|
|
|
/// We need to place backslash back in front of istr.
|
2016-08-24 16:52:17 +00:00
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
ReadBuffer prefix(const_cast<char *>("\\"), 1, 0);
|
|
|
|
ConcatReadBuffer prepended_istr(prefix, istr);
|
2016-08-24 16:52:17 +00:00
|
|
|
|
2016-12-30 05:22:45 +00:00
|
|
|
nested_data_type->deserializeTextEscaped(nested, prepended_istr);
|
2016-12-30 05:13:14 +00:00
|
|
|
});
|
|
|
|
}
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("NULL", ostr);
|
2016-07-11 14:54:46 +00:00
|
|
|
else
|
2016-08-17 17:35:54 +00:00
|
|
|
nested_data_type->serializeTextQuoted(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-30 05:13:14 +00:00
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-12-30 05:13:14 +00:00
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr] { return checkStringByFirstCharacterAndAssertTheRestCaseInsensitive("NULL", istr); },
|
|
|
|
[this, &istr] (IColumn & nested) { nested_data_type->deserializeTextQuoted(nested, istr); } );
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("\\N", ostr);
|
2016-07-11 16:37:44 +00:00
|
|
|
else
|
2016-08-17 17:35:54 +00:00
|
|
|
nested_data_type->serializeTextCSV(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-12-30 05:13:14 +00:00
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr] { return checkStringByFirstCharacterAndAssertTheRest("\\N", istr); },
|
2016-12-30 05:31:52 +00:00
|
|
|
[this, delimiter, &istr] (IColumn & nested) { nested_data_type->deserializeTextCSV(nested, istr, delimiter); } );
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("NULL", ostr);
|
2016-07-11 14:54:46 +00:00
|
|
|
else
|
2016-08-17 17:35:54 +00:00
|
|
|
nested_data_type->serializeText(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 15:00:56 +00:00
|
|
|
void DataTypeNullable::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr,
|
|
|
|
bool force_quoting_64bit_integers) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("null", ostr);
|
2016-07-11 16:37:44 +00:00
|
|
|
else
|
2016-10-19 15:00:56 +00:00
|
|
|
nested_data_type->serializeTextJSON(*col.getNestedColumn(), row_num, ostr,
|
|
|
|
force_quoting_64bit_integers);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 16:37:44 +00:00
|
|
|
void DataTypeNullable::deserializeTextJSON(IColumn & column, ReadBuffer & istr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-12-30 05:13:14 +00:00
|
|
|
safeDeserialize(column,
|
|
|
|
[&istr] { return checkStringByFirstCharacterAndAssertTheRest("null", istr); },
|
2016-12-30 05:22:45 +00:00
|
|
|
[this, &istr] (IColumn & nested) { nested_data_type->deserializeTextJSON(nested, istr); } );
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-11 14:54:46 +00:00
|
|
|
void DataTypeNullable::serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
2016-07-05 16:23:37 +00:00
|
|
|
{
|
2016-08-17 17:35:54 +00:00
|
|
|
const ColumnNullable & col = static_cast<const ColumnNullable &>(column);
|
2016-07-05 16:23:37 +00:00
|
|
|
|
2016-08-17 17:35:54 +00:00
|
|
|
if (col.isNullAt(row_num))
|
2016-12-30 05:13:14 +00:00
|
|
|
writeCString("\\N", ostr);
|
2016-07-11 14:54:46 +00:00
|
|
|
else
|
2016-08-17 17:35:54 +00:00
|
|
|
nested_data_type->serializeTextXML(*col.getNestedColumn(), row_num, ostr);
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeNullable::createColumn() const
|
|
|
|
{
|
2016-08-16 22:40:05 +00:00
|
|
|
ColumnPtr new_col = nested_data_type->createColumn();
|
|
|
|
return std::make_shared<ColumnNullable>(new_col, std::make_shared<ColumnUInt8>());
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr DataTypeNullable::createConstColumn(size_t size, const Field & field) const
|
|
|
|
{
|
2016-08-16 22:40:05 +00:00
|
|
|
ColumnPtr new_col = nested_data_type->createConstColumn(size, field);
|
|
|
|
return std::make_shared<ColumnNullable>(new_col, std::make_shared<ColumnUInt8>(size));
|
2016-07-05 16:23:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|