anorm.ToStatementMisc.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc.
*/
package anorm
import java.util.{ UUID => JUUID }
import java.math.{ BigDecimal => JBigDec, BigInteger }
import java.net.{ URI, URL }
import java.lang.{ Boolean => JBool, Byte => JByte, Double => JDouble, Float => JFloat, Long => JLong, Short => JShort }
import java.sql.{ PreparedStatement, Timestamp }
private[anorm] trait ToStatementBase[A] { self =>
/**
* Sets value |v| on statement |s| at specified |index|.
*/
def set(s: PreparedStatement, index: Int, v: A): Unit
}
/*
* Provided instances of `ToStatement` with the lower priority.
* Actually it makes sure that `byteArrayToStatement`
* (defined in `ToStatementPriority1`) is resolved before `arrayToParameter`.
*/
sealed trait ToStatementPriority0 {
import scala.collection.immutable.SortedSet
import java.io.{ InputStream, Reader }
import scala.language.reflectiveCalls
/**
* Sets a binary stream as parameter on statement.
* For `null` value, `setNull` with `LONGVARBINARY` is called on statement.
*
* {{{
* // skip-doc-5f98a5e
* import anorm._
*
* def foo(inputStream: java.io.InputStream) =
* SQL("INSERT INTO Table(bin) VALUES {b}").on("b" -> inputStream)
* }}}
*/
implicit def binaryStreamToStatement[S <: InputStream]: ToStatement[S] =
new ToStatement[S] {
val jdbcType = implicitly[ParameterMetaData[InputStream]].jdbcType
def set(s: PreparedStatement, i: Int, bin: S) =
if (bin == (null: InputStream)) s.setNull(i, jdbcType)
else s.setBinaryStream(i, bin)
}
/**
* Sets a blob as parameter on statement.
* For `null` value, `setNull` with `BLOB` is called on statement.
*
* {{{
* // skip-doc-5f98a5e
* import anorm._
*
* def foo(byteArray: Array[Byte])(implicit con: java.sql.Connection) = {
* val blob = con.createBlob()
* blob.setBytes(1, byteArray)
*
* SQL("INSERT INTO Table(bin) VALUES {b}").on("b" -> blob)
* }
* }}}
*/
implicit def blobToStatement[B <: java.sql.Blob]: ToStatement[B] =
new ToStatement[B] {
val jdbcType = implicitly[ParameterMetaData[java.sql.Blob]].jdbcType
def set(s: PreparedStatement, i: Int, blob: B) =
if (blob == (null: java.sql.Blob)) s.setNull(i, jdbcType)
else s.setBlob(i, blob)
}
/**
* Sets a character stream as parameter on statement.
* For `null` value, `setNull` with `VARCHAR` is called on statement.
*
* {{{
* // skip-doc-5f98a5e
* import anorm._
*
* def foo(reader: java.io.Reader) =
* SQL("INSERT INTO Table(chars) VALUES {c}").on("c" -> reader)
* }}}
*/
implicit def characterStreamToStatement[R <: Reader]: ToStatement[R] =
new ToStatement[R] {
val jdbcType = implicitly[ParameterMetaData[Reader]].jdbcType
def set(s: PreparedStatement, i: Int, chars: R) =
if (chars == (null: Reader)) s.setNull(i, jdbcType)
else s.setCharacterStream(i, chars)
}
/**
* Sets boolean value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE enabled = {b}").on("b" -> true)
* }}}
*/
implicit object booleanToStatement extends ToStatement[Boolean] {
def set(s: PreparedStatement, i: Int, b: Boolean): Unit = s.setBoolean(i, b)
}
/**
* Sets Java Boolean object on statement.
* For `null` value, `setNull` with `BOOLEAN` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE enabled = {b}").
* on("b" -> java.lang.Boolean.TRUE)
* }}}
*/
implicit object javaBooleanToStatement extends ToStatement[JBool] {
val jdbcType = implicitly[ParameterMetaData[JBool]].jdbcType
def set(s: PreparedStatement, i: Int, b: JBool): Unit =
if (b != (null: JBool)) s.setBoolean(i, b) else s.setNull(i, jdbcType)
}
/**
* Sets byte value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1.toByte)
* }}}
*/
implicit object byteToStatement extends ToStatement[Byte] {
def set(s: PreparedStatement, i: Int, b: Byte): Unit = s.setByte(i, b)
}
/**
* Sets Java Byte object on statement.
* For `null` value, `setNull` with `TINYINT` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Byte(1: Byte))
* }}}
*/
implicit object javaByteToStatement extends ToStatement[JByte] {
val jdbcType = implicitly[ParameterMetaData[JByte]].jdbcType
def set(s: PreparedStatement, i: Int, b: JByte): Unit =
if (b != (null: JByte)) s.setByte(i, b) else s.setNull(i, jdbcType)
}
/**
* Sets double value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1D)
* }}}
*/
implicit object doubleToStatement extends ToStatement[Double] {
def set(s: PreparedStatement, i: Int, d: Double): Unit = s.setDouble(i, d)
}
/**
* Sets Java Double object on statement.
* For `null` value, `setNull` with `DOUBLE` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Double(1D))
* }}}
*/
implicit object javaDoubleToStatement extends ToStatement[JDouble] {
val jdbcType = implicitly[ParameterMetaData[JDouble]].jdbcType
def set(s: PreparedStatement, i: Int, d: JDouble): Unit =
if (d != (null: JDouble)) s.setDouble(i, d) else s.setNull(i, jdbcType)
}
/**
* Sets float value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1F)
* }}}
*/
implicit object floatToStatement extends ToStatement[Float] {
def set(s: PreparedStatement, i: Int, f: Float): Unit = s.setFloat(i, f)
}
/**
* Sets Java Float object on statement.
* For `null` value, `setNull` with `FLOAT` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Float(1F))
* }}}
*/
implicit object javaFloatToStatement extends ToStatement[JFloat] {
val jdbcType = implicitly[ParameterMetaData[JFloat]].jdbcType
def set(s: PreparedStatement, i: Int, f: JFloat): Unit =
if (f != (null: JFloat)) s.setFloat(i, f) else s.setNull(i, jdbcType)
}
/**
* Sets long value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1L)
* }}}
*/
implicit object longToStatement extends ToStatement[Long] {
def set(s: PreparedStatement, i: Int, l: Long): Unit = s.setLong(i, l)
}
/**
* Sets Java Long object on statement.
* For `null` value, `setNull` with `BIGINT` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Long(1L))
* }}}
*/
implicit object javaLongToStatement extends ToStatement[JLong] {
val jdbcType = implicitly[ParameterMetaData[JLong]].jdbcType
def set(s: PreparedStatement, i: Int, l: JLong): Unit =
if (l != (null: JLong)) s.setLong(i, l) else s.setNull(i, jdbcType)
}
/**
* Sets integer value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1)
* }}}
*/
implicit object intToStatement extends ToStatement[Int] {
def set(s: PreparedStatement, i: Int, v: Int): Unit = s.setInt(i, v)
}
/**
* Sets Java Integer object on statement.
* For `null` value, `setNull` with `INTEGER` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Integer(1))
* }}}
*/
implicit object integerToStatement extends ToStatement[Integer] {
val jdbcType = implicitly[ParameterMetaData[Integer]].jdbcType
def set(s: PreparedStatement, i: Int, v: Integer): Unit =
if (v != (null: Integer)) s.setInt(i, v) else s.setNull(i, jdbcType)
}
/**
* Sets short value on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").on("b" -> 1.toShort)
* }}}
*/
implicit object shortToStatement extends ToStatement[Short] {
def set(s: PreparedStatement, i: Int, v: Short): Unit = s.setShort(i, v)
}
/**
* Sets Java Short object on statement.
* For `null` value, `setNull` with `SMALLINT` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE flag = {b}").
* on("b" -> new java.lang.Short(1.toShort))
* }}}
*/
implicit object javaShortToStatement extends ToStatement[JShort] {
val jdbcType = implicitly[ParameterMetaData[JShort]].jdbcType
def set(s: PreparedStatement, i: Int, v: JShort): Unit =
if (v != (null: JShort)) s.setShort(i, v) else s.setNull(i, jdbcType)
}
/**
* Sets Java Character as parameter value.
* For `null` character, `setNull` with `VARCHAR` is called on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM tbl WHERE flag = {c}").
* on("c" -> new java.lang.Character('f'))
* }}}
*/
implicit object characterToStatement extends ToStatement[Character] {
val jdbcType = implicitly[ParameterMetaData[Character]].jdbcType
def set(s: PreparedStatement, i: Int, ch: Character) =
if (ch != (null: Character)) s.setString(i, ch.toString)
else s.setNull(i, jdbcType)
}
/**
* Sets character as parameter value.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM tbl WHERE flag = {c}").on("c" -> 'f')
* }}}
*/
implicit object charToStatement extends ToStatement[Char] {
def set(s: PreparedStatement, i: Int, ch: Char): Unit =
s.setString(i, ch.toString)
}
/**
* Sets string as parameter value.
* Value `null` is accepted.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM tbl WHERE name = {n}").on("n" -> "str")
* }}}
*/
implicit object stringToStatement extends ToStatement[String] {
def set(s: PreparedStatement, i: Int, str: String) = s.setString(i, str)
}
/**
* Sets null for None value.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE category = {c}").on("c" -> None)
*
* // Rather use:
* anorm.SQL("SELECT * FROM Test WHERE category = {c}").
* on("c" -> Option.empty[String]) // Not deprecated
* }}}
*/
@deprecated("Parameter value should be passed using `Option.empty[T]`", since = "2.3.7")
implicit object noneToStatement extends ToStatement[None.type] {
def set(s: PreparedStatement, i: Int, n: None.type) =
s.setObject(i, null: Object)
}
/**
* Sets not empty optional A inferred as Some[A].
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE category = {c}").on("c" -> Some("cat"))
* }}}
*/
implicit def someToStatement[A](implicit c: ToStatement[A]): ToStatement[Some[A]] =
new ToStatement[Some[A]] with NotNullGuard {
def set(s: PreparedStatement, index: Int, v: Some[A]): Unit =
c.set(s, index, v.get)
}
/**
* Sets optional A inferred as Option[A].
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE category = {c}").on("c" -> Option("cat"))
* SQL"SELECT * FROM Test WHERE nullable_int = \\${Option.empty[Int]}"
* }}}
*/
implicit def optionToStatement[A](implicit c: ToStatement[A], meta: ParameterMetaData[A]): ToStatement[Option[A]] =
new ToStatement[Option[A]] with NotNullGuard {
def set(s: PreparedStatement, index: Int, o: Option[A]) = {
o.fold[Unit](s.setNull(index, meta.jdbcType))(c.set(s, index, _))
}
}
/**
* Sets Java big integer on statement.
* For `null` value, `setNull` with `NUMERIC` is called on statement.
*
* {{{
* import anorm._
*
* SQL("UPDATE tbl SET max = {m}").
* on("m" -> new java.math.BigInteger("15"))
* }}}
*/
implicit object javaBigIntegerToStatement extends ToStatement[BigInteger] {
val jdbcType = implicitly[ParameterMetaData[BigInteger]].jdbcType
def set(s: PreparedStatement, index: Int, v: BigInteger): Unit =
if (v != (null: BigInteger)) s.setBigDecimal(index, new JBigDec(v))
else s.setNull(index, jdbcType)
}
/**
* Sets big integer on statement.
* For `null` value, `setNull` with `NUMERIC` is called on statement.
*
* {{{
* import anorm._
*
* SQL("UPDATE tbl SET max = {m}").on("m" -> BigInt(15))
* }}}
*/
implicit object scalaBigIntegerToStatement extends ToStatement[BigInt] {
val jdbcType = implicitly[ParameterMetaData[BigInt]].jdbcType
def set(s: PreparedStatement, index: Int, v: BigInt): Unit =
if (v != (null: BigInt)) s.setBigDecimal(index, new JBigDec(v.bigInteger))
else s.setNull(index, jdbcType)
}
/**
* Sets Java big decimal on statement.
* Value `null` is accepted.
*
* {{{
* import anorm._
*
* SQL("UPDATE tbl SET max = {m}").
* on("m" -> new java.math.BigDecimal(10.02F))
* }}}
*/
implicit object javaBigDecimalToStatement extends ToStatement[JBigDec] {
def set(s: PreparedStatement, index: Int, v: JBigDec): Unit =
s.setBigDecimal(index, v)
}
/**
* Sets big decimal on statement.
* For `null` value, `setNull` with `DECIMAL` is called on statement.
*
* {{{
* import anorm._
*
* SQL("UPDATE tbl SET max = {m}").on("m" -> BigDecimal(10.02F))
* }}}
*/
implicit object scalaBigDecimalToStatement extends ToStatement[BigDecimal] {
val jdbcType = implicitly[ParameterMetaData[BigDecimal]].jdbcType
def set(s: PreparedStatement, index: Int, v: BigDecimal): Unit =
if (v != (null: BigDecimal)) s.setBigDecimal(index, v.bigDecimal)
else s.setNull(index, jdbcType)
}
/**
* Sets timestamp as statement parameter.
* Value `null` is accepted.
*
* {{{
* import anorm._
*
* def foo(date: java.util.Date) =
* SQL("UPDATE tbl SET modified = {ts}").
* on("ts" -> new java.sql.Timestamp(date.getTime))
* }}}
*/
implicit object timestampToStatement extends ToStatement[Timestamp] {
def set(s: PreparedStatement, index: Int, ts: Timestamp): Unit =
s.setTimestamp(index, ts)
}
/**
* Sets date as statement parameter.
* For `null` value, `setNull` with `TIMESTAMP` is called on statement.
*
* {{{
* import anorm._
*
* SQL("UPDATE tbl SET modified = {d}").on("d" -> new java.util.Date())
* }}}
*/
implicit object dateToStatement extends ToStatement[java.util.Date] {
val jdbcType = implicitly[ParameterMetaData[java.util.Date]].jdbcType
def set(s: PreparedStatement, index: Int, date: java.util.Date): Unit =
if (date != (null: java.util.Date)) {
s.setTimestamp(index, new Timestamp(date.getTime))
} else s.setNull(index, jdbcType)
}
/**
* Sets a wrapped timestamp as statement parameter.
* For `null` value, `setNull` with `TIMESTAMP` is called on statement.
*
* {{{
* // skip-doc-5f98a5e
* import anorm._
*
* val wrapper = new {
* // Any value with a `.getTimestamp`
* val getTimestamp = new java.sql.Timestamp(123L)
* }
*
* SQL("UPDATE tbl SET modified = {ts}").on("ts" -> wrapper)
* }}}
*/
implicit def timestampWrapper1ToStatement[T <: TimestampWrapper1]: ToStatement[T] = new ToStatement[T] {
def set(s: PreparedStatement, index: Int, tsw: T): Unit =
if (
tsw != (null: TimestampWrapper1) &&
tsw.getTimestamp != (null: TimestampWrapper1)
) {
s.setTimestamp(index, tsw.getTimestamp)
} else s.setNull(index, timestampWrapper1JdbcType)
}
private val timestampWrapper1JdbcType =
implicitly[ParameterMetaData[TimestampWrapper1]].jdbcType
/**
* Sets UUID as statement parameter.
* For `null` value, `setNull` with `VARCHAR` is called on statement.
*
* {{{
* import anorm._
*
* SQL("INSERT INTO lang_tbl(id, name) VALUE ({i}, {n})").
* on("i" -> java.util.UUID.randomUUID(), "n" -> "lang")
* }}}
*/
implicit object uuidToStatement extends ToStatement[JUUID] {
val jdbcType = implicitly[ParameterMetaData[JUUID]].jdbcType
def set(s: PreparedStatement, index: Int, id: JUUID): Unit =
if (id != (null: JUUID)) s.setString(index, id.toString)
else s.setNull(index, jdbcType)
}
/**
* Sets URI as statement parameter.
* For `null` value, `setNull` with `VARCHAR` is called on statement.
*
* {{{
* import anorm._
*
* SQL("INSERT INTO lang_tbl(id, name) VALUE ({i}, {n})").
* on("i" -> new java.net.URI("https://github.com/playframework/"),
* "n" -> "lang")
* }}}
*/
implicit object uriToStatement extends ToStatement[URI] {
val jdbcType = implicitly[ParameterMetaData[URI]].jdbcType
def set(s: PreparedStatement, index: Int, uri: URI): Unit =
if (uri != (null: URI)) s.setString(index, uri.toString)
else s.setNull(index, jdbcType)
}
/**
* Sets URL as statement parameter.
* For `null` value, `setNull` with `VARCHAR` is called on statement.
*
* {{{
* import anorm._
*
* SQL("INSERT INTO lang_tbl(id, name) VALUE ({i}, {n})").
* on("i" -> new java.net.URL("https://github.com/playframework/"),
* "n" -> "lang")
* }}}
*/
implicit object urlToStatement extends ToStatement[URL] {
val jdbcType = implicitly[ParameterMetaData[URL]].jdbcType
def set(s: PreparedStatement, index: Int, url: URL): Unit =
if (url != (null: URL)) s.setString(index, url.toString)
else s.setNull(index, jdbcType)
}
/**
* Sets opaque value as statement parameter.
* UNSAFE: It's set using `java.sql.PreparedStatement.setObject`.
*
* {{{
* import anorm._
*
* SQL("EXEC indexed_at {d}").
* on("d" -> anorm.Object(new java.util.Date()))
* }}}
*/
implicit object objectToStatement extends ToStatement[anorm.Object] {
def set(s: PreparedStatement, index: Int, o: anorm.Object): Unit =
s.setObject(index, o.value)
}
/**
* Sets multi-value parameter from list on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE cat IN ({categories})").
* on("categories" -> List(1, 3, 4))
* }}}
*/
implicit def listToStatement[A](implicit c: ToStatement[A]): ToStatement[List[A]] = traversableToStatement[A, List[A]]
/**
* Sets multi-value parameter from sequence on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE cat IN ({categories})").
* on("categories" -> Seq("a", "b", "c"))
* }}}
*/
implicit def seqToStatement[A](implicit c: ToStatement[A]): ToStatement[Seq[A]] = traversableToStatement[A, Seq[A]]
/**
* Sets multi-value parameter from set on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE cat IN ({categories})").
* on("categories" -> Set(1, 3, 4))
* }}}
*/
implicit def setToStatement[A](implicit c: ToStatement[A]): ToStatement[Set[A]] = traversableToStatement[A, Set[A]]
/**
* Sets multi-value parameter from sorted set on statement.
*
* {{{
* import scala.collection.immutable.SortedSet
*
* import anorm._
*
* SQL("SELECT * FROM Test WHERE cat IN ({categories})").
* on("categories" -> SortedSet("a", "b", "c"))
* }}}
*/
implicit def sortedSetToStatement[A](implicit c: ToStatement[A]): ToStatement[SortedSet[A]] =
traversableToStatement[A, SortedSet[A]]
/**
* Sets multi-value parameter from stream on statement.
*/
implicit def streamToStatement[A](implicit c: ToStatement[A]): ToStatement[Compat.LazyLst[A]] =
traversableToStatement[A, Compat.LazyLst[A]]
/**
* Sets multi-value parameter from vector on statement.
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test WHERE cat IN ({categories})").
* on("categories" -> Vector("a", "b", "c"))
* }}}
*/
implicit def vectorToStatement[A](implicit c: ToStatement[A]): ToStatement[Vector[A]] =
traversableToStatement[A, Vector[A]]
/**
* Sets multi-value parameter on statement, with custom formatting
* (using [[SeqParameter]]).
*
* {{{
* import anorm._
*
* SQL("SELECT * FROM Test t WHERE {categories}").
* on("categories" -> SeqParameter(
* seq = Seq("a", "b", "c"), sep = " OR ",
* pre = "EXISTS (SELECT NULL FROM j WHERE t.id=j.id AND name=",
* post = ")"))
* }}}
*/
implicit def seqParamToStatement[A](implicit c: ToStatement[Seq[A]]): ToStatement[SeqParameter[A]] =
new ToStatement[SeqParameter[A]] with NotNullGuard {
def set(s: PreparedStatement, offset: Int, ps: SeqParameter[A]): Unit =
c.set(s, offset, ps.values)
}
@inline private def traversableToStatement[A, T <: Compat.Trav[A]](implicit c: ToStatement[A]) = new ToStatement[T]
with NotNullGuard {
def set(s: PreparedStatement, offset: Int, ps: T) =
if (ps == (null: Compat.Trav[A])) throw new IllegalArgumentException()
else {
ps.foldLeft(offset) { (i, p) => c.set(s, i, p); i + 1 }
()
}
}
/**
* Sets an array parameter on statement (see `java.sql.Array`).
*
* {{{
* import anorm._
*
* SQL("INSERT INTO Table(arr) VALUES {a}").
* on("a" -> Array("A", "2", "C"))
* }}}
*/
implicit def arrayToParameter[A <: AnyRef](implicit m: ParameterMetaData[A]): ToStatement[Array[A]] =
new ToStatement[Array[A]] with NotNullGuard {
def set(s: PreparedStatement, i: Int, arr: Array[A]) =
if (arr == (null: AnyRef)) throw new IllegalArgumentException()
else s.setArray(i, s.getConnection.createArrayOf(m.sqlType, arr.map(a => a: AnyRef)))
}
}
/** Meta data for Joda parameters */
object JodaParameterMetaData {
import org.joda.time.{ DateTime, LocalDate, LocalDateTime, Instant }
import java.sql.Types
sealed trait JodaTimeMetaData {
val sqlType = "TIMESTAMP"
val jdbcType = Types.TIMESTAMP
}
/** Date/time parameter meta data */
implicit object JodaDateTimeMetaData extends ParameterMetaData[DateTime] with JodaTimeMetaData
/** Local date/time parameter meta data */
implicit object JodaLocalDateTimeMetaData extends ParameterMetaData[LocalDateTime] with JodaTimeMetaData
/** Instant parameter meta data */
implicit object JodaInstantMetaData extends ParameterMetaData[Instant] with JodaTimeMetaData
/** Local date parameter meta data */
implicit object JodaLocalDateMetaData extends ParameterMetaData[LocalDate] with JodaTimeMetaData
}
sealed trait JodaToStatement {
import org.joda.time.{ DateTime, LocalDate, LocalDateTime, Instant }
/**
* Sets joda-time DateTime as statement parameter.
* For `null` value, `setNull` with `TIMESTAMP` is called on statement.
*/
implicit def jodaDateTimeToStatement(implicit meta: ParameterMetaData[DateTime]): ToStatement[DateTime] =
new ToStatement[DateTime] {
def set(s: PreparedStatement, index: Int, date: DateTime): Unit =
if (date != (null: DateTime)) {
s.setTimestamp(index, new Timestamp(date.getMillis()))
} else s.setNull(index, meta.jdbcType)
}
/**
* Sets a local date/time on statement.
*/
implicit def jodaLocalDateTimeToStatement(implicit
meta: ParameterMetaData[LocalDateTime]
): ToStatement[LocalDateTime] = new ToStatement[LocalDateTime] {
def set(s: PreparedStatement, i: Int, t: LocalDateTime): Unit =
if (t == (null: LocalDateTime)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, new Timestamp(t.toDateTime.getMillis))
}
/**
* Sets a local date on statement.
*/
implicit def jodaLocalDateToStatement(implicit meta: ParameterMetaData[LocalDate]): ToStatement[LocalDate] =
new ToStatement[LocalDate] {
def set(s: PreparedStatement, i: Int, t: LocalDate): Unit =
if (t == (null: LocalDate)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, new Timestamp(t.toDate.getTime))
}
/**
* Sets joda-time Instant as statement parameter.
* For `null` value, `setNull` with `TIMESTAMP` is called on statement.
*/
implicit def jodaInstantToStatement(implicit meta: ParameterMetaData[Instant]): ToStatement[Instant] =
new ToStatement[Instant] {
def set(s: PreparedStatement, index: Int, instant: Instant): Unit =
if (instant != (null: Instant)) {
s.setTimestamp(index, new Timestamp(instant.getMillis))
} else s.setNull(index, meta.jdbcType)
}
}
sealed trait JavaTimeToStatement {
import java.time.{ Instant, LocalDate, LocalDateTime, ZonedDateTime }
/**
* Sets a temporal instant on statement.
*
* {{{
* import java.time.Instant
* import anorm._
*
* SQL("SELECT * FROM Test WHERE time < {b}").on("b" -> Instant.now)
* }}}
*/
implicit def instantToStatement(implicit meta: ParameterMetaData[Instant]): ToStatement[Instant] =
new ToStatement[Instant] {
def set(s: PreparedStatement, i: Int, t: Instant): Unit =
if (t == (null: Instant)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, Timestamp.from(t))
}
/**
* Sets a local date/time on statement.
*
* {{{
* import java.time.LocalDateTime
* import anorm._
*
* SQL("SELECT * FROM Test WHERE time < {b}").on("b" -> LocalDateTime.now)
* }}}
*/
implicit def localDateTimeToStatement(implicit meta: ParameterMetaData[LocalDateTime]): ToStatement[LocalDateTime] =
new ToStatement[LocalDateTime] {
def set(s: PreparedStatement, i: Int, t: LocalDateTime): Unit =
if (t == (null: LocalDateTime)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, Timestamp.valueOf(t))
}
/**
* Sets a local date on statement.
*
* {{{
* import java.time.LocalDate
* import anorm._
*
* SQL("SELECT * FROM Test WHERE time < {b}").on("b" -> LocalDate.now)
* }}}
*/
implicit def localDateToStatement(implicit meta: ParameterMetaData[LocalDate]): ToStatement[LocalDate] =
new ToStatement[LocalDate] {
def set(s: PreparedStatement, i: Int, t: LocalDate): Unit =
if (t == (null: LocalDate)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, Timestamp.valueOf(t.atStartOfDay()))
}
/**
* Sets a zoned date/time on statement.
*
* {{{
* import java.time.ZonedDateTime
* import anorm._
*
* SQL("SELECT * FROM Test WHERE time < {b}").on("b" -> ZonedDateTime.now)
* }}}
*/
implicit def zonedDateTimeToStatement(implicit meta: ParameterMetaData[ZonedDateTime]): ToStatement[ZonedDateTime] =
new ToStatement[ZonedDateTime] {
def set(s: PreparedStatement, i: Int, t: ZonedDateTime): Unit =
if (t == (null: ZonedDateTime)) s.setNull(i, meta.jdbcType)
else s.setTimestamp(i, Timestamp.from(t.toInstant))
}
}
sealed trait ToStatementPriority1 extends ToStatementPriority0 {
/**
* Sets an array of byte as parameter on statement.
* For `null` value, `setNull` with `LONGVARBINARY` is called on statement.
*
* {{{
* import anorm._
*
* def foo(arrayOfBytes: Array[Byte]) =
* SQL("INSERT INTO Table(bin) VALUES {b}").on("b" -> arrayOfBytes)
* }}}
*/
implicit object byteArrayToStatement extends ToStatement[Array[Byte]] {
val jdbcType = implicitly[ParameterMetaData[Array[Byte]]].jdbcType
@SuppressWarnings(Array("ArrayEquals" /*null check*/ ))
def set(s: PreparedStatement, i: Int, bin: Array[Byte]) =
if (bin == (null: Array[Byte])) s.setNull(i, jdbcType)
else s.setBytes(i, bin)
}
}
/**
* Provided conversions to set statement parameter.
*/
private[anorm] class ToStatementConversions extends ToStatementPriority1 with JodaToStatement with JavaTimeToStatement {
/**
* Resolves `ToStatement` instance for the given type.
*
* {{{
* import anorm.ToStatement
*
* val to: ToStatement[String] = ToStatement.of[String]
* }}}
*/
@inline def of[T](implicit to: ToStatement[T]): ToStatement[T] = to
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy