Permalink
Browse files

Some bug fixes concerning Option types:

- Allow `GetOrElse`-equivalent `OptionFold` in insert operations. This
  is required for using `getOrElse` calls in inserts, which was
  supported before 2.1 when they were always encoded as `GetOrElse`.

- Produce the correct Option-mapped type for the `unary_!` operator.
  It used to return `Boolean` instead of `Option[Boolean]` when applied
  to an operand of type `Option[Boolean]`.

- Implement `Library.StartsWith` and `Library.EndsWith` in
  `QueryInterpreter`.

Test in NestingTest.testGetOrElse. Fixes the remaining issues of #1018.
The main problem was already fixed in the Option improvements in 2.1 and
the new query compiler back-end in 3.1.
  • Loading branch information...
szeiger committed Sep 24, 2015
1 parent 97b35a8 commit b739255e1a5b4211c06c3ed10290e43b5d7d2f47
@@ -211,4 +211,27 @@ class NestingTest extends AsyncTest[RelationalTestDB] {
setup >> t1 >> t2 >> t3 >> t4 >> t5 >> t6
}
def testGetOrElse = {
case class Chord(name: String, popularOptions: String, id: Long = -1L)
class Chords(tag: Tag) extends Table[Chord](tag, "chords") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[Option[String]]("name")
def popularOptions = column[Option[String]]("popularOptions")
def * = (name.getOrElse(""), popularOptions.getOrElse(""), id) <> (Chord.tupled, Chord.unapply)
}
val chords = TableQuery[Chords]
val allChords = Set(Chord("maj7", "9 #11"), Chord("m7", "9 11"), Chord("7", "9 13"), Chord("m7b5", "11"), Chord("aug7", "9"), Chord("dim7", ""))
val minorChords = for {
chord <- chords if chord.name.startsWith("m7")
} yield (chord.name.getOrElse(""), chord.popularOptions.getOrElse(""))
val otherChords = for {
chord <- chords if !chord.name.startsWith("m7")
} yield (chord.name.getOrElse(""), chord.popularOptions.getOrElse(""))
DBIO.seq(
chords.schema.create,
chords ++= allChords,
(minorChords ++ otherChords).result.map(_.toSet shouldBe allChords.map(c => (c.name, c.popularOptions)))
)
}
}
@@ -34,6 +34,7 @@ class InsertCompiler(val mode: InsertCompiler.Mode) extends Phase {
def tr(n: Node): Node = n match {
case _: OptionApply | _: GetOrElse | _: ProductNode | _: TypeMapping => n.mapChildren(tr, keepType = true)
case OptionFold(from, _, Ref(s2), s1) if s1 == s2 => tr(GetOrElse(from, null).infer())
case te @ TableExpansion(_, _, expansion) =>
setTable(te)
tr(expansion)
@@ -103,7 +103,7 @@ final class BooleanColumnExtensionMethods[P1](val c: Rep[P1]) extends AnyVal wit
om.column(Library.And, n, b.toNode)
def ||[P2, R](b: Rep[P2])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]) =
om.column(Library.Or, n, b.toNode)
def unary_! = Library.Not.column[Boolean](n)
def unary_! = Library.Not.column[P1](n)
}
/** Extension methods for Rep[String] and Rep[Option[String]] */
@@ -417,6 +417,8 @@ class QueryInterpreter(db: HeapBackend#Database, params: Any) extends Logging {
replace(args(1)._2.asInstanceOf[String], args(2)._2.asInstanceOf[String])
case Library.Reverse => args(0)._2.asInstanceOf[String].reverse
case Library.IndexOf => args(0)._2.asInstanceOf[String].indexOf(args(1)._2.asInstanceOf[String])
case Library.StartsWith => args(0)._2.asInstanceOf[String].startsWith(args(1)._2.asInstanceOf[String])
case Library.EndsWith => args(0)._2.asInstanceOf[String].endsWith(args(1)._2.asInstanceOf[String])
}
def unwrapSingleColumn(coll: Coll, tpe: Type): (Iterator[Any], Type) = tpe.asCollectionType.elementType match {

0 comments on commit b739255

Please sign in to comment.