22.2.2

```sql
create table source (a UInt64, b UInt64, c String) Engine= Memory;

insert into source select number, number, 'attr-'||toString(number) from numbers(10);

CREATE DICTIONARY dict1
( a UInt64 , b UInt64  HIERARCHICAL, c String
) PRIMARY KEY a
SOURCE(clickhouse(DB 'default' TABLE 'source'))
LIFETIME(300) LAYOUT(flat());

SELECT dictGetDescendants('dict1', toUInt64(2), 0)
DB::Exception: Illegal type of third argument of function dictGetDescendants
Expected const unsigned integer.: While processing dictGetDescendants('dict1', toUInt64(2), 0). (ILLEGAL_TYPE_OF_ARGUMENT)

-- but !

SELECT dictGetDescendants('dict1', materialize(toUInt64(2)), 0)
┌─dictGetDescendants('dict1', materialize(toUInt64(2)), 0)─┐
│ [2]                                                      │
└──────────────────────────────────────────────────────────┘

SELECT dictGetDescendants('dict1', number, 0)
FROM numbers(3)
┌─dictGetDescendants('dict1', number, 0)─┐
│ [0]                                    │
│ [1]                                    │
│ [2]                                    │
└────────────────────────────────────────┘
```

> "DB::Exception: Illegal type of third argument of function dictGetDescendants"

Also the message is incorrect, the problem is in the second argument,  not the third argument 
{
        if (input_rows_count == 0)
            return result_type->createColumn();
        /** We call dictHas function to get which map is key presented in dictionary.
            For key that presented in dictionary dict has result for that key index value will be 1. Otherwise 0.
            We invert result, and then for key that is not presented in dictionary value will be 1. Otherwise 0.
            This inverted result will be used as null column map.
            After that we call dict get function, by contract for key that are not presented in dictionary we
            return default value.
            We create nullable column from dict get result column and null column map.
            2 additional implementation details:
            1. Result from dict get can be tuple if client requested multiple attributes we apply such operation on each result column.
            2. If column is already nullable we merge column null map with null map that we get from dict has.
          */
        auto dict_has_arguments = filterAttributeNameArgumentForDictHas(arguments);
        auto is_key_in_dictionary_column = dictionary_has_func_impl.executeImpl(dict_has_arguments, std::make_shared<DataTypeUInt8>(), input_rows_count);
        auto is_key_in_dictionary_column_mutable = is_key_in_dictionary_column->assumeMutable();
        ColumnVector<UInt8> & is_key_in_dictionary_column_typed = assert_cast<ColumnVector<UInt8> &>(*is_key_in_dictionary_column_mutable);
        PaddedPODArray<UInt8> & is_key_in_dictionary_data = is_key_in_dictionary_column_typed.getData();
        for (auto & key : is_key_in_dictionary_data)
            key = !key;
        auto dictionary_get_result_type = dictionary_get_func_impl.getReturnTypeImpl(arguments);
        auto dictionary_get_result_column = dictionary_get_func_impl.executeImpl(arguments, dictionary_get_result_type, input_rows_count);
        ColumnPtr result;
        WhichDataType dictionary_get_result_data_type(dictionary_get_result_type);