Skip to content

Commit

Permalink
Merge pull request #46 from lucidsoftware/uuid-postgres
Browse files Browse the repository at this point in the history
Support UUID columns across more databases
  • Loading branch information
gregghz authored Mar 1, 2017
2 parents da8217e + a2ecb80 commit ed07442
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
8 changes: 2 additions & 6 deletions relate/src/main/scala/com/lucidchart/relate/ColReader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,8 @@ object ColReader {
implicit val longReader: ColReader[Long] = optReader((col, rs) => rs.getLong(col))
implicit val shortReader: ColReader[Short] = optReader((col, rs) => rs.getShort(col))
implicit val stringReader: ColReader[String] = optReader((col, rs) => rs.getString(col))
implicit val uuidReader: ColReader[UUID] = byteArrayReader.map { bytes =>
require(bytes.length == 16)
val bb = ByteBuffer.wrap(bytes)
val high = bb.getLong
val low = bb.getLong
new UUID(high, low)
implicit val uuidReader: ColReader[UUID] = ColReader[UUID] { (col, row) =>
row.uuidOption(col)
}

def enumReader[A <: Enumeration](e: A): ColReader[e.Value] = {
Expand Down
22 changes: 16 additions & 6 deletions relate/src/main/scala/com/lucidchart/relate/SqlRow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,23 @@ class SqlRow(val resultSet: java.sql.ResultSet) extends ResultSetWrapper {

def uuid(column: String): UUID = uuidOption(column).get
def uuidOption(column: String): Option[UUID] = {
byteArrayOption(column).map { bytes =>
require(bytes.length == 16)
extractOption(column) {
case u: UUID => u
case b => {
val bytes = b match {
case x: Array[Byte] => x
case x: Blob => x.getBytes(0, x.length.toInt)
case x: Clob => x.getSubString(1, x.length.asInstanceOf[Int]).getBytes
case x: String => x.toCharArray.map(_.toByte)
}

require(bytes.length == 16)

val bb = ByteBuffer.wrap(bytes)
val high = bb.getLong
val low = bb.getLong
new UUID(high, low)
val bb = ByteBuffer.wrap(bytes)
val high = bb.getLong
val low = bb.getLong
new UUID(high, low)
}
}
}

Expand Down
20 changes: 19 additions & 1 deletion relate/src/test/scala/ColReaderTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object RecordA extends Mockito {
rs.getLong("long") returns 100L
rs.getShort("short") returns (5: Short)
rs.getString("str") returns "hello"
rs.getBytes("uuid") returns Array[Byte](1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
rs.getObject("uuid") returns Array[Byte](1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
rs.getInt("thing") returns 1
SqlRow(rs)
}
Expand Down Expand Up @@ -185,4 +185,22 @@ class ColReaderTest extends Specification with Mockito {
)
}
}

"uuidReader" should {
"parse a byte array" in {
val rs = mock[java.sql.ResultSet]
val row = SqlRow(rs)
rs.getObject("col") returns Array[Byte]('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')

ColReader.uuidReader.read("col", row) mustEqual Some(new UUID(3472611983179986487L, 4051376414998685030L))
}

"parse a uuid" in {
val rs = mock[java.sql.ResultSet]
val row = SqlRow(rs)
rs.getObject("col") returns new UUID(3472611983179986487L, 4051376414998685030L)

ColReader.uuidReader.read("col", row) mustEqual Some(new UUID(3472611983179986487L, 4051376414998685030L))
}
}
}
11 changes: 10 additions & 1 deletion relate/src/test/scala/SqlResultSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -874,14 +874,23 @@ class SqlResultSpec extends Specification with Mockito {
}

"uuid" should {
"return the correct value" in {
"return the correct value when stored as a byte array" in {
val (rs, row, _) = getMocks

val res = Array[Byte]('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
rs.getObject("uuid") returns res
row.uuid("uuid") equals new UUID(3472611983179986487L, 4051376414998685030L)
row.uuidOption("uuid") must beSome(new UUID(3472611983179986487L, 4051376414998685030L))
}

"return the correct value when stored as UUID" in {
val (rs, row, _) = getMocks

val res = new UUID(3472611983179986487L, 4051376414998685030L)
rs.getObject("uuid") returns res
row.uuid("uuid") equals res
row.uuidOption("uuid") must beSome(res)
}
}

"uuidFromString" should {
Expand Down

0 comments on commit ed07442

Please sign in to comment.