scalikejdbc.SQL.scala Maven / Gradle / Ivy
package scalikejdbc
import java.sql.PreparedStatement
import scala.language.higherKinds
import scala.collection.compat._
/**
* SQL abstraction's companion object
*
* {{{
* ConnectionPool.singleton("jdbc:...","user","password")
* case class User(id: Int, name: String)
*
* val users = DB.readOnly { implicit session =>
* SQL("select * from user").map { rs =>
* User(rs.int("id"), rs.string("name"))
* }.list.apply()
* }
*
* DB .autoCommit { implicit session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* DB localTx { implicit session =>
* SQL("insert into user values (?,?)").bind(123, "Alice").update.apply()
* }
*
* using(DB(ConnectionPool.borrow())) { db =>
* db.begin()
* try {
* DB withTx { implicit session =>
* SQL("update user set name = ? where id = ?").bind("Alice", 123).update.apply()
* }
* db.commit()
* } catch { case e =>
* db.rollbackIfActive()
* throw e
* }
* }
* }}}
*/
object SQL {
private[scalikejdbc] def noExtractor[A](message: String): WrappedResultSet => A = { (rs: WrappedResultSet) =>
throw new IllegalStateException(message)
}
def apply[A](sql: String): SQL[A, NoExtractor] = new SQLToIterableImpl[A, NoExtractor](sql, Seq.empty)(noExtractor[A](
ErrorMessage.THIS_IS_A_BUG))
}
/**
* Name binding [[scalikejdbc.SQL]] instance factory.
*/
private[scalikejdbc] object validateAndConvertToNormalStatement extends LogSupport {
def apply(sql: String, settings: SettingsProvider, parameters: scala.collection.Seq[(Symbol, Any)]): (String, scala.collection.Seq[Any]) = {
val names = SQLTemplateParser.extractAllParameters(sql)
val sqlWithPlaceHolders = SQLTemplateParser.convertToSQLWithPlaceHolders(sql)
apply(sql, sqlWithPlaceHolders, names, settings, parameters)
}
def apply(sql: String, sqlWithPlaceHolders: String, names: List[Symbol], settings: SettingsProvider, parameters: scala.collection.Seq[(Symbol, Any)]): (String, scala.collection.Seq[Any]) = {
// check all the parameters passed by #bindByName are actually used
import scalikejdbc.globalsettings._
settings.nameBindingSQLValidator(GlobalSettings.nameBindingSQLValidator).ignoredParams match {
case NoCheckForIgnoredParams => // no op
case validation =>
parameters.foreach {
param =>
if (!names.contains(param._1)) {
validation match {
case NoCheckForIgnoredParams => // no op
case InfoLoggingForIgnoredParams => log.info(ErrorMessage.BINDING_IS_IGNORED + " (" + param._1 + ")")
case WarnLoggingForIgnoredParams => log.warn(ErrorMessage.BINDING_IS_IGNORED + " (" + param._1 + ")")
case ExceptionForIgnoredParams => throw new IllegalStateException(ErrorMessage.BINDING_IS_IGNORED + " (" + param._1 + ")")
}
}
}
}
(sqlWithPlaceHolders, names.map { name =>
parameters match {
case Nil => Nil
case _ =>
parameters.find(_._1 == name).orElse {
throw new IllegalArgumentException(ErrorMessage.BINDING_PARAMETER_IS_MISSING + " (" + name + ")")
}.map(_._2).orNull[Any]
}
})
}
}
/**
* Represents an extractor is already specified or not
*/
sealed trait WithExtractor
/**
* Represents that this SQL already has an extractor
*/
trait HasExtractor extends WithExtractor
/**
* Represents that this SQL doesn't have an extractor yet
*/
trait NoExtractor extends WithExtractor
/**
* Generalized type constraints for WithExtractor
*/
object GeneralizedTypeConstraintsForWithExtractor {
// customized error message
@annotation.implicitNotFound(msg = "No extractor is specified. You have forgotten call #map(...) before #apply().")
sealed abstract class =:=[From, To] extends (From => To) with Serializable
private[this] final val singleton_=:= = new =:=[WithExtractor, WithExtractor] { def apply(x: WithExtractor): WithExtractor = x }
object =:= {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}
}
/**
* Extractor
*/
private[scalikejdbc] trait Extractor[A] {
def extractor: (WrappedResultSet) => A
}
/**
* SQL abstraction.
*
* @param statement SQL template
* @param rawParameters parameters
* @param f extractor function
* @tparam A return type
*/
abstract class SQL[A, E <: WithExtractor](
val statement: String,
private[scalikejdbc] val rawParameters: scala.collection.Seq[Any])(f: WrappedResultSet => A)
extends Extractor[A] {
final lazy val parameters: scala.collection.Seq[Any] = rawParameters.map {
case ParameterBinder(v) => v
case x => x
}
override def extractor: (WrappedResultSet) => A = f
private[this] var _fetchSize: Option[Int] = None
private[this] val _tags: scala.collection.mutable.ListBuffer[String] = new scala.collection.mutable.ListBuffer[String]()
private[this] var _queryTimeout: Option[Int] = None
private[this] var _settings: SettingsProvider = SettingsProvider.default
type ThisSQL = SQL[A, E]
type SQLWithExtractor = SQL[A, HasExtractor]
protected def withParameters(params: scala.collection.Seq[Any]): SQL[A, E] = ???
protected def withStatementAndParameters(state: String, params: scala.collection.Seq[Any]): SQL[A, E] = ???
protected def withExtractor[B](f: WrappedResultSet => B): SQL[B, HasExtractor] = ???
def dbSettingSettings(settings: SettingsProvider): this.type = {
this._settings = settings
this
}
/**
* Set fetchSize for this query.
*
* @param fetchSize fetch size
* @return this
*/
def fetchSize(fetchSize: Int): this.type = {
this._fetchSize = Some(fetchSize)
this
}
def fetchSize(fetchSize: Option[Int]): this.type = {
this._fetchSize = fetchSize
this
}
/**
* Appends tags to this SQL object.
*
* @param tags tags
* @return this
*/
def tags(tags: String*): this.type = {
this._tags ++= tags
this
}
/**
* Returns tags for this SQL object.
*
* @return tags
*/
def tags: scala.collection.Seq[String] = this._tags.toSeq
/**
* Returns fetchSize for this query.
*
* @return fetch size
*/
def fetchSize: Option[Int] = this._fetchSize
/**
* Set queryTimeout for this query.
*
* @param seconds query timeout seconds
* @return this
*/
def queryTimeout(seconds: Int): this.type = {
this._queryTimeout = Some(seconds)
this
}
def queryTimeout(seconds: Option[Int]): this.type = {
this._queryTimeout = seconds
this
}
/**
* Returns queryTimeout for this query.
*
* @return query timeout seconds
*/
def queryTimeout: Option[Int] = this._queryTimeout
/**
* Creates a new DBSessionAttributesSwitcher which enables switching the attributes for a DBSession.
*/
protected def createDBSessionAttributesSwitcher(): DBSessionAttributesSwitcher = {
new DBSessionAttributesSwitcher(this)
}
/**
* Returns One-to-X API builder.
*/
def one[Z](f: (WrappedResultSet) => A): OneToXSQL[A, E, Z] = {
val q: OneToXSQL[A, E, Z] = new OneToXSQL[A, E, Z](statement, rawParameters)(f)
q.queryTimeout(queryTimeout)
q.fetchSize(fetchSize)
q.tags(tags.toSeq: _*)
q
}
/**
* Binds parameters to SQL template in order.
*
* @param parameters parameters
* @return SQL instance
*/
def bind(parameters: Any*): SQL[A, E] = {
withParameters(parameters).fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Binds named parameters to SQL template.
*
* @param parametersByName named parameters
* @return SQL instance
*/
def bindByName(parametersByName: (Symbol, Any)*): SQL[A, E] = {
val (_statement, _parameters) = validateAndConvertToNormalStatement(statement, _settings, parametersByName)
withStatementAndParameters(_statement, _parameters).fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Binds parameters for batch
*
* @param parameters parameters
* @return SQL for batch
*/
def batch(parameters: scala.collection.Seq[Any]*): SQLBatch = {
new SQLBatch(statement, parameters, tags)
}
/**
* Binds parameters for largeBatch
*
* @param parameters parameters
* @return SQL for batch
*/
def largeBatch(parameters: scala.collection.Seq[Any]*): SQLLargeBatch =
new SQLLargeBatch(statement, parameters, tags)
/**
* Binds parameters for batch
*
* @param parameters parameters
* @return SQL for batch
*/
def batchAndReturnGeneratedKey(parameters: scala.collection.Seq[Any]*): SQLBatchWithGeneratedKey = {
new SQLBatchWithGeneratedKey(statement, parameters, tags)(None)
}
/**
* Binds parameters for batch
*
* @param generatedKeyName generated key name
* @param parameters parameters
* @return SQL for batch
*/
def batchAndReturnGeneratedKey(generatedKeyName: String, parameters: scala.collection.Seq[Any]*): SQLBatchWithGeneratedKey = {
new SQLBatchWithGeneratedKey(statement, parameters, tags)(Some(generatedKeyName))
}
/**
* Binds parameters for batch
*
* @param parameters parameters
* @return SQL for batch
*/
def batchByName(parameters: scala.collection.Seq[(Symbol, Any)]*): SQLBatch = {
val names = SQLTemplateParser.extractAllParameters(statement)
val sqlWithPlaceHolders = SQLTemplateParser.convertToSQLWithPlaceHolders(statement)
val _sql = validateAndConvertToNormalStatement(statement, sqlWithPlaceHolders, names, _settings, parameters.headOption.getOrElse(Seq.empty))._1
val _parameters: scala.collection.Seq[scala.collection.Seq[Any]] = parameters.map { p =>
validateAndConvertToNormalStatement(statement, sqlWithPlaceHolders, names, _settings, p)._2
}
new SQLBatch(_sql, _parameters, tags)
}
/**
* Apply the operation to all elements of result set
*
* @param op operation
*/
def foreach(op: WrappedResultSet => Unit)(implicit session: DBSession): Unit = {
val attributesSwitcher = createDBSessionAttributesSwitcher()
val f: DBSession => Unit =
DBSessionWrapper(_, attributesSwitcher).foreach(statement, rawParameters.toSeq: _*)(op)
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
/**
* folding into one value
*
* @param z initial value
* @param op operation
*/
def foldLeft[A](z: A)(op: (A, WrappedResultSet) => A)(implicit session: DBSession): A = {
val attributesSwitcher = createDBSessionAttributesSwitcher()
val f: DBSession => A =
DBSessionWrapper(_, attributesSwitcher).foldLeft(statement, rawParameters.toSeq: _*)(z)(op)
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
/**
* Maps values from each [[scalikejdbc.WrappedResultSet]] object.
*
* @param f extractor function
* @tparam A return type
* @return SQL instance
*/
def map[A](f: WrappedResultSet => A): SQL[A, HasExtractor] = {
withExtractor[A](f).fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Maps values as a Map value from each [[scalikejdbc.WrappedResultSet]] object.
*
* @return SQL instance
*/
def toMap(): SQL[Map[String, Any], HasExtractor] = map(_.toMap)
/**
* Same as #single.
*
* @return SQL instance
*/
def toOption(): SQLToOption[A, E] = {
new SQLToOptionImpl[A, E](statement, rawParameters)(extractor)(isSingle = true)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Set execution type as single.
*
* @return SQL instance
*/
def single(): SQLToOption[A, E] = toOption()
/**
* Same as #first.
*
* @return SQL instance
*/
def headOption(): SQLToOption[A, E] = {
new SQLToOptionImpl[A, E](statement, rawParameters)(extractor)(isSingle = false)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Set execution type as first.
*
* @return SQL instance
*/
def first(): SQLToOption[A, E] = headOption()
/**
* Same as #list
*
* @return SQL instance
*/
def toList(): SQLToList[A, E] = {
new SQLToListImpl[A, E](statement, rawParameters)(extractor)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Set execution type as list.
*
* @return SQL instance
*/
def list(): SQLToList[A, E] = toList()
/**
* Same as #collection
*
* @return SQL instance
*/
def toCollection: SQLToCollection[A, E] = {
new SQLToCollectionImpl[A, E](statement, rawParameters)(extractor)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* Set execution type as collection.
*
* @return SQL instance
*/
def collection: SQLToCollection[A, E] = toCollection
/**
* Same as #iterable.
*
* @return SQL instance
*/
def toIterable(): SQLToIterable[A, E] = {
new SQLToIterableImpl[A, E](statement, rawParameters)(extractor)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
@deprecated(message = "will be removed. use toIterable() instead", since = "3.3.0")
def toTraverable(): SQLToIterable[A, E] = toIterable()
/**
* Set execution type as iterable.
*
* @return SQL instance
*/
def iterable(): SQLToIterable[A, E] = toIterable()
@deprecated(message = "will be removed. use iterable() instead", since = "3.3.0")
def traversable(): SQLToIterable[A, E] = toIterable()
/**
* Set execution type as execute
*
* @return SQL instance
*/
def execute(): SQLExecution = {
new SQLExecution(statement, rawParameters, tags)((stmt: PreparedStatement) => {})((stmt: PreparedStatement) => {})
}
/**
* Set execution type as execute with filters
*
* @param before before filter
* @param after after filter
* @return SQL instance
*/
def executeWithFilters(before: (PreparedStatement) => Unit, after: (PreparedStatement) => Unit): SQLExecution = {
new SQLExecution(statement, rawParameters, tags)(before)(after)
}
/**
* Set execution type as executeUpdate
*
* @return SQL instance
*/
def executeUpdate(): SQLUpdate = update()
/**
* Set execution type as executeUpdate with filters
*
* @param before before filter
* @param after after filter
* @return SQL instance
*/
def executeUpdateWithFilters(before: (PreparedStatement) => Unit, after: (PreparedStatement) => Unit): SQLUpdate = {
updateWithFilters(before, after)
}
/**
* Set execution type as executeUpdate
*
* @return SQL instance
*/
def update(): SQLUpdate = {
new SQLUpdate(statement, rawParameters, tags)((stmt: PreparedStatement) => {})((stmt: PreparedStatement) => {})
}
/**
* Set execution type as executeUpdate with filters
*
* @param before before filter
* @param after after filter
* @return SQL instance
*/
def updateWithFilters(before: (PreparedStatement) => Unit, after: (PreparedStatement) => Unit): SQLUpdate = {
new SQLUpdate(statement, rawParameters, tags)(before)(after)
}
/**
* Set execution type as `executeLargeUpdate`
*
* @return SQL instance
*/
def largeUpdate(): SQLLargeUpdate =
new SQLLargeUpdate(statement, rawParameters, tags)(_ => {})(_ => {})
/**
* Set execution type as `executeLargeUpdate` with filters
*
* @param before before filter
* @param after after filter
* @return SQL instance
*/
def largeUpdateWithFilters(before: PreparedStatement => Unit, after: PreparedStatement => Unit): SQLLargeUpdate =
new SQLLargeUpdate(statement, rawParameters, tags)(before)(after)
/**
* Set execution type as updateAndReturnGeneratedKey
*
* @return SQL instance
*/
def updateAndReturnGeneratedKey(): SQLUpdateWithGeneratedKey = {
updateAndReturnGeneratedKey(1)
}
def updateAndReturnGeneratedKey(name: String): SQLUpdateWithGeneratedKey = {
new SQLUpdateWithGeneratedKey(statement, rawParameters, this.tags)(name)
}
def updateAndReturnGeneratedKey(index: Int): SQLUpdateWithGeneratedKey = {
new SQLUpdateWithGeneratedKey(statement, rawParameters, this.tags)(index)
}
def stripMargin(marginChar: Char): SQL[A, E] =
withStatementAndParameters(statement.stripMargin(marginChar), rawParameters)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
def stripMargin: SQL[A, E] =
withStatementAndParameters(statement.stripMargin, rawParameters)
.fetchSize(fetchSize).tags(tags.toSeq: _*).queryTimeout(queryTimeout)
}
/**
* SQL which execute java.sql.Statement#executeBatch().
*
* @param statement SQL template
* @param parameters parameters
*/
class SQLBatch(val statement: String, val parameters: scala.collection.Seq[scala.collection.Seq[Any]], val tags: scala.collection.Seq[String] = Nil) {
def apply[C[_]]()(implicit session: DBSession, factory: Factory[Int, C[Int]]): C[Int] = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
val f: DBSession => C[Int] = DBSessionWrapper(_, attributesSwitcher).batch(statement, parameters.toSeq: _*)
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
object SQLBatch {
def unapply(sqlObject: SQLBatch): Option[(String, scala.collection.Seq[scala.collection.Seq[Any]], scala.collection.Seq[String])] = {
Some((sqlObject.statement, sqlObject.parameters, sqlObject.tags))
}
}
/**
* SQL which execute java.sql.Statement#executeLargeBatch().
*
* @param statement SQL template
* @param parameters parameters
*/
class SQLLargeBatch private[scalikejdbc] (statement: String, parameters: scala.collection.Seq[scala.collection.Seq[Any]], tags: scala.collection.Seq[String]) {
def apply[C[_]]()(implicit session: DBSession, factory: Factory[Long, C[Long]]): C[Long] = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
val f: DBSession => C[Long] = DBSessionWrapper(_, attributesSwitcher).largeBatch(statement, parameters.toSeq: _*)
session match {
case AutoSession =>
DB.autoCommit(f)
case NamedAutoSession(name, _) =>
NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession =>
DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) =>
NamedDB(name, session.settings).readOnly(f)
case _ =>
f(session)
}
}
}
class SQLBatchWithGeneratedKey(val statement: String, val parameters: scala.collection.Seq[scala.collection.Seq[Any]], val tags: scala.collection.Seq[String] = Nil)(val key: Option[String]) {
def apply[C[_]]()(implicit session: DBSession, factory: Factory[Long, C[Long]]): C[Long] = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
val f: DBSession => C[Long] = (session) => {
key match {
case Some(k) => DBSessionWrapper(session, attributesSwitcher).batchAndReturnSpecifiedGeneratedKey(statement, k, parameters.toSeq: _*)
case _ => DBSessionWrapper(session, attributesSwitcher).batchAndReturnGeneratedKey(statement, parameters.toSeq: _*)
}
}
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
object SQLBatchWithGeneratedKey {
def unapply(sqlObject: SQLBatchWithGeneratedKey): Option[(String, scala.collection.Seq[scala.collection.Seq[Any]], scala.collection.Seq[String], Option[String])] = {
Some((sqlObject.statement, sqlObject.parameters, sqlObject.tags, sqlObject.key))
}
}
/**
* SQL which execute java.sql.Statement#execute().
*
* @param statement SQL template
* @param parameters parameters
* @param before before filter
* @param after after filter
*/
class SQLExecution(val statement: String, val parameters: scala.collection.Seq[Any], val tags: scala.collection.Seq[String] = Nil)(
val before: (PreparedStatement) => Unit)(
val after: (PreparedStatement) => Unit) {
def apply()(implicit session: DBSession): Boolean = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
val f: DBSession => Boolean = DBSessionWrapper(_, attributesSwitcher).executeWithFilters(before, after, statement, parameters.toSeq: _*)
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
object SQLExecution {
def unapply(sqlObject: SQLExecution): Option[(String, scala.collection.Seq[Any], scala.collection.Seq[String], PreparedStatement => Unit, PreparedStatement => Unit)] = {
Some((sqlObject.statement, sqlObject.parameters, sqlObject.tags, sqlObject.before, sqlObject.after))
}
}
/**
* SQL which execute java.sql.Statement#executeUpdate().
*
* @param statement SQL template
* @param parameters parameters
* @param before before filter
* @param after after filter
*/
class SQLUpdate(val statement: String, val parameters: scala.collection.Seq[Any], val tags: scala.collection.Seq[String] = Nil)(
val before: (PreparedStatement) => Unit)(
val after: (PreparedStatement) => Unit) {
def apply()(implicit session: DBSession): Int = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
session match {
case AutoSession =>
DB.autoCommit(DBSessionWrapper(_, attributesSwitcher).updateWithFilters(before, after, statement, parameters.toSeq: _*))
case NamedAutoSession(name, _) =>
NamedDB(name, session.settings).autoCommit(DBSessionWrapper(_, attributesSwitcher).updateWithFilters(before, after, statement, parameters.toSeq: _*))
case ReadOnlyAutoSession =>
DB.readOnly(DBSessionWrapper(_, attributesSwitcher).updateWithFilters(before, after, statement, parameters.toSeq: _*))
case ReadOnlyNamedAutoSession(name, _) =>
NamedDB(name, session.settings).readOnly(DBSessionWrapper(_, attributesSwitcher).updateWithFilters(before, after, statement, parameters.toSeq: _*))
case _ =>
DBSessionWrapper(session, attributesSwitcher).updateWithFilters(before, after, statement, parameters.toSeq: _*)
}
}
}
object SQLUpdate {
def unapply(sqlObject: SQLUpdate): Option[(String, scala.collection.Seq[Any], scala.collection.Seq[String], PreparedStatement => Unit, PreparedStatement => Unit)] = {
Some((sqlObject.statement, sqlObject.parameters, sqlObject.tags, sqlObject.before, sqlObject.after))
}
}
/**
* SQL which execute java.sql.Statement#executeLargeUpdate().
*
* @param statement SQL template
* @param parameters parameters
* @param before before filter
* @param after after filter
*/
class SQLLargeUpdate private[scalikejdbc] (statement: String, parameters: scala.collection.Seq[Any], tags: scala.collection.Seq[String] = Nil)(
before: PreparedStatement => Unit)(
after: PreparedStatement => Unit) {
def apply()(implicit session: DBSession): Long = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
session match {
case AutoSession =>
DB.autoCommit(DBSessionWrapper(_, attributesSwitcher).largeUpdateWithFilters(before, after, statement, parameters.toSeq: _*))
case NamedAutoSession(name, _) =>
NamedDB(name, session.settings).autoCommit(DBSessionWrapper(_, attributesSwitcher).largeUpdateWithFilters(before, after, statement, parameters.toSeq: _*))
case ReadOnlyAutoSession =>
DB.readOnly(DBSessionWrapper(_, attributesSwitcher).largeUpdateWithFilters(before, after, statement, parameters.toSeq: _*))
case ReadOnlyNamedAutoSession(name, _) =>
NamedDB(name, session.settings).readOnly(DBSessionWrapper(_, attributesSwitcher).largeUpdateWithFilters(before, after, statement, parameters.toSeq: _*))
case _ =>
DBSessionWrapper(session, attributesSwitcher).largeUpdateWithFilters(before, after, statement, parameters.toSeq: _*)
}
}
}
/**
* SQL which execute java.sql.Statement#executeUpdate() and get generated key value.
*
* @param statement SQL template
* @param parameters parameters
*/
class SQLUpdateWithGeneratedKey(val statement: String, val parameters: scala.collection.Seq[Any], val tags: scala.collection.Seq[String] = Nil)(val key: Any) {
def apply()(implicit session: DBSession): Long = {
val attributesSwitcher = new DBSessionAttributesSwitcher(SQL("").tags(tags.toSeq: _*))
val f: DBSession => Long = DBSessionWrapper(_, attributesSwitcher).updateAndReturnSpecifiedGeneratedKey(statement, parameters.toSeq: _*)(key)
// format: OFF
session match {
case AutoSession => DB.autoCommit(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).autoCommit(f)
case ReadOnlyAutoSession => DB.readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
object SQLUpdateWithGeneratedKey {
def unapply(sqlObject: SQLUpdateWithGeneratedKey): Option[(String, scala.collection.Seq[Any], scala.collection.Seq[String], Any)] = {
Some((sqlObject.statement, sqlObject.parameters, sqlObject.tags, sqlObject.key))
}
}
trait SQLToResult[A, E <: WithExtractor, C[_]] extends SQL[A, E] with Extractor[A] {
import GeneralizedTypeConstraintsForWithExtractor._
def result[AA](f: WrappedResultSet => AA, session: DBSession): C[AA]
val statement: String
private[scalikejdbc] val rawParameters: scala.collection.Seq[Any]
def apply()(
implicit
session: DBSession,
context: ConnectionPoolContext = NoConnectionPoolContext,
hasExtractor: ThisSQL =:= SQLWithExtractor): C[A] = {
val attributesSwitcher = createDBSessionAttributesSwitcher()
val f: DBSession => C[A] = s => result[A](extractor, DBSessionWrapper(s, attributesSwitcher))
// format: OFF
session match {
case AutoSession | ReadOnlyAutoSession => DB.readOnly(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
/**
* SQL which execute java.sql.Statement#executeQuery() and returns the result as scala.collection.Iterable value.
*
* @tparam A return type
*/
trait SQLToIterable[A, E <: WithExtractor] extends SQLToResult[A, E, Iterable] {
def result[AA](f: WrappedResultSet => AA, session: DBSession): Iterable[AA] = {
session.iterable[AA](statement, rawParameters.toSeq: _*)(f)
}
}
/**
* SQL which execute java.sql.Statement#executeQuery() and returns the result as scala.collection.Iterable value.
*
* @param statement SQL template
* @param rawParameters parameters
* @param extractor extractor function
* @tparam A return type
*/
class SQLToIterableImpl[A, E <: WithExtractor](
override val statement: String, override val rawParameters: scala.collection.Seq[Any])(
override val extractor: WrappedResultSet => A)
extends SQL[A, E](statement, rawParameters)(extractor)
with SQLToIterable[A, E] {
override protected def withParameters(params: scala.collection.Seq[Any]): SQLToResult[A, E, Iterable] = {
new SQLToIterableImpl[A, E](statement, params)(extractor)
}
override protected def withStatementAndParameters(state: String, params: scala.collection.Seq[Any]): SQLToResult[A, E, Iterable] = {
new SQLToIterableImpl[A, E](state, params)(extractor)
}
override protected def withExtractor[B](f: WrappedResultSet => B): SQLToResult[B, HasExtractor, Iterable] = {
new SQLToIterableImpl[B, HasExtractor](statement, rawParameters)(f)
}
}
object SQLToIterableImpl {
def unapply[A, E <: WithExtractor](sqlObject: SQLToIterableImpl[A, E]): Option[(String, scala.collection.Seq[Any], WrappedResultSet => A)] = {
Some((sqlObject.statement, sqlObject.rawParameters, sqlObject.extractor))
}
}
/**
* SQL to Collection
*
* @tparam A return type
* @tparam E extractor settings
*/
trait SQLToCollection[A, E <: WithExtractor] extends SQL[A, E] with Extractor[A] {
import GeneralizedTypeConstraintsForWithExtractor._
val statement: String
private[scalikejdbc] val rawParameters: scala.collection.Seq[Any]
def apply[C[_]]()(implicit session: DBSession, context: ConnectionPoolContext = NoConnectionPoolContext, hasExtractor: ThisSQL =:= SQLWithExtractor, factory: Factory[A, C[A]]): C[A] = {
val attributesSwitcher = createDBSessionAttributesSwitcher()
val f: DBSession => C[A] = DBSessionWrapper(_, attributesSwitcher).collection[A, C](statement, rawParameters.toSeq: _*)(extractor)
// format: OFF
session match {
case AutoSession | ReadOnlyAutoSession => DB.readOnly(f)
case NamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case ReadOnlyNamedAutoSession(name, _) => NamedDB(name, session.settings).readOnly(f)
case _ => f(session)
}
// format: ON
}
}
class SQLToCollectionImpl[A, E <: WithExtractor](
override val statement: String, override val rawParameters: scala.collection.Seq[Any])(
override val extractor: WrappedResultSet => A)
extends SQL[A, E](statement, rawParameters)(extractor)
with SQLToCollection[A, E] {
override protected def withParameters(params: scala.collection.Seq[Any]): SQLToCollection[A, E] = {
new SQLToCollectionImpl[A, E](statement, params)(extractor)
}
override protected def withStatementAndParameters(state: String, params: scala.collection.Seq[Any]): SQLToCollection[A, E] = {
new SQLToCollectionImpl[A, E](state, params)(extractor)
}
override protected def withExtractor[B](f: WrappedResultSet => B): SQLToCollection[B, HasExtractor] = {
new SQLToCollectionImpl[B, HasExtractor](statement, rawParameters)(f)
}
}
object SQLToCollectionImpl {
def unapply[A, E <: WithExtractor](sqlObject: SQLToCollectionImpl[A, E]): Option[(String, scala.collection.Seq[Any], WrappedResultSet => A)] = {
Some((sqlObject.statement, sqlObject.rawParameters, sqlObject.extractor))
}
}
/**
* SQL to List
*
* @tparam A return type
* @tparam E extractor settings
*/
trait SQLToList[A, E <: WithExtractor] extends SQLToResult[A, E, List] {
def result[AA](f: WrappedResultSet => AA, session: DBSession): List[AA] = {
session.list[AA](statement, rawParameters.toSeq: _*)(f)
}
}
/**
* SQL which execute java.sql.Statement#executeQuery() and returns the result as scala.collection.immutable.List value.
*
* @param statement SQL template
* @param rawParameters parameters
* @param extractor extractor function
* @tparam A return type
*/
class SQLToListImpl[A, E <: WithExtractor](
override val statement: String, override val rawParameters: scala.collection.Seq[Any])(
override val extractor: WrappedResultSet => A)
extends SQL[A, E](statement, rawParameters)(extractor)
with SQLToList[A, E] {
override protected def withParameters(params: scala.collection.Seq[Any]): SQLToList[A, E] = {
new SQLToListImpl[A, E](statement, params)(extractor)
}
override protected def withStatementAndParameters(state: String, params: scala.collection.Seq[Any]): SQLToList[A, E] = {
new SQLToListImpl[A, E](state, params)(extractor)
}
override protected def withExtractor[B](f: WrappedResultSet => B): SQLToList[B, HasExtractor] = {
new SQLToListImpl[B, HasExtractor](statement, rawParameters)(f)
}
}
object SQLToListImpl {
def unapply[A, E <: WithExtractor](sqlObject: SQLToListImpl[A, E]): Option[(String, scala.collection.Seq[Any], WrappedResultSet => A)] = {
Some((sqlObject.statement, sqlObject.rawParameters, sqlObject.extractor))
}
}
/**
* SQL to Option
*
* @tparam A return type
* @tparam E extractor settings
*/
trait SQLToOption[A, E <: WithExtractor] extends SQLToResult[A, E, Option] {
protected def isSingle: Boolean
def result[AA](f: WrappedResultSet => AA, session: DBSession): Option[AA] = {
if (isSingle) {
session.single[AA](statement, rawParameters.toSeq: _*)(f)
} else {
session.first[AA](statement, rawParameters.toSeq: _*)(f)
}
}
}
/**
* SQL which execute java.sql.Statement#executeQuery() and returns the result as scala.Option value.
*
* @param statement SQL template
* @param rawParameters parameters
* @param extractor extractor function
* @tparam A return type
*/
class SQLToOptionImpl[A, E <: WithExtractor](
override val statement: String, override val rawParameters: scala.collection.Seq[Any])(
override val extractor: WrappedResultSet => A)(val isSingle: Boolean = true)
extends SQL[A, E](statement, rawParameters)(extractor)
with SQLToOption[A, E] {
override protected def withParameters(params: scala.collection.Seq[Any]): SQLToOption[A, E] = {
new SQLToOptionImpl[A, E](statement, params)(extractor)(isSingle)
}
override protected def withStatementAndParameters(state: String, params: scala.collection.Seq[Any]): SQLToOption[A, E] = {
new SQLToOptionImpl[A, E](state, params)(extractor)(isSingle)
}
override protected def withExtractor[B](f: WrappedResultSet => B): SQLToOption[B, HasExtractor] = {
new SQLToOptionImpl[B, HasExtractor](statement, rawParameters)(f)(isSingle)
}
}
object SQLToOptionImpl {
def unapply[A, E <: WithExtractor](sqlObject: SQLToOptionImpl[A, E]): Option[(String, scala.collection.Seq[Any], WrappedResultSet => A, Boolean)] = {
Some((sqlObject.statement, sqlObject.rawParameters, sqlObject.extractor, sqlObject.isSingle))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy