/
dev-npgsql
/
npgsql
Обзор
Документация
Войти
/
dev-npgsql
/
npgsql
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
test-logs
test/Npgsql.Tests/Types/MultirangeTests.cs
180 строк
8 KB
Shay Rojansky
Remove multiplexing (#6457)
28 фев 2026, 10:17
Не верифицирован
28 фев 2026, 10:17
2fea281
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Data; using System.Threading.Tasks; using Npgsql.Properties; using NpgsqlTypes; using NUnit.Framework; using static Npgsql.Tests.TestUtil; namespace Npgsql.Tests.Types; public class MultirangeTests : TestBase { static readonly TestCaseData[] MultirangeTestCases = [ // int4multirange new TestCaseData( new NpgsqlRange<int>[] { new(3, true, false, 7, false, false), new(9, true, false, 0, false, true) }, "{[3,7),[9,)}", "int4multirange", DataTypeInference.Match, true, default(NpgsqlRange<int>)) .SetName("Int"), // int8multirange new TestCaseData( new NpgsqlRange<long>[] { new(3, true, false, 7, false, false), new(9, true, false, 0, false, true) }, "{[3,7),[9,)}", "int8multirange", DataTypeInference.Match, true, default(NpgsqlRange<long>)) .SetName("Long"), // nummultirange // numeric is non-discrete so doesn't undergo normalization, use that to test bound scenarios which otherwise get normalized new TestCaseData( new NpgsqlRange<decimal>[] { new(3, true, false, 7, true, false), new(9, false, false, 0, false, true) }, "{[3,7],(9,)}", "nummultirange", DataTypeInference.Match, true, default(NpgsqlRange<decimal>)) .SetName("Decimal"), // daterange new TestCaseData( new NpgsqlRange<DateOnly>[] { new(new(2020, 1, 1), true, false, new(2020, 1, 5), false, false), new(new(2020, 1, 10), true, false, default, false, true) }, "{[2020-01-01,2020-01-05),[2020-01-10,)}", "datemultirange", DataTypeInference.Match, true, default(NpgsqlRange<DateOnly>)) .SetName("DateTime DateMultirange"), // tsmultirange new TestCaseData( new NpgsqlRange<DateTime>[] { new(new(2020, 1, 1), true, false, new(2020, 1, 5), false, false), new(new(2020, 1, 10), true, false, default, false, true) }, """{["2020-01-01 00:00:00","2020-01-05 00:00:00"),["2020-01-10 00:00:00",)}""", "tsmultirange", DataTypeInference.Match, true, default(NpgsqlRange<DateTime>)) .SetName("DateTime TimestampMultirange"), // tstzmultirange new TestCaseData( new NpgsqlRange<DateTime>[] { new(new(2020, 1, 1, 0, 0, 0, kind: DateTimeKind.Utc), true, false, new(2020, 1, 5, 0, 0, 0, kind: DateTimeKind.Utc), false, false), new(new(2020, 1, 10, 0, 0, 0, kind: DateTimeKind.Utc), true, false, default, false, true) }, """{["2020-01-01 01:00:00+01","2020-01-05 01:00:00+01"),["2020-01-10 01:00:00+01",)}""", "tstzmultirange", DataTypeInference.Match, true, default(NpgsqlRange<DateTime>)) .SetName("DateTime TimestampTzMultirange"), new TestCaseData( new NpgsqlRange<DateOnly>[] { new(new(2020, 1, 1), true, false, new(2020, 1, 5), false, false), new(new(2020, 1, 10), true, false, default, false, true) }, "{[2020-01-01,2020-01-05),[2020-01-10,)}", "datemultirange", DataTypeInference.Mismatch, true, default(NpgsqlRange<DateOnly>)) .SetName("DateOnly") ]; [Test, TestCaseSource(nameof(MultirangeTestCases))] public Task Multirange_as_array<T, TRange>( T multirangeAsArray, string sqlLiteral, string dataTypeName, DataTypeInference datatypeDataTypeInference, bool valueTypeEqualsFieldType, TRange _) => AssertType(multirangeAsArray, sqlLiteral, dataTypeName, dataTypeInference: datatypeDataTypeInference, valueTypeEqualsFieldType: valueTypeEqualsFieldType); [Test, TestCaseSource(nameof(MultirangeTestCases))] public Task Multirange_as_list<T, TRange>( T multirangeAsArray, string sqlLiteral, string dataTypeName, DataTypeInference datatypeDataTypeInference, bool valueTypeEqualsFieldType, TRange _) where T : IList<TRange> => AssertType( new List<TRange>(multirangeAsArray), sqlLiteral, dataTypeName, dataTypeInference: datatypeDataTypeInference, valueTypeEqualsFieldType: false); [Test] public async Task Unmapped_multirange_with_mapped_subtype() { await using var dataSource = CreateDataSource(b => b.EnableUnmappedTypes().ConnectionStringBuilder.MaxPoolSize = 1); await using var conn = await dataSource.OpenConnectionAsync(); var typeName = await GetTempTypeName(conn); await conn.ExecuteNonQueryAsync($"CREATE TYPE {typeName} AS RANGE(subtype=text)"); conn.ReloadTypes(); Assert.That(await conn.ExecuteScalarAsync("SELECT 1"), Is.EqualTo(1)); var value = new[] {new NpgsqlRange<char[]>( new string('a', conn.Settings.WriteBufferSize + 10).ToCharArray(), new string('z', conn.Settings.WriteBufferSize + 10).ToCharArray() )}; await using var cmd = new NpgsqlCommand("SELECT @p", conn); cmd.Parameters.Add(new NpgsqlParameter { DataTypeName = typeName + "_multirange", ParameterName = "p", Value = value }); await using var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess); await reader.ReadAsync(); Assert.That(reader.GetFieldType(0), Is.EqualTo(typeof(NpgsqlRange<string>[]))); var result = reader.GetFieldValue<NpgsqlRange<char[]>[]>(0); Assert.That(result, Is.EqualTo(value).Using<NpgsqlRange<char[]>[]>((actual, expected) => actual[0].LowerBound!.SequenceEqual(expected[0].LowerBound!) && actual[0].UpperBound!.SequenceEqual(expected[0].UpperBound!))); } [Test] public async Task Unmapped_multirange_supported_only_with_EnableUnmappedTypes() { await using var connection = await DataSource.OpenConnectionAsync(); var rangeType = await GetTempTypeName(connection); var multirangeTypeName = rangeType + "_multirange"; await connection.ExecuteNonQueryAsync($"CREATE TYPE {rangeType} AS RANGE(subtype=text)"); await connection.ReloadTypesAsync(); var errorMessage = string.Format( NpgsqlStrings.UnmappedRangesNotEnabled, nameof(NpgsqlSlimDataSourceBuilder.EnableUnmappedTypes), nameof(NpgsqlDataSourceBuilder)); var exception = await AssertTypeUnsupportedWrite( new NpgsqlRange<string>[] { new("bar", "foo"), new("moo", "zoo"), }, multirangeTypeName); Assert.That(exception.InnerException, Is.InstanceOf<NotSupportedException>()); Assert.That(exception.InnerException!.Message, Is.EqualTo(errorMessage)); exception = await AssertTypeUnsupportedRead<object>("""{["bar","foo"],["moo","zoo"]}""", multirangeTypeName); Assert.That(exception.InnerException, Is.InstanceOf<NotSupportedException>()); Assert.That(exception.InnerException!.Message, Is.EqualTo(errorMessage)); exception = await AssertTypeUnsupportedRead<NpgsqlRange<string>>( """{["bar","foo"],["moo","zoo"]}""", multirangeTypeName); Assert.That(exception.InnerException, Is.InstanceOf<NotSupportedException>()); Assert.That(exception.InnerException!.Message, Is.EqualTo(errorMessage)); } protected override NpgsqlDataSource DataSource { get; } public MultirangeTests() => DataSource = CreateDataSource(builder => { builder.ConnectionStringBuilder.Timezone = "Europe/Berlin"; }); [OneTimeSetUp] public async Task Setup() { await using var conn = await OpenConnectionAsync(); MinimumPgVersion(conn, "14.0", "Multirange types were introduced in PostgreSQL 14"); } [OneTimeTearDown] public void TearDown() => DataSource.Dispose(); }