Add allow_experimental_geo_types; add test

This commit is contained in:
Alexey Ilyukhov 2020-05-30 18:26:19 +03:00
parent a65923b028
commit b84c8fcbd8
5 changed files with 84 additions and 24 deletions

View File

@ -416,6 +416,8 @@ struct Settings : public SettingsCollection<Settings>
M(SettingBool, allow_nondeterministic_mutations, false, "Allow non-deterministic functions in ALTER UPDATE/ALTER DELETE statements", 0) \
M(SettingSeconds, lock_acquire_timeout, DBMS_DEFAULT_LOCK_ACQUIRE_TIMEOUT_SEC, "How long locking request should wait before failing", 0) \
\
M(SettingBool, allow_experimental_geo_types, false, "Allow geo data types such as Point, Ring, Polygon, MultiPolygon", 0) \
\
/** Obsolete settings that do nothing but left for compatibility reasons. Remove each one after half a year of obsolescence. */ \
\
M(SettingBool, allow_experimental_low_cardinality_type, true, "Obsolete setting, does nothing. Will be removed after 2019-08-13", 0) \

View File

@ -19,62 +19,89 @@ private:
DataTypePtr tuple;
public:
DataTypeCustomPointSerialization() : tuple(std::make_unique<DataTypeTuple>(
DataTypes({std::make_unique<DataTypeFloat64>(), std::make_unique<DataTypeFloat64>()})))
DataTypeCustomPointSerialization()
{}
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override
{
tuple->serializeAsText(column, row_num, ostr, settings);
nestedDataType()->serializeAsText(column, row_num, ostr, settings);
}
void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override
{
tuple->deserializeAsWholeText(column, istr, settings);
nestedDataType()->deserializeAsWholeText(column, istr, settings);
}
static DataTypePtr nestedDataType() {
static auto dataType = DataTypePtr(std::make_unique<DataTypeTuple>(
DataTypes({std::make_unique<DataTypeFloat64>(), std::make_unique<DataTypeFloat64>()})));
return dataType;
}
};
class DataTypeCustomRingSerialization : public DataTypeCustomSimpleTextSerialization
{
public:
DataTypeCustomRingSerialization()
{}
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override
{
nestedDataType()->serializeAsText(column, row_num, ostr, settings);
}
void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override
{
nestedDataType()->deserializeAsWholeText(column, istr, settings);
}
static DataTypePtr nestedDataType() {
static auto dataType = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomPointSerialization::nestedDataType()));
return dataType;
}
};
class DataTypeCustomPolygonSerialization : public DataTypeCustomSimpleTextSerialization
{
private:
DataTypePtr array;
public:
DataTypeCustomPolygonSerialization() : array(std::make_unique<DataTypeArray>(std::make_unique<DataTypeArray>(std::make_unique<DataTypeTuple>(
DataTypes({std::make_unique<DataTypeFloat64>(), std::make_unique<DataTypeFloat64>()})))))
DataTypeCustomPolygonSerialization()
{}
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override
{
array->serializeAsText(column, row_num, ostr, settings);
nestedDataType()->serializeAsText(column, row_num, ostr, settings);
}
void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override
{
array->deserializeAsWholeText(column, istr, settings);
nestedDataType()->deserializeAsWholeText(column, istr, settings);
}
static DataTypePtr nestedDataType() {
static auto dataType = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomRingSerialization::nestedDataType()));
return dataType;
}
};
class DataTypeCustomMultiPolygonSerialization : public DataTypeCustomSimpleTextSerialization
{
private:
DataTypePtr array;
public:
DataTypeCustomMultiPolygonSerialization() : array(
std::make_unique<DataTypeArray>(std::make_unique<DataTypeArray>(
std::make_unique<DataTypeArray>(std::make_unique<DataTypeTuple>(
DataTypes({std::make_unique<DataTypeFloat64>(), std::make_unique<DataTypeFloat64>()}))))))
DataTypeCustomMultiPolygonSerialization()
{}
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override
{
array->serializeAsText(column, row_num, ostr, settings);
nestedDataType()->serializeAsText(column, row_num, ostr, settings);
}
void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override
{
array->deserializeAsWholeText(column, istr, settings);
nestedDataType()->deserializeAsWholeText(column, istr, settings);
}
static DataTypePtr nestedDataType() {
static auto dataType = DataTypePtr(std::make_unique<DataTypeArray>(DataTypeCustomPolygonSerialization::nestedDataType()));
return dataType;
}
};
@ -89,12 +116,18 @@ void registerDataTypeDomainGeo(DataTypeFactory & factory)
std::make_unique<DataTypeCustomDesc>(std::make_unique<DataTypeCustomFixedName>("Point"), std::make_unique<DataTypeCustomPointSerialization>()));
});
// Custom type for polygon with holes stored as Array(Array(Point))
// Each element of outer array represents a simple polygon without holes stored as array of points
// Custom type for simple polygon without holes stored as Array(Point)
factory.registerSimpleDataTypeCustom("Ring", []
{
return std::make_pair(DataTypeFactory::instance().get("Array(Point)"),
std::make_unique<DataTypeCustomDesc>(std::make_unique<DataTypeCustomFixedName>("Ring"), std::make_unique<DataTypeCustomRingSerialization>()));
});
// Custom type for polygon with holes stored as Array(Ring)
// First element of outer array is outer shape of polygon and all the following are holes
factory.registerSimpleDataTypeCustom("Polygon", []
{
return std::make_pair(DataTypeFactory::instance().get("Array(Array(Point))"),
return std::make_pair(DataTypeFactory::instance().get("Array(Ring)"),
std::make_unique<DataTypeCustomDesc>(std::make_unique<DataTypeCustomFixedName>("Polygon"), std::make_unique<DataTypeCustomPolygonSerialization>()));
});

View File

@ -70,6 +70,7 @@ namespace ErrorCodes
extern const int BAD_DATABASE_FOR_TEMPORARY_TABLE;
extern const int SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY;
extern const int DICTIONARY_ALREADY_EXISTS;
extern const int ILLEGAL_COLUMN;
}
@ -381,7 +382,6 @@ ConstraintsDescription InterpreterCreateQuery::getConstraintsDescription(const A
return res;
}
InterpreterCreateQuery::TableProperties InterpreterCreateQuery::setProperties(ASTCreateQuery & create) const
{
TableProperties properties;
@ -471,6 +471,21 @@ void InterpreterCreateQuery::validateTableStructure(const ASTCreateQuery & creat
}
}
}
if (!create.attach && !context.getSettingsRef().allow_experimental_geo_types)
{
for (const auto & name_and_type_pair : properties.columns.getAllPhysical())
{
const auto& type = name_and_type_pair.type->getName();
if (type == "MultiPolygon" || type == "Polygon" || type == "Ring" || type == "Point")
{
String message = "Cannot create table with column '" + name_and_type_pair.name + "' which type is '"
+ type + "' because experimental geo types are not allowed. "
+ "Set setting allow_experimental_geo_types = 1 in order to allow it.";
throw Exception(message, ErrorCodes::ILLEGAL_COLUMN);
}
}
}
}
void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const

View File

@ -0,0 +1 @@
(0,0) [(0,0),(10,0),(10,10),(0,10)] [[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]] [[[(0,0),(10,0),(10,10),(0,10)]],[[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]]]

View File

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS geo;
SET allow_experimental_geo_types = 1;
CREATE TABLE geo (a Point, b Ring, c Polygon, d MultiPolygon) ENGINE=Memory();
INSERT INTO geo VALUES((0, 0), [(0, 0), (10, 0), (10, 10), (0, 10)], [[(20, 20), (50, 20), (50, 50), (20, 50)], [(30, 30), (50, 50), (50, 30)]], [[[(0, 0), (10, 0), (10, 10), (0, 10)]], [[(20, 20), (50, 20), (50, 50), (20, 50)],[(30, 30), (50, 50), (50, 30)]]]);
SELECT * from geo;