Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Split into two projects (API and Play implementation)

  • Loading branch information...
commit e92670b0ccf81def72c4c54baed433f158849764 1 parent 990496e
Teo Klestrup Röijezon authored
0  nina/.gitignore → .gitignore
View
File renamed without changes
7 nina-play/build.sbt
View
@@ -0,0 +1,7 @@
+name := "nina-play"
+
+libraryDependencies += "play" %% "anorm" % "2.0"
+
+libraryDependencies += "org.specs2" %% "specs2" % "1.7.1" % "test"
+
+libraryDependencies += "play" %% "play-test" % "2.0" % "test"
19 nina-play/src/main/scala/Main.scala
View
@@ -0,0 +1,19 @@
+package nina.impl.play
+
+import nina._
+
+import java.util.Date
+import java.sql.PreparedStatement
+
+trait NinaPlayImplPackage {
+ implicit def toStatement2ninaSetter[T](stmt: anorm.ToStatement[T]): NinaSetter[T] = new NinaSetter[T] {
+ def set(s: PreparedStatement, index: Int, value: T) { stmt.set(s, index, value) }
+ }
+ implicit def ninaSetter2toStatement[T](setter: NinaSetter[T]): anorm.ToStatement[T] = new anorm.ToStatement[T] {
+ def set(s: PreparedStatement, index: Int, aValue: T) { setter.set(s, index, aValue) }
+ }
+
+ implicit def anySetter[T]: NinaSetter[T] = anorm.ToStatement.anyParameter[T]
+ implicit val dateSetter: NinaSetter[java.util.Date] = anorm.ToStatement.dateToStatement
+ implicit def optionSetter[T](implicit ts: NinaSetter[T]): NinaSetter[Option[T]] = anorm.ToStatement.optionToStatement[T](ts)
+}
57 nina-play/src/main/scala/MySQL.scala
View
@@ -0,0 +1,57 @@
+package nina.impl.play
+
+import nina._
+
+import java.sql.Connection
+
+import anorm._
+
+package object mysql extends NinaPlayImplPackage {
+ implicit val ninaPlayMySQLExecutor: NinaExecutor = NinaPlayMySQLExecutor
+}
+
+package mysql {
+ object NinaPlayMySQLExecutor extends NinaExecutor {
+ def insert(table: String, data: Map[String, Any])(implicit conn: Connection): Boolean = (
+ SQL("INSERT INTO "+table+"("+data.keys.mkString(",")+") VALUES("+data.keys.map("{"+_.toString+"}").mkString(",")+")")
+ .on(data.toSeq.map { (kv) => val (key, value) = kv; (key, toParameterValue(value)) }: _*)
+ .executeUpdate() > 0
+ )
+
+ def count(table: String, filters: Seq[Filter[_, _]])(implicit conn: Connection): Long = getOne(table, filters, Seq("count(*)")).get("count(*)").asInstanceOf[Option[Long]].get
+ def getOne(table: String, filters: Seq[Filter[_, _]], columns: Seq[String])(implicit conn: Connection): Option[Map[String, Option[Any]]] = {
+ getMultiple(table, filters, columns, 1).headOption
+ }
+ def getMultiple(table: String, filters: Seq[Filter[_, _]], columns: Seq[String], amount: Long)(implicit conn: Connection): Seq[Map[String, Option[Any]]] = {
+ val filtersStr = if (filters.isEmpty) ""
+ else " WHERE "+filters.map(_ match {
+ case Filter(col, filter.Like, _) => col.name+" LIKE {"+col.name+"}"
+ case Filter(col, filter.EQ, _) => col.name+"={"+col.name+"}"
+ case Filter(col, filter.NEQ, _) => col.name+"!={"+col.name+"}"
+ case Filter(col, filter.GT, _) => col.name+">{"+col.name+"}"
+ case Filter(col, filter.GTE, _) => col.name+">={"+col.name+"}"
+ case Filter(col, filter.LT, _) => col.name+"<{"+col.name+"}"
+ case Filter(col, filter.LTE, _) => col.name+"<={"+col.name+"}"
+ }).mkString(" AND ")
+ val limitStr = if (amount == -1) ""
+ else " LIMIT "+amount
+ val sql = "SELECT "+columns.mkString(",")+" FROM "+table+filtersStr+limitStr
+ val rows = SQL(sql).on(filters.map(_ match {
+ case filter: Filter[_, _] => filter.column.name -> ParameterValue(filter.other, filter.setter)
+ }): _*)()
+
+ var allRows = Seq[Row]() // Hack to make sure that all rows are fetched
+ for (row <- rows) {
+ allRows :+= row
+ }
+
+ allRows map { row =>
+ columns.map[(String, Option[Any]), Seq[(String, Option[Any])]] { name =>
+ (name, row[Option[Any]](name)(Column.rowToOption(Column { (value, metadata) =>
+ Right(value)
+ })))
+ } toMap
+ }
+ }
+ }
+}
5 nina/test/TableSpec.scala → nina-play/src/test/scala/TableSpec.scala
View
@@ -1,6 +1,7 @@
package test
import nina._
+import nina.impl.play.mysql._
import org.specs2.mutable._
@@ -12,9 +13,7 @@ import play.api.test.Helpers._
import play.api.db.DB
class TableSpec extends Specification {
- object TestingTable extends Table with PrimaryKey[Int] {
- val tableName = "languages"
-
+ object TestingTable extends Table("languages") with PrimaryKey[Int] {
val id = col[Int]("id")
val name = col[String]("name")
val rating = optCol[Int]("rating")
51 nina/app/DefaultExecutors.scala
View
@@ -1,51 +0,0 @@
-package nina.executors
-
-import nina._
-
-import java.sql.Connection
-
-import anorm._
-
-object MySQL extends NinaExecutor {
- def insert(table: String, data: Map[String, Any])(implicit conn: Connection): Boolean = (
- SQL("INSERT INTO "+table+"("+data.keys.mkString(",")+") VALUES("+data.keys.map("{"+_.toString+"}").mkString(",")+")")
- .on(data.toSeq.map { (kv) => val (key, value) = kv; (key, toParameterValue(value)) }: _*)
- .executeUpdate() > 0
- )
-
- def count(table: String, filters: Seq[Filter[_, _]])(implicit conn: Connection): Long = getOne(table, filters, Seq("count(*)")).get("count(*)").asInstanceOf[Option[Long]].get
- def getOne(table: String, filters: Seq[Filter[_, _]], columns: Seq[String])(implicit conn: Connection): Option[Map[String, Option[Any]]] = {
- getMultiple(table, filters, columns, 1).headOption
- }
- def getMultiple(table: String, filters: Seq[Filter[_, _]], columns: Seq[String], amount: Long)(implicit conn: Connection): Seq[Map[String, Option[Any]]] = {
- val filtersStr = if (filters.isEmpty) ""
- else " WHERE "+filters.map(_ match {
- case Filter(col, filter.Like, _) => col.name+" LIKE {"+col.name+"}"
- case Filter(col, filter.EQ, _) => col.name+"={"+col.name+"}"
- case Filter(col, filter.NEQ, _) => col.name+"!={"+col.name+"}"
- case Filter(col, filter.GT, _) => col.name+">{"+col.name+"}"
- case Filter(col, filter.GTE, _) => col.name+">={"+col.name+"}"
- case Filter(col, filter.LT, _) => col.name+"<{"+col.name+"}"
- case Filter(col, filter.LTE, _) => col.name+"<={"+col.name+"}"
- }).mkString(" AND ")
- val limitStr = if (amount == -1) ""
- else " LIMIT "+amount
- val sql = "SELECT "+columns.mkString(",")+" FROM "+table+filtersStr+limitStr
- val rows = SQL(sql).on(filters.map(_ match {
- case filter: Filter[_, _] => filter.column.name -> ParameterValue(filter.other, filter.setter)
- }): _*)()
-
- var allRows = Seq[Row]() // Hack to make sure that all rows are fetched
- for (row <- rows) {
- allRows :+= row
- }
-
- allRows map { row =>
- columns.map[(String, Option[Any]), Seq[(String, Option[Any])]] { name =>
- (name, row[Option[Any]](name)(Column.rowToOption(Column { (value, metadata) =>
- Right(value)
- })))
- } toMap
- }
- }
-}
7 nina/app/Package.scala
View
@@ -1,7 +0,0 @@
-package object nina {
- implicit def table2query[T <: Table](t: T) = Query(t, Seq[Filter[_, T]]())
-
- implicit def anyToStatement[T] = anorm.ToStatement.anyParameter[T]
- implicit val dateToStatement = anorm.ToStatement.dateToStatement
- implicit def optionToStatement[T](implicit ts: anorm.ToStatement[T]) = anorm.ToStatement.optionToStatement[T](ts)
-}
5 nina/build.sbt
View
@@ -0,0 +1,5 @@
+name := "nina"
+
+organization := "se.nullable.nina"
+
+name := "nina"
18 nina/project/Build.scala
View
@@ -1,18 +0,0 @@
-import sbt._
-import Keys._
-import PlayProject._
-
-object ApplicationBuild extends Build {
-
- val appName = "nina"
- val appVersion = "0.0.1-SNAPSHOT"
-
- val appDependencies = Seq(
- // Add your project dependencies here,
- )
-
- val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
- // Add your own project settings here
- )
-
-}
1  nina/project/build.properties
View
@@ -1 +0,0 @@
-sbt.version=0.11.2
8 nina/project/plugins.sbt
View
@@ -1,8 +0,0 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// The Typesafe repository
-resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
-
-// Use the Play sbt plugin for Play projects
-addSbtPlugin("play" % "sbt-plugin" % "2.1-SNAPSHOT")
0  nina/app/Executor.scala → nina/src/main/scala/Executor.scala
View
File renamed without changes
3  nina/src/main/scala/Package.scala
View
@@ -0,0 +1,3 @@
+package object nina {
+ implicit def table2query[T <: Table](t: T) = Query(t, Seq[Filter[_, T]]())
+}
12 nina/app/Query.scala → nina/src/main/scala/Query.scala
View
@@ -1,6 +1,6 @@
package nina
-import java.sql.Connection
+import java.sql.{Connection, PreparedStatement}
package filter {
sealed trait Kind
@@ -13,12 +13,16 @@ package filter {
case object LTE extends Kind
}
-case class Filter[A, T <: Table](column: T#Column[A], kind: filter.Kind, other: A)(implicit val setter: anorm.ToStatement[A])
+trait NinaSetter[A] {
+ def set(s: PreparedStatement, index: Int, value: A)
+}
+
+case class Filter[A, T <: Table](column: T#Column[A], kind: filter.Kind, other: A)(implicit val setter: NinaSetter[A])
case class Query[T <: Table](table: T, filters: Seq[Filter[_, T]]) {
def count(implicit conn: Connection) = table.executor.count(table.tableName, filters)
- def where[A](p: => (table.Column[A], nina.filter.Kind, A))(implicit setter: anorm.ToStatement[A]): Query[T] = {
+ def where[A](p: => (table.Column[A], nina.filter.Kind, A))(implicit setter: NinaSetter[A]): Query[T] = {
val (col, kind, other) = p
Query(table, filters :+ Filter(col, kind, other))
}
@@ -27,8 +31,6 @@ case class Query[T <: Table](table: T, filters: Seq[Filter[_, T]]) {
}
case class GetQuery[A, T <: Table](query: Query[T], cols: T#Columns[A], lazyFilters: Seq[A => Boolean]) {
- def withFilter[B](p: A => Boolean)(implicit setter: anorm.ToStatement[A], bNullable: Null <:< B): GetQuery[A, T] = GetQuery(query, cols, lazyFilters :+ p)
-
def single()(implicit conn: Connection): Option[A] = query.table.executor.getOne(query.table.tableName, query.filters, cols.columnNames).map(cols.bindFromMap(_).value)
def take(amount: Long)(implicit conn: Connection): Seq[A] = query.table.executor.getMultiple(query.table.tableName, query.filters, cols.columnNames, amount).map(cols.bindFromMap(_).value)
def all()(implicit conn: Connection): Seq[A] = query.table.executor.getMultiple(query.table.tableName, query.filters, cols.columnNames).map(cols.bindFromMap(_).value)
15 nina/app/Table.scala → nina/src/main/scala/Table.scala
View
@@ -1,7 +1,5 @@
package nina
-import play.api.Play._
-
import java.sql.Connection
sealed trait Columns[A] {
@@ -17,18 +15,7 @@ trait BoundColumn[A] {
case class &[+A, +B](_1: A, _2: B)
-trait Table {
- def tableName: String
-
- def executor: NinaExecutor = {
- val executor = configuration getString "nina.executor" getOrElse "mysql" match {
- case "mysql" => "nina.executors.MySQL"
- case x => x
- }
- val clazz = classloader.loadClass(executor+"$")
- clazz.getField("MODULE$").get(null).asInstanceOf[NinaExecutor]
- }
-
+abstract class Table(val tableName: String)(implicit val executor: NinaExecutor) {
case class BoundColumn[A](column: Columns[A], value: A) extends nina.BoundColumn[A]
case class SingleBoundColumn[A](column: Column[A], value: A) extends nina.BoundColumn[A]
15 project/Build.scala
View
@@ -0,0 +1,15 @@
+import sbt._
+import Keys._
+
+object NinaBuild extends Build {
+ lazy val ninaSettings = Seq(
+ resolvers += "Nullable.se" at "http://nexus.nullable.se/nexus/content/groups/public/",
+ organization := "se.nullable.nina",
+ version := "0.0.1-SNAPSHOT"
+ )
+ override lazy val settings = super.settings ++ ninaSettings
+
+ lazy val all = Project(id = "nina-all", base = file(".")) aggregate(main, play)
+ lazy val main = Project(id = "nina", base = file("nina"))
+ lazy val play = Project(id = "nina-play", base = file("nina-play")) dependsOn(main)
+}
Please sign in to comment.
Something went wrong with that request. Please try again.