These are chat archives for tpolecat/doobie

22nd
Dec 2015
Frank S. Thomas
@fthomas
Dec 22 2015 07:35
@beefyhalo @tpolecat That sounds reasonable. If you know how to xmap Foo you should know how to xmap Foo with fancy refinement since fancy refinement is only an addition to the type Foo but the underlying value has conceptually the same representation as the unrefined Foo. The interesting question is what to do if you get a value from the DB that doesn't satisfies the refinement. From reading the book of doobie it seems to be okay to throw an exception in this case.
Btw, the Meta implementation would probably look similar to this circe De/Encoder or this scodec Codec
Kevin Horlick
@beefyhalo
Dec 22 2015 13:30
Coolness! I'll try to find some time shortly to start on it, unless someone else beats me to it
Frank S. Thomas
@fthomas
Dec 22 2015 14:03
:+1:
Feel free to ping me if anything is unclear
Kevin Horlick
@beefyhalo
Dec 22 2015 14:42

This is what I got so far:

implicit def refinedMeta[T: Meta, P, F[_, _]](implicit tt: TypeTag[F[T, P]], ct: ClassTag[F[T, P]], validate: Validate[T, P], refType: RefType[F]): Meta[F[T, P]] =
    Meta[T].xmap(refType.refine[P](_) match {
      case Left(err) => throw InvalidObjectMapping(ct.runtimeClass, ct.getClass)
      case Right(t)  => t
    }, refType.unwrap)

And almost identical code for Composite. Not sure if I'm throwing the right exception. What do you guys think?

Frank S. Thomas
@fthomas
Dec 22 2015 15:32
What would the an actual message of this exception look like? I think it would be more informative if you could add err to that message.
Kevin Horlick
@beefyhalo
Dec 22 2015 16:00
The message is "SQL object of class ${actual.getName} cannot be cast to mapped class ${expected.getName}."
Frank S. Thomas
@fthomas
Dec 22 2015 16:28
So that doesn't include the actual value that doesn't match the refinement and I wonder if ${expected.getName}would contain the predicate P
Kevin Horlick
@beefyhalo
Dec 22 2015 17:51
Yeah, I'm not really sure what should go there. I think throwing some sort of doobie invariant exception is a good idea, but there's not too many implementations to choose from. Please advise @tpolecat :)
Rob Norris
@tpolecat
Dec 22 2015 17:51
Yeah you can throw anything there. Probably a new subtype of InvariantViolation.
The next version is going to break the invariant functors in half so you can have asymmetric read/write pairs.
Which would allow you to do something more friendly than throwing.
Ian McIntosh
@cranst0n
Dec 22 2015 18:10

I'm running into a NullPointerException during query typechecking.
Here's the stacktrace:

[error]       ! SQL Compiles and Typechecks
[error]        java.lang.NullPointerException: null (pretty.scala:58)
[error] doobie.util.pretty$.wrap(pretty.scala:58)
[error] doobie.contrib.specs2.analysisspec$AnalysisSpec$class.doobie$contrib$specs2$analysisspec$AnalysisSpec$$formatError(specs2.scala:87)
[error] doobie.contrib.specs2.analysisspec$AnalysisSpec$$anonfun$checkAnalysis$3$$anonfun$apply$1.apply(specs2.scala:64)
[error] doobie.contrib.specs2.analysisspec$AnalysisSpec$$anonfun$checkAnalysis$3$$anonfun$apply$1.apply(specs2.scala:64)

And the query (which I've verified returns what I want in the MySQL console):

sql"""
      (select
        s.unixTime, s.sampleRate, s.zoneSpacing, s.zoneOffset, s.frameTime, s.numZones, s.firstZone
      from SystemState s where s.unixTime <= 1427127113072
        order by s.unixTime desc limit 1)
      union
      (select
        s.unixTime, s.sampleRate, 11, s.zoneOffset, s.frameTime, s.numZones, s.firstZone
      from SystemState s where s.unixTime between 1427127113072 and 1427127113072
        order by s.unixTime desc)
    """.query[SystemState]
Rob Norris
@tpolecat
Dec 22 2015 18:14
If you try to run that query does it work? It looks like preparing the statement and fetching the metadata is raising an exception whose message is null, which is breaking the formatter.
Can you open an issue for this?
Ian McIntosh
@cranst0n
Dec 22 2015 18:40
#262 opened with a little more info on what's happening.
Rob Norris
@tpolecat
Dec 22 2015 18:40
Thanks!
Peter Neyens
@peterneyens
Dec 22 2015 18:47
I am not sure if this is the right place for my question, but if you design a FooRepository as in this example (a trait with Query0 and Update0 and another where they are turned into Task) , in which way do you test the next layer (this ToDo in the same example) which uses the repository ? Do you use an in memory database (like Derby) or do you manually create a test version of your repository , ... ? I haven't yet found an elegant way.
Rob Norris
@tpolecat
Dec 22 2015 18:59
I don't have a good answer for that. I have always used a test db, but if you happen to be using an embedded DB then an in-memory db is a nice option. I'm working on some stuff for 0.3 that will make it easier to write tests, provoke failure conditions, and examine "what happened" in detail to ensure that your logic does what you think it does. But for now I think it's probably a matter of exploring what seems to work for you.
Please open an issue if you have any ideas or just want to provide feedback on what you're doing. I think this is a place where doobie (and its doc) could be improved a lot.