1+ using System . Data ;
12using Xunit ;
23using Ydb . Sdk . Ado . Tests . Utils ;
4+ using Ydb . Sdk . Ado . YdbType ;
35
46namespace Ydb . Sdk . Ado . Tests ;
57
68public abstract class TestBase : IAsyncLifetime
79{
810 protected static string ConnectionString => TestUtils . ConnectionString ;
911
12+ protected static readonly string [ ] IdNameColumns = [ "Id" , "Name" ] ;
13+
1014 protected static YdbConnection CreateConnection ( ) => new (
1115 new YdbConnectionStringBuilder ( ConnectionString ) { LoggerFactory = TestUtils . LoggerFactory }
1216 ) ;
@@ -25,6 +29,200 @@ protected static async Task<YdbConnection> CreateOpenConnectionAsync()
2529 return connection ;
2630 }
2731
32+ private static string CreateIdNameTableSql ( string table , string idType = "Int32" , bool nameNullable = false ) => $ """
33+ CREATE TABLE { table } (
34+ Id { idType } ,
35+ Name Text{ ( nameNullable ? "?" : "" ) } ,
36+ PRIMARY KEY (Id)
37+ )
38+ """ ;
39+
40+ private static string CreateAllTypesTableSql ( string table ) => @$ "
41+ CREATE TABLE { table } (
42+ id INT32,
43+ bool_column BOOL,
44+ bigint_column INT64,
45+ smallint_column INT16,
46+ tinyint_column INT8,
47+ float_column FLOAT,
48+ double_column DOUBLE,
49+ decimal_column DECIMAL(22,9),
50+ uint8_column UINT8,
51+ uint16_column UINT16,
52+ uint32_column UINT32,
53+ uint64_column UINT64,
54+ text_column TEXT,
55+ binary_column BYTES,
56+ json_column JSON,
57+ jsondocument_column JSONDOCUMENT,
58+ date_column DATE,
59+ datetime_column DATETIME,
60+ timestamp_column TIMESTAMP,
61+ interval_column INTERVAL,
62+ PRIMARY KEY (id)
63+ )
64+ " ;
65+
66+ private static async Task UsingTempTableCoreAsync (
67+ YdbConnection conn ,
68+ Func < string , string > createSqlFactory ,
69+ Func < YdbConnection , string , Task > body ,
70+ Func < string , string > ? dropSqlFactory = null )
71+ {
72+ var table = $ "tmp_{ Guid . NewGuid ( ) : N} ";
73+
74+ await using ( var create = conn . CreateCommand ( ) )
75+ {
76+ create . CommandText = createSqlFactory ( table ) ;
77+ await create . ExecuteNonQueryAsync ( ) ;
78+ }
79+
80+ try
81+ {
82+ await body ( conn , table ) ;
83+ }
84+ finally
85+ {
86+ await using var drop = conn . CreateCommand ( ) ;
87+ drop . CommandText = ( dropSqlFactory ?? ( t => $ "DROP TABLE { t } ") ) ( table ) ;
88+ try { await drop . ExecuteNonQueryAsync ( ) ; } catch { /* ignore */ }
89+ }
90+ }
91+
92+ private static async Task UsingTempTableAsync (
93+ Func < string , string > createSqlFactory ,
94+ Func < YdbConnection , string , Task > body ,
95+ Func < string , string > ? dropSqlFactory = null )
96+ {
97+ await using var conn = await CreateOpenConnectionAsync ( ) ;
98+ await UsingTempTableCoreAsync ( conn , createSqlFactory , body , dropSqlFactory ) ;
99+ }
100+
101+ protected static Task WithIdNameTableAsync (
102+ Func < YdbConnection , string , Task > body ,
103+ string idType = "Int32" ,
104+ bool nameNullable = false ) =>
105+ UsingTempTableAsync ( t => CreateIdNameTableSql ( t , idType , nameNullable ) , body ) ;
106+
107+ protected static Task WithAllTypesTableAsync ( Func < YdbConnection , string , Task > body ) =>
108+ UsingTempTableAsync ( CreateAllTypesTableSql , body ) ;
109+
110+ private static async Task UsingTempTablesCoreAsync (
111+ YdbConnection conn ,
112+ int count ,
113+ Func < string [ ] , string [ ] > createSqlsFactory ,
114+ Func < YdbConnection , string [ ] , Task > body ,
115+ Func < string [ ] , string [ ] > ? dropSqlsFactory = null )
116+ {
117+ var names = Enumerable . Range ( 0 , count ) . Select ( _ => $ "tmp_{ Guid . NewGuid ( ) : N} ") . ToArray ( ) ;
118+
119+ foreach ( var sql in createSqlsFactory ( names ) )
120+ {
121+ await using var cmd = conn . CreateCommand ( ) ;
122+ cmd . CommandText = sql ;
123+ await cmd . ExecuteNonQueryAsync ( ) ;
124+ }
125+
126+ try
127+ {
128+ await body ( conn , names ) ;
129+ }
130+ finally
131+ {
132+ var drops = ( dropSqlsFactory ?? ( ts => ts . Select ( t => $ "DROP TABLE { t } ") . ToArray ( ) ) ) ( names ) ;
133+ foreach ( var sql in drops )
134+ {
135+ await using var cmd = conn . CreateCommand ( ) ;
136+ cmd . CommandText = sql ;
137+ try { await cmd . ExecuteNonQueryAsync ( ) ; } catch { /* ignore */ }
138+ }
139+ }
140+ }
141+
142+ private static async Task UsingTempTablesAsync (
143+ int count ,
144+ Func < string [ ] , string [ ] > createSqlsFactory ,
145+ Func < YdbConnection , string [ ] , Task > body ,
146+ Func < string [ ] , string [ ] > ? dropSqlsFactory = null )
147+ {
148+ await using var conn = await CreateOpenConnectionAsync ( ) ;
149+ await UsingTempTablesCoreAsync ( conn , count , createSqlsFactory , body , dropSqlsFactory ) ;
150+ }
151+
152+ protected static Task WithTwoIdNameTablesAsync (
153+ Func < YdbConnection , string [ ] , Task > body ,
154+ string idType = "Int32" ,
155+ bool nameNullable = false ) =>
156+ UsingTempTablesAsync (
157+ 2 ,
158+ tables => tables . Select ( t => CreateIdNameTableSql ( t , idType , nameNullable ) ) . ToArray ( ) ,
159+ body
160+ ) ;
161+
162+ protected static async Task < int > CountAsync ( YdbConnection c , string table )
163+ {
164+ await using var cmd = c . CreateCommand ( ) ;
165+ cmd . CommandText = $ "SELECT COUNT(*) FROM { table } ";
166+ return Convert . ToInt32 ( await cmd . ExecuteScalarAsync ( ) ) ;
167+ }
168+
169+ protected static async Task < List < string > > ReadNamesAsync ( YdbConnection c , string table )
170+ {
171+ var names = new List < string > ( ) ;
172+ await using var cmd = c . CreateCommand ( ) ;
173+ cmd . CommandText = $ "SELECT Name FROM { table } ORDER BY Id";
174+ await using var r = await cmd . ExecuteReaderAsync ( ) ;
175+ while ( await r . ReadAsync ( ) ) names . Add ( r . GetString ( 0 ) ) ;
176+ return names ;
177+ }
178+
179+ protected static async Task ImportAsync ( YdbConnection c , string table , params object [ ] [ ] rows )
180+ {
181+ var importer = c . BeginBulkUpsertImport ( table , IdNameColumns ) ;
182+ foreach ( var row in rows ) await importer . AddRowAsync ( row ) ;
183+ await importer . FlushAsync ( ) ;
184+ }
185+
186+ protected static async Task ImportRangeAsync ( YdbConnection c , string table , int n , string prefix )
187+ {
188+ var importer = c . BeginBulkUpsertImport ( table , IdNameColumns ) ;
189+ foreach ( var row in Enumerable . Range ( 0 , n ) . Select ( i => new object [ ] { i , $ "{ prefix } { i } " } ) )
190+ await importer . AddRowAsync ( row ) ;
191+ await importer . FlushAsync ( ) ;
192+ }
193+
194+ protected static void PrepareAllTypesInsert ( YdbCommand cmd , string table )
195+ {
196+ cmd . CommandText = @$ "
197+ INSERT INTO { table }
198+ (id, bool_column, bigint_column, smallint_column, tinyint_column, float_column, double_column, decimal_column,
199+ uint8_column, uint16_column, uint32_column, uint64_column, text_column, binary_column, json_column,
200+ jsondocument_column, date_column, datetime_column, timestamp_column, interval_column) VALUES
201+ (@name1, @name2, @name3, @name4, @name5, @name6, @name7, @name8, @name9, @name10, @name11, @name12, @name13, @name14,
202+ @name15, @name16, @name17, @name18, @name19, @name20);
203+ " ;
204+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name1" , DbType = DbType . Int32 , Value = null } ) ;
205+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name2" , DbType = DbType . Boolean , Value = null } ) ;
206+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name3" , DbType = DbType . Int64 , Value = null } ) ;
207+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name4" , DbType = DbType . Int16 , Value = null } ) ;
208+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name5" , DbType = DbType . SByte , Value = null } ) ;
209+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name6" , DbType = DbType . Single , Value = null } ) ;
210+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name7" , DbType = DbType . Double , Value = null } ) ;
211+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name8" , DbType = DbType . Decimal , Value = null } ) ;
212+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name9" , DbType = DbType . Byte , Value = null } ) ;
213+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name10" , DbType = DbType . UInt16 , Value = null } ) ;
214+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name11" , DbType = DbType . UInt32 , Value = null } ) ;
215+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name12" , DbType = DbType . UInt64 , Value = null } ) ;
216+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name13" , DbType = DbType . String , Value = null } ) ;
217+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name14" , DbType = DbType . Binary , Value = null } ) ;
218+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name15" , YdbDbType = YdbDbType . Json } ) ;
219+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name16" , YdbDbType = YdbDbType . JsonDocument } ) ;
220+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name17" , DbType = DbType . Date , Value = null } ) ;
221+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name18" , DbType = DbType . DateTime , Value = null } ) ;
222+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name19" , DbType = DbType . DateTime2 , Value = null } ) ;
223+ cmd . Parameters . Add ( new YdbParameter { ParameterName = "name20" , YdbDbType = YdbDbType . Interval } ) ;
224+ }
225+
28226 public async Task InitializeAsync ( ) => await OnInitializeAsync ( ) . ConfigureAwait ( false ) ;
29227
30228 public async Task DisposeAsync ( ) => await OnDisposeAsync ( ) . ConfigureAwait ( false ) ;
0 commit comments