Dynamic orderBy with Squeryl

643 views Asked by At

I can not figure out how to change orderBy dynamically in runtime. I need something like:

def samplesSorted(fields: List[String]) = {
  from(Schema.samples)(s => select(s) orderBy(fields.map(getterByName))
}

Or something like

def samplesSorted(fields: List[String]) = {
  val q = from(Schema.samples)(s => select(s))
  fields.forEach(field => q.addOrderBy(getterByName(field)))
  q
}

I am trying to write a help function to manipulate AST now. But that does not seem like the right solution.

2

There are 2 answers

0
Vitamon On

This works for me

def ord(dr: DataRow, name: String): ExpressionNode = if (orderAscending) {
  dr.getterByName(name) asc
} else {
  dr.getterByName(name) desc
}

case class DataRow(id: Long,
  @Column("resource_id") resourceId: String,

  def getterByName(name: String) = {
    name match {
      case "resource_id" => resourceId.~
      case _ => id.~
    }
  }
}

from(DataSchema.dataRows) { dr =>
    where(dr.id === id).select(dr).orderBy(ord(dr, filedName))
}.page(offset, limit)
0
voronaam On

Did not notice there is a version of orderBy that accepts a list of ExpressionNodes. Was able to solve it like this:

def samplesSorted(fields: List[String]) = {
  from(Schema.samples)(s => select(s) orderBy(fields.map(buildOrderBy(s)))
}
def buildOrderBy(row: Row)(field: String): ExpressionNode = {
  getterByName(row, field)
}
def getterByName(row: Row, field: String): String = field match {
  case "Name" => row.name
  case "Address" => row.address
}

Have not tried with fields of different types yet - implicits may not work in this case. But I could always call them explicitly.

Upd:

To do the same with descending order one could use a helper like this one:

def desc(node: ExpressionNode):ExpressionNode = new OrderByArg(node) {desc}