```
CREATE TABLE dictionary_nullable_source_table(    id UInt64,    value Int64) ENGINE=TinyLog;
INSERT INTO dictionary_nullable_source_table VALUES (0, 0);
DROP DICTIONARY IF EXISTS flat_dictionary;
CREATE DICTIONARY flat_dictionary (  id UInt64,  value Int64 ) PRIMARY KEY id
SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_nullable_source_table'))
LIFETIME(MIN 1 MAX 1000)
LAYOUT(FLAT());
SELECT dictGet('flat_dictionary', 'value', Null);
```

On 21.6 and older - returns Null. 
On 21.7 and newer:
```
Received exception from server (version 21.8.4):
Code: 43. DB::Exception: Received from localhost:9000. DB::Exception: Third argument of function dictGet must be UInt64 when dictionary is simple. Actual type Nullable(Nothing).: While processing dictGet('flat_dictionary', 'value', NULL). Stack trace:

0. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool) @ 0x8f9557a in /usr/bin/clickhouse
1. DB::Exception::Exception<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&) @ 0xa7b78de in /usr/bin/clickhouse
2. DB::FunctionDictGetNoType<(DB::DictionaryGetFunctionType)0>::executeImpl(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long) const @ 0xb5da99c in /usr/bin/clickhouse
3. DB::IFunction::executeImplDryRun(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long) const @ 0xb1266ca in /usr/bin/clickhouse
4. DB::FunctionToExecutableFunctionAdaptor::executeDryRunImpl(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long) const @ 0xb12574e in /usr/bin/clickhouse
5. DB::IExecutableFunction::executeWithoutLowCardinalityColumns(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long, bool) const @ 0xfa6cd85 in /usr/bin/clickhouse
6. DB::IExecutableFunction::defaultImplementationForConstantArguments(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long, bool) const @ 0xfa6c772 in /usr/bin/clickhouse
7. DB::IExecutableFunction::executeWithoutLowCardinalityColumns(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long, bool) const @ 0xfa6cd45 in /usr/bin/clickhouse
8. DB::IExecutableFunction::execute(std::__1::vector<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> > const&, std::__1::shared_ptr<DB::IDataType const> const&, unsigned long, bool) const @ 0xfa6d3b2 in /usr/bin/clickhouse
9. DB::ActionsDAG::addFunction(std::__1::shared_ptr<DB::IFunctionOverloadResolver> const&, std::__1::vector<DB::ActionsDAG::Node const*, std::__1::allocator<DB::ActionsDAG::Node const*> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) @ 0xff4629f in /usr/bin/clickhouse
10. DB::ScopeStack::addFunction(std::__1::shared_ptr<DB::IFunctionOverloadResolver> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) @ 0x101bcdb2 in /usr/bin/clickhouse
11. DB::ActionsMatcher::visit(DB::ASTFunction const&, std::__1::shared_ptr<DB::IAST> const&, DB::ActionsMatcher::Data&) @ 0x101c6f0c in /usr/bin/clickhouse
12. DB::ActionsMatcher::visit(DB::ASTExpressionList&, std::__1::shared_ptr<DB::IAST> const&, DB::ActionsMatcher::Data&) @ 0x101cef7e in /usr/bin/clickhouse
13. DB::InDepthNodeVisitor<DB::ActionsMatcher, true, std::__1::shared_ptr<DB::IAST> const>::visit(std::__1::shared_ptr<DB::IAST> const&) @ 0x1018e917 in /usr/bin/clickhouse
14. DB::ExpressionAnalyzer::getRootActions(std::__1::shared_ptr<DB::IAST> const&, bool, std::__1::shared_ptr<DB::ActionsDAG>&, bool) @ 0x1018e605 in /usr/bin/clickhouse
15. DB::SelectQueryExpressionAnalyzer::appendSelect(DB::ExpressionActionsChain&, bool) @ 0x1019bda8 in /usr/bin/clickhouse
16. DB::ExpressionAnalysisResult::ExpressionAnalysisResult(DB::SelectQueryExpressionAnalyzer&, std::__1::shared_ptr<DB::StorageInMemoryMetadata const> const&, bool, bool, bool, std::__1::shared_ptr<DB::FilterDAGInfo> const&, DB::Block const&) @ 0x101a1422 in /usr/bin/clickhouse
17. DB::InterpreterSelectQuery::getSampleBlockImpl() @ 0x103a97e6 in /usr/bin/clickhouse
18. ? @ 0x103a236b in /usr/bin/clickhouse
19. DB::InterpreterSelectQuery::InterpreterSelectQuery(std::__1::shared_ptr<DB::IAST> const&, std::__1::shared_ptr<DB::Context const>, std::__1::shared_ptr<DB::IBlockInputStream> const&, std::__1::optional<DB::Pipe>, std::__1::shared_ptr<DB::IStorage> const&, DB::SelectQueryOptions const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, std::__1::shared_ptr<DB::StorageInMemoryMetadata const> const&) @ 0x1039c77f in /usr/bin/clickhouse
20. DB::InterpreterSelectQuery::InterpreterSelectQuery(std::__1::shared_ptr<DB::IAST> const&, std::__1::shared_ptr<DB::Context const>, DB::SelectQueryOptions const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) @ 0x1039af7e in /usr/bin/clickhouse
21. DB::InterpreterSelectWithUnionQuery::InterpreterSelectWithUnionQuery(std::__1::shared_ptr<DB::IAST> const&, std::__1::shared_ptr<DB::Context const>, DB::SelectQueryOptions const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) @ 0x10575909 in /usr/bin/clickhouse
22. DB::InterpreterFactory::get(std::__1::shared_ptr<DB::IAST>&, std::__1::shared_ptr<DB::Context>, DB::SelectQueryOptions const&) @ 0x1017c2b7 in /usr/bin/clickhouse
23. ? @ 0x10739886 in /usr/bin/clickhouse
24. DB::executeQuery(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, bool) @ 0x107381c3 in /usr/bin/clickhouse
25. DB::TCPHandler::runImpl() @ 0x10fcd88d in /usr/bin/clickhouse
26. DB::TCPHandler::run() @ 0x10fe06d9 in /usr/bin/clickhouse
27. Poco::Net::TCPServerConnection::start() @ 0x13b5730f in /usr/bin/clickhouse
28. Poco::Net::TCPServerDispatcher::run() @ 0x13b58d9a in /usr/bin/clickhouse
29. Poco::PooledThread::run() @ 0x13c8bc19 in /usr/bin/clickhouse
30. Poco::ThreadImpl::runnableEntry(void*) @ 0x13c87eaa in /usr/bin/clickhouse
31. start_thread @ 0x9609 in /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
```
{
        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);