```py
## writing ArrowStream file from python
import pyarrow as pa
data = [
    pa.array([1, 2, 3, 4, 5]),
    pa.array(["one", "two", "three", "four", "five"]).dictionary_encode(),
    pa.array([1, 2, 3, 4, 5]).dictionary_encode(),
    pa.array([True, False, True, True, True])
]
batch = pa.record_batch(data, names=['id', 'lc_nullable', 'lc_int_nullable', 'bool_nullable'])
writer = pa.ipc.new_stream("test4.arrows", batch.schema)
writer.write_batch(batch)
writer.close()
```

```
clickhouse-local --query='SELECT * FROM table FORMAT TSVWithNamesAndTypes' --stacktrace --input-format=ArrowStream < test4.arrows
id	lc_nullable	lc_int_nullable	bool_nullable
Nullable(Int64)	LowCardinality(Nullable(String))	LowCardinality(Nullable(Int64))	Nullable(UInt8)
1		0	1
2	one	1	0
3	two	2	1
4	three	3	1
5	four	4	1
```

0 in LowCardianality dictionary in ClickHouse have special meaning (null/default), while in Arrow it's a regular values.

Probably remapping needed... :|
if (hint_header)
        nested_table_names = Nested::getAllTableNames(*hint_header, ignore_case);
    for (const auto & field : schema.fields())
    {
        if (hint_header && !hint_header->has(field->name(), ignore_case)
            && !nested_table_names.contains(ignore_case ? boost::to_lower_copy(field->name()) : field->name()))
            continue;
        
        arrow::MemoryPool * pool = arrow::default_memory_pool();
        std::unique_ptr<arrow::ArrayBuilder> array_builder;
        arrow::Status status = MakeBuilder(pool, field->type(), &array_builder);
        checkStatus(status, field->name(), format_name);
        std::shared_ptr<arrow::Array> arrow_array;
        status = array_builder->Finish(&arrow_array);
        checkStatus(status, field->name(), format_name);
        arrow::ArrayVector array_vector = {arrow_array};
        auto arrow_column = std::make_shared<arrow::ChunkedArray>(array_vector);
        std::unordered_map<std::string, std::shared_ptr<ColumnWithTypeAndName>> dict_values;
        bool skipped = false;
        bool allow_null_type = false;
        if (hint_header && hint_header->has(field->name()) && hint_header->getByName(field->name()).type->isNullable())
            allow_null_type = true;
        ColumnWithTypeAndName sample_column = readColumnFromArrowColumn(
            arrow_column, field->name(), format_name, false, dict_values, false, allow_null_type, skip_columns_with_unsupported_types, skipped);
        if (!skipped)
            sample_columns.emplace_back(std::move(sample_column));
    }
    return Block(std::move(sample_columns));
}
ArrowColumnToCHColumn::ArrowColumnToCHColumn(