Skip to content

Commit 0e4e39b

Browse files
authored
Support NULL-value passthrough for all TypeMappers (#39)
Similarly to #38, adding support for passing nulls (both ways, via get/set) through the remaining TypeMappers.
1 parent 53cbad7 commit 0e4e39b

File tree

1 file changed

+44
-14
lines changed

1 file changed

+44
-14
lines changed

scalasql/src/dialects/Dialect.scala

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ trait Dialect extends DialectTypeMappers {
9999
r.getObject(idx) match {
100100
case u: UUID => u
101101
case s: String => UUID.fromString(s)
102+
case null => null
102103
}
103104
}
104105

@@ -110,16 +111,29 @@ trait Dialect extends DialectTypeMappers {
110111
implicit def BytesType: TypeMapper[geny.Bytes] = new BytesType
111112
class BytesType extends TypeMapper[geny.Bytes] {
112113
def jdbcType = JDBCType.VARBINARY
113-
def get(r: ResultSet, idx: Int) = new geny.Bytes(r.getBytes(idx))
114-
def put(r: PreparedStatement, idx: Int, v: geny.Bytes) = r.setBytes(idx, v.array)
114+
def get(r: ResultSet, idx: Int) = {
115+
val bytes = r.getBytes(idx)
116+
if (bytes == null) null
117+
else new geny.Bytes(bytes)
118+
}
119+
def put(r: PreparedStatement, idx: Int, v: geny.Bytes) = {
120+
val byteArray = if (v == null) null else v.array
121+
r.setBytes(idx, byteArray)
122+
}
115123
}
116124

117125
implicit def UtilDateType: TypeMapper[java.util.Date] = new UtilDateType
118126
class UtilDateType extends TypeMapper[java.util.Date] {
119127
def jdbcType = JDBCType.TIMESTAMP
120-
def get(r: ResultSet, idx: Int) = new java.util.Date(r.getTimestamp(idx).getTime)
121-
def put(r: PreparedStatement, idx: Int, v: java.util.Date) =
122-
r.setTimestamp(idx, new java.sql.Timestamp(v.getTime))
128+
def get(r: ResultSet, idx: Int) = {
129+
val ts = r.getTimestamp(idx)
130+
if (ts == null) null
131+
else new java.util.Date(ts.getTime)
132+
}
133+
def put(r: PreparedStatement, idx: Int, v: java.util.Date) = {
134+
val time = if (v == null) null else new java.sql.Timestamp(v.getTime)
135+
r.setTimestamp(idx, time)
136+
}
123137
}
124138

125139
implicit def LocalDateType: TypeMapper[LocalDate] = new LocalDateType
@@ -147,9 +161,15 @@ trait Dialect extends DialectTypeMappers {
147161
class ZonedDateTimeType extends TypeMapper[ZonedDateTime] {
148162
def jdbcType = JDBCType.TIMESTAMP_WITH_TIMEZONE
149163
override def castTypeString = "TIMESTAMP WITH TIME ZONE"
150-
def get(r: ResultSet, idx: Int) = r.getTimestamp(idx).toInstant.atZone(ZoneId.systemDefault())
151-
def put(r: PreparedStatement, idx: Int, v: ZonedDateTime) = r
152-
.setTimestamp(idx, java.sql.Timestamp.from(v.toInstant))
164+
def get(r: ResultSet, idx: Int) = {
165+
val ts = r.getTimestamp(idx)
166+
if (ts == null) null
167+
else ts.toInstant.atZone(ZoneId.systemDefault())
168+
}
169+
def put(r: PreparedStatement, idx: Int, v: ZonedDateTime) = {
170+
val ts = if (v == null) null else java.sql.Timestamp.from(v.toInstant)
171+
r.setTimestamp(idx, ts)
172+
}
153173
}
154174

155175
implicit def InstantType: TypeMapper[Instant] = new InstantType
@@ -173,8 +193,10 @@ trait Dialect extends DialectTypeMappers {
173193
}
174194
}
175195

176-
def put(r: PreparedStatement, idx: Int, v: Instant) = r
177-
.setTimestamp(idx, java.sql.Timestamp.from(v))
196+
def put(r: PreparedStatement, idx: Int, v: Instant) = {
197+
val ts = if (v == null) null else java.sql.Timestamp.from(v)
198+
r.setTimestamp(idx, ts)
199+
}
178200
}
179201

180202
implicit def OffsetTimeType: TypeMapper[OffsetTime] = new OffsetTimeType
@@ -190,19 +212,27 @@ trait Dialect extends DialectTypeMappers {
190212
def jdbcType = JDBCType.TIMESTAMP_WITH_TIMEZONE
191213
override def castTypeString = "TIMESTAMP WITH TIME ZONE"
192214
def get(r: ResultSet, idx: Int) = {
193-
r.getTimestamp(idx).toInstant.atOffset(OffsetDateTime.now().getOffset)
215+
val ts = r.getTimestamp(idx)
216+
if (ts == null) null
217+
else ts.toInstant.atOffset(OffsetDateTime.now().getOffset)
194218
}
195219
def put(r: PreparedStatement, idx: Int, v: OffsetDateTime) = {
196-
r.setTimestamp(idx, java.sql.Timestamp.from(v.toInstant))
220+
val ts = if (v == null) null else java.sql.Timestamp.from(v.toInstant)
221+
r.setTimestamp(idx, ts)
197222
}
198223
}
199224

200225
implicit def EnumType[T <: Enumeration#Value](implicit constructor: String => T): TypeMapper[T] =
201226
new EnumType[T]
202227
class EnumType[T](implicit constructor: String => T) extends TypeMapper[T] {
203228
def jdbcType: JDBCType = JDBCType.VARCHAR
204-
def get(r: ResultSet, idx: Int): T = constructor(r.getString(idx))
205-
def put(r: PreparedStatement, idx: Int, v: T) = r.setObject(idx, v, java.sql.Types.OTHER)
229+
def get(r: ResultSet, idx: Int): T = {
230+
val str = r.getString(idx)
231+
if (str == null) null.asInstanceOf[T]
232+
else constructor(str)
233+
}
234+
def put(r: PreparedStatement, idx: Int, v: T) =
235+
r.setObject(idx, v, java.sql.Types.OTHER)
206236
}
207237

208238
implicit def from(x: Byte): Expr[Byte] = Expr(x)

0 commit comments

Comments
 (0)