Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to store BigDecimal with negative scale in NUMERIC(19,6) column #3263

Closed
digulla opened this issue Dec 15, 2021 · 6 comments · Fixed by #3267
Closed

Unable to store BigDecimal with negative scale in NUMERIC(19,6) column #3263

digulla opened this issue Dec 15, 2021 · 6 comments · Fixed by #3267

Comments

@digulla
Copy link

digulla commented Dec 15, 2021

I have a BigDecimal with the value "3.81E+3". The internal state of the instance is:

arg0	BigDecimal  (id=319)	
	intCompact = 381	
	intVal = null	
	precision = 3	
	scale = -1	
	stringCache = "3.81E+3"

toPlainString() prints "3810".

When I try to store that into a NUMERIC(19,6) column, I get an exception with v2.0 of H2 because ValueNumeric was changed in katzyn@8bdb209#diff-2be2d3cabf9b48cf9d45ab2ca2c8f9fef25aaa172d4ed7d4ba39ddbc68a174f2 to check for negative scales.

I think this is a misconception how BigDecimal works in Java. From the documenation:

Returns the scale of this BigDecimal. If zeroor positive, the scale is the number of digits to the right ofthe decimal point. If negative, the unscaled value of thenumber is multiplied by ten to the power of the negation of thescale. For example, a scale of -3 means the unscaledvalue is multiplied by 1000.

Please remove the check and add a unit test: Try to store BigDecimal.ONE.scaleByPowerOfTen(3)

@digulla
Copy link
Author

digulla commented Dec 15, 2021

Workaround: Call setScale(0) before storing the value or use DECIMAL as column type.

@katzyn
Copy link
Contributor

katzyn commented Dec 15, 2021

H2 should convert passed BigDecimal values with negative scale to values with scale 0 by itself.

@digulla
Copy link
Author

digulla commented Dec 15, 2021

Where in the code does that happen?

@digulla
Copy link
Author

digulla commented Dec 15, 2021

Stack trace of the error:

org.h2.value.ValueNumeric.<init>(BigDecimal) line: 48	
org.h2.value.ValueNumeric.get(BigDecimal) line: 171	
org.h2.jdbc.JdbcPreparedStatement.setBigDecimal(int, BigDecimal) line: 397	
org.hibernate.type.descriptor.sql.DecimalTypeDescriptor$1.doBind(PreparedStatement, X, int, WrapperOptions) line: 47	

At no point is code which tries to fix the scale.

Note: Fixing the scale is a good idea because right now, numerically identical BigDecimal instances with different internal state will create different cache entries.

@katzyn
Copy link
Contributor

katzyn commented Dec 16, 2021

Where in the code does that happen?

I meant this needs to be implemented in PreparedStatement and possibly in Java functions and triggers. I'll take a look on it.

@digulla
Copy link
Author

digulla commented Dec 16, 2021

Thanks for the quick fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants