fix: EXPOSED-108 Incorrect mapping for UInt data type #1809
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Related to PR #1799
Current State of
UIntColumnType
(excluding MySQL/MariaDB):When attempting to insert a UInt value outside of the range
0..Int.MAX_VALUE
, Exposed first truncates the value by callingvalue.toInt()
before sending it to the DB:The value is successfully stored as a negative number because most databases don't support unsigned types natively, which means Exposed is actually mapping UInt to 4-byte
INT
, which accepts the range-2^31..(2^31)-1
. The value returned from the DB is the negative overflow and anIllegalStateException
is thrown byvalueFromDB()
.Note: The compiler will prevent a negative number from being assigned to
it[unsignedInt]
, but there is nothing stopping the DB from storing a negative number that is inserted directly using raw SQL:Solution:
Change the column type in the DB to use the next higher type,
BIGINT
in this case, and add a check constraint whenuinteger()
is registered. This would ensure that only UInt values are accepted, even if raw SQL is used.Exception:
[Oracle] The type has not changed because it was already set to
NUMBER(13)
(versus theINT
alias forNUMBER(38)
), but a check constraint has been implemented.Saving Storage Space:
While using a larger numeric type with a check constraint is a common solution for supporting unsigned integers, some users may not want to use 8 bytes of storage for every number. If the end-goal of the user is a column that only uses 4-bytes but does not allow negative values and they know for a fact that inserted data won't exceed
Int.MAX_VALUE
, then the recommendation should be to use ainteger()
column with a manually created check constraint: