| 1 | #include <DataTypes/DataTypeFactory.h> |
| 2 | #include <DataTypes/DataTypeCustom.h> |
| 3 | #include <Parsers/parseQuery.h> |
| 4 | #include <Parsers/ParserCreateQuery.h> |
| 5 | #include <Parsers/ASTFunction.h> |
| 6 | #include <Parsers/ASTIdentifier.h> |
| 7 | #include <Parsers/ASTLiteral.h> |
| 8 | #include <Common/typeid_cast.h> |
| 9 | #include <Poco/String.h> |
| 10 | #include <Common/StringUtils/StringUtils.h> |
| 11 | #include <IO/WriteHelpers.h> |
| 12 | |
| 13 | namespace DB |
| 14 | { |
| 15 | |
| 16 | namespace ErrorCodes |
| 17 | { |
| 18 | extern const int LOGICAL_ERROR; |
| 19 | extern const int UNKNOWN_TYPE; |
| 20 | extern const int ILLEGAL_SYNTAX_FOR_DATA_TYPE; |
| 21 | extern const int UNEXPECTED_AST_STRUCTURE; |
| 22 | extern const int DATA_TYPE_CANNOT_HAVE_ARGUMENTS; |
| 23 | } |
| 24 | |
| 25 | |
| 26 | DataTypePtr DataTypeFactory::get(const String & full_name) const |
| 27 | { |
| 28 | ParserIdentifierWithOptionalParameters parser; |
| 29 | ASTPtr ast = parseQuery(parser, full_name.data(), full_name.data() + full_name.size(), "data type" , 0); |
| 30 | return get(ast); |
| 31 | } |
| 32 | |
| 33 | DataTypePtr DataTypeFactory::get(const ASTPtr & ast) const |
| 34 | { |
| 35 | if (const auto * func = ast->as<ASTFunction>()) |
| 36 | { |
| 37 | if (func->parameters) |
| 38 | throw Exception("Data type cannot have multiple parenthesed parameters." , ErrorCodes::ILLEGAL_SYNTAX_FOR_DATA_TYPE); |
| 39 | return get(func->name, func->arguments); |
| 40 | } |
| 41 | |
| 42 | if (const auto * ident = ast->as<ASTIdentifier>()) |
| 43 | { |
| 44 | return get(ident->name, {}); |
| 45 | } |
| 46 | |
| 47 | if (const auto * lit = ast->as<ASTLiteral>()) |
| 48 | { |
| 49 | if (lit->value.isNull()) |
| 50 | return get("Null" , {}); |
| 51 | } |
| 52 | |
| 53 | throw Exception("Unexpected AST element for data type." , ErrorCodes::UNEXPECTED_AST_STRUCTURE); |
| 54 | } |
| 55 | |
| 56 | DataTypePtr DataTypeFactory::get(const String & family_name_param, const ASTPtr & parameters) const |
| 57 | { |
| 58 | String family_name = getAliasToOrName(family_name_param); |
| 59 | |
| 60 | if (endsWith(family_name, "WithDictionary" )) |
| 61 | { |
| 62 | ASTPtr low_cardinality_params = std::make_shared<ASTExpressionList>(); |
| 63 | String param_name = family_name.substr(0, family_name.size() - strlen("WithDictionary" )); |
| 64 | if (parameters) |
| 65 | { |
| 66 | auto func = std::make_shared<ASTFunction>(); |
| 67 | func->name = param_name; |
| 68 | func->arguments = parameters; |
| 69 | low_cardinality_params->children.push_back(func); |
| 70 | } |
| 71 | else |
| 72 | low_cardinality_params->children.push_back(std::make_shared<ASTIdentifier>(param_name)); |
| 73 | |
| 74 | return get("LowCardinality" , low_cardinality_params); |
| 75 | } |
| 76 | |
| 77 | return findCreatorByName(family_name)(family_name_param, parameters); |
| 78 | } |
| 79 | |
| 80 | |
| 81 | void DataTypeFactory::registerDataType(const String & family_name, Creator creator, CaseSensitiveness case_sensitiveness) |
| 82 | { |
| 83 | if (creator == nullptr) |
| 84 | throw Exception("DataTypeFactory: the data type family " + family_name + " has been provided " |
| 85 | " a null constructor" , ErrorCodes::LOGICAL_ERROR); |
| 86 | |
| 87 | String family_name_lowercase = Poco::toLower(family_name); |
| 88 | |
| 89 | if (isAlias(family_name) || isAlias(family_name_lowercase)) |
| 90 | throw Exception("DataTypeFactory: the data type family name '" + family_name + "' is already registered as alias" , |
| 91 | ErrorCodes::LOGICAL_ERROR); |
| 92 | |
| 93 | if (!data_types.emplace(family_name, creator).second) |
| 94 | throw Exception("DataTypeFactory: the data type family name '" + family_name + "' is not unique" , |
| 95 | ErrorCodes::LOGICAL_ERROR); |
| 96 | |
| 97 | |
| 98 | if (case_sensitiveness == CaseInsensitive |
| 99 | && !case_insensitive_data_types.emplace(family_name_lowercase, creator).second) |
| 100 | throw Exception("DataTypeFactory: the case insensitive data type family name '" + family_name + "' is not unique" , |
| 101 | ErrorCodes::LOGICAL_ERROR); |
| 102 | } |
| 103 | |
| 104 | void DataTypeFactory::registerSimpleDataType(const String & name, SimpleCreator creator, CaseSensitiveness case_sensitiveness) |
| 105 | { |
| 106 | if (creator == nullptr) |
| 107 | throw Exception("DataTypeFactory: the data type " + name + " has been provided " |
| 108 | " a null constructor" , ErrorCodes::LOGICAL_ERROR); |
| 109 | |
| 110 | registerDataType(name, [name, creator](const String & type_name, const ASTPtr & ast) |
| 111 | { |
| 112 | if (ast) |
| 113 | throw Exception("Data type " + name + " cannot have arguments" , ErrorCodes::DATA_TYPE_CANNOT_HAVE_ARGUMENTS); |
| 114 | return creator(type_name); |
| 115 | }, case_sensitiveness); |
| 116 | } |
| 117 | |
| 118 | void DataTypeFactory::registerDataTypeCustom(const String & family_name, CreatorWithCustom creator, CaseSensitiveness case_sensitiveness) |
| 119 | { |
| 120 | registerDataType(family_name, [creator](const String & type_name, const ASTPtr & ast) |
| 121 | { |
| 122 | auto res = creator(type_name, ast); |
| 123 | res.first->setCustomization(std::move(res.second)); |
| 124 | |
| 125 | return res.first; |
| 126 | }, case_sensitiveness); |
| 127 | } |
| 128 | |
| 129 | void DataTypeFactory::registerSimpleDataTypeCustom(const String & name, SimpleCreatorWithCustom creator, CaseSensitiveness case_sensitiveness) |
| 130 | { |
| 131 | registerDataTypeCustom(name, [creator](const String & type_name, const ASTPtr & /*ast*/) |
| 132 | { |
| 133 | return creator(type_name); |
| 134 | }, case_sensitiveness); |
| 135 | } |
| 136 | |
| 137 | const DataTypeFactory::Creator& DataTypeFactory::findCreatorByName(const String & family_name) const |
| 138 | { |
| 139 | { |
| 140 | DataTypesDictionary::const_iterator it = data_types.find(family_name); |
| 141 | if (data_types.end() != it) |
| 142 | return it->second; |
| 143 | } |
| 144 | |
| 145 | String family_name_lowercase = Poco::toLower(family_name); |
| 146 | |
| 147 | { |
| 148 | DataTypesDictionary::const_iterator it = case_insensitive_data_types.find(family_name_lowercase); |
| 149 | if (case_insensitive_data_types.end() != it) |
| 150 | return it->second; |
| 151 | } |
| 152 | |
| 153 | auto hints = this->getHints(family_name); |
| 154 | if (!hints.empty()) |
| 155 | throw Exception("Unknown data type family: " + family_name + ". Maybe you meant: " + toString(hints), ErrorCodes::UNKNOWN_TYPE); |
| 156 | else |
| 157 | throw Exception("Unknown data type family: " + family_name, ErrorCodes::UNKNOWN_TYPE); |
| 158 | } |
| 159 | |
| 160 | DataTypeFactory::DataTypeFactory() |
| 161 | { |
| 162 | registerDataTypeNumbers(*this); |
| 163 | registerDataTypeDecimal(*this); |
| 164 | registerDataTypeDate(*this); |
| 165 | registerDataTypeDateTime(*this); |
| 166 | registerDataTypeDateTime64(*this); |
| 167 | registerDataTypeString(*this); |
| 168 | registerDataTypeFixedString(*this); |
| 169 | registerDataTypeEnum(*this); |
| 170 | registerDataTypeArray(*this); |
| 171 | registerDataTypeTuple(*this); |
| 172 | registerDataTypeNullable(*this); |
| 173 | registerDataTypeNothing(*this); |
| 174 | registerDataTypeUUID(*this); |
| 175 | registerDataTypeAggregateFunction(*this); |
| 176 | registerDataTypeNested(*this); |
| 177 | registerDataTypeInterval(*this); |
| 178 | registerDataTypeLowCardinality(*this); |
| 179 | registerDataTypeDomainIPv4AndIPv6(*this); |
| 180 | registerDataTypeDomainSimpleAggregateFunction(*this); |
| 181 | } |
| 182 | |
| 183 | DataTypeFactory::~DataTypeFactory() |
| 184 | {} |
| 185 | |
| 186 | DataTypeFactory & DataTypeFactory::instance() |
| 187 | { |
| 188 | static DataTypeFactory ret; |
| 189 | return ret; |
| 190 | } |
| 191 | |
| 192 | } |
| 193 | |