https://clickhouse.com/docs/en/sql-reference/statements/create/dictionary/

```
CREATE DICTIONARY [IF NOT EXISTS] [db.]dictionary_name [ON CLUSTER cluster]
(
    key1 type1  [DEFAULT|EXPRESSION expr1] [HIERARCHICAL|INJECTIVE|IS_OBJECT_ID],
    key2 type2  [DEFAULT|EXPRESSION expr2] [HIERARCHICAL|INJECTIVE|IS_OBJECT_ID],
    attr1 type2 [DEFAULT|EXPRESSION expr3],
    attr2 type2 [DEFAULT|EXPRESSION expr4]

```

`[HIERARCHICAL|INJECTIVE|IS_OBJECT_ID]` -- about attr1 not key1. 
And what is `IS_OBJECT_ID` ?
const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix, const std::string & default_type)
{
    const auto name = config.getString(config_prefix + ".name", "");
    const auto expression = config.getString(config_prefix + ".expression", "");
    if (name.empty() && !expression.empty())
        throw Exception(ErrorCodes::BAD_ARGUMENTS, "Element {}.name is empty");
    const auto type_name = config.getString(config_prefix + ".type", default_type);
    return DictionaryTypedSpecialAttribute{std::move(name), std::move(expression), DataTypeFactory::instance().get(type_name)};
}
std::optional<AttributeUnderlyingType> maybeGetAttributeUnderlyingType(TypeIndex index)
{
    switch (index) 
    {
        case TypeIndex::Date:       return AttributeUnderlyingType::UInt16;
        case TypeIndex::DateTime:   return AttributeUnderlyingType::UInt32;
        case TypeIndex::DateTime64: return AttributeUnderlyingType::UInt64;
        default: break;
    }
    return magic_enum::enum_cast<AttributeUnderlyingType>(static_cast<TypeIndexUnderlying>(index));
}
}
DictionarySpecialAttribute::DictionarySpecialAttribute(const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix)