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

on leftJoin TypeMapper for T is being applied on Option[T] #65

Open
NPCRUS opened this issue Jan 29, 2025 · 1 comment
Open

on leftJoin TypeMapper for T is being applied on Option[T] #65

NPCRUS opened this issue Jan 29, 2025 · 1 comment

Comments

@NPCRUS
Copy link
Contributor

NPCRUS commented Jan 29, 2025

having two tables wiith relation A.bId = B.id
on of witch has field of custom type T and therefore provided with TypeMapper for this custom type.

case class A[T[_]](id: T[Int], bId: T[Option[Int]])
object A extends Table[A]

enum Custom {
  case Foo, Bar
}
object Custom {
  given TypeMapper[Custom] = StringType.bimap(_.toString, Custom.valueOf)
}

case class B[T[_]](id: T[Int], custom: T[Custom])
object B extends Table[B]

having in database only records for table A, so in table B there are no records
and performing leftJoin on table B in such way:

A.select.leftJoin(B)(_.bId `=` _.id)

i get following error: enum Custom has no case with name: null
when in fact there are no records of table B and no custom field to perform type mapping on.

Expected result: it shouldn't try to serialize null into Custom, in fact there should be no value to serialize on at all

@NPCRUS
Copy link
Contributor Author

NPCRUS commented Feb 11, 2025

what I found out is that in dialects a get method on type mapper for Enum is implemented in such manner:

def get(r: ResultSet, idx: Int): T = {
  val str = r.getString(idx)
  if (str == null) null.asInstanceOf[T]
  else constructor(str)
}

a hack that worked until I implemented my own type mapper for scala3 enums.
Another interesting thing here is that surprisingly type mapping for Options doesn't stop at None, even though type mapper for options is defined like this:

def get(r: ResultSet, idx: Int): Option[T] = {
  if (r.getObject(idx) == null) None else Some(inner.get(r, idx))
}

where inner is TypeMapper[T]

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

No branches or pull requests

1 participant