22
33namespace Ydb . Sdk . Ado . BulkUpsert ;
44
5- public sealed class YdbBulkUpsertProtoImporter : IAsyncDisposable
5+ public sealed class BulkUpsertImporter : IBulkUpsertImporter
66{
77 private readonly YdbConnection _connection ;
88 private readonly string _tablePath ;
99 private readonly List < string > _columns ;
1010 private readonly List < Type > _types ;
1111 private readonly int _maxBytes ;
12-
1312 private readonly List < Ydb . Value > _rows = new ( ) ;
1413 private bool _disposed ;
1514
16- public YdbBulkUpsertProtoImporter (
15+ public BulkUpsertImporter (
1716 YdbConnection connection ,
1817 string tablePath ,
1918 IReadOnlyList < string > columns ,
@@ -22,15 +21,14 @@ public YdbBulkUpsertProtoImporter(
2221 {
2322 _connection = connection ;
2423 _tablePath = tablePath ;
25- _columns = columns is List < string > colList ? colList : new List < string > ( columns ) ;
26- _types = types is List < Type > typList ? typList : new List < Type > ( types ) ;
24+ _columns = columns . ToList ( ) ;
25+ _types = types . ToList ( ) ;
2726 _maxBytes = maxBytes ;
2827 }
2928
3029 public async ValueTask AddRowAsync ( params YdbValue [ ] values )
3130 {
3231 ThrowIfDisposed ( ) ;
33-
3432 if ( values . Length != _columns . Count )
3533 throw new ArgumentException ( "Values count must match columns count" , nameof ( values ) ) ;
3634
@@ -41,76 +39,88 @@ public async ValueTask AddRowAsync(params YdbValue[] values)
4139 _rows . Add ( structValue ) ;
4240
4341 var totalSize = _rows . Sum ( r => r . CalculateSize ( ) ) ;
44-
4542 if ( totalSize >= _maxBytes )
4643 await FlushAsync ( ) ;
4744 }
4845
49- public async ValueTask AddRowsAsync ( IEnumerable < YdbValue [ ] > rows , CancellationToken cancellationToken = default )
46+ public async ValueTask AddRowAsync ( params object ? [ ] values )
5047 {
5148 ThrowIfDisposed ( ) ;
49+ if ( values . Length != _columns . Count )
50+ throw new ArgumentException ( "Values count must match columns count" , nameof ( values ) ) ;
5251
53- foreach ( var values in rows )
52+ var ydbValues = new YdbValue [ values . Length ] ;
53+ for ( int i = 0 ; i < values . Length ; i ++ )
5454 {
55- if ( values . Length != _columns . Count )
56- throw new ArgumentException ( "Values count must match columns count" , nameof ( values ) ) ;
57-
58- var dict = _columns . Zip ( values , ( name , value ) => new KeyValuePair < string , YdbValue > ( name , value ) )
59- . ToDictionary ( x => x . Key , x => x . Value ) ;
60-
61- var structValue = YdbValue . MakeStruct ( dict ) . GetProto ( ) . Value ;
62- _rows . Add ( structValue ) ;
55+ ydbValues [ i ] = YdbValueFromObject ( values [ i ] , _types [ i ] ) ;
56+ }
57+ await AddRowAsync ( ydbValues ) ;
58+ }
6359
64- var totalSize = _rows . Sum ( r => r . CalculateSize ( ) ) ;
60+ public async ValueTask AddRowsAsync ( IEnumerable < YdbValue [ ] > rows , CancellationToken cancellationToken = default )
61+ {
62+ ThrowIfDisposed ( ) ;
6563
66- if ( totalSize >= _maxBytes )
67- await FlushAsync ( cancellationToken ) ;
68- }
64+ foreach ( var values in rows )
65+ await AddRowAsync ( values ) ;
6966 }
7067
71- public async ValueTask DisposeAsync ( )
68+ public async ValueTask AddRowsAsync ( IEnumerable < object ? [ ] > rows , CancellationToken cancellationToken = default )
7269 {
73- if ( _disposed ) return ;
74- await FlushAsync ( ) ;
75- _disposed = true ;
70+ ThrowIfDisposed ( ) ;
71+
72+ foreach ( var values in rows )
73+ await AddRowAsync ( values ) ;
7674 }
7775
7876 public async ValueTask FlushAsync ( CancellationToken cancellationToken = default )
7977 {
8078 ThrowIfDisposed ( ) ;
79+ if ( _rows . Count == 0 ) return ;
8180
82- if ( _rows . Count == 0 )
83- return ;
81+ await _connection . BulkUpsertProtoAsync ( _tablePath , GetStructType ( ) , _rows . ToList ( ) , cancellationToken ) ;
82+ _rows . Clear ( ) ;
83+ }
8484
85- await _connection . BulkUpsertProtoAsync (
86- _tablePath ,
87- GetStructType ( ) ,
88- new List < Ydb . Value > ( _rows ) ,
89- cancellationToken ) ;
85+ public IReadOnlyList < Ydb . Value > GetBufferedRows ( ) => _rows ;
9086
91- _rows . Clear ( ) ;
87+ public async ValueTask DisposeAsync ( )
88+ {
89+ if ( _disposed ) return ;
90+ await FlushAsync ( ) ;
91+ _disposed = true ;
9292 }
9393
9494 private Type GetStructType ( )
9595 {
9696 var structType = new Type { StructType = new StructType ( ) } ;
9797 for ( var i = 0 ; i < _columns . Count ; i ++ )
98- {
99- structType . StructType . Members . Add ( new StructMember
100- {
101- Name = _columns [ i ] ,
102- Type = _types [ i ]
103- } ) ;
104- }
105-
98+ structType . StructType . Members . Add ( new StructMember { Name = _columns [ i ] , Type = _types [ i ] } ) ;
10699 return structType ;
107100 }
108101
109102 private void ThrowIfDisposed ( )
110103 {
111104 if ( _disposed )
112- throw new ObjectDisposedException ( nameof ( YdbBulkUpsertProtoImporter ) ) ;
105+ throw new ObjectDisposedException ( nameof ( BulkUpsertImporter ) ) ;
113106 }
114107
115- public IReadOnlyList < Ydb . Value > GetBufferedRows ( ) => _rows ;
116- }
108+ private static YdbValue YdbValueFromObject ( object ? value , Type columnType )
109+ {
110+ switch ( value )
111+ {
112+ case YdbValue ydbValue :
113+ return ydbValue ;
114+ default :
115+ switch ( columnType . TypeId )
116+ {
117+ case Type . Types . PrimitiveTypeId . Int32 :
118+ return YdbValue . MakeInt32 ( Convert . ToInt32 ( value ) ) ;
119+ case Type . Types . PrimitiveTypeId . Utf8 :
120+ return YdbValue . MakeUtf8 ( value ? . ToString ( ) ! ) ;
121+ default :
122+ throw new NotSupportedException ( $ "Type '{ columnType . TypeId } ' not supported in YdbValueFromObject") ;
123+ }
124+ }
125+ }
126+ }
0 commit comments