Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change SHOW COLUMNS query to display MySQL types in MySQL Compatibility mode #49577

Merged
merged 25 commits into from Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
18d1a43
Change SHOW COLUMNS query to display MySQL types in MySQL Compatibili…
tpanetti May 5, 2023
ddbad79
Change SHOW COLUMNS query to display MySQL types in MySQL Compatibili…
tpanetti May 5, 2023
4bc55cd
Merge branch 'master' into mysql_compatible_types
tpanetti May 30, 2023
6e8dc67
Merge branch 'mysql_compatible_types' of https://github.com/tpanetti/…
tpanetti May 30, 2023
38634cc
Convert Clickhouse Types to MySQL types in Compatibility mode
tpanetti May 24, 2023
bd5a1ae
Revert "Change SHOW COLUMNS query to display MySQL types in MySQL Com…
tpanetti May 30, 2023
4c92bc7
Fix incompatible ClickHouse -> MySQL types for compability mode
tpanetti May 31, 2023
05dfe58
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 2, 2023
423afec
Change case and function name for MySQL Compatible types
tpanetti Jun 2, 2023
495482c
Refactor ClickHouse->MySQL Type conversion and add configuration sett…
tpanetti Jun 5, 2023
016e30c
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 7, 2023
96d7b2e
Disable fasttest for MySQL Compatibility Type Conversion and refactor…
tpanetti Jun 9, 2023
5769d7f
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 9, 2023
cb8c207
Rename setting and description for MySQL compatible types
tpanetti Jun 10, 2023
252a10c
Add "no-parallel" tag to MySQL Compatible Types test to fix test issue
tpanetti Jun 12, 2023
8683f5e
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 12, 2023
fa4bc6b
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 13, 2023
d1b96b5
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 13, 2023
a502967
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 14, 2023
0477221
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 14, 2023
45328a4
Fix test for MySQL Compatible Types to use clickhouse_client rather t…
tpanetti Jun 14, 2023
6959486
Fix test for MySQL Compatible types (drop database properly)
tpanetti Jun 14, 2023
18fb4fb
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 14, 2023
8790497
Fix test for MySQL Compatible Types (suppress password warning)
tpanetti Jun 14, 2023
dbdf77c
Merge branch 'master' into mysql_compatible_types
tpanetti Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Core/Settings.h
Expand Up @@ -197,6 +197,7 @@ class IColumn;
M(Bool, allow_experimental_inverted_index, false, "If it is set to true, allow to use experimental inverted index.", 0) \
\
M(UInt64, mysql_max_rows_to_insert, 65536, "The maximum number of rows in MySQL batch insertion of the MySQL storage engine", 0) \
M(Bool, use_mysql_types_in_show_columns, false, "Use MySQL converted types when connected via MySQL compatibility for show columns query", 0) \
\
M(UInt64, optimize_min_equality_disjunction_chain_length, 3, "The minimum length of the expression `expr = x1 OR ... expr = xN` for optimization ", 0) \
\
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeAggregateFunction.h
Expand Up @@ -45,6 +45,7 @@ class DataTypeAggregateFunction final : public IDataType
String doGetName() const override;
String getNameWithoutVersion() const;
const char * getFamilyName() const override { return "AggregateFunction"; }
String getSQLCompatibleName() const override { return "TEXT"; }
TypeIndex getTypeId() const override { return TypeIndex::AggregateFunction; }

Array getParameters() const { return parameters; }
Expand Down
4 changes: 4 additions & 0 deletions src/DataTypes/DataTypeArray.h
Expand Up @@ -30,6 +30,10 @@ class DataTypeArray final : public IDataType
{
return "Array";
}
String getSQLCompatibleName() const override
{
return "TEXT";
}

