“In” clause in anorm?

前端 未结 7 877
轮回少年
轮回少年 2020-12-30 23:53

It seems no easy way to use \"in\" clause in anorm:

val ids = List(\"111\", \"222\", \"333\")
val users = SQL(\"select * from users where id in ({ids})\").on         


        
7条回答
  •  悲哀的现实
    2020-12-31 00:01

    Maybe it's too late but here is a tip for using custom string interpolation that also works for solve the problem of IN clause.

    I have implemented a helper class to define a string interpolation. You can see it below, and you can simply copy and paste, but first let's see how you can use it.

    Instead of write something

    SQL("select * from car where brand = {brand} and color = {color} and year = {year} order by name").on("brand" -> brand, "color" -> color, "year" -> year).as(Car.simple *)
    

    You can simply write:

    SQL"select * from car where brand = $brand and color = $color and year = $year order by name".as(Car.simple *)
    

    So using string interpolation it's more concise and easier to read.

    And for the case of using the IN clause, you can write:

    val carIds = List(1, 3, 5)
    SQLin"select * from car where id in ($carIds)".as(Car.simple *)
    

    Or for your example:

    val ids = List("111", "222", "333")
    val users = SQLin"select * from users where id in ($ids)".as(parser *)
    

    For more information about string interpolation, check this link

    The code for this implicit class is the following:

    package utils
    
    object AnormHelpers {
    
      def wild (str: String) = "%" + str + "%"
    
      implicit class AnormHelper (val sc: StringContext) extends AnyVal {
    
        // SQL raw -> it simply create an anorm.Sql using string interpolation
        def SQLr (args: Any*) = {
          // Matches every argument to an arbitrary name -> ("p0", value0), ("p1", value1), ...
          val params = args.zipWithIndex.map(p => ("p"+p._2, p._1))
          // Regenerates the original query substituting each argument by its name with the brackets -> "select * from user where id = {p0}"
          val query = (sc.parts zip params).map{ case (s, p) => s + "{"+p._1+"}" }.mkString("") + sc.parts.last
          // Creates the anorm.Sql
          anorm.SQL(query).on( params.map(p => (p._1, anorm.toParameterValue(p._2))) :_*)
        }
    
        // SQL -> similar to SQLr but trimming any string value
        def SQL (args: Any*) = {
          val params = args.zipWithIndex.map {
            case (arg: String, index) => ("p"+index, arg.trim.replaceAll("\\s{2,}", " "))
            case (arg, index) => ("p"+index, arg)
          } 
          val query = (sc.parts zip params).map { case (s, p) => s + "{"+ p._1 + "}" }.mkString("") + sc.parts.last
          anorm.SQL(query).on( params.map(p => (p._1, anorm.toParameterValue(p._2))) :_*)
        }
    
        // SQL in clause -> similar to SQL but expanding Seq[Any] values separated by commas
        def SQLin (args: Any*) = {
          // Matches every argument to an arbitrary name -> ("p0", value0), ("p1", value1), ...
          val params = args.zipWithIndex.map {
            case (arg: String, index) => ("p"+index, arg.trim.replaceAll("\\s{2,}", " "))
            case (arg, index) => ("p"+index, arg)
          }
          // Expands the Seq[Any] values with their names -> ("p0", v0), ("p1_0", v1_item0), ("p1_1", v1_item1), ...
          val onParams = params.flatMap {
            case (name, values: Seq[Any]) => values.zipWithIndex.map(v => (name+"_"+v._2, anorm.toParameterValue(v._1)))
            case (name, value) => List((name, anorm.toParameterValue(value)))
          }
          // Regenerates the original query substituting each argument by its name expanding Seq[Any] values separated by commas
          val query = (sc.parts zip params).map {
            case (s, (name, values: Seq[Any])) => s + values.indices.map(name+"_"+_).mkString("{", "},{", "}")
            case (s, (name, value)) => s + "{"+name+"}"
          }.mkString("") + sc.parts.last
          // Creates the anorm.Sql
          anorm.SQL(query).on(onParams:_*)
        }
      }
    
    }
    

提交回复
热议问题