public override Delegate GetConverter <TLogical, TPhysical>(ColumnDescriptor columnDescriptor, ColumnChunkMetaData columnChunkMetaData)
 {
     // VolumeInDollars is bitwise identical to float, so we can reuse the native converter.
     if (typeof(TLogical) == typeof(VolumeInDollars))
     {
         return(LogicalRead.GetNativeConverter <VolumeInDollars, float>());
     }
     return(base.GetConverter <TLogical, TPhysical>(columnDescriptor, columnChunkMetaData));
 }
 public override Delegate?GetDirectReader <TLogical, TPhysical>()
 {
     // Optional: the following is an optimisation and not stricly needed (but helps with speed).
     // Since VolumeInDollars is bitwise identical to float, we can read the values in-place.
     if (typeof(TLogical) == typeof(VolumeInDollars))
     {
         return(LogicalRead.GetDirectReader <VolumeInDollars, float>());
     }
     return(base.GetDirectReader <TLogical, TPhysical>());
 }
        private static ExpectedColumn[] CreateExpectedColumns()
        {
            return(new[]
            {
                new ExpectedColumn
                {
                    Name = "boolean_field",
                    PhysicalType = PhysicalType.Boolean,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 3 == 0).ToArray(),
                    Min = false,
                    Max = true
                },
                new ExpectedColumn
                {
                    Name = "boolean?_field",
                    PhysicalType = PhysicalType.Boolean,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (bool?)null : i % 3 == 0).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = false,
                    Max = true
                },
                new ExpectedColumn
                {
                    Name = "int8_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(8, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => (sbyte)i).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int8?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(8, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (sbyte?)null : (sbyte)i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint8_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(8, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => (byte)i).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint8?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(8, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (byte?)null : (byte)i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int16_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(16, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => (short)i).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int16?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(16, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (short?)null : (short)i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint16_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(16, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => (ushort)i).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint16?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(16, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (ushort?)null : (ushort)i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int32_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(32, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int32?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(32, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (int?)null : i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint32_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(32, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => (uint)i).ToArray(),
                    Min = 0,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "uint32?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Int(32, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (uint?)null : (uint)i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = NumRows - 1
                },
                new ExpectedColumn
                {
                    Name = "int64_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => (long)i * i).ToArray(),
                    Min = 0,
                    Max = (NumRows - 1) * (NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "int64?_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (long?)null : (long)i * i).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = (NumRows - 1) * (NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "uint64_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => (ulong)(i * i)).ToArray(),
                    Min = 0,
                    Max = (NumRows - 1) * (NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "uint64?_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: false),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (ulong?)null : (ulong)(i * i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = (NumRows - 1) * (NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "int96_field",
                    PhysicalType = PhysicalType.Int96,
                    LogicalType = LogicalType.None(),
                    Values = Enumerable.Range(0, NumRows).Select(i => new Int96(i, i * i, i * i * i)).ToArray(),
                    HasStatistics = false
                },
                new ExpectedColumn
                {
                    Name = "int96?_field",
                    PhysicalType = PhysicalType.Int96,
                    LogicalType = LogicalType.None(),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (Int96?)null : new Int96(i, i * i, i * i * i)).ToArray(),
                    HasStatistics = false
                },
                new ExpectedColumn
                {
                    Name = "float_field",
                    PhysicalType = PhysicalType.Float,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 5 == 0 ? float.NaN : (float)Math.Sqrt(i)).ToArray(),
                    Min = 1,
                    Max = (float)Math.Sqrt(NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "float?_field",
                    PhysicalType = PhysicalType.Float,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (float?)null : i % 5 == 0 ? float.NaN : (float)Math.Sqrt(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = 1,
                    Max = (float)Math.Sqrt(NumRows - 1)
                },
                new ExpectedColumn
                {
                    Name = "double_field",
                    PhysicalType = PhysicalType.Double,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 7 == 0 ? double.NaN : i * Math.PI).ToArray(),
                    Min = Math.PI,
                    Max = (NumRows - 1) * Math.PI
                },
                new ExpectedColumn
                {
                    Name = "double?_field",
                    PhysicalType = PhysicalType.Double,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (double?)null : i % 7 == 0 ? double.NaN : i * Math.PI).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = Math.PI,
                    Max = (NumRows - 1) * Math.PI
                },
                new ExpectedColumn
                {
                    Name = "decimal128_field",
                    PhysicalType = PhysicalType.FixedLenByteArray,
                    LogicalType = LogicalType.Decimal(29, 3),
                    LogicalTypeOverride = LogicalType.Decimal(29, 3),
                    Length = 16,
                    Values = Enumerable.Range(0, NumRows).Select(i => ((decimal)i * i * i) / 1000 - 10).ToArray(),
                    Min = -10m,
                    Max = ((NumRows - 1m) * (NumRows - 1m) * (NumRows - 1m)) / 1000 - 10,
                    Converter = v => LogicalRead.ToDecimal((FixedLenByteArray)v, 3)
                },
                new ExpectedColumn
                {
                    Name = "decimal128?_field",
                    PhysicalType = PhysicalType.FixedLenByteArray,
                    LogicalType = LogicalType.Decimal(29, 3),
                    LogicalTypeOverride = LogicalType.Decimal(29, 3),
                    Length = 16,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? null : ((decimal?)i * i * i) / 1000 - 10).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = -9.999m,
                    Max = ((NumRows - 1m) * (NumRows - 1m) * (NumRows - 1m)) / 1000 - 10,
                    Converter = v => LogicalRead.ToDecimal((FixedLenByteArray)v, 3)
                },
                new ExpectedColumn
                {
                    Name = "uuid_field",
                    PhysicalType = PhysicalType.FixedLenByteArray,
                    LogicalType = LogicalType.Uuid(),
                    LogicalTypeOverride = LogicalType.Uuid(),
                    Length = 16,
                    Values = Enumerable.Range(0, NumRows).Select(i => new Guid(i, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F)).ToArray(),
                    Min = new Guid(0, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F),
                    Max = new Guid(NumRows - 1, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F),
                    Converter = v => LogicalRead.ToUuid((FixedLenByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "uuid?_field",
                    PhysicalType = PhysicalType.FixedLenByteArray,
                    LogicalType = LogicalType.Uuid(),
                    LogicalTypeOverride = LogicalType.Uuid(),
                    Length = 16,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? null : (Guid?)new Guid(i, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new Guid(1, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F),
                    Max = new Guid(NumRows - 1, 0x1234, 0x5678, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x7F),
                    Converter = v => LogicalRead.ToUuid((FixedLenByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "date_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Date(),
                    Values = Enumerable.Range(0, NumRows).Select(i => new Date(2018, 01, 01).AddDays(i)).ToArray(),
                    Min = new Date(2018, 01, 01).Days,
                    Max = new Date(2018, 01, 01).AddDays(NumRows - 1).Days
                },
                new ExpectedColumn
                {
                    Name = "date?_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Date(),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (Date?)null : new Date(2018, 01, 01).AddDays(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new Date(2018, 01, 01).AddDays(1).Days,
                    Max = new Date(2018, 01, 01).AddDays(NumRows - 1).Days
                },
                new ExpectedColumn
                {
                    Name = "datetime_micros_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Micros),
                    Values = Enumerable.Range(0, NumRows).Select(i => new DateTime(2018, 01, 01) + TimeSpan.FromHours(i)).ToArray(),
                    Min = new DateTime(2018, 01, 01),
                    Max = new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1),
                    Converter = v => LogicalRead.ToDateTimeMicros((long)v)
                },
                new ExpectedColumn
                {
                    Name = "datetime?_micros_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Micros),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (DateTime?)null : new DateTime(2018, 01, 01) + TimeSpan.FromHours(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new DateTime(2018, 01, 01) + TimeSpan.FromHours(1),
                    Max = new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1),
                    Converter = v => LogicalRead.ToDateTimeMicros((long)v)
                },
                new ExpectedColumn
                {
                    Name = "datetime_millis_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Millis),
                    LogicalTypeOverride = LogicalType.Timestamp(true, TimeUnit.Millis),
                    Values = Enumerable.Range(0, NumRows).Select(i => new DateTime(2018, 01, 01) + TimeSpan.FromHours(i)).ToArray(),
                    Min = new DateTime(2018, 01, 01),
                    Max = new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1),
                    Converter = v => LogicalRead.ToDateTimeMillis((long)v)
                },
                new ExpectedColumn
                {
                    Name = "datetime?_millis_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Millis),
                    LogicalTypeOverride = LogicalType.Timestamp(true, TimeUnit.Millis),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (DateTime?)null : new DateTime(2018, 01, 01) + TimeSpan.FromHours(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new DateTime(2018, 01, 01) + TimeSpan.FromHours(1),
                    Max = new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1),
                    Converter = v => LogicalRead.ToDateTimeMillis((long)v)
                },
                new ExpectedColumn
                {
                    Name = "datetime_nanos_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Nanos),
                    Values = Enumerable.Range(0, NumRows).Select(i => new DateTimeNanos(new DateTime(2018, 01, 01) + TimeSpan.FromHours(i))).ToArray(),
                    Min = new DateTimeNanos(new DateTime(2018, 01, 01)),
                    Max = new DateTimeNanos(new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1)),
                    Converter = v => new DateTimeNanos((long)v)
                },
                new ExpectedColumn
                {
                    Name = "datetime?_nanos_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Timestamp(true, TimeUnit.Nanos),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (DateTimeNanos?)null : new DateTimeNanos(new DateTime(2018, 01, 01) + TimeSpan.FromHours(i))).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new DateTimeNanos(new DateTime(2018, 01, 01) + TimeSpan.FromHours(1)),
                    Max = new DateTimeNanos(new DateTime(2018, 01, 01) + TimeSpan.FromHours(NumRows - 1)),
                    Converter = v => new DateTimeNanos((long)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan_micros_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Time(true, TimeUnit.Micros),
                    Values = Enumerable.Range(0, NumRows).Select(i => TimeSpan.FromHours(-13) + TimeSpan.FromHours(i)).ToArray(),
                    Min = TimeSpan.FromHours(-13),
                    Max = TimeSpan.FromHours(-13 + NumRows - 1),
                    Converter = v => LogicalRead.ToTimeSpanMicros((long)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan?_micros_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Time(true, TimeUnit.Micros),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (TimeSpan?)null : TimeSpan.FromHours(-13) + TimeSpan.FromHours(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = TimeSpan.FromHours(-13 + 1),
                    Max = TimeSpan.FromHours(-13 + NumRows - 1),
                    Converter = v => LogicalRead.ToTimeSpanMicros((long)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan_millis_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Time(true, TimeUnit.Millis),
                    LogicalTypeOverride = LogicalType.Time(true, TimeUnit.Millis),
                    Values = Enumerable.Range(0, NumRows).Select(i => TimeSpan.FromHours(-13) + TimeSpan.FromHours(i)).ToArray(),
                    Min = TimeSpan.FromHours(-13),
                    Max = TimeSpan.FromHours(-13 + NumRows - 1),
                    Converter = v => LogicalRead.ToTimeSpanMillis((int)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan?_millis_field",
                    PhysicalType = PhysicalType.Int32,
                    LogicalType = LogicalType.Time(true, TimeUnit.Millis),
                    LogicalTypeOverride = LogicalType.Time(true, TimeUnit.Millis),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (TimeSpan?)null : TimeSpan.FromHours(-13) + TimeSpan.FromHours(i)).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = TimeSpan.FromHours(-13 + 1),
                    Max = TimeSpan.FromHours(-13 + NumRows - 1),
                    Converter = v => LogicalRead.ToTimeSpanMillis((int)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan_nanos_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Time(true, TimeUnit.Nanos),
                    Values = Enumerable.Range(0, NumRows).Select(i => new TimeSpanNanos(TimeSpan.FromHours(-13) + TimeSpan.FromHours(i))).ToArray(),
                    Min = new TimeSpanNanos(TimeSpan.FromHours(-13)),
                    Max = new TimeSpanNanos(TimeSpan.FromHours(-13 + NumRows - 1)),
                    Converter = v => new TimeSpanNanos((long)v)
                },
                new ExpectedColumn
                {
                    Name = "timespan?_nanos_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Time(true, TimeUnit.Nanos),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 11 == 0 ? (TimeSpanNanos?)null : new TimeSpanNanos(TimeSpan.FromHours(-13) + TimeSpan.FromHours(i))).ToArray(),
                    NullCount = (NumRows + 10) / 11,
                    NumValues = NumRows - (NumRows + 10) / 11,
                    Min = new TimeSpanNanos(TimeSpan.FromHours(-13 + 1)),
                    Max = new TimeSpanNanos(TimeSpan.FromHours(-13 + NumRows - 1)),
                    Converter = v => new TimeSpanNanos((long)v)
                },
                new ExpectedColumn
                {
                    Name = "string_field",
                    PhysicalType = PhysicalType.ByteArray,
                    LogicalType = LogicalType.String(),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 9 == 0 ? i % 18 == 0 ? null : "" : $"Hello, {i}!").ToArray(),
                    NullCount = (NumRows + 17) / 18,
                    NumValues = NumRows - (NumRows + 17) / 18,
                    Min = "",
                    Max = "Hello, 98!",
                    Converter = v => LogicalRead.ToString((ByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "json_field",
                    PhysicalType = PhysicalType.ByteArray,
                    LogicalType = LogicalType.Json(),
                    LogicalTypeOverride = LogicalType.Json(),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 9 == 0 ? null : $"{{ \"id\", {i} }}").ToArray(),
                    NullCount = (NumRows + 8) / 9,
                    NumValues = NumRows - (NumRows + 8) / 9,
                    Min = "{ \"id\", 1 }",
                    Max = "{ \"id\", 98 }",
                    Converter = v => LogicalRead.ToString((ByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "bytearray_field",
                    PhysicalType = PhysicalType.ByteArray,
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 3 == 0 ? i % 6 == 0 ? null : new byte[0] : BitConverter.GetBytes(i)).ToArray(),
                    NullCount = (NumRows + 5) / 6,
                    NumValues = NumRows - (NumRows + 5) / 6,
                    Min = new byte[0],
                    Max = BitConverter.GetBytes(NumRows - 1),
                    Converter = v => LogicalRead.ToByteArray((ByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "bson_field",
                    PhysicalType = PhysicalType.ByteArray,
                    LogicalType = LogicalType.Bson(),
                    LogicalTypeOverride = LogicalType.Bson(),
                    Values = Enumerable.Range(0, NumRows).Select(i => i % 3 == 0 ? null : BitConverter.GetBytes(i)).ToArray(),
                    NullCount = (NumRows + 2) / 3,
                    NumValues = NumRows - (NumRows + 2) / 3,
                    Min = BitConverter.GetBytes(1),
                    Max = BitConverter.GetBytes(NumRows - 1),
                    Converter = v => LogicalRead.ToByteArray((ByteArray)v)
                },
                new ExpectedColumn
                {
                    Name = "nested_array_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i =>
                    {
                        if (i % 3 == 0)
                        {
                            return new[]
                            {
                                new long[] { 1, 2 },
                                new long[] { 3, 4 }
                            };
                        }

                        if (i % 3 == 1)
                        {
                            return new[]
                            {
                                null,
                                null,
                                new long[] { 13, 14 },
                                null,
                                new long[] { 15, 16 }
                            };
                        }

                        return new long[][]
                        {
                            null
                        };
                    }).ToArray(),
                    NullCount = (NumRows / 3 + 1) * 4 - 1,
                    NumValues = (NumRows / 3 + 1) * 8,
                    Min = 1,
                    Max = 16
                },
                new ExpectedColumn
                {
                    Name = "nullable_nested_array_field",
                    PhysicalType = PhysicalType.Int64,
                    LogicalType = LogicalType.Int(64, isSigned: true),
                    Values = Enumerable.Range(0, NumRows).Select(i =>
                    {
                        if (i % 3 == 0)
                        {
                            return new[]
                            {
                                new long?[] { 1, 2 },
                                new long?[] { 3, null }
                            };
                        }

                        if (i % 3 == 1)
                        {
                            return new[]
                            {
                                null,
                                null,
                                new long?[] { 13, 14 },
                                null,
                                new long?[] { null, 16 }
                            };
                        }

                        return new long?[][]
                        {
                            null
                        };
                    }).ToArray(),
                    NullCount = (NumRows / 3 + 1) * 6 - 1,
                    NumValues = (NumRows / 3 + 1) * 6,
                    Min = 1,
                    Max = 16
                },
                new ExpectedColumn
                {
                    Name = "array_of_bytearrays",
                    PhysicalType = PhysicalType.ByteArray,
                    Values = Enumerable.Range(0, NumRows).Select(i =>
                    {
                        if (i % 3 == 0)
                        {
                            return new[]
                            {
                                BitConverter.GetBytes(3 * i),
                                BitConverter.GetBytes(2 * i)
                            };
                        }

                        if (i % 3 == 1)
                        {
                            return new[]
                            {
                                null,
                                null,
                                BitConverter.GetBytes(i),
                                null
                            };
                        }

                        return new byte[][]
                        {
                            null
                        };
                    }).ToArray(),
                    NullCount = (NumRows / 3 + 1) * 4 - 1,
                    NumValues = (NumRows / 3 + 1) * 3,
                    Min = BitConverter.GetBytes(0),
                    Max = BitConverter.GetBytes(252),
                    Converter = v => LogicalRead.ToByteArray((ByteArray)v)
                }
            });
        }