bool canBeInsideNullable() const override
{
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeDate.h
Expand Up @@ -13,6 +13,7 @@ class DataTypeDate final : public DataTypeNumberBase<UInt16>

TypeIndex getTypeId() const override { return TypeIndex::Date; }
const char * getFamilyName() const override { return family_name; }
String getSQLCompatibleName() const override { return "DATE"; }

bool canBeUsedAsVersion() const override { return true; }
bool canBeInsideNullable() const override { return true; }
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeDate32.h
Expand Up @@ -13,6 +13,7 @@ class DataTypeDate32 final : public DataTypeNumberBase<Int32>

TypeIndex getTypeId() const override { return TypeIndex::Date32; }
const char * getFamilyName() const override { return family_name; }
String getSQLCompatibleName() const override { return "DATE"; }

Field getDefault() const override
{
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeDateTime.h
Expand Up @@ -36,6 +36,7 @@ class DataTypeDateTime final : public DataTypeNumberBase<UInt32>, public Timezon
static constexpr auto family_name = "DateTime";

const char * getFamilyName() const override { return family_name; }
String getSQLCompatibleName() const override { return "DATETIME"; }
String doGetName() const override;
TypeIndex getTypeId() const override { return TypeIndex::DateTime; }

Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeDateTime64.h
Expand Up @@ -28,6 +28,7 @@ class DataTypeDateTime64 final : public DataTypeDecimalBase<DateTime64>, public
DataTypeDateTime64(UInt32 scale_, const TimezoneMixin & time_zone_info);

const char * getFamilyName() const override { return family_name; }
String getSQLCompatibleName() const override { return "DATETIME"; }
std::string doGetName() const override;
TypeIndex getTypeId() const override { return type_id; }

Expand Down
23 changes: 23 additions & 0 deletions src/DataTypes/DataTypeEnum.cpp
Expand Up @@ -36,6 +36,29 @@ const char * DataTypeEnum<Type>::getFamilyName() const
return EnumName<FieldType>::value;
}

template <typename Type>
std::string DataTypeEnum<Type>::generateMySQLName(const Values & values)
{
WriteBufferFromOwnString out;

writeString("ENUM", out);
writeChar('(', out);

auto first = true;
for (const auto & name_and_value : values)
{
if (!first)
writeString(", ", out);

first = false;

writeQuotedString(name_and_value.first, out);
}

writeChar(')', out);

return out.str();
}

template <typename Type>
std::string DataTypeEnum<Type>::generateName(const Values & values)
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeEnum.h
Expand Up @@ -46,12 +46,14 @@ class DataTypeEnum final : public IDataTypeEnum, public EnumValues<Type>
private:
std::string type_name;
static std::string generateName(const Values & values);
static std::string generateMySQLName(const Values & values);

public:
explicit DataTypeEnum(const Values & values_);

std::string doGetName() const override { return type_name; }
const char * getFamilyName() const override;
String getSQLCompatibleName() const override { return generateMySQLName(this->getValues()); }

TypeIndex getTypeId() const override { return type_id; }

Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeFixedString.h
Expand Up @@ -42,6 +42,8 @@ class DataTypeFixedString final : public IDataType
TypeIndex getTypeId() const override { return type_id; }

const char * getFamilyName() const override { return "FixedString"; }
/// Use TEXT for compatibility with MySQL to allow arbitrary bytes.
String getSQLCompatibleName() const override { return "TEXT"; }

size_t getN() const
{
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeFunction.h
Expand Up @@ -24,6 +24,7 @@ class DataTypeFunction final : public IDataTypeDummy

std::string doGetName() const override;
const char * getFamilyName() const override { return "Function"; }
String getSQLCompatibleName() const override { return "TEXT"; }
TypeIndex getTypeId() const override { return TypeIndex::Function; }

const DataTypes & getArgumentTypes() const
Expand Down
4 changes: 4 additions & 0 deletions src/DataTypes/DataTypeIPv4andIPv6.h
Expand Up @@ -19,6 +19,8 @@ class DataTypeIPv4 : public IDataType
static constexpr auto type_id = TypeToTypeIndex<IPv4>;

const char * getFamilyName() const override { return TypeName<IPv4>.data(); }
String getSQLCompatibleName() const override { return "TEXT"; }

TypeIndex getTypeId() const override { return type_id; }

Field getDefault() const override { return IPv4{}; }
Expand Down Expand Up @@ -59,6 +61,8 @@ class DataTypeIPv6 : public IDataType
static constexpr auto type_id = TypeToTypeIndex<IPv6>;

const char * getFamilyName() const override { return TypeName<IPv6>.data(); }
String getSQLCompatibleName() const override { return "TEXT"; }

TypeIndex getTypeId() const override { return type_id; }

Field getDefault() const override { return IPv6{}; }
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeInterval.h
Expand Up @@ -26,6 +26,7 @@ class DataTypeInterval final : public DataTypeNumberBase<Int64>

std::string doGetName() const override { return fmt::format("Interval{}", kind.toString()); }
const char * getFamilyName() const override { return "Interval"; }
String getSQLCompatibleName() const override { return "TEXT"; }
TypeIndex getTypeId() const override { return TypeIndex::Interval; }

bool equals(const IDataType & rhs) const override;
Expand Down
3 changes: 3 additions & 0 deletions src/DataTypes/DataTypeLowCardinality.h
Expand Up @@ -12,6 +12,7 @@ class DataTypeLowCardinality : public IDataType
private:
DataTypePtr dictionary_type;


public:
explicit DataTypeLowCardinality(DataTypePtr dictionary_type_);

Expand All @@ -22,6 +23,8 @@ class DataTypeLowCardinality : public IDataType
return "LowCardinality(" + dictionary_type->getName() + ")";
}
const char * getFamilyName() const override { return "LowCardinality"; }
String getSQLCompatibleName() const override { return dictionary_type->getSQLCompatibleName(); }

TypeIndex getTypeId() const override { return TypeIndex::LowCardinality; }

MutableColumnPtr createColumn() const override;
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeMap.h
Expand Up @@ -30,6 +30,7 @@ class DataTypeMap final : public IDataType
TypeIndex getTypeId() const override { return TypeIndex::Map; }
std::string doGetName() const override;
const char * getFamilyName() const override { return "Map"; }
String getSQLCompatibleName() const override { return "JSON"; }

bool canBeInsideNullable() const override { return false; }

Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeNothing.h
Expand Up @@ -16,6 +16,8 @@ class DataTypeNothing final : public IDataTypeDummy
static constexpr bool is_parametric = false;

const char * getFamilyName() const override { return "Nothing"; }
String getSQLCompatibleName() const override { return "TEXT"; }

TypeIndex getTypeId() const override { return TypeIndex::Nothing; }

MutableColumnPtr createColumn() const override;
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeNullable.h
Expand Up @@ -16,6 +16,7 @@ class DataTypeNullable final : public IDataType
explicit DataTypeNullable(const DataTypePtr & nested_data_type_);
std::string doGetName() const override { return "Nullable(" + nested_data_type->getName() + ")"; }
const char * getFamilyName() const override { return "Nullable"; }
String getSQLCompatibleName() const override { return nested_data_type->getSQLCompatibleName(); }
TypeIndex getTypeId() const override { return TypeIndex::Nullable; }

MutableColumnPtr createColumn() const override;
Expand Down
28 changes: 27 additions & 1 deletion src/DataTypes/DataTypeNumberBase.cpp
Expand Up @@ -11,6 +11,33 @@ Field DataTypeNumberBase<T>::getDefault() const
{
return NearestFieldType<FieldType>();
}
template <typename T>
String DataTypeNumberBase<T>::getSQLCompatibleName() const
{
if constexpr (std::is_same_v<T, Int8>)
rschu1ze marked this conversation as resolved.
Show resolved Hide resolved
return "TINYINT";
else if constexpr (std::is_same_v<T, Int16>)
return "SMALLINT";
else if constexpr (std::is_same_v<T, Int32>)
return "INTEGER";
else if constexpr (std::is_same_v<T, Int64>)
return "BIGINT";
else if constexpr (std::is_same_v<T, UInt8>)
return "TINYINT UNSIGNED";
else if constexpr (std::is_same_v<T, UInt16>)
return "SMALLINT UNSIGNED";
else if constexpr (std::is_same_v<T, UInt32>)
return "INTEGER UNSIGNED";
else if constexpr (std::is_same_v<T, UInt64>)
return "BIGINT UNSIGNED";
else if constexpr (std::is_same_v<T, Float32>)
return "FLOAT";
else if constexpr (std::is_same_v<T, Float64>)
return "DOUBLE";
/// Unsupported types are converted to TEXT
else
return "TEXT";
}

template <typename T>
MutableColumnPtr DataTypeNumberBase<T>::createColumn() const
Expand All @@ -30,7 +57,6 @@ bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
return is_integer<T> && is_unsigned_v<T>;
}


