```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... :|
columns_list.push_back(std::move(column.column));
                    continue;
                }
            }
        }
        else
        {
            auto arrow_column = name_to_column_ptr[search_column_name];
            column = readColumnFromArrowColumn(
                arrow_column, header_column.name, format_name, false, dictionary_values, true, true, false, skipped);
        }
        try
        {
            column.column = castColumn(column, header_column.type);
        }
        catch (Exception & e)
        {
            e.addMessage(fmt::format(
                "while converting column {} from type {} to type {}",
                backQuote(header_column.name),
                column.type->getName(),
                header_column.type->getName()));
            throw;
        }
        column.type = header_column.type;
        columns_list.push_back(std::move(column.column));
    }
    res.setColumns(columns_list, num_rows);
}
std::vector<size_t> ArrowColumnToCHColumn::getMissingColumns(const arrow::Schema & schema) const