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

fix: EXPOSED-382 ClassCastException when uuid().references() is used with EntityID column #2079

Merged
merged 1 commit into from May 13, 2024

Conversation

bog-walk
Copy link
Member

Since version 0.50.0, using Column.references() invoked on a UUIDColumnType that targets an EntityIDColumnType<UUID> causes a ClassCastException.
This occurs because PreparedStatementApi.fillParameters() tries to get the valueToDB() from EntityIDColumnType rather than the underlying UUIDColumnType.

uuid("col_name").references(UUIDTable.id)

// throws when trying to access the DAO entity's delegated field
java.util.UUID cannot be cast to org.jetbrains.exposed.dao.id.EntityID
java.lang.ClassCastException: java.util.UUID cannot be cast to org.jetbrains.exposed.dao.id.EntityID
	at org.jetbrains.exposed.sql.EntityIDColumnType.notNullValueToDB(ColumnType.kt:199)
	at org.jetbrains.exposed.sql.IColumnType$DefaultImpls.valueToDB(ColumnType.kt:39)
	at org.jetbrains.exposed.sql.ColumnType.valueToDB(ColumnType.kt:103)
	at org.jetbrains.exposed.sql.statements.api.PreparedStatementApi$DefaultImpls.fillParameters(PreparedStatementApi.kt:24)
	at org.jetbrains.exposed.sql.statements.jdbc.JdbcPreparedStatementImpl.fillParameters(JdbcPreparedStatementImpl.kt:22)

This exception does not happen with Int- or LongColumnType because their EntityID variants are wrapped as AutoIncColumnType that delegates to the correct underlying type.
And this also doesn't happen if reference() is used instead because it creates an EntityIDColumnType under-the-hood which avoids any type mismatch.

This was likely quietly happening before but only causes an issue now that a stricter column type-safety has been introduced.

Note: I considered adding similar logic to OptionalReference.getValue(), but there is no optional variant for Column.references(), so this point should not be reached.

…with EntityID column

Using references() invoked on a UUIDColumnType that targets an EntityIDColumnType<UUID>
causes a ClassCastException. This occurs because PreparedStatementApi.fillParameters()
tries to get the valueToDB() from EntityIDColumnType rather than the underlying UUIDColumnType
and it is not possible to cast the refValue UUID to EntityID<UUID>.

This exception does not happen with Int- or LongColumnType because their EntityID
variants are wrapped as AutoIncColumnTypes that delegate to the correct underlying
type. And this also doesn't happen if reference() is used because it creates an
EntityIDColumnType under-the-hood which avoids type mismatch.

This was most likely always happening but only causes an issue now that a stricter
column type-safety has been introduced, which does not tolerate well a foreign
key constraint between columns of different types.
@bog-walk bog-walk requested a review from e5l May 11, 2024 00:06
Comment on lines +128 to +133
val castReferee = reference.referee<REF>()!!
val baseReferee = (castReferee.columnType as? EntityIDColumnType<REF>)?.idColumn ?: castReferee
factory.findWithCacheCondition({
reference.referee!!.getValue(this, desc) == refValue
}) {
reference.referee<REF>()!! eq refValue
baseReferee eq refValue
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This forces the query clause to use the underlying/wrapped type of EntityIDColumnType when setting statement parameters.

The elvis op is necessary in case the cast fails, which covers cases when an entity may have a foreign key on a target refColumn that is not actually an entityID column.

Copy link
Member

@e5l e5l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@bog-walk bog-walk merged commit 6261abd into main May 13, 2024
5 checks passed
@bog-walk bog-walk deleted the bog-walk/fix-uuid-references branch May 13, 2024 14:20
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 this pull request may close these issues.

None yet

2 participants