Fixed parsing and interpreting of tuples [#CLICKHOUSE-2].

This commit is contained in:
Alexey Milovidov 2017-12-03 11:16:49 +03:00
parent 22f69f5c5f
commit 903dc680bb
4 changed files with 63 additions and 35 deletions

View File

@ -122,7 +122,10 @@ void DataTypeTuple::deserializeText(IColumn & column, ReadBuffer & istr) const
{ {
skipWhitespaceIfAny(istr); skipWhitespaceIfAny(istr);
if (i != 0) if (i != 0)
{
assertChar(',', istr); assertChar(',', istr);
skipWhitespaceIfAny(istr);
}
elems[i]->deserializeTextQuoted(extractElementColumn(column, i), istr); elems[i]->deserializeTextQuoted(extractElementColumn(column, i), istr);
} }
}); });
@ -174,7 +177,10 @@ void DataTypeTuple::deserializeTextJSON(IColumn & column, ReadBuffer & istr) con
{ {
skipWhitespaceIfAny(istr); skipWhitespaceIfAny(istr);
if (i != 0) if (i != 0)
{
assertChar(',', istr); assertChar(',', istr);
skipWhitespaceIfAny(istr);
}
elems[i]->deserializeTextJSON(extractElementColumn(column, i), istr); elems[i]->deserializeTextJSON(extractElementColumn(column, i), istr);
} }
}); });

View File

