Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor top level definitions for Scala 3 compatibility #573

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ inThisBuild(
List(
// scalaVersion := "2.13.3",
semanticdbEnabled := true,
semanticdbVersion := scalafixSemanticdb.revision,
scalafixDependencies ++= Seq("com.github.liancheng" %% "organize-imports" % "0.5.0")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer required as no scalafix builtin

semanticdbVersion := scalafixSemanticdb.revision
)
)

Expand Down Expand Up @@ -161,6 +160,13 @@ lazy val `anorm-core` = project
}
},
mimaBinaryIssueFilters ++= Seq(
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$ResultSetResource$$"),
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$StatementResource$$"),
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$StringWrapper2$$"),
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$TimestampWrapper1$$"),
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$TimestampWrapper2$$"),
ProblemFilters.exclude[MissingClassProblem](f"anorm.package$$features$$"),
// ---
ProblemFilters.exclude[IncompatibleSignatureProblem]("anorm.SqlStatementParser.elem"),
ProblemFilters.exclude[IncompatibleSignatureProblem]("anorm.SqlStatementParser.accept"),
// ---
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/scala-2/anorm/SqlQueryCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package anorm

private[anorm] trait SqlQueryCompat {}
39 changes: 39 additions & 0 deletions core/src/main/scala-2/anorm/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package object anorm extends anorm.TopLevelDefinitions {

/**
* Creates an SQL query using String Interpolation feature.
* It is a 1-step alternative for SQL("...").on(...) functions.
*
* {{{
* import java.util.Date
* import java.sql.Connection
*
* import anorm._
*
* case class Computer(
* name: String,
* introduced: Date,
* discontinued: Date,
* companyId: String)
*
* def foo(computer: Computer, id: String)(implicit con: Connection) =
* SQL"""
* UPDATE computer SET name = \\${computer.name},
* introduced = \\${computer.introduced},
* discontinued = \\${computer.discontinued},
* company_id = \\${computer.companyId}
* WHERE id = \\$id
* """.executeUpdate()
* }}}
*/
implicit class SqlStringInterpolation(val sc: StringContext) extends AnyVal {
def SQL(args: ParameterValue*) = {
val (ts, ps) = TokenizedStatement.stringInterpolation(sc.parts, args)
SimpleSql(SqlQuery.prepare(ts, ts.names), ps, RowParser(Success(_)))
}
}
}
202 changes: 1 addition & 201 deletions core/src/main/scala-3/anorm/PackageCompat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,204 +4,4 @@

package anorm

import java.sql.Connection

import scala.util.Try

private[anorm] trait PackageCompat:

extension (query: SqlQuery)
/**
* Returns the query prepared with named parameters.
*
* {{{
* import anorm._
*
* val baseSql = SQL("SELECT * FROM table WHERE id = {id}") // one named param
* val preparedSql = baseSql.on("id" -> "value")
* }}}
*/
def on(args: NamedParameter*): SimpleSql[Row] =
query.asSimple.on(args: _*)

/**
* Returns the query prepared with parameters using initial order
* of placeholder in statement.
*
* {{{
* import anorm._
*
* val baseSql =
* SQL("SELECT * FROM table WHERE name = {name} AND lang = {lang}")
*
* val preparedSql = baseSql.onParams("1st", "2nd")
* // 1st param = name, 2nd param = lang
* }}}
*/
def onParams(args: ParameterValue*): SimpleSql[Row] = {
val simple = query.asSimple

simple.copy(params = simple.params ++ Sql.zipParams(simple.sql.paramsInitialOrder, args, Map.empty))
}

/**
* Returns the query prepared with the named parameters,
* provided by the appropriate `converter`.
*
* @param value the value to be converted as list of [[NamedParameter]]
* @param converter the function used to convert the `value`
* @tparam U the type of the value
*/
def bind[U](value: U)(using converter: ToParameterList[U]): SimpleSql[Row] =
query.asSimple.bind[U](value)

def map[T](f: Row => T): SimpleSql[T] = {
val simple = query.asSimple

simple.copy(defaultParser = simple.defaultParser.map(f))
}

/** Returns a copy with updated timeout. */
def withQueryTimeout(seconds: Option[Int]): SimpleSql[Row] = {
val simple = query.asSimple

simple.copy(sql = simple.sql.withQueryTimeout(seconds))
}

/** Returns a copy with updated flag. */
def withResultSetOnFirstRow(onFirst: Boolean): SimpleSql[Row] =
query.asSimple.copy(resultSetOnFirstRow = onFirst)

/** Fetch size */
def fetchSize: Option[Int] = None

/**
* Returns this query with the fetch suze updated to the row `count`.
* @see [[SqlQuery.fetchSize]]
*/
def withFetchSize(count: Option[Int]): SimpleSql[Row] = {
val simple = query.asSimple

simple.copy(simple.sql.withFetchSize(count))
}

/**
* Aggregates over all rows using the specified operator.
*
* @param z the start value
* @param aliaser the column aliaser
* @param op Aggregate operator
* @return Either list of failures at left, or aggregated value
* @see #foldWhile
* @see #withResult
*/
def fold[T](z: => T, aliaser: ColumnAliaser)(
op: (T, Row) => T
)(using connection: Connection): Either[List[Throwable], T] =
query.asSimple.fold[T](z, aliaser)(op)(connection)

/**
* Aggregates over part of or the while row stream,
* using the specified operator.
*
* @param z the start value
* @param aliaser the column aliaser
* @param op Aggregate operator. Returns aggregated value along with true if aggregation must process next value, or false to stop with current value.
* @return Either list of failures at left, or aggregated value
* @see #withResult
*/
def foldWhile[T](z: => T, aliaser: ColumnAliaser)(
op: (T, Row) => (T, Boolean)
)(using connection: Connection): Either[List[Throwable], T] =
query.asSimple.foldWhile[T](z, aliaser)(op)(connection)

/**
* Processes all or some rows from current result.
*
* @param op Operation applied with row cursor
* @param aliaser the column aliaser
*
* {{{
* import java.sql.Connection
* import anorm._
*
* @annotation.tailrec
* def go(c: Option[Cursor], l: List[Row]): List[Row] = c match {
* case Some(cursor) => go(cursor.next, l :+ cursor.row)
* case _ => l
* }
*
* def l(using con: Connection): Either[List[Throwable], List[Row]] =
* SQL"SELECT * FROM Test".withResult(go(_, List.empty))
* }}}
*/
def withResult[T](op: Option[Cursor] => T)(using connection: Connection): Either[List[Throwable], T] =
withResult[T](op, ColumnAliaser.empty)

/**
* Processes all or some rows from current result.
*
* @param op Operation applied with row cursor
*
* {{{
* import java.sql.Connection
* import anorm._
*
* @annotation.tailrec
* def go(c: Option[Cursor], l: List[Row]): List[Row] = c match {
* case Some(cursor) => go(cursor.next, l :+ cursor.row)
* case _ => l
* }
*
* def l(implicit con: Connection): Either[List[Throwable], List[Row]] =
* SQL"SELECT * FROM Test".withResult(go(_, List.empty))
* }}}
*/
def withResult[T](op: Option[Cursor] => T, aliaser: ColumnAliaser)(implicit
connection: Connection
): Either[List[Throwable], T] =
query.asSimple.withResult[T](op, aliaser)(connection)

/**
* Converts this query result as `T`, using parser.
*
* @param parser the result parser
* @see #asTry
*/
def as[T](parser: ResultSetParser[T])(implicit connection: Connection): T =
query.asSimple.asTry[T](parser, ColumnAliaser.empty).get

/**
* Converts this query result as `T`, using parser.
*
* @param parser the result parser
* @param aliaser the column aliaser
*/
def asTry[T](parser: ResultSetParser[T], aliaser: ColumnAliaser = ColumnAliaser.empty)(implicit
connection: Connection
): Try[T] = query.asSimple.asTry[T](parser, aliaser)(connection)

/**
* Executes this SQL statement.
* @return true if resultset was returned from execution
* (statement is query), or false if it executed update.
*
* {{{
* import anorm._
*
* def res(implicit con: java.sql.Connection): Boolean =
* SQL"""INSERT INTO Test(a, b) VALUES(\\${"A"}, \\${"B"}""".execute()
* }}}
*/
def execute()(using connection: Connection): Boolean =
query.asSimple.execute()

/**
* Executes this SQL as an update statement.
* @return Count of updated row(s)
*/
@throws[java.sql.SQLException]("If statement is query not update")
def executeUpdate()(using connection: Connection): Int =
query.asSimple.executeUpdate()

end PackageCompat
private[anorm] trait PackageCompat {}
Loading