```
SELECT categoricalInformationValue(x.1, x.2) FROM (SELECT arrayJoin([(0, 0), (NULL, 2), (1, 0), (1, 1)]) AS x)
```
ColumnPtr & column,
    size_t limit,
    DeserializeBinaryBulkSettings & settings,
    DeserializeBinaryBulkStatePtr & state,
    SubstreamsCache * cache) const
{
    auto mutable_column = column->assumeMutable();
    ColumnArray & column_array = typeid_cast<ColumnArray &>(*mutable_column);
    settings.path.push_back(Substream::ArraySizes);
    if (auto cached_column = getFromSubstreamsCache(cache, settings.path))
    {
        column_array.getOffsetsPtr() = arraySizesToOffsets(*cached_column);
    }
    else if (auto * stream = settings.getter(settings.path))
    {
        if (settings.position_independent_encoding)
            deserializeArraySizesPositionIndependent(column_array, *stream, limit);
        else
            SerializationNumber<ColumnArray::Offset>().deserializeBinaryBulk(column_array.getOffsetsColumn(), *stream, limit, 0);
        addToSubstreamsCache(cache, settings.path, arrayOffsetsToSizes(column_array.getOffsetsColumn()));
    }
    settings.path.back() = Substream::ArrayElements;
    ColumnArray::Offsets & offset_values = column_array.getOffsets();
    ColumnPtr & nested_column = column_array.getDataPtr();
    
    size_t last_offset = offset_values.back();
    if (last_offset < nested_column->size())
        throw Exception("Nested column is longer than last offset", ErrorCodes::LOGICAL_ERROR);
    size_t nested_limit = last_offset - nested_column->size();