Search code examples
scalaplayframeworkslick

Scala slick sort by column string name


I'm trying to implement such method in slick:

def paged(page: Long, sorting: String, order: String) = {
    infos.sortBy(_.???).drop((page - 1)*INFOS_PER_PAGE).take(INFOS_PER_PAGE).result
}

But I don't know what to put in sortBy and how to cast String to column. I tried simple function like this:

class PaymentInfoTable(tag: Tag) extends Table[PaymentInfo](tag, "payment_info") {

def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def date = column[DateTime]("date")
def paymentType = column[String]("payment_type")
def category = column[String]("category")
def subCategory = column[String]("sub_category")
def value = column[BigDecimal]("value")
def comment = column[Option[String]]("comment")
def outsidePaypal = column[Boolean]("outside_paypal")
def outsidePayer = column[Option[String]]("outside_payer")
def sorting(col: String) = {
        if(col == "id") {
            id
        } else if (col == "date") {
            date
        } else if (col == "paymentType") {
            paymentType
        } else if (col == "category") {
            category
        } else if (col == "subCategory") {
            subCategory
        } else if (col == "value") {
            value
        } else if (col == "comment") {
            comment
        } else if (col == "outsidePaypal") {
            outsidePaypal
        } else if (col == "outsidePayer") {
            outsidePayer
        } else {
            id
        }
    }

but then I can't do

sortBy(_.sorting(sorting).asc)

It says

value asc is not a member of slick.lifted.Rep[_1]

And I have imported

import slick.jdbc.MySQLProfile.api._

How can I sort by string column name?


Solution

  • Basically what you can do is to add a map with the string/property of the table

    class ColorsTable(tag: Tag) extends Table[Color](tag, "color") with DynamicSortBySupport.ColumnSelector {
      def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
      def name = column[String]("name")
      def * = (id, name) <> ((Color.apply _).tupled, Color.unapply)
      val select = Map(
        "id" -> (this.id),
        "name" -> (this.name)
      )
    }
    

    Then you only need to access that map

    case ((sortColumn, sortOrder), queryToSort) =>
      val sortOrderRep: Rep[_] => Ordered = ColumnOrdered(_, Ordering(sortOrder))
      val sortColumnRep: A => Rep[_] = _.select(sortColumn)
      queryToSort.sortBy(sortColumnRep)(sortOrderRep)
    

    You can find more info in this, like, but not same, question Dynamic order by in scala slick with several columns

    If you want something more simple, then just create an Order column with your column

    if(col == "id") {
      ColumnOrdered(id, Ordering(sortOrder))
    }