66using System . Diagnostics ;
77using System . Text ;
88using System . Threading . Tasks ;
9- using Npgsql . Internal ;
109using Npgsql . Internal . Converters ;
11- using Npgsql . Internal . Postgres ;
1210using NpgsqlTypes ;
1311using NUnit . Framework ;
1412using static Npgsql . Tests . TestUtil ;
@@ -503,30 +501,6 @@ public async Task Generics_read_empty_multidim_array()
503501 Assert . That ( reader . GetFieldValue < int [ , ] > ( 0 ) . Length , Is . Zero ) ;
504502 }
505503
506- [ Test ]
507- public async Task Nullable_array_write_state_flows ( [ Values ] bool fixedSize )
508- {
509- // Verifies that provider-produced write state flows through IsDbNull and Write
510- // for nullable array elements, both fixed-size and variable-size.
511- var dataSourceBuilder = new NpgsqlSlimDataSourceBuilder ( ConnectionString ) ;
512- dataSourceBuilder . EnableArrays ( ) ;
513- dataSourceBuilder . AddTypeInfoResolverFactory ( new WriteStateTrackingResolverFactory ( fixedSize ) ) ;
514- await using var dataSource = dataSourceBuilder . Build ( ) ;
515- await using var conn = await dataSource . OpenConnectionAsync ( ) ;
516-
517- WriteStateTrackingConverter . Reset ( ) ;
518-
519- var input = new [ ] { 1 , 2 , 3 } ;
520-
521- await using var cmd = new NpgsqlCommand ( "SELECT @p" , conn ) ;
522- cmd . Parameters . Add ( new NpgsqlParameter < int [ ] > { ParameterName = "p" , TypedValue = input , DataTypeName = "integer[]" } ) ;
523- await cmd . ExecuteNonQueryAsync ( ) ;
524-
525- if ( fixedSize )
526- Assert . That ( WriteStateTrackingConverter . IsDbNullWriteStateReceived , Is . True , "IsDbNullValue did not receive write state" ) ;
527- Assert . That ( WriteStateTrackingConverter . WriteWriteStateReceived , Is . True , "Write did not receive write state" ) ;
528- }
529-
530504 [ Test ]
531505 public async Task Arrays_not_supported_by_default_on_NpgsqlSlimSourceBuilder ( )
532506 {
@@ -547,90 +521,3 @@ public async Task NpgsqlSlimSourceBuilder_EnableArrays()
547521 await AssertType ( dataSource , new [ ] { 1 , 2 , 3 } , "{1,2,3}" , "integer[]" ) ;
548522 }
549523}
550-
551- sealed class WriteStateTrackingConverter ( bool fixedSize ) : PgBufferedConverter < int > ( customDbNullPredicate : true )
552- {
553- internal static bool IsDbNullWriteStateReceived ;
554- internal static bool WriteWriteStateReceived ;
555-
556- internal static void Reset ( )
557- {
558- IsDbNullWriteStateReceived = false ;
559- WriteWriteStateReceived = false ;
560- }
561-
562- public override bool CanConvert ( DataFormat format , out BufferRequirements bufferRequirements )
563- {
564- bufferRequirements = fixedSize ? BufferRequirements . CreateFixedSize ( sizeof ( int ) ) : BufferRequirements . Create ( Size . CreateUpperBound ( sizeof ( int ) ) ) ;
565- return format is DataFormat . Binary ;
566- }
567-
568- protected override bool IsDbNullValue ( int value , object ? writeState )
569- {
570- if ( writeState is not null )
571- IsDbNullWriteStateReceived = true ;
572- return false ;
573- }
574-
575- protected override int ReadCore ( PgReader reader ) => reader . ReadInt32 ( ) ;
576-
577- protected override void WriteCore ( PgWriter writer , int value )
578- {
579- if ( writer . Current . WriteState is not null )
580- WriteWriteStateReceived = true ;
581- writer . WriteInt32 ( value ) ;
582- }
583-
584- public override Size GetSize ( SizeContext context , int value , ref object ? writeState )
585- => sizeof ( int ) ;
586- }
587-
588- sealed class WriteStateTrackingProvider ( PgSerializerOptions options , bool fixedSize ) : PgConcreteTypeInfoProvider < int >
589- {
590- PgConcreteTypeInfo ? _concreteTypeInfo ;
591-
592- PgConcreteTypeInfo GetOrCreate ( )
593- => _concreteTypeInfo ??= new ( options , new WriteStateTrackingConverter ( fixedSize ) , options . GetCanonicalTypeId ( DataTypeNames . Int4 ) ) ;
594-
595- protected override PgConcreteTypeInfo GetDefaultCore ( PgTypeId ? pgTypeId ) => GetOrCreate ( ) ;
596-
597- protected override PgConcreteTypeInfo ? GetForValueCore ( ProviderValueContext context , int value , ref object ? writeState )
598- {
599- writeState = "provider-state" ;
600- return GetOrCreate ( ) ;
601- }
602- }
603-
604- sealed class WriteStateTrackingResolverFactory ( bool fixedSize ) : PgTypeInfoResolverFactory
605- {
606- public override IPgTypeInfoResolver CreateResolver ( ) => new Resolver ( fixedSize ) ;
607- public override IPgTypeInfoResolver CreateArrayResolver ( ) => new ArrayResolver ( ) ;
608-
609- sealed class Resolver ( bool fixedSize ) : IPgTypeInfoResolver
610- {
611- public PgTypeInfo ? GetTypeInfo ( Type ? type , DataTypeName ? dataTypeName , PgSerializerOptions options )
612- {
613- if ( dataTypeName == DataTypeNames . Int4 && ( type == typeof ( int ) || type is null ) )
614- return new PgProviderTypeInfo ( options , new WriteStateTrackingProvider ( options , fixedSize ) , DataTypeNames . Int4 ) ;
615-
616- return null ;
617- }
618- }
619-
620- sealed class ArrayResolver : IPgTypeInfoResolver
621- {
622- public PgTypeInfo ? GetTypeInfo ( Type ? type , DataTypeName ? dataTypeName , PgSerializerOptions options )
623- {
624- if ( dataTypeName != DataTypeNames . Int4 . ToArrayName ( ) )
625- return null ;
626-
627- var elementInfo = options . GetTypeInfo ( typeof ( int ) , DataTypeNames . Int4 ) ;
628- if ( elementInfo is not PgProviderTypeInfo providerTypeInfo )
629- return null ;
630-
631- return new PgProviderTypeInfo ( options ,
632- new ArrayTypeInfoProvider < int [ ] , int > ( providerTypeInfo , typeof ( int [ ] ) ) ,
633- dataTypeName ) ;
634- }
635- }
636- }
0 commit comments