-
Notifications
You must be signed in to change notification settings - Fork 2
/
MyCustomTypes.scala
156 lines (114 loc) · 4.54 KB
/
MyCustomTypes.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package example
import org.squeryl._
import org.squeryl.dsl._
import org.joda.time._
import java.sql.Timestamp
import java.sql.ResultSet
import org.squeryl.adapters.H2Adapter
import java.util.Date
/**
* PrimitiveTypeMode being a trait, can be extended to
* support additionnal field types than what the native JDBC.
*
* To support a non JDBC native type, one extends PrimitiveTypeMode
* and adds 4 new implicits in it's scope. Then all aspects
* of the Query DSL that are available for the native type
* becomes available for the new type
*
*
*/
object MyCustomTypes extends PrimitiveTypeMode {
/**
* The 3 type arguments are :
* 1) Timestamp : the native JDBC type that will back our custom type (in this case JodaTime's DateTime)
* 2) The new type we want to support
* 3) One of the sealed traits defined here :
* https://github.com/max-l/Squeryl/blob/AST-lifting-overhaul/src/main/scala/org/squeryl/dsl/TypedExpression.scala#L28
* This will define the behavior of the new type, we want that in the DSL it behaves like
* a timestamp, this will for example enable comparison operators (<, >, between, etc...)
* as well as min, max functions, if we chose TBoolean, then min max is not available,
* if we chose TBigDecimal (of TFloat), then avg, sum, etc become available.
*
*/
implicit val jodaTimeTEF = new NonPrimitiveJdbcMapper[Timestamp, DateTime, TTimestamp](timestampTEF, this) {
/**
* Here we implement functions fo convert to and from the native JDBC type
*/
def convertFromJdbc(t: Timestamp) = new DateTime(t)
def convertToJdbc(t: DateTime) = new Timestamp(t.getMillis())
}
/**
* We define this one here to allow working with Option of our new type, this allso
* allows the 'nvl' function to work
*/
implicit val optionJodaTimeTEF =
new TypedExpressionFactory[Option[DateTime], TOptionTimestamp]
with DeOptionizer[Timestamp, DateTime, TTimestamp, Option[DateTime], TOptionTimestamp] {
val deOptionizer = jodaTimeTEF
}
/**
* the following are necessary for the AST lifting
*/
implicit def jodaTimeToTE(s: DateTime) = jodaTimeTEF.create(s)
implicit def optionJodaTimeToTE(s: Option[DateTime]) = optionJodaTimeTEF.create(s)
implicit val dateAsLongTEF = new NonPrimitiveJdbcMapper[Long, MyDateWrapper, TLong](longTEF, this) {
def convertFromJdbc(v: Long) = new MyDateWrapper(new Date(v))
def convertToJdbc(v: MyDateWrapper) = v.d.getTime
}
implicit val optionDateAsLongTEF = new TypedExpressionFactory[Option[MyDateWrapper], TOptionLong]
with DeOptionizer[Long, MyDateWrapper, TLong, Option[MyDateWrapper], TOptionLong] {
val deOptionizer = dateAsLongTEF
}
implicit def dateAsLongTE(s: MyDateWrapper) = dateAsLongTEF.create(s)
implicit def optionDateAsLongTE(s: Option[MyDateWrapper]) = optionDateAsLongTEF.create(s)
implicit def date2MyDateWrapper(d:Date) = new MyDateWrapper(d)
}
class TimestampTester(val time: DateTime, val optionalTime: Option[DateTime], val longBackedDate: MyDateWrapper) {
def this(t: DateTime, d: MyDateWrapper) = this(t, None, d)
}
import MyCustomTypes._
object TimestampTesterSchema extends Schema {
val timestampTester = table[TimestampTester]
}
class MyDateWrapper(val d: Date)
object JodaTimeTests {
import TimestampTesterSchema._
def main(args: Array[String]): Unit = {
Class.forName("org.h2.Driver")
SessionFactory.concreteFactory = Some(() =>
Session.create(
java.sql.DriverManager.getConnection("jdbc:h2:~/test", "sa", ""),
new H2Adapter))
transaction {
try { drop } catch { case e: Exception => {} }
create
}
test1
}
def test1 = transaction {
val d = (new DateTime)
val b10 = d.minusDays(10)
val b5 = d.minusDays(5)
val a5 = d.plusDays(5)
timestampTester.insert(new TimestampTester(b10, b10.toDate))
timestampTester.insert(new TimestampTester(b5, Option(new DateTime), b5.toDate))
timestampTester.insert(new TimestampTester(a5, a5.toDate))
val x1 =
from(timestampTester)(tt =>
where(tt.time < b5)
select (&(tt.time)))
assert(x1.size == 1)
println(x1.mkString("\n"))
val x2 =
from(timestampTester)(tt =>
where(tt.time >= b5)
select (tt))
assert(x2.size == 2)
println(x2.map(_.time).mkString("\n"))
val x3 =
from(timestampTester)(tt =>
where(tt.longBackedDate >= b5.toDate.getTime)
select (tt))
assert(x3.size == 2)
}
}