scalaslick-3.0slick-2.0

Is it possible to return a custom column value from the sql database table using slick?


There is a scenario when the requestType="HR" (which comes from the HTTP PUT request), it should return all the students information but return title as "EMPLOYEE"

For example, consider a "student" table with columns name,id, and title

 +-------+----+--------------------+
 + name  | id | title              +            
 +-------+----+--------------------+
 | KING  | 10 | SOFTWARE ENGINEER  |
 | BLAKE | 30 | SYSTEMS  ENGINEER  |
 +-------+----+--------------------+

GOAL: return all students, and override title="EMPLOYEE"

Here is what I have so far

 case class Student(name: String, id: Long, title: String)

 class StudentTable(tag: Tag) extends Table[Student](tag, "student") {
      def name = column[String]("name")
      def id = column[Long]("id")
      def title = column[String]("title")
      override def * = (name, id, title) <> ((Student.tupled, Student.unapply)
 }

 lazy val studentsQuery = TableQuery[StudentTable]

When i try to map and change the title value in the query, it complains about "re-assignment to val"

 val f = studentsQuery.map(p => p.title = "EMPLOYEE).result

complier error: Reassignment to val

Approach 2: I tried to pass in the requestType as a function parameter to the StudentTable, so that I can modify the title value based on the requestType. But then was not able to define studentsQuery since it was complaining about the "required tag".

 class StudentTable(tag: Tag)(reqType: String) extends Table[Student](tag, "student") {
      def name = column[String]("name")
      def id = column[Long]("id")
      def title = req.type match {
           case "HR" => "EMPLOYEE"
           case _ => column[String]("title")
      }
      override def * = (name, id, title) <> ((Student.tupled, Student.unapply)
 }

 // Didn't understand how to provide tag 
 lazy val studentsQuery = TableQuery[StudentTable]()("HR")

compilation error: unspecified value parameters: Cons: (Tag) => StudentTable


Solution

  • I wasn't able to do it from Slick, but found a way to do it using json serialization.

     import scala.concurrent.Await
     import scala.concurrent.duration._
     import slick.driver.MySQLDriver.api._
    
     case class Student(name: String, id: Long, title: String)
    
     class StudentTable(tag: Tag) extends Table[Student](tag, "student") {
          def name = column[String]("name")
          def id = column[Long]("id")
          def title = column[String]("title")
          override def * = (name, id, title) <> ((Student.tupled,Student.unapply)}
    
     lazy val studentsQuery = TableQuery[StudentTable]
    
    
     implicit def StudentDataWrites = new Writes[Student] {
         def writes(student: Student) =
              Json.obj(
                  "name"  -> student.name,
                  "id"    -> student.id,
                  "title" -> "EMPLOYEE"
                )
     }
    
     def getStudentsInfo() = Action {
        val students= Await.Result(db.run(studentsQuery.size.result), 10.seconds) 
        Ok(Json.obj("students" -> Json.toJson(students)))
    }