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

Better error message about lifting for enum types #1803

Merged
merged 2 commits into from Mar 17, 2020
Merged

Conversation

majk-p
Copy link
Contributor

@majk-p majk-p commented Mar 6, 2020

Problem

Explain here the context, and why you're making that change.
What is the problem you're trying to solve?

When trying to update enum filed, Scala infers the value type instead of enum type. Minimal reproducible example:

package example
import io.getquill._

case class User(role: UserRole)
sealed trait UserRole extends Product with Serializable
object UserRole {
  case object Writer extends UserRole
  case object Reader extends UserRole
  implicit val encodeStatus: MappedEncoding[UserRole, String] = MappedEncoding[UserRole, String]{
    case Reader => "Reader" 
    case Writer => "Writer"
  }
  implicit val decodeStatus: MappedEncoding[String, UserRole] = MappedEncoding[String, UserRole]{
    case "Reader" => Reader
    case "Writer" => Writer
  }
}

object Hello extends App {
  val ctx = new SqlMirrorContext(MirrorSqlDialect, Literal)
  import ctx._
  val updateQuery = quote {
    query[User].update(_.role -> lift(UserRole.Writer))
  }
  run(updateQuery)
}

The error message isn't really helpful:

sbt:Quill ADT test> run                                                                                   
...
[error] .../Code/personal/quill-adt-test/src/main/scala/example/Hello.scala:31:6: exception during macro expansion: 
[error] java.lang.IllegalStateException: Can't tokenize a non-scalar lifting. Hello.this.updateQuery.UserRole.Writer
[error]                                                                                                   
[error] This might happen because:                                                                        
[error] * You are trying to insert or update an `Option[A]` field, but Scala infers the type
[error]   to `Some[A]` or `None.type`. For example:
[error]     run(query[Users].update(_.optionalField -> lift(Some(value))))  In that case, make sure the type is `Option`:
[error]     run(query[Users].update(_.optionalField -> lift(Some(value): Option[Int])))
[error]   or                                                                                              
[error]     run(query[Users].update(_.optionalField -> lift(Option(value))))
[error]             
[error] * You are trying to insert or update whole Embedded case class. For example:
[error]     run(query[Users].update(_.embeddedCaseClass -> lift(someInstance)))
[error]   In that case, make sure you are updating individual columns, for example:
[error]     run(query[Users].update(
[error]        _.embeddedCaseClass.a -> lift(someInstance.a),
[error]        _.embeddedCaseClass.b -> lift(someInstance.b)
[error]     ))
[error]         at io.getquill.util.Messages$.fail(Messages.scala:43)

This issue can be simply worked around by uplifting the type:

query[User].update(_.role -> lift(UserRole.Writer: UserRole))

Solution

Although the type inference issue is hard to solve here, the error message can be more helpful. This PR introduces updated error message.

Updated message provides following guidance on how to solve the issue:

[error] * You are trying to insert or update an enum field, but Scala infers the value
[error]   instead of the enum type. For example:
[error]     case class User(role: UserRole)
[error]     sealed trait UserRole extends Product with Serializable
[error]     object UserRole {                                                                             
[error]       case object Writer extends UserRole                                                         
[error]       case object Reader extends UserRole
[error]       implicit val encodeStatus: MappedEncoding[UserRole, String] = ...
[error]       implicit val decodeStatus: MappedEncoding[String, UserRole] = ...
[error]     }
[error]     run(query[User].update(_.role -> lift(UserRole.Writer)))
[error]   In that case, make sure you are uplifting to enum type, for example:
[error]     run(query[User].update(_.role -> lift(UserRole.Writer: UserRole)))

Checklist

  • Unit test all changes
  • Update README.md if applicable
  • Add [WIP] to the pull request title if it's work in progress
  • Squash commits that aren't meaningful changes
  • Run sbt scalariformFormat test:scalariformFormat to make sure that the source files are formatted

@getquill/maintainers

@majk-p
Copy link
Contributor Author

@majk-p majk-p commented Mar 11, 2020

The build has failed but it's unlikely to be caused by this change. The exception according to logs is com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'alpha.information_schema.tables' but it really tells me nothing.

Any ideas? can we simply retry the build?

@majk-p
Copy link
Contributor Author

@majk-p majk-p commented Mar 17, 2020

@juliano @deusaquilus can you please have a look?

Copy link
Collaborator

@juliano juliano left a comment

Thanks for your contribution! 💯

@juliano juliano merged commit 661e897 into zio:master Mar 17, 2020
1 check passed
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

3 participants