@@ -150,123 +150,136 @@ public async Task Date_WhenSetDateOnly_ReturnDateTime()
150150 [ InlineData ( "54321" , "54321" , 5 , 0 ) ]
151151 [ InlineData ( "493235.4" , "493235.40" , 8 , 2 ) ]
152152 [ InlineData ( "123.46" , "123.46" , 5 , 2 ) ]
153+ [ InlineData ( "0.46" , "0.46" , 2 , 2 ) ]
153154 [ InlineData ( "-184467434073.70911616" , "-184467434073.7091161600" , 35 , 10 ) ]
154155 [ InlineData ( "-18446744074" , "-18446744074" , 12 , 0 ) ]
155156 [ InlineData ( "-184467440730709551616" , "-184467440730709551616" , 21 , 0 ) ]
156157 [ InlineData ( "-218446744073.709551616" , "-218446744073.7095516160" , 22 , 10 ) ]
158+ [ InlineData ( "79228162514264337593543950335" , "79228162514264337593543950335" , 29 , 0 ) ]
159+ [ InlineData ( "79228162514264337593543950.335" , "79228162514264337593543950.335" , 29 , 3 ) ]
160+ [ InlineData ( "-79228162514264337593543950335" , "-79228162514264337593543950335" , 29 , 0 ) ]
161+ [ InlineData ( "-79228162514264337593543950.335" , "-79228162514264337593543950.335" , 29 , 3 ) ]
157162 [ InlineData ( null , null , 22 , 9 ) ]
158163 [ InlineData ( null , null , 35 , 9 ) ]
159164 [ InlineData ( null , null , 35 , 0 ) ]
160165 public async Task Decimal_WhenDecimalIsScaleAndPrecision_ReturnDecimal ( string ? value , string ? expected ,
161166 byte precision , byte scale )
162167 {
163168 await using var ydbConnection = await CreateOpenConnectionAsync ( ) ;
164- var decimalTableName = $ "DecimalTable_{ Random . Shared . Next ( ) } ";
169+ var tableName = $ "DecimalTable_{ Random . Shared . Next ( ) } ";
165170 var decimalValue = value == null ? ( decimal ? ) null : decimal . Parse ( value , CultureInfo . InvariantCulture ) ;
166171 await new YdbCommand ( ydbConnection )
167- {
168- CommandText = $ """
169- CREATE TABLE { decimalTableName } (
170- DecimalField Decimal({ precision } , { scale } ),
171- PRIMARY KEY (DecimalField)
172- )
173- """
174- } . ExecuteNonQueryAsync ( ) ;
172+ { CommandText = $ "CREATE TABLE { tableName } (d Decimal({ precision } , { scale } ), PRIMARY KEY (d))" }
173+ . ExecuteNonQueryAsync ( ) ;
175174 await new YdbCommand ( ydbConnection )
176175 {
177- CommandText = $ "INSERT INTO { decimalTableName } (DecimalField ) VALUES (@DecimalField );",
176+ CommandText = $ "INSERT INTO { tableName } (d ) VALUES (@d );",
178177 Parameters =
179- {
180- new YdbParameter ( "DecimalField" , DbType . Decimal , decimalValue ) { Precision = precision , Scale = scale }
181- }
178+ { new YdbParameter ( "d" , DbType . Decimal , decimalValue ) { Precision = precision , Scale = scale } }
182179 } . ExecuteNonQueryAsync ( ) ;
183180
184181 Assert . Equal ( expected == null ? DBNull . Value : decimal . Parse ( expected , CultureInfo . InvariantCulture ) ,
185- await new YdbCommand ( ydbConnection ) { CommandText = $ "SELECT DecimalField FROM { decimalTableName } ;" }
182+ await new YdbCommand ( ydbConnection ) { CommandText = $ "SELECT DecimalField FROM { tableName } ;" }
186183 . ExecuteScalarAsync ( ) ) ;
187184
188- await new YdbCommand ( ydbConnection ) { CommandText = $ "DROP TABLE { decimalTableName } ;" } . ExecuteNonQueryAsync ( ) ;
185+ await new YdbCommand ( ydbConnection ) { CommandText = $ "DROP TABLE { tableName } ;" } . ExecuteNonQueryAsync ( ) ;
189186 }
190187
191- [ Fact ]
192- public async Task Decimal_WhenFractionalDigitsExceedScale_Throws ( )
193- {
194- await using var ydb = await CreateOpenConnectionAsync ( ) ;
195- var t = $ "T_{ Random . Shared . Next ( ) } ";
196- await new YdbCommand ( ydb ) { CommandText = $ "CREATE TABLE { t } (d Decimal(5,2), PRIMARY KEY(d))" }
197- . ExecuteNonQueryAsync ( ) ;
198-
199- var cmd = new YdbCommand ( ydb )
200- {
201- CommandText = $ "INSERT INTO { t } (d) VALUES (@d);",
202- Parameters = { new YdbParameter ( "d" , DbType . Decimal , 123.456m ) { Precision = 5 , Scale = 2 } }
203- } ;
204-
205- await Assert . ThrowsAsync < OverflowException > ( ( ) => cmd . ExecuteNonQueryAsync ( ) ) ;
206- }
207-
208- [ Fact ]
209- public async Task Decimal_WhenIntegerDigitsExceedPrecisionMinusScale_Throws ( )
188+ [ Theory ]
189+ [ InlineData ( "123.456" , 5 , 2 ) ]
190+ [ InlineData ( "1.46" , 2 , 2 ) ]
191+ [ InlineData ( "654321" , 5 , 0 ) ]
192+ [ InlineData ( "493235.4" , 7 , 2 ) ]
193+ [ InlineData ( "10.46" , 3 , 2 ) ]
194+ [ InlineData ( "99.999" , 5 , 2 ) ]
195+ [ InlineData ( "0.001" , 3 , 2 ) ]
196+ [ InlineData ( "-12.345" , 5 , 2 ) ]
197+ [ InlineData ( "7.001" , 4 , 2 ) ]
198+ [ InlineData ( "1.0001" , 5 , 3 ) ]
199+ [ InlineData ( "1000.00" , 5 , 2 ) ]
200+ [ InlineData ( "123456.7" , 6 , 1 ) ]
201+ [ InlineData ( "999.99" , 5 , 4 ) ]
202+ [ InlineData ( "-100" , 2 , 0 ) ]
203+ [ InlineData ( "-0.12" , 2 , 1 ) ]
204+ [ InlineData ( "10.0" , 2 , 0 ) ]
205+ [ InlineData ( "-0.1" , 1 , 0 ) ]
206+ [ InlineData ( "10000" , 4 , 0 ) ]
207+ [ InlineData ( "12345" , 4 , 0 ) ]
208+ [ InlineData ( "12.3456" , 6 , 3 ) ]
209+ [ InlineData ( "123.45" , 4 , 1 ) ]
210+ [ InlineData ( "9999.9" , 5 , 0 ) ]
211+ [ InlineData ( "-1234.56" , 5 , 1 ) ]
212+ [ InlineData ( "-1000" , 3 , 0 ) ]
213+ [ InlineData ( "0.0001" , 4 , 3 ) ]
214+ [ InlineData ( "99999" , 4 , 0 ) ]
215+ [ InlineData ( "9.999" , 3 , 2 ) ]
216+ [ InlineData ( "123.4" , 3 , 0 ) ]
217+ [ InlineData ( "1.234" , 4 , 2 ) ]
218+ [ InlineData ( "-98.765" , 5 , 2 ) ]
219+ [ InlineData ( "100.01" , 5 , 1 ) ]
220+ [ InlineData ( "100000" , 5 , 0 ) ]
221+ public async Task Decimal_WhenNotRepresentableBySystemDecimal_ThrowsOverflowException ( string value , byte precision ,
222+ byte scale )
210223 {
211- await using var ydb = await CreateOpenConnectionAsync ( ) ;
212- var t = $ "T_{ Random . Shared . Next ( ) } ";
213- await new YdbCommand ( ydb ) { CommandText = $ "CREATE TABLE { t } (d Decimal(5,0), PRIMARY KEY(d))" }
224+ await using var ydbConnection = await CreateOpenConnectionAsync ( ) ;
225+ var tableName = $ "DecimalOverflowTable__{ Random . Shared . Next ( ) } ";
226+ var decimalValue = decimal . Parse ( value , CultureInfo . InvariantCulture ) ;
227+ await new YdbCommand ( ydbConnection )
228+ { CommandText = $ "CREATE TABLE { tableName } (d Decimal(5,2), PRIMARY KEY(d))" }
214229 . ExecuteNonQueryAsync ( ) ;
215230
216- var cmd = new YdbCommand ( ydb )
217- {
218- CommandText = $ "INSERT INTO { t } (d) VALUES (@d);",
219- Parameters = { new YdbParameter ( "d" , DbType . Decimal , 100000m ) { Precision = 5 , Scale = 0 } }
220- } ;
221-
222- await Assert . ThrowsAsync < OverflowException > ( ( ) => cmd . ExecuteNonQueryAsync ( ) ) ;
231+ Assert . Equal ( $ "Value { decimalValue } does not fit Decimal({ precision } , { scale } )",
232+ ( await Assert . ThrowsAsync < OverflowException > ( ( ) => new YdbCommand ( ydbConnection )
233+ {
234+ CommandText = $ "INSERT INTO { tableName } (d) VALUES (@d);",
235+ Parameters =
236+ {
237+ new YdbParameter ( "d" , DbType . Decimal , 123.456m )
238+ { Value = decimalValue , Precision = precision , Scale = scale }
239+ }
240+ } . ExecuteNonQueryAsync ( ) ) ) . Message ) ;
241+
242+ Assert . Equal ( 0ul ,
243+ ( ulong ) ( await new YdbCommand ( ydbConnection ) { CommandText = $ "SELECT COUNT(*) FROM { tableName } ;" }
244+ . ExecuteScalarAsync ( ) ) !
245+ ) ;
246+
247+ await new YdbCommand ( ydbConnection ) { CommandText = $ "DROP TABLE { tableName } ;" } . ExecuteNonQueryAsync ( ) ;
223248 }
224249
225- [ Fact ]
226- public async Task Decimal_WhenScaleGreaterThanPrecision_ThrowsByMathNotByIf ( )
227- {
228- await using var ydb = await CreateOpenConnectionAsync ( ) ;
229- var t = $ "T_{ Random . Shared . Next ( ) } ";
230- await new YdbCommand ( ydb ) { CommandText = $ "CREATE TABLE { t } (d Decimal(5,4), PRIMARY KEY(d))" }
231- . ExecuteNonQueryAsync ( ) ;
232-
233- var cmd = new YdbCommand ( ydb )
234- {
235- CommandText = $ "INSERT INTO { t } (d) VALUES (@d);",
236- Parameters = { new YdbParameter ( "d" , DbType . Decimal , 0.0m ) { Precision = 1 , Scale = 2 } }
237- } ;
238-
239- await Assert . ThrowsAnyAsync < Exception > ( ( ) => cmd . ExecuteNonQueryAsync ( ) ) ;
240- }
241250
242251 [ Fact ]
243- public async Task Decimal_WhenYdbReturnsDecimal35_0_OverflowsDotNetDecimal ( )
244- {
245- await using var ydb = await CreateOpenConnectionAsync ( ) ;
246- var t = $ "T_{ Random . Shared . Next ( ) } ";
247- await new YdbCommand ( ydb ) { CommandText = $ "CREATE TABLE { t } (d Decimal(35,0), PRIMARY KEY(d))" }
248- . ExecuteNonQueryAsync ( ) ;
252+ public void Decimal_WhenScaleGreaterThanPrecision_ThrowsArgumentOutOfRangeException ( ) =>
253+ Assert . Throws < ArgumentOutOfRangeException > ( ( ) =>
254+ new YdbParameter ( "d" , DbType . Decimal , 0.0m ) { Precision = 1 , Scale = 2 } . TypedValue ) ;
249255
250- await new YdbCommand ( ydb )
251- {
252- CommandText = $@ "INSERT INTO { t } (d) VALUES (CAST('10000000000000000000000000000000000' AS Decimal(35,0)));"
253- } . ExecuteNonQueryAsync ( ) ;
254-
255- var select = new YdbCommand ( ydb ) { CommandText = $ "SELECT d FROM { t } ;" } ;
256-
257- await Assert . ThrowsAsync < OverflowException > ( ( ) => select . ExecuteScalarAsync ( ) ) ;
258- }
259-
260- [ Fact ]
261- public void Decimal_WhenEncodingP35_10_With25IntegerDigits_DoesNotOverflow ( )
256+ [ Theory ]
257+ [ InlineData ( "10000000000000000000000000000000000" , 35 , 0 ) ]
258+ [ InlineData ( "1000000000000000000000000.0000000000" , 35 , 10 ) ]
259+ [ InlineData ( "1000000000000000000000000000000000" , 34 , 0 ) ]
260+ [ InlineData ( "100000000000000000000000.0000000000" , 34 , 10 ) ]
261+ [ InlineData ( "100000000000000000000000000000000" , 33 , 0 ) ]
262+ [ InlineData ( "10000000000000000000000.0000000000" , 33 , 10 ) ]
263+ [ InlineData ( "-10000000000000000000000000000000" , 32 , 0 ) ]
264+ [ InlineData ( "-1000000000000000000000.0000000000" , 32 , 10 ) ]
265+ [ InlineData ( "-1000000000000000000000000000000" , 31 , 0 ) ]
266+ [ InlineData ( "-100000000000000000000.0000000000" , 31 , 10 ) ]
267+ [ InlineData ( "1000000000000000000000000000000" , 30 , 0 ) ]
268+ [ InlineData ( "100000000000000000000.0000000000" , 30 , 10 ) ]
269+ [ InlineData ( "79228162514264337593543950336" , 29 , 0 ) ]
270+ [ InlineData ( "79228162514264337593543950.336" , 29 , 3 ) ]
271+ [ InlineData ( "-79228162514264337593543950336" , 29 , 0 ) ]
272+ [ InlineData ( "-79228162514264337593543950.336" , 29 , 3 ) ]
273+ [ InlineData ( "100000" , 4 , 0 ) ] // inf
274+ public async Task Decimal_WhenYdbReturnsDecimalWithPrecisionGreaterThan28_ThrowsOverflowException ( string value ,
275+ int precision , int scale )
262276 {
263- var val = decimal . Parse ( "1234567890123456789012345" , CultureInfo . InvariantCulture ) ;
264- var param = new YdbParameter ( "d" , DbType . Decimal , val ) { Precision = 35 , Scale = 10 } ;
265-
266- var tv = param . TypedValue ;
267-
268- Assert . Equal ( ( byte ) 35 , tv . Type . DecimalType . Precision ) ;
269- Assert . Equal ( ( byte ) 10 , tv . Type . DecimalType . Scale ) ;
277+ await using var ydbConnection = await CreateOpenConnectionAsync ( ) ;
278+ Assert . Equal ( "Value does not fit into decimal" , ( await Assert . ThrowsAsync < OverflowException > ( ( ) =>
279+ new YdbCommand ( ydbConnection )
280+ { CommandText = $ "SELECT (CAST('{ value } ' AS Decimal({ precision } , { scale } )));" }
281+ . ExecuteScalarAsync ( ) )
282+ ) . Message ) ;
270283 }
271284
272285 [ Fact ]
0 commit comments