/// Explicit template instantiations - to avoid code bloat in headers.
template class DataTypeNumberBase<UInt8>;
template class DataTypeNumberBase<UInt16>;
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeNumberBase.h
Expand Up @@ -25,6 +25,7 @@ class DataTypeNumberBase : public IDataType
using ColumnType = ColumnVector<T>;

const char * getFamilyName() const override { return TypeName<T>.data(); }
String getSQLCompatibleName() const override;
TypeIndex getTypeId() const override { return TypeToTypeIndex<T>; }

Field getDefault() const override;
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeObject.h
Expand Up @@ -23,6 +23,7 @@ class DataTypeObject : public IDataType
DataTypeObject(const String & schema_format_, bool is_nullable_);

const char * getFamilyName() const override { return "Object"; }
String getSQLCompatibleName() const override { return "JSON"; }
String doGetName() const override;
TypeIndex getTypeId() const override { return TypeIndex::Object; }

Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeSet.h
Expand Up @@ -15,6 +15,8 @@ class DataTypeSet final : public IDataTypeDummy
public:
static constexpr bool is_parametric = true;
const char * getFamilyName() const override { return "Set"; }
String getSQLCompatibleName() const override { return "TEXT"; }

TypeIndex getTypeId() const override { return TypeIndex::Set; }
bool equals(const IDataType & rhs) const override { return typeid(rhs) == typeid(*this); }
bool isParametric() const override { return true; }
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeString.h
Expand Up @@ -21,6 +21,8 @@ class DataTypeString final : public IDataType
return "String";
}

String getSQLCompatibleName() const override { return "BLOB"; }

