Advertisement
mitrakov

Slick: countDistinct

Aug 19th, 2018
378
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.15 KB | None | 0 0
  1. // Testing Slick countDistinct
  2.  
  3. // Prerequisites:
  4. // Setup Play Evolutions (https://pastebin.com/5qhdsZp2) and create "students" table (https://pastebin.com/GK2A0eVx)
  5.  
  6. // 2.sql:
  7. # students schema, student table
  8.  
  9. # --- !Ups
  10.  
  11. CREATE TABLE `student` (
  12.     `student_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'primary key',
  13.     `name` VARCHAR(64) NOT NULL COMMENT 'student name',
  14.     `birthday` DATE NOT NULL COMMENT 'day of birthday',
  15.     `sex` ENUM('Male','Female') NOT NULL COMMENT 'sex: male/female',
  16.     `admission_year` SMALLINT(5) UNSIGNED NOT NULL COMMENT 'year of admission',
  17.     `faculty_id` BIGINT(20) UNSIGNED NOT NULL COMMENT 'reference to faculty table',
  18.     PRIMARY KEY (`student_id`),
  19.     INDEX `IDX_student_admission_year` (`admission_year`),
  20.     INDEX `FK_student_faculty` (`faculty_id`),
  21.     CONSTRAINT `FK_student_faculty` FOREIGN KEY (`faculty_id`) REFERENCES `faculty` (`faculty_id`) ON UPDATE CASCADE ON DELETE CASCADE
  22. ) COMMENT 'student table' COLLATE 'utf8_general_ci' ENGINE InnoDB;
  23.  
  24. # --- !Downs
  25.  
  26. DROP TABLE IF EXISTS `student`;
  27.  
  28. '
  29. // insert some data:
  30. INSERT INTO `students`.`faculty` (`name`, `isArts`) VALUES ('Mathematics', 0);
  31. INSERT INTO `students`.`student` (`name`, `birthday`, `sex`, `admission_year`, `faculty_id`) VALUES ('Tommy', '2010-08-19', 'Male', 2010, 1);
  32. INSERT INTO `students`.`student` (`name`, `birthday`, `sex`, `admission_year`, `faculty_id`) VALUES ('Bobby', '2015-08-19', 'Male', 2011, 1);
  33. INSERT INTO `students`.`student` (`name`, `birthday`, `sex`, `admission_year`, `faculty_id`) VALUES ('Jessica', '2011-08-19', 'Female', 2010, 1);
  34.  
  35. // StudentDAO.scala:
  36. import java.sql.Timestamp
  37. import javax.inject.Inject
  38. import scala.concurrent.Future
  39. import play.api.db.slick._
  40. import play.db.NamedDatabase
  41. import slick.jdbc.JdbcProfile
  42. import slick.lifted.ProvenShape
  43.  
  44. case class Student(studentId: Option[Long], name: String, birthday: Timestamp, sex: String, year: Int, facultyId: Long) {
  45.   require(Set("Male", "Female") contains sex)
  46. }
  47.  
  48. class StudentDao @Inject()(
  49.     @NamedDatabase("students") protected val dbConfigProvider: DatabaseConfigProvider
  50.   ) extends HasDatabaseConfigProvider[JdbcProfile] {
  51.  
  52.   import profile.api._
  53.  
  54.   private class StudentTable(tag: Tag) extends Table[Student](tag, "student") {
  55.     def studentId: Rep[Long] = column[Long]("student_id", O.PrimaryKey, O.AutoInc)
  56.     def name: Rep[String] = column[String]("name")
  57.     def birthday: Rep[Timestamp] = column[Timestamp]("birthday")
  58.     def sex: Rep[String] = column[String]("sex")
  59.     def year: Rep[Int] = column[Int]("admission_year")
  60.     def facultyId: Rep[Long] = column[Long]("faculty_id")
  61.  
  62.     override def * : ProvenShape[Student] = (studentId.?, name, birthday, sex, year,
  63.       facultyId) <> (Student.tupled, Student.unapply)
  64.   }
  65.  
  66.   private lazy val table = TableQuery[StudentTable]
  67.  
  68.   def getAll: Future[Seq[Student]] = {
  69.     val query = table.result
  70.     println(query.statements.mkString)
  71.     db.run(query)
  72.   }
  73.  
  74.   def getDistinct: Future[Int] = {
  75.     val query = table.map(student => student.year).distinct.length.result // or just "countDistinct" instead of "distinct.length"
  76.     println(query.statements.mkString)
  77.     db.run(query)
  78.   }
  79. }
  80.  
  81. // StudentController.scala:
  82. import javax.inject.Inject
  83. import scala.concurrent.ExecutionContext
  84. import scala.util.control.NonFatal
  85. import dao.StudentDao
  86. import play.api.mvc._
  87.  
  88. /**
  89.  * StudentsController
  90.  * @param studentDao Students Data Access Object
  91.  * @param cc Controller Components
  92.  */
  93. class StudentsController @Inject()(
  94.     studentDao: StudentDao,
  95.     cc: ControllerComponents
  96.   )(implicit val ec: ExecutionContext) extends AbstractController(cc) {
  97.  
  98.   // add to routes: GET    /test/distinct    controllers.StudentsController.getDistinct
  99.   def getDistinct: Action[AnyContent] = Action.async {
  100.     studentDao.getDistinct map { count =>
  101.       Ok(s"There are $count different years stored in DB")
  102.     } recover {
  103.       case NonFatal(ex) => BadRequest(s"Error occured: $ex")
  104.     }
  105.   }
  106. }
  107.  
  108. // Come on!
  109. // Call: http://localhost:9000/test/distinct
  110. // Stdout: select count(1) from (select distinct `admission_year` from `student`) x2
  111. // Output: There are 2 different years stored in DB
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement