Skip to content

Commit

Permalink
Merge pull request #182 from tminglei/composite-hstore
Browse files Browse the repository at this point in the history
#178 Support for hstore within composite types
  • Loading branch information
tminglei committed Jul 19, 2015
2 parents dc33c37 + 6cc2d02 commit 6599266
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,15 @@ object PgTokenHelper {
}
//-- process marker tokens
// mark + escape
case Marker(m) if (level(m) != math.round(level(m)) && tokens(i-1) == Comma) => {
val index = math.pow(2, stack.top.level).toInt
case Marker(m) if (level(m) != math.round(level(m))
&& (tokens(i-1) == Comma || tokens(i-1).isInstanceOf[Open])) => {
val index = math.pow(2, stack.top.level +1).toInt
stack.push(WorkingGroup(Marker(m.substring(0, index)), stack.top.level +1))
stack.top.tokens += Marker(m.substring(0, index)) += Escape(m.substring(index))
}
// escape + mark
case Marker(m) if (level(m) != math.round(level(m)) && tokens(i+1) == Comma) => {
case Marker(m) if (level(m) != math.round(level(m))
&& (tokens(i+1) == Comma || tokens(i+1).isInstanceOf[Close])) => {
val existed = stack.find(g => m.endsWith(g.border.marker)).get
for (_ <- 0 to stack.lastIndexOf(existed)) {
if (stack.top == existed) {
Expand All @@ -219,23 +221,30 @@ object PgTokenHelper {
}
}
// mark + escape + mark
case Marker(m) if (tokens(i-1) == Comma && tokens(i+1) == Comma) => {
case Marker(m) if ((tokens(i-1) == Comma || tokens(i-1).isInstanceOf[Open])
&& (tokens(i+1) == Comma || tokens(i+1).isInstanceOf[Close])) => {
val topMarker = stack.top.border.marker
if ((m.length > topMarker.length * 2) && m.startsWith(topMarker) && m.endsWith(topMarker)) {
stack.top.tokens += Escape(m.substring(topMarker.length -1, m.length -topMarker.length))
} else stack.top.tokens += Escape(m)
}
case t @ Marker(m) => {
val existed = stack.find(g => g.border.marker == m)
if (existed.isDefined) {
for (_ <- 0 to stack.lastIndexOf(existed.get)) {
if (stack.top == existed.get) stack.top.tokens += t
val toBeMerged = GroupToken(stack.pop.tokens.toList)
stack.top.tokens += toBeMerged
val escape = stack.top.tokens.find(e => e.isInstanceOf[Escape] && e.value == m)
// mark + escape ... + [escape]
if (escape.isDefined) {
stack.top.tokens += Escape(m)
} else { // others
val existed = stack.find(g => g.border.marker == m)
if (existed.isDefined) {
for (_ <- 0 to stack.lastIndexOf(existed.get)) {
if (stack.top == existed.get) stack.top.tokens += t
val toBeMerged = GroupToken(stack.pop.tokens.toList)
stack.top.tokens += toBeMerged
}
} else {
stack.push(WorkingGroup(t, stack.top.level +1))
stack.top.tokens += t
}
} else {
stack.push(WorkingGroup(t, stack.top.level +1))
stack.top.tokens += t
}
}
//-- process close tokens
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.github.tminglei.slickpg

import org.postgresql.util.HStoreConverter
import org.scalatest.FunSuite

import slick.driver.PostgresDriver
import slick.jdbc.{GetResult, PositionedResult}
import scala.collection.convert.{WrapAsScala, WrapAsJava}
import scala.reflect.runtime.{universe => u}
import java.sql.Timestamp
import java.text.SimpleDateFormat
Expand All @@ -26,7 +28,8 @@ object PgCompositeSupportSuite {
case class Composite2(
id: Long,
comp1: Composite1,
confirm: Boolean
confirm: Boolean,
map: Map[String, String]
) extends Struct

case class Composite3(
Expand All @@ -42,10 +45,16 @@ object PgCompositeSupportSuite {

val plainImplicits = new Implicits with CompositePlainImplicits {}

def mapToString(m: Map[String, String]): String = HStoreConverter.toString(WrapAsJava.mapAsJavaMap(m))
def stringToMap(s: String): Map[String, String] = WrapAsScala.mapAsScalaMap(HStoreConverter.fromString(s)
.asInstanceOf[java.util.Map[String, String]]).toMap

///
trait CompositeImplicits {
utils.TypeConverters.register(PgRangeSupportUtils.mkRangeFn(ts))
utils.TypeConverters.register(PgRangeSupportUtils.toStringFn[Timestamp](tsFormat.format))
utils.TypeConverters.register(mapToString)
utils.TypeConverters.register(stringToMap)

implicit val composite1TypeMapper = createCompositeJdbcType[Composite1]("composite1")
implicit val composite2TypeMapper = createCompositeJdbcType[Composite2]("composite2")
Expand Down Expand Up @@ -126,10 +135,10 @@ class PgCompositeSupportSuite extends FunSuite {
//-------------------------------------------------------------------

val rec1 = TestBean(333, List(Composite2(201, Composite1(101, "(test1'", ts("2001-1-3 13:21:00"),
Some(Range(ts("2010-01-01 14:30:00"), ts("2010-01-03 15:30:00")))), true)))
Some(Range(ts("2010-01-01 14:30:00"), ts("2010-01-03 15:30:00")))), true, Map("t" -> "haha", "t2" -> "133"))))
val rec2 = TestBean(335, List(Composite2(202, Composite1(102, "test2\\", ts("2012-5-8 11:31:06"),
Some(Range(ts("2011-01-01 14:30:00"), ts("2011-11-01 15:30:00")))), false)))
val rec3 = TestBean(337, List(Composite2(203, Composite1(103, "ABC ABC", ts("2015-3-8 17:17:03"), None), false)))
Some(Range(ts("2011-01-01 14:30:00"), ts("2011-11-01 15:30:00")))), false, Map("t't" -> "1,363"))))
val rec3 = TestBean(337, List(Composite2(203, Composite1(103, "ABC ABC", ts("2015-3-8 17:17:03"), None), false, Map("t,t" -> "ewtew"))))

val rec11 = TestBean1(111, List(Composite3(Some("(test1'"))))
val rec12 = TestBean1(112, List(Composite3(code = Some(102))))
Expand All @@ -139,7 +148,7 @@ class PgCompositeSupportSuite extends FunSuite {
Await.result(db.run(
DBIO.seq(
sqlu"create type composite1 as (id int8, txt text, date timestamp, ts_range tsrange)",
sqlu"create type composite2 as (id int8, comp1 composite1, confirm boolean)",
sqlu"create type composite2 as (id int8, comp1 composite1, confirm boolean, map hstore)",
sqlu"create type composite3 as (txt text, id int4, code int4, bool boolean)",
(CompositeTests.schema ++ CompositeTests1.schema) create,
CompositeTests forceInsertAll List(rec1, rec2, rec3),
Expand Down Expand Up @@ -187,7 +196,7 @@ class PgCompositeSupportSuite extends FunSuite {

Await.result(db.run(DBIO.seq(
sqlu"create type composite1 as (id int8, txt text, date timestamp, ts_range tsrange)",
sqlu"create type composite2 as (id int8, comp1 composite1, confirm boolean)",
sqlu"create type composite2 as (id int8, comp1 composite1, confirm boolean, map hstore)",
sqlu"create type composite3 as (txt text, id int4, code int4, bool boolean)",
sqlu"create table CompositeTest (id BIGINT NOT NULL, comps composite2[] DEFAULT '{}' NOT NULL)",
sqlu"create table CompositeTest1 (id BIGINT NOT NULL, comps composite3[] NOT NULL)",
Expand Down

0 comments on commit 6599266

Please sign in to comment.