TypeIndex getTypeId() const override { return type_id; }

MutableColumnPtr createColumn() const override;
Expand Down
1 change: 1 addition & 0 deletions src/DataTypes/DataTypeTuple.h
Expand Up @@ -33,6 +33,7 @@ class DataTypeTuple final : public IDataType
TypeIndex getTypeId() const override { return TypeIndex::Tuple; }
std::string doGetName() const override;
const char * getFamilyName() const override { return "Tuple"; }
String getSQLCompatibleName() const override { return "JSON"; }

bool canBeInsideNullable() const override { return false; }
bool supportsSparseSerialization() const override { return true; }
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeUUID.h
Expand Up @@ -18,6 +18,8 @@ class DataTypeUUID : public IDataType
static constexpr auto type_id = TypeIndex::UUID;

const char * getFamilyName() const override { return "UUID"; }
String getSQLCompatibleName() const override { return "CHAR"; }

TypeIndex getTypeId() const override { return type_id; }

Field getDefault() const override;
Expand Down
5 changes: 5 additions & 0 deletions src/DataTypes/DataTypesDecimal.cpp
Expand Up @@ -28,6 +28,11 @@ std::string DataTypeDecimal<T>::doGetName() const
return fmt::format("Decimal({}, {})", this->precision, this->scale);
}

template <is_decimal T>
std::string DataTypeDecimal<T>::getSQLCompatibleName() const
{
return fmt::format("DECIMAL({}, {})", this->precision, this->scale);
}

template <is_decimal T>
bool DataTypeDecimal<T>::equals(const IDataType & rhs) const
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypesDecimal.h
Expand Up @@ -39,6 +39,8 @@ class DataTypeDecimal final : public DataTypeDecimalBase<T>
static constexpr auto family_name = "Decimal";

const char * getFamilyName() const override { return family_name; }
String getSQLCompatibleName() const override;

std::string doGetName() const override;
TypeIndex getTypeId() const override { return TypeToTypeIndex<T>; }
bool canBePromoted() const override { return true; }
Expand Down
2 changes: 2 additions & 0 deletions src/DataTypes/IDataType.h
Expand Up @@ -75,6 +75,8 @@ class IDataType : private boost::noncopyable, public std::enable_shared_from_thi

/// Name of data type family (example: FixedString, Array).
virtual const char * getFamilyName() const = 0;
/// Name of corresponding data type in MySQL (exampe: Bigint, Blob, etc)
rschu1ze marked this conversation as resolved.
Show resolved Hide resolved
virtual String getSQLCompatibleName() const = 0;

/// Data type id. It's used for runtime type checks.
virtual TypeIndex getTypeId() const = 0;
Expand Down
18 changes: 17 additions & 1 deletion src/Storages/System/StorageSystemColumns.cpp
Expand Up @@ -74,6 +74,8 @@ class ColumnsSource : public ISource
: ISource(header_)
, columns_mask(std::move(columns_mask_)), max_block_size(max_block_size_)
, databases(std::move(databases_)), tables(std::move(tables_)), storages(std::move(storages_))
, client_info_interface(context->getClientInfo().interface)
, use_mysql_types(context->getSettingsRef().use_mysql_types_in_show_columns)
, total_tables(tables->size()), access(context->getAccess())
, query_id(context->getCurrentQueryId()), lock_acquire_timeout(context->getSettingsRef().lock_acquire_timeout)
{
Expand Down Expand Up @@ -129,6 +131,18 @@ class ColumnsSource : public ISource

bool check_access_for_columns = check_access_for_tables && !access->isGranted(AccessType::SHOW_COLUMNS, database_name, table_name);

auto get_type_name = [this](const IDataType& type) -> std::string
{
// Check if the use_mysql_types_in_show_columns setting is enabled and client is connected via MySQL protocol
if (use_mysql_types && client_info_interface == DB::ClientInfo::Interface::MYSQL)
{
return type.getSQLCompatibleName();
}
else
{
return type.getName();
}
};
size_t position = 0;
for (const auto & column : columns)
{
Expand All @@ -146,7 +160,7 @@ class ColumnsSource : public ISource
if (columns_mask[src_index++])
res_columns[res_index++]->insert(column.name);
if (columns_mask[src_index++])
res_columns[res_index++]->insert(column.type->getName());
res_columns[res_index++]->insert(get_type_name(*column.type));
if (columns_mask[src_index++])
res_columns[res_index++]->insert(position);

Expand Down Expand Up @@ -281,6 +295,8 @@ class ColumnsSource : public ISource
ColumnPtr databases;
ColumnPtr tables;
Storages storages;
ClientInfo::Interface client_info_interface;
bool use_mysql_types;
size_t db_table_num = 0;
size_t total_tables;
std::shared_ptr<const ContextAccess> access;
Expand Down