@ -4,6 +4,7 @@
#include <IO/ReadHelpers.h> #include <IO/ReadHelpers.h>
#include <DataTypes/DataTypeArray.h> #include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypesNumber.h> #include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeString.h> #include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypeFixedString.h> #include <DataTypes/DataTypeFixedString.h>
@ -107,16 +108,16 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type)
{ {
if (type.isNumeric()) if (type.isNumeric())
{ {
if (typeid_cast<const DataTypeUInt8 *>(&type)) return convertNumericType<UInt8>(src, type); if (typeid_cast<const DataTypeUInt8 *>(&type)) return convertNumericType<UInt8>(src, type);
if (typeid_cast<const DataTypeUInt16 *>(&type)) return convertNumericType<UInt16>(src, type); if (typeid_cast<const DataTypeUInt16 *>(&type)) return convertNumericType<UInt16>(src, type);
if (typeid_cast<const DataTypeUInt32 *>(&type)) return convertNumericType<UInt32>(src, type); if (typeid_cast<const DataTypeUInt32 *>(&type)) return convertNumericType<UInt32>(src, type);
if (typeid_cast<const DataTypeUInt64 *>(&type)) return convertNumericType<UInt64>(src, type); if (typeid_cast<const DataTypeUInt64 *>(&type)) return convertNumericType<UInt64>(src, type);
if (typeid_cast<const DataTypeInt8 *>(&type)) return convertNumericType<Int8>(src, type); if (typeid_cast<const DataTypeInt8 *>(&type)) return convertNumericType<Int8>(src, type);
if (typeid_cast<const DataTypeInt16 *>(&type)) return convertNumericType<Int16>(src, type); if (typeid_cast<const DataTypeInt16 *>(&type)) return convertNumericType<Int16>(src, type);
if (typeid_cast<const DataTypeInt32 *>(&type)) return convertNumericType<Int32>(src, type); if (typeid_cast<const DataTypeInt32 *>(&type)) return convertNumericType<Int32>(src, type);
if (typeid_cast<const DataTypeInt64 *>(&type)) return convertNumericType<Int64>(src, type); if (typeid_cast<const DataTypeInt64 *>(&type)) return convertNumericType<Int64>(src, type);
if (typeid_cast<const DataTypeFloat32 *>(&type)) return convertNumericType<Float32>(src, type); if (typeid_cast<const DataTypeFloat32 *>(&type)) return convertNumericType<Float32>(src, type);
if (typeid_cast<const DataTypeFloat64 *>(&type)) return convertNumericType<Float64>(src, type); if (typeid_cast<const DataTypeFloat64 *>(&type)) return convertNumericType<Float64>(src, type);
const bool is_date = typeid_cast<const DataTypeDate *>(&type); const bool is_date = typeid_cast<const DataTypeDate *>(&type);
bool is_datetime = false; bool is_datetime = false;
@ -155,41 +156,51 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type)
return dynamic_cast<const IDataTypeEnum &>(type).castToValue(src); return dynamic_cast<const IDataTypeEnum &>(type).castToValue(src);
} }
} }
}
throw Exception("Type mismatch in IN or VALUES section. Expected: " + type.getName() + ". Got: " else if (typeid_cast<const DataTypeString *>(&type)
+ Field::Types::toString(src.getType()), ErrorCodes::TYPE_MISMATCH); || typeid_cast<const DataTypeFixedString *>(&type))
{
if (src.getType() == Field::Types::String)
return src;
} }
else if (const DataTypeArray * type_array = typeid_cast<const DataTypeArray *>(&type)) else if (const DataTypeArray * type_array = typeid_cast<const DataTypeArray *>(&type))
{ {
if (src.getType() != Field::Types::Array) if (src.getType() == Field::Types::Array)
throw Exception("Type mismatch in IN or VALUES section. Expected: " + type.getName() + ". Got: " {
+ Field::Types::toString(src.getType()), ErrorCodes::TYPE_MISMATCH); const IDataType & nested_type = *DataTypeTraits::removeNullable(type_array->getNestedType());
const IDataType & nested_type = *DataTypeTraits::removeNullable(type_array->getNestedType()); const Array & src_arr = src.get<Array>();
size_t src_arr_size = src_arr.size();
const Array & src_arr = src.get<Array>(); Array res(src_arr_size);
size_t src_arr_size = src_arr.size(); for (size_t i = 0; i < src_arr_size; ++i)
res[i] = convertFieldToType(src_arr[i], nested_type);
Array res(src_arr_size); return res;
for (size_t i = 0; i < src_arr_size; ++i) }
res[i] = convertFieldToType(src_arr[i], nested_type);
return res;
} }
else else if (const DataTypeTuple * type_tuple = typeid_cast<const DataTypeTuple *>(&type))
{ {
if (src.getType() == Field::Types::UInt64 if (src.getType() == Field::Types::Tuple)
|| src.getType() == Field::Types::Int64 {
|| src.getType() == Field::Types::Float64 const TupleBackend & src_tuple = src.get<Tuple>();
|| src.getType() == Field::Types::Array size_t src_tuple_size = src_tuple.size();
|| (src.getType() == Field::Types::String size_t dst_tuple_size = type_tuple->getElements().size();
&& !typeid_cast<const DataTypeString *>(&type)
&& !typeid_cast<const DataTypeFixedString *>(&type))) if (dst_tuple_size != src_tuple_size)
throw Exception("Type mismatch in IN or VALUES section. Expected: " + type.getName() + ". Got: " throw Exception("Bad size of tuple in IN or VALUES section. Expected size: "
+ Field::Types::toString(src.getType()), ErrorCodes::TYPE_MISMATCH); + toString(dst_tuple_size) + ", actual size: " + toString(src_tuple_size), ErrorCodes::TYPE_MISMATCH);
TupleBackend res(dst_tuple_size);
for (size_t i = 0; i < dst_tuple_size; ++i)
res[i] = convertFieldToType(src_tuple[i], *type_tuple->getElements()[i]);
return res;
}
} }
return src; throw Exception("Type mismatch in IN or VALUES section. Expected: " + type.getName() + ". Got: "
+ Field::Types::toString(src.getType()), ErrorCodes::TYPE_MISMATCH);
} }
} }

View File

@ -0,0 +1,2 @@
('2000-01-01',15,51)
('2000-01-01',123,456)

View File

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS test.tuple;
CREATE TABLE test.tuple (t Tuple(Date, UInt32, UInt64)) ENGINE = Memory;
INSERT INTO test.tuple VALUES ((concat('2000', '-01-01'), /* Hello */ 12+3, 45+6));
SET input_format_values_interpret_expressions = 0;
INSERT INTO test.tuple VALUES (('2000-01-01', 123, 456));
SELECT * FROM test.tuple;
DROP TABLE test.tuple;