DeOptionizer and ConstantTypedExpression

35 views
Skip to first unread message

Peter Brant

unread,
Jul 10, 2012, 6:43:16 PM7/10/12
to Squeryl
Hi Max,

We ran into a strange gotcha with custom types.  With e.g. Joda's LocalDate and an entity class like

class Foo(..., bar: Option[LocalDate])

where(f.bar === new LocalDate) works fine, but where(f.bar === Some(new LocalDate)) compiles fine, but then throws an exception at runtime.  It looks like the problem is that ConstantTypedExpression is getting the unwrapped Option[LocalDate] as its nativeJdbcValue (which in turn is just what DeOptionizer#convertToJdbc does).  The JDBC driver then throws an exception when #setObject(...) gets the LocalDate.

Needless to say the former where(...) is better style, but it seems like the latter should work too.  I thought fixing this would mean delegating to deOptionizer like most of the rest of DeOptionizer does, but I'm getting all tangled up in the type parameters involved so I'm appealing to a higher power. ;-)

Pete

Maxime Lévesque

unread,
Jul 10, 2012, 9:23:02 PM7/10/12
to squ...@googlegroups.com

Do you have a reproducible case ? 

Perhaps a slight alteration of this  :


?


2012/7/10 Peter Brant <peter...@gmail.com>



--
“I'd rather be an optimist and a fool than a pessimist and right.” 
― Albert Einstein

Peter Brant

unread,
Jul 11, 2012, 5:32:00 AM7/11/12
to squ...@googlegroups.com
Hi Max,


It looks like H2's setObject(...) serializes non-SQL types and uses the Base-64 encoding thereof as the field's value.  This makes the error message a little less transparent than with PG, but it's the same underlying problem.

Pete

Maxime Lévesque

unread,
Jul 11, 2012, 9:23:05 AM7/11/12
to squ...@googlegroups.com

Oh, that's good to know, I'll do some tinkering...

2012/7/11 Peter Brant <peter...@gmail.com>

Hi Max,


It looks like H2's setObject(...) serializes non-SQL types and uses the Base-64 encoding thereof as the field's value.  This makes the error message a little less transparent than with PG, but it's the same underlying problem.

Pete


On Wed, Jul 11, 2012 at 3:23 AM, Maxime Lévesque <maxime....@gmail.com> wrote:

Do you have a reproducible case ? 

Perhaps a slight alteration of this  :


?


2012/7/10 Peter Brant <peter...@gmail.com>
Hi Max,

We ran into a strange gotcha with custom types.  With e.g. Joda's LocalDate and an entity class like

class Foo(..., bar: Option[LocalDate])

where(f.bar === new LocalDate) works fine, but where(f.bar === Some(new LocalDate)) compiles fine, but then throws an exception at runtime.  It looks like the problem is that ConstantTypedExpression is getting the unwrapped Option[LocalDate] as its nativeJdbcValue (which in turn is just what DeOptionizer#convertToJdbc does).  The JDBC driver then throws an exception when #setObject(...) gets the LocalDate.

Needless to say the former where(...) is better style, but it seems like the latter should work too.  I thought fixing this would mean delegating to deOptionizer like most of the rest of DeOptionizer does, but I'm getting all tangled up in the type parameters involved so I'm appealing to a higher power. ;-)

Pete



--
“I'd rather be an optimist and a fool than a pessimist and right.” 
― Albert Einstein

Peter Brant

unread,
Jul 25, 2012, 9:37:03 AM7/25/12
to squ...@googlegroups.com
Hi Max,

Just in case this is still on your radar... I think I've got a fix here.  It needs a bit more testing, but I'll post for comment and review shortly.

Pete

Maxime Lévesque

unread,
Jul 25, 2012, 12:04:06 PM7/25/12
to squ...@googlegroups.com

Cool, it is in fact on my radar, but not on my workbench ;-) 
Glad to see you are looking into it ! 

2012/7/25 Peter Brant <peter...@gmail.com>



--
Growth for the sake of growth is the ideology of the cancer cell

Peter Brant

unread,
Jul 25, 2012, 5:59:45 PM7/25/12
to squ...@googlegroups.com

Maxime Lévesque

unread,
Jul 25, 2012, 10:29:36 PM7/25/12
to squ...@googlegroups.com

It's nice to have "imposter" out of the source code :

323  
-  private val imposter = { 
324  
-    (a2:A2) => if(a2 == None) null else (a2:Option[A1]).get.asInstanceOf[AnyRef]
325  
-  }.asInstanceOf[Function1[A2,A1]]


Looks much better now, I'm impressed !!! 

Peter Brant

unread,
Jul 26, 2012, 9:51:49 AM7/26/12
to squ...@googlegroups.com
Cool.  Applied to master.

Pete

Maxime Lévesque

unread,
Jul 26, 2012, 10:17:52 AM7/26/12
to squ...@googlegroups.com

BTW it is my understanding that the P1 type parameter you added to DeOptionizer would't be necessary
if it were not for the Enumeration type meaning that in all other case A1 == P1.

is that correct ?


2012/7/26 Peter Brant <peter...@gmail.com>

Peter Brant

unread,
Jul 26, 2012, 10:54:38 AM7/26/12
to squ...@googlegroups.com
Only for primitive types.  For custom types, DeOptionizer needed to know about the underlying JDBC type.  e.g.

  implicit val optJodaLocalDateTimeTEF = new TypedExpressionFactory[Option[LocalDateTime], TOptionTimestamp]
      with DeOptionizer[
        Timestamp,
        LocalDateTime,
        TTimestamp,
        Option[LocalDateTime],
        TOptionTimestamp] {
    val deOptionizer = jodaLocalDateTimeTEF
  }

Pete
Reply all
Reply to author
Forward
0 new messages