Use of custom query/placeholder for external dictionaries.
The `placeholder` is similar to `update_field`

Current implementation supports only simple table field like 
`SOURCE(CLICKHOUSE(... update_field 'added_time' update_lag 15))`
but miss support for complex/compound expressions (that for example could use index more efficiently).

Example: 
query = "
    ....
    from t1
    where :placeholder between col1 and col2 and col3=42
    "
invalidate_query=
placeholder_query = "select max(col1) from t1 ...",
placeholder_init_str = "toDateTime('1970-01-01')"

So initial value of placeholder is calculated from `placeholder_init_str`,
next value from `invalidate_query`
and could be used in query.

By introducing this feature work with dictionary sources will be more flexible and general.
writeString(" WHERE ", out);
            composeKeysCondition(key_columns, requested_rows, method, partition_key_prefix, out);
            writeString(";", out);
            return out.str();
        }
        WriteBufferFromOwnString condition_value_buffer;
        composeKeysCondition(key_columns, requested_rows, method, partition_key_prefix, condition_value_buffer);
        const auto & condition_value = condition_value_buffer.str();
        auto query_copy = query;
        query_copy.replace(condition_position, CONDITION_PLACEHOLDER_TO_REPLACE_VALUE.size(), condition_value);
        return query_copy;
    }
}
void ExternalQueryBuilder::composeKeyCondition(const Columns & key_columns, size_t row, WriteBuffer & out,
                                               size_t beg, size_t end) const
{
    auto first = true;
    for (size_t i = beg; i < end; ++i)
    {
        if (!first)
            writeString(" AND ", out);
        first = false;
        const auto & key_description = (*dict_struct.key)[i];
        
        writeQuoted(key_description.name, out);
        writeString("=", out);
        key_description.type_serialization->serializeTextQuoted(*key_columns[i], row, out, format_settings);
    }
}
void ExternalQueryBuilder::composeInWithTuples(const Columns & key_columns, const std::vector<size_t> & requested_rows,