diff --git a/src/DataTypes/DataTypeAggregateFunction.h b/src/DataTypes/DataTypeAggregateFunction.h index 6331c23222f..7d1bb355ccf 100644 --- a/src/DataTypes/DataTypeAggregateFunction.h +++ b/src/DataTypes/DataTypeAggregateFunction.h @@ -45,7 +45,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeArray.h b/src/DataTypes/DataTypeArray.h index 3a83babbc23..6a09b3b530d 100644 --- a/src/DataTypes/DataTypeArray.h +++ b/src/DataTypes/DataTypeArray.h @@ -35,10 +35,6 @@ public: { return "Array"; } - String getSQLCompatibleName() const override - { - return "TEXT"; - } bool canBeInsideNullable() const override { diff --git a/src/DataTypes/DataTypeDate.h b/src/DataTypes/DataTypeDate.h index 0d557cad5f0..2f17207cc07 100644 --- a/src/DataTypes/DataTypeDate.h +++ b/src/DataTypes/DataTypeDate.h @@ -13,7 +13,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeDate32.h b/src/DataTypes/DataTypeDate32.h index 0879a404179..9160b62dc15 100644 --- a/src/DataTypes/DataTypeDate32.h +++ b/src/DataTypes/DataTypeDate32.h @@ -13,7 +13,6 @@ public: 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 { diff --git a/src/DataTypes/DataTypeDateTime.h b/src/DataTypes/DataTypeDateTime.h index a473aae1faf..a4a05917ba5 100644 --- a/src/DataTypes/DataTypeDateTime.h +++ b/src/DataTypes/DataTypeDateTime.h @@ -38,7 +38,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeDateTime64.h b/src/DataTypes/DataTypeDateTime64.h index 7663518807f..64cedd798d1 100644 --- a/src/DataTypes/DataTypeDateTime64.h +++ b/src/DataTypes/DataTypeDateTime64.h @@ -28,7 +28,6 @@ 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; } diff --git a/src/DataTypes/DataTypeEnum.cpp b/src/DataTypes/DataTypeEnum.cpp index 1750ae785bf..e5efb73cfca 100644 --- a/src/DataTypes/DataTypeEnum.cpp +++ b/src/DataTypes/DataTypeEnum.cpp @@ -36,30 +36,6 @@ const char * DataTypeEnum::getFamilyName() const return EnumName::value; } -template -std::string DataTypeEnum::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 std::string DataTypeEnum::generateName(const Values & values) { diff --git a/src/DataTypes/DataTypeEnum.h b/src/DataTypes/DataTypeEnum.h index d148f753c82..2f607fc2aa6 100644 --- a/src/DataTypes/DataTypeEnum.h +++ b/src/DataTypes/DataTypeEnum.h @@ -46,14 +46,12 @@ public: 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; } diff --git a/src/DataTypes/DataTypeFixedString.h b/src/DataTypes/DataTypeFixedString.h index 22ec793208d..8d114121c1a 100644 --- a/src/DataTypes/DataTypeFixedString.h +++ b/src/DataTypes/DataTypeFixedString.h @@ -42,8 +42,6 @@ public: 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 { diff --git a/src/DataTypes/DataTypeFunction.h b/src/DataTypes/DataTypeFunction.h index 9acec676ce0..e8ce6871d8d 100644 --- a/src/DataTypes/DataTypeFunction.h +++ b/src/DataTypes/DataTypeFunction.h @@ -24,7 +24,6 @@ public: 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 diff --git a/src/DataTypes/DataTypeIPv4andIPv6.h b/src/DataTypes/DataTypeIPv4andIPv6.h index 487ce04f67c..5aea55751a7 100644 --- a/src/DataTypes/DataTypeIPv4andIPv6.h +++ b/src/DataTypes/DataTypeIPv4andIPv6.h @@ -19,7 +19,6 @@ public: static constexpr auto type_id = TypeToTypeIndex; const char * getFamilyName() const override { return TypeName.data(); } - String getSQLCompatibleName() const override { return "TEXT"; } TypeIndex getTypeId() const override { return type_id; } @@ -61,7 +60,6 @@ public: static constexpr auto type_id = TypeToTypeIndex; const char * getFamilyName() const override { return TypeName.data(); } - String getSQLCompatibleName() const override { return "TEXT"; } TypeIndex getTypeId() const override { return type_id; } diff --git a/src/DataTypes/DataTypeInterval.h b/src/DataTypes/DataTypeInterval.h index c398a54268e..b0e747555e3 100644 --- a/src/DataTypes/DataTypeInterval.h +++ b/src/DataTypes/DataTypeInterval.h @@ -27,7 +27,6 @@ public: SerializationPtr doGetDefaultSerialization() const override; 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; diff --git a/src/DataTypes/DataTypeLowCardinality.h b/src/DataTypes/DataTypeLowCardinality.h index d2a414cb073..527f0475720 100644 --- a/src/DataTypes/DataTypeLowCardinality.h +++ b/src/DataTypes/DataTypeLowCardinality.h @@ -23,7 +23,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeMap.h b/src/DataTypes/DataTypeMap.h index 619815fdf20..257888a8e44 100644 --- a/src/DataTypes/DataTypeMap.h +++ b/src/DataTypes/DataTypeMap.h @@ -31,7 +31,6 @@ public: std::string doGetName() const override; std::string doGetPrettyName(size_t indent) const override; const char * getFamilyName() const override { return "Map"; } - String getSQLCompatibleName() const override { return "JSON"; } bool canBeInsideNullable() const override { return false; } diff --git a/src/DataTypes/DataTypeNothing.h b/src/DataTypes/DataTypeNothing.h index c3a7e2d09f0..3cafaecc7cc 100644 --- a/src/DataTypes/DataTypeNothing.h +++ b/src/DataTypes/DataTypeNothing.h @@ -16,7 +16,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeNullable.h b/src/DataTypes/DataTypeNullable.h index e3165414c07..06d46fb15ed 100644 --- a/src/DataTypes/DataTypeNullable.h +++ b/src/DataTypes/DataTypeNullable.h @@ -16,7 +16,6 @@ public: 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; diff --git a/src/DataTypes/DataTypeNumberBase.cpp b/src/DataTypes/DataTypeNumberBase.cpp index 4cefc4945c6..be448fe1491 100644 --- a/src/DataTypes/DataTypeNumberBase.cpp +++ b/src/DataTypes/DataTypeNumberBase.cpp @@ -11,34 +11,6 @@ Field DataTypeNumberBase::getDefault() const { return NearestFieldType(); } -template -String DataTypeNumberBase::getSQLCompatibleName() const -{ - if constexpr (std::is_same_v) - return "TINYINT"; - else if constexpr (std::is_same_v) - return "SMALLINT"; - else if constexpr (std::is_same_v) - return "INTEGER"; - else if constexpr (std::is_same_v) - return "BIGINT"; - else if constexpr (std::is_same_v) - return "TINYINT UNSIGNED"; - else if constexpr (std::is_same_v) - return "SMALLINT UNSIGNED"; - else if constexpr (std::is_same_v) - return "INTEGER UNSIGNED"; - else if constexpr (std::is_same_v) - return "BIGINT UNSIGNED"; - else if constexpr (std::is_same_v) - return "FLOAT"; - else if constexpr (std::is_same_v) - return "DOUBLE"; - /// Unsupported types are converted to TEXT - else - return "TEXT"; -} - template MutableColumnPtr DataTypeNumberBase::createColumn() const { diff --git a/src/DataTypes/DataTypeNumberBase.h b/src/DataTypes/DataTypeNumberBase.h index d902c62505e..3a5b11c5124 100644 --- a/src/DataTypes/DataTypeNumberBase.h +++ b/src/DataTypes/DataTypeNumberBase.h @@ -25,7 +25,6 @@ public: using ColumnType = ColumnVector; const char * getFamilyName() const override { return TypeName.data(); } - String getSQLCompatibleName() const override; TypeIndex getTypeId() const override { return TypeToTypeIndex; } Field getDefault() const override; diff --git a/src/DataTypes/DataTypeObject.h b/src/DataTypes/DataTypeObject.h index 2e1e5398f7e..937a9091371 100644 --- a/src/DataTypes/DataTypeObject.h +++ b/src/DataTypes/DataTypeObject.h @@ -23,7 +23,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypeSet.h b/src/DataTypes/DataTypeSet.h index e71a345a195..1c898de9c6d 100644 --- a/src/DataTypes/DataTypeSet.h +++ b/src/DataTypes/DataTypeSet.h @@ -15,7 +15,6 @@ 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); } diff --git a/src/DataTypes/DataTypeString.h b/src/DataTypes/DataTypeString.h index c39fa90f6e7..5f3bde43a13 100644 --- a/src/DataTypes/DataTypeString.h +++ b/src/DataTypes/DataTypeString.h @@ -21,8 +21,6 @@ public: return "String"; } - String getSQLCompatibleName() const override { return "BLOB"; } - TypeIndex getTypeId() const override { return type_id; } MutableColumnPtr createColumn() const override; diff --git a/src/DataTypes/DataTypeTuple.h b/src/DataTypes/DataTypeTuple.h index 0a1e78e23a0..db49b7f22d1 100644 --- a/src/DataTypes/DataTypeTuple.h +++ b/src/DataTypes/DataTypeTuple.h @@ -34,7 +34,6 @@ public: std::string doGetName() const override; std::string doGetPrettyName(size_t indent) 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; } diff --git a/src/DataTypes/DataTypeUUID.h b/src/DataTypes/DataTypeUUID.h index 8664c3bcfd1..90cdd90d68d 100644 --- a/src/DataTypes/DataTypeUUID.h +++ b/src/DataTypes/DataTypeUUID.h @@ -18,7 +18,6 @@ public: 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; } diff --git a/src/DataTypes/DataTypesDecimal.cpp b/src/DataTypes/DataTypesDecimal.cpp index 49214f4aa45..7ad9f0b6fd8 100644 --- a/src/DataTypes/DataTypesDecimal.cpp +++ b/src/DataTypes/DataTypesDecimal.cpp @@ -28,18 +28,6 @@ std::string DataTypeDecimal::doGetName() const return fmt::format("Decimal({}, {})", this->precision, this->scale); } -template -std::string DataTypeDecimal::getSQLCompatibleName() const -{ - /// See https://dev.mysql.com/doc/refman/8.0/en/precision-math-decimal-characteristics.html - /// DECIMAL(M,D) - /// M is the maximum number of digits (the precision). It has a range of 1 to 65. - /// D is the number of digits to the right of the decimal point (the scale). It has a range of 0 to 30 and must be no larger than M. - if (this->precision > 65 || this->scale > 30) - return "TEXT"; - return fmt::format("DECIMAL({}, {})", this->precision, this->scale); -} - template bool DataTypeDecimal::equals(const IDataType & rhs) const { diff --git a/src/DataTypes/DataTypesDecimal.h b/src/DataTypes/DataTypesDecimal.h index 5e4cfab7928..e2b433cbe2f 100644 --- a/src/DataTypes/DataTypesDecimal.h +++ b/src/DataTypes/DataTypesDecimal.h @@ -39,7 +39,6 @@ public: 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; } diff --git a/src/DataTypes/IDataType.h b/src/DataTypes/IDataType.h index c30b009c931..fb0a015821d 100644 --- a/src/DataTypes/IDataType.h +++ b/src/DataTypes/IDataType.h @@ -83,8 +83,6 @@ public: /// 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) - virtual String getSQLCompatibleName() const = 0; /// Data type id. It's used for runtime type checks. virtual TypeIndex getTypeId() const = 0; diff --git a/src/Formats/SchemaInferenceUtils.cpp b/src/Formats/SchemaInferenceUtils.cpp index d4d66ec76da..94166aa9002 100644 --- a/src/Formats/SchemaInferenceUtils.cpp +++ b/src/Formats/SchemaInferenceUtils.cpp @@ -83,11 +83,6 @@ namespace String doGetName() const override { return finalize()->getName(); } TypeIndex getTypeId() const override { return TypeIndex::JSONPaths; } - String getSQLCompatibleName() const override - { - throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Method getSQLCompatibleName is not implemented for JSONObjectForInference type"); - } - bool isParametric() const override { throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Method isParametric is not implemented for JSONObjectForInference type"); diff --git a/src/Interpreters/InterpreterShowColumnsQuery.cpp b/src/Interpreters/InterpreterShowColumnsQuery.cpp index e1f736ba4fb..0c78907ffee 100644 --- a/src/Interpreters/InterpreterShowColumnsQuery.cpp +++ b/src/Interpreters/InterpreterShowColumnsQuery.cpp @@ -24,6 +24,8 @@ String InterpreterShowColumnsQuery::getRewrittenQuery() { const auto & query = query_ptr->as(); + [[maybe_unused]] const bool use_mysql_types = getContext()->getSettingsRef().use_mysql_types_in_show_columns; + WriteBufferFromOwnString buf_database; String resolved_database = getContext()->resolveDatabase(query.database); writeEscapedString(resolved_database, buf_database); @@ -33,18 +35,64 @@ String InterpreterShowColumnsQuery::getRewrittenQuery() writeEscapedString(query.table, buf_table); String table = buf_table.str(); - String rewritten_query = R"( + String rewritten_query; + if (use_mysql_types) + /// Cheapskate mapping from native to MySQL types, see https://dev.mysql.com/doc/refman/8.0/en/data-types.html + /// Known issues: + /// - Enums are translated to TEXT + rewritten_query += R"( +WITH map( + 'Int8', 'TINYINT', + 'Int16', 'SMALLINT', + 'Int32', 'INTEGER', + 'Int64', 'BIGINT', + 'UInt8', 'TINYINT UNSIGNED', + 'UInt16', 'SMALLINT UNSIGNED', + 'UInt32', 'INTEGER UNSIGNED', + 'UInt64', 'BIGINT UNSIGNED', + 'Float32', 'FLOAT', + 'Float64', 'DOUBLE', + 'String', 'BLOB', + 'UUID', 'CHAR', + 'Bool', 'TINYINT', + 'Date', 'DATE', + 'Date32', 'DATE', + 'DateTime', 'DATETIME', + 'DateTime64', 'DATETIME', + 'Map', 'JSON', + 'Tuple', 'JSON', + 'Object', 'JSON') AS native_to_mysql_mapping, + splitByRegexp('\(|\)', type) AS split, + multiIf(startsWith(type, 'LowCardinality(Nullable'), split[3], + startsWith(type, 'LowCardinality'), split[2], + startsWith(type, 'Nullable'), split[2], + split[1]) AS inner_type, + if(length(split) > 1, splitByString(', ', split[2]), []) AS decimal_scale_and_precision, + multiIf(inner_type = 'Decimal' AND toInt8(decimal_scale_and_precision[1]) <= 65 AND toInt8(decimal_scale_and_precision[2]) <= 30, concat('DECIMAL(', decimal_scale_and_precision[1], ', ', decimal_scale_and_precision[2], ')'), + mapContains(native_to_mysql_mapping, inner_type) = true, native_to_mysql_mapping[inner_type], + 'TEXT') AS mysql_type + )"; + + rewritten_query += R"( SELECT name AS field, + )"; + + if (use_mysql_types) + rewritten_query += R"( + mysql_type AS type, + )"; + else + rewritten_query += R"( type AS type, - if (startsWith(type, 'Nullable'), 'YES', 'NO') AS `null`, + )"; + + rewritten_query += R"( + multiIf(startsWith(type, 'Nullable('), 'YES', startsWith(type, 'LowCardinality(Nullable('), 'YES', 'NO') AS `null`, trim(concatWithSeparator(' ', if (is_in_primary_key, 'PRI', ''), if (is_in_sorting_key, 'SOR', ''))) AS key, if (default_kind IN ('ALIAS', 'DEFAULT', 'MATERIALIZED'), default_expression, NULL) AS default, '' AS extra )"; - // Known issue: Field 'null' is wrong for types like 'LowCardinality(Nullable(String))'. Can't simply replace 'startsWith' by - // `hasSubsequence` as that would return `true` for non-nullable types such as `Tuple(Nullable(String), String)`... - // TODO Interpret query.extended. It is supposed to show internal/virtual columns. Need to fetch virtual column names, see // IStorage::getVirtuals(). We can't easily do that via SQL. diff --git a/src/Storages/System/StorageSystemColumns.cpp b/src/Storages/System/StorageSystemColumns.cpp index bf81ef1917d..ad65f6f5476 100644 --- a/src/Storages/System/StorageSystemColumns.cpp +++ b/src/Storages/System/StorageSystemColumns.cpp @@ -76,7 +76,6 @@ public: , 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) { @@ -149,7 +148,7 @@ protected: if (columns_mask[src_index++]) res_columns[res_index++]->insert(column.name); if (columns_mask[src_index++]) - res_columns[res_index++]->insert(use_mysql_types ? (column.type->getSQLCompatibleName()) : (column.type->getName())); + res_columns[res_index++]->insert(column.type->getName()); if (columns_mask[src_index++]) res_columns[res_index++]->insert(position); @@ -285,7 +284,6 @@ private: 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 access;