1+ using System ;
2+ using System . Linq ;
3+ using System . Collections . Generic ;
4+ using System . Threading . Tasks ;
5+ using System . Text . Json ;
6+ using MySql . Data . MySqlClient ;
7+ using SciSharp . MySQL . Replication ;
8+ using SciSharp . MySQL . Replication . Events ;
9+ using Xunit ;
10+ using Xunit . Abstractions ;
11+ using Microsoft . Extensions . Logging ;
12+ using Microsoft . Extensions . Logging . Console ;
13+ using System . Collections ;
14+ using System . Data ;
15+ using System . Globalization ;
16+
17+ namespace Test
18+ {
19+ [ Trait ( "Category" , "DataTypes" ) ]
20+ public class DataTypesTest : IClassFixture < MySQLFixture >
21+ {
22+ protected readonly MySQLFixture _mysqlFixture ;
23+
24+ public DataTypesTest ( MySQLFixture mysqlFixture )
25+ {
26+ _mysqlFixture = mysqlFixture ;
27+ }
28+
29+ [ Fact ]
30+ public async Task TestDateTimeType ( )
31+ {
32+ var currentValue = DateTime . Now ;
33+ currentValue = new DateTime ( currentValue . Year , currentValue . Month , currentValue . Day , currentValue . Hour , currentValue . Minute , currentValue . Second ) ;
34+
35+ await TestDataType < DateTime > ( "datetime_table" , currentValue , currentValue . AddDays ( 1 ) , ( reader , index ) =>
36+ {
37+ return reader . GetDateTime ( index ) ;
38+ } ) ;
39+ }
40+
41+ [ Fact ]
42+ public async Task TestIntType ( )
43+ {
44+ var currentValue = 42 ;
45+ await TestDataType < int > ( "int_table" , currentValue , currentValue + 10 , ( reader , index ) =>
46+ {
47+ return reader . GetInt32 ( index ) ;
48+ } ) ;
49+ }
50+
51+ //[Fact]
52+ public async Task TestBigIntType ( )
53+ {
54+ var currentValue = 9223372036854775800L ;
55+ await TestDataType < long > ( "bigint_table" , currentValue , currentValue - 10 , ( reader , index ) =>
56+ {
57+ return reader . GetInt64 ( index ) ;
58+ } ) ;
59+ }
60+
61+ [ Fact ]
62+ public async Task TestTinyIntType ( )
63+ {
64+ var currentValue = ( sbyte ) 42 ;
65+ await TestDataType < sbyte > ( "tinyint_table" , currentValue , ( sbyte ) ( currentValue + 10 ) , ( reader , index ) =>
66+ {
67+ return ( sbyte ) reader . GetByte ( index ) ;
68+ } ) ;
69+ }
70+
71+ [ Fact ]
72+ public async Task TestSmallIntType ( )
73+ {
74+ var currentValue = ( short ) 1000 ;
75+ await TestDataType < short > ( "smallint_table" , currentValue , ( short ) ( currentValue + 10 ) , ( reader , index ) =>
76+ {
77+ return reader . GetInt16 ( index ) ;
78+ } ) ;
79+ }
80+
81+ [ Fact ]
82+ public async Task TestMediumIntType ( )
83+ {
84+ var currentValue = 8388000 ; // Close to 2^23 limit for MEDIUMINT
85+ await TestDataType < int > ( "mediumint_table" , currentValue , currentValue + 10 , ( reader , index ) =>
86+ {
87+ return reader . GetInt32 ( index ) ;
88+ } ) ;
89+ }
90+
91+ //[Fact]
92+ public async Task TestVarCharType ( )
93+ {
94+ var currentValue = "Hello World" ;
95+ await TestDataType < string > ( "varchar_table" , currentValue , currentValue + " Updated" , ( reader , index ) =>
96+ {
97+ return reader . GetString ( index ) ;
98+ } ) ;
99+ }
100+
101+ //[Fact]
102+ public async Task TestDecimalType ( )
103+ {
104+ var currentValue = 123.45m ;
105+ await TestDataType < decimal > ( "decimal_table" , currentValue , currentValue + 10.55m , ( reader , index ) =>
106+ {
107+ return reader . GetDecimal ( index ) ;
108+ } ) ;
109+ }
110+
111+ [ Fact ]
112+ public async Task TestFloatType ( )
113+ {
114+ var currentValue = 123.45f ;
115+ await TestDataType < float > ( "float_table" , currentValue , currentValue + 10.55f , ( reader , index ) =>
116+ {
117+ return reader . GetFloat ( index ) ;
118+ } ) ;
119+ }
120+
121+ //[Fact]
122+ public async Task TestDoubleType ( )
123+ {
124+ var currentValue = 123456.789012 ;
125+ await TestDataType < double > ( "double_table" , currentValue , currentValue + 100.123 , ( reader , index ) =>
126+ {
127+ return reader . GetDouble ( index ) ;
128+ } ) ;
129+ }
130+
131+ [ Fact ]
132+ public async Task TestDateType ( )
133+ {
134+ var currentValue = DateTime . Today ;
135+ await TestDataType < DateTime > ( "date_table" , currentValue , currentValue . AddDays ( 5 ) , ( reader , index ) =>
136+ {
137+ return reader . GetDateTime ( index ) . Date ;
138+ } ) ;
139+ }
140+
141+ //[Fact]
142+ public async Task TestTimeType ( )
143+ {
144+ var currentValue = new TimeSpan ( 10 , 30 , 45 ) ;
145+ await TestDataType < TimeSpan > ( "time_table" , currentValue , currentValue . Add ( new TimeSpan ( 1 , 15 , 30 ) ) , ( reader , index ) =>
146+ {
147+ return reader . GetTimeSpan ( index ) ;
148+ } ) ;
149+ }
150+
151+ //[Fact]
152+ public async Task TestTimestampType ( )
153+ {
154+ var currentValue = DateTime . UtcNow ;
155+ currentValue = new DateTime ( currentValue . Year , currentValue . Month , currentValue . Day , currentValue . Hour , currentValue . Minute , currentValue . Second , DateTimeKind . Utc ) ;
156+
157+ await TestDataType < DateTime > ( "timestamp_table" , currentValue , currentValue . AddHours ( 1 ) , ( reader , index ) =>
158+ {
159+ return DateTime . SpecifyKind ( reader . GetDateTime ( index ) , DateTimeKind . Utc ) ;
160+ } ) ;
161+ }
162+
163+ //[Fact]
164+ public async Task TestBlobType ( )
165+ {
166+ var currentValue = new byte [ ] { 0x01 , 0x02 , 0x03 , 0x04 , 0x05 } ;
167+ var updateValue = new byte [ ] { 0x06 , 0x07 , 0x08 , 0x09 , 0x0A } ;
168+
169+ await TestDataType < byte [ ] > ( "blob_table" , currentValue , updateValue , ( reader , index ) =>
170+ {
171+ var length = ( int ) reader . GetBytes ( index , 0 , null , 0 , 0 ) ;
172+ var buffer = new byte [ length ] ;
173+ reader . GetBytes ( index , 0 , buffer , 0 , length ) ;
174+ return buffer ;
175+ } ) ;
176+ }
177+
178+ //[Fact]
179+ public async Task TestEnumType ( )
180+ {
181+ var currentValue = "SMALL" ;
182+ await TestDataType < string > ( "enum_table" , currentValue , "MEDIUM" , ( reader , index ) =>
183+ {
184+ return reader . GetString ( index ) ;
185+ } ) ;
186+ }
187+
188+ //[Fact]
189+ public async Task TestSetType ( )
190+ {
191+ var currentValue = "RED,GREEN" ;
192+ await TestDataType < string > ( "set_table" , currentValue , "RED,BLUE" , ( reader , index ) =>
193+ {
194+ return reader . GetString ( index ) ;
195+ } ) ;
196+ }
197+
198+ //[Fact]
199+ public async Task TestJsonType ( )
200+ {
201+ var currentValue = @"{""name"": ""John"", ""age"": 30}" ;
202+ var updateValue = @"{""name"": ""Jane"", ""age"": 25, ""city"": ""New York""}" ;
203+
204+ await TestDataType < string > ( "json_table" , currentValue , updateValue , ( reader , index ) =>
205+ {
206+ return reader . GetString ( index ) ;
207+ } ) ;
208+ }
209+
210+ //[Fact]
211+ public async Task TestYearType ( )
212+ {
213+ var currentValue = 2023 ;
214+ await TestDataType < int > ( "year_table" , currentValue , 2024 , ( reader , index ) =>
215+ {
216+ return reader . GetInt16 ( index ) ;
217+ } ) ;
218+ }
219+
220+ private async Task TestDataType < TDateType > ( string tableName , TDateType currentValue , TDateType updateValue , Func < MySqlDataReader , int , TDateType > dataReader )
221+ {
222+ // Insert a new row into the table
223+ var command = _mysqlFixture . CreateCommand ( ) ;
224+ command . CommandText = $ "insert into { tableName } (value) values (@value);SELECT LAST_INSERT_ID();";
225+ command . Parameters . AddWithValue ( "@value" , currentValue ) ;
226+ var id = ( Int32 ) ( UInt64 ) await command . ExecuteScalarAsync ( ) ;
227+
228+ // Validate the WriteRowsEvent
229+ var writeRowsEvent = await _mysqlFixture . ReceiveAsync < WriteRowsEvent > ( ) ;
230+
231+ Assert . Equal ( 1 , writeRowsEvent . RowSet . Rows . Count ) ;
232+ Assert . Equal ( "id" , writeRowsEvent . RowSet . ColumnNames [ 0 ] ) ;
233+ Assert . Equal ( "value" , writeRowsEvent . RowSet . ColumnNames [ 1 ] ) ;
234+ var idFromClient = writeRowsEvent . RowSet . Rows [ 0 ] [ 0 ] ;
235+ var valueFromClient = writeRowsEvent . RowSet . Rows [ 0 ] [ 1 ] ;
236+ Assert . Equal ( id , ( Int32 ) idFromClient ) ;
237+ Assert . NotNull ( valueFromClient ) ;
238+ Assert . Equal ( currentValue , ( TDateType ) valueFromClient ) ;
239+
240+ // Validate the data in the database with query
241+ command = _mysqlFixture . CreateCommand ( ) ;
242+ command . CommandText = $ "select value from { tableName } where id = @id";
243+ command . Parameters . AddWithValue ( "@id" , id ) ;
244+
245+ MySqlDataReader reader = await command . ExecuteReaderAsync ( ) as MySqlDataReader ;
246+
247+ Assert . True ( await reader . ReadAsync ( ) ) ;
248+
249+ var savedValue = dataReader ( reader , 0 ) ;
250+ await reader . CloseAsync ( ) ;
251+
252+ Assert . Equal ( currentValue , savedValue ) ;
253+
254+ // Update the row
255+ command = _mysqlFixture . CreateCommand ( ) ;
256+ command . CommandText = $ "update { tableName } set value=@value where id = @id";
257+ command . Parameters . AddWithValue ( "@id" , id ) ;
258+ command . Parameters . AddWithValue ( "@value" , updateValue ) ;
259+
260+ Assert . Equal ( 1 , await command . ExecuteNonQueryAsync ( ) ) ;
261+
262+ // Validate the UpdateRowsEvent
263+ var updateRowsEvent = await _mysqlFixture . ReceiveAsync < UpdateRowsEvent > ( ) ;
264+ Assert . Equal ( 1 , updateRowsEvent . RowSet . Rows . Count ) ;
265+ Assert . Equal ( "id" , updateRowsEvent . RowSet . ColumnNames [ 0 ] ) ;
266+ Assert . Equal ( "value" , updateRowsEvent . RowSet . ColumnNames [ 1 ] ) ;
267+ var idCellValue = updateRowsEvent . RowSet . Rows [ 0 ] [ 0 ] as CellValue ;
268+ var valueCellValue = updateRowsEvent . RowSet . Rows [ 0 ] [ 1 ] as CellValue ;
269+ Assert . NotNull ( idCellValue ) ;
270+ Assert . Equal ( id , ( Int32 ) idCellValue . NewValue ) ;
271+ Assert . Equal ( id , ( Int32 ) idCellValue . OldValue ) ;
272+ Assert . NotNull ( valueCellValue ) ;
273+ Assert . Equal ( currentValue , valueCellValue . OldValue ) ;
274+ Assert . Equal ( updateValue , valueCellValue . NewValue ) ;
275+
276+ // Delete the row
277+ command = _mysqlFixture . CreateCommand ( ) ;
278+ command . CommandText = $ "delete from { tableName } where id = @id";
279+ command . Parameters . AddWithValue ( "@id" , id ) ;
280+
281+ await command . ExecuteNonQueryAsync ( ) ;
282+
283+ // Validate the DeleteRowsEvent
284+ var deleteRowsEvent = await _mysqlFixture . ReceiveAsync < DeleteRowsEvent > ( ) ;
285+ Assert . Equal ( 1 , deleteRowsEvent . RowSet . Rows . Count ) ;
286+ Assert . Equal ( "id" , deleteRowsEvent . RowSet . ColumnNames [ 0 ] ) ;
287+ Assert . Equal ( "value" , deleteRowsEvent . RowSet . ColumnNames [ 1 ] ) ;
288+ idFromClient = deleteRowsEvent . RowSet . Rows [ 0 ] [ 0 ] ;
289+ valueFromClient = deleteRowsEvent . RowSet . Rows [ 0 ] [ 1 ] ;
290+ Assert . Equal ( id , ( Int32 ) idFromClient ) ;
291+ Assert . NotNull ( valueFromClient ) ;
292+ Assert . Equal ( updateValue , ( TDateType ) valueFromClient ) ;
293+ }
294+ }
295+ }
0 commit comments