Permalink
Browse files

[scala] Fix inference of on scala RowList1:

```scala
import acolyte.Implicits._
import acolyte.RowLists.stringList

stringList :+ null // fixed inference of null (as String there)
```
  • Loading branch information...
cchantep
cchantep committed Jan 7, 2014
1 parent 2397517 commit f87782144a691847cf4a390cced9a838cdfa2db8
@@ -24,7 +24,6 @@
*
* @author Cedric Chantepie
* @todo Add nullable property to Column
* @todo Check NPE in RowResultSet.getObject
*/
public abstract class RowList<R extends Row> {
@@ -218,7 +217,7 @@ private Column(final Class<T> columnClass, final String name) {
/**
* Cell on a row.
*/
private static final class Cell<C> {
private static final class Cell<C> { // TODO: Remove useless Cell class
public final C value;
public Cell(final C v) {
@@ -367,7 +366,6 @@ public Object getObject(final int columnIndex) throws SQLException {
final int idx = columnIndex - 1;
final List<Object> cells = this.rows.get(this.row-1).cells();
// stringList :+ null -> .get -> NPE
if (idx < 0 || idx >= cells.size()) {
throw new SQLException("Invalid column index: " + columnIndex);
View
@@ -18,10 +18,10 @@ sourceGenerators in Compile <+= (baseDirectory in Compile) zip (sourceManaged in
IO.writer[java.io.File](rlf, "", IO.defaultCharset, false) { w
val letter = ('A' to 'Z').map(_.toString) ++: ('A' to 'Z').map(l "A" + l)
val lim = letter.size
val conv = for (n 1 to lim) yield {
val conv = Nil ++: Seq("implicit def RowList1AsScala[A](l: RowList1[A]): ScalaRowList1[A] = new ScalaRowList1[A](l)") ++: (for (n 2 to lim) yield {
val gp = (for (i 0 until n) yield letter(i)).mkString(", ")
"""implicit def RowList%dAsScala[%s](l: RowList%d[%s]): ScalaRowList[RowList%d[%s], Row%d[%s]] = new ScalaRowList[RowList%d[%s], Row%d[%s]](l)""".format(n, gp, n, gp, n, gp, n, gp, n, gp, n, gp)
}
})
val tmpl = base / "src" / "main" / "templates" / "RowLists.tmpl"
IO.reader[Unit](tmpl) { r
IO.foreachLine(r) { l
@@ -301,7 +301,8 @@ trait CompositeHandlerImplicits { srl: ScalaRowLists ⇒
* stringList :+ "singleVal" // SingleValueRow("singleVal")
* }}}
*/
implicit def SingleValueRow[A, B](value: A)(implicit f: A B): Row.Row1[B] = Rows.row1[B](f(value))
implicit def SingleValueRow[A, B](value: A)(implicit f: A B): Row.Row1[B] =
Rows.row1[B](f(value))
}
@@ -319,6 +320,46 @@ final class ScalaResultRow(r: Row) extends Row {
}
// TODO: Move ScalaRowListX to separate file
// TODO: Gather common :+(RowN[_] and withLabels
import acolyte.Row.Row1
/**
* Pimped row list.
*/
final class ScalaRowList1[A](l: RowList1[A]) {
/**
* Symbolic alias for `append` operation with null as single value
* (inferred as expected row type).
* !! If value is not null, usual `:+` is called.
*
*/
def :+(n: Null)(implicit f: A Row.Row1[A]): RowList1[A] =
l.append(f(null.asInstanceOf[A])).asInstanceOf[RowList1[A]]
/**
* Symbolic alias for `append` operation.
*
* {{{
* rowList :+ row
* }}}
*/
def :+(row: Row1[A]): RowList1[A] = l.append(row).asInstanceOf[RowList1[A]]
/**
* Defines column label(s) per position(s) (> 0).
*
* {{{
* rowList.withLabels(1 -> "label1", 2 -> "label2")
* }}}
*/
def withLabels(labels: (Int, String)*): RowList1[A] =
labels.foldLeft(l) { (l, t)
l.withLabel(t._1, t._2).asInstanceOf[RowList1[A]]
}
}
/**
* Pimped row list.
*/
@@ -332,6 +373,7 @@ final class ScalaRowList[L <: RowList[R], R <: Row](l: L) {
* }}}
*/
def :+(row: R): L = l.append(row).asInstanceOf[L]
// TODO: Remove asInstanceOf (implicit?)
/**
* Defines column label(s) per position(s) (> 0).
@@ -3,12 +3,11 @@ package acolyte
import scala.language.implicitConversions
import Row.Row1
// Acolyte DSL
private[acolyte] trait ScalaRowLists {
#SRL#
// If no specific convertion found, default to this one
implicit def RowListAsScala[R <: Row](l: RowList[R]): ScalaRowList[RowList[R], R] = new ScalaRowList(l)
// TODO: Remove
//implicit def RowListAsScala[R <: Row](l: RowList[R]): ScalaRowList[RowList[R], R] = new ScalaRowList(l)
}
@@ -1,5 +1,6 @@
package acolyte
import acolyte.RowLists.stringList
import acolyte.Implicits._
object RowSpec extends org.specs2.mutable.Specification {
@@ -14,4 +15,20 @@ object RowSpec extends org.specs2.mutable.Specification {
Rows.row2("str", 4).list aka "cells" mustEqual List("str", 4)
}
}
"Null single value" should {
lazy val list = (stringList :+ null)
lazy val expectedRow = new Row.Row1[String](null)
"be inferred on :+" in {
val rows = list.getRows
val rs = list.resultSet
rs.next()
println(s"#rows=${list.getRows}")
(rows.size aka "row count" mustEqual 1).
and(rows.get(0) aka "row" mustEqual expectedRow).
and(rs.getObject(1) aka "single column" must beNull)
}
}
}

0 comments on commit f877821

Please sign in to comment.