Anorm String Interpolation不替换变量

时间:2015-01-10 00:46:39

标签: scala playframework-2.3 anorm

我们正在使用Scala Play,我正在尝试确保所有SQL查询都使用Anorm的字符串插值。它适用于某些查询,但许多实际上并不在查询执行之前替换变量。

import anorm.SQL
import anorm.SqlStringInterpolation

object SecureFile 
{
  val table = "secure_file"
  val pk = "secure_file_idx"
  ...

// This method works exactly as I would hope
def insert(secureFile: SecureFile): Option[Long] = {
  DBExec { implicit connection =>
    SQL"""
      INSERT INTO secure_file (
        subscriber_idx,
        mime_type,
        file_size_bytes,
        portal_msg_idx
      ) VALUES (
        ${secureFile.subscriberIdx},
        ${secureFile.mimeType},
        ${secureFile.fileSizeBytes},
        ${secureFile.portalMsgIdx}
        )
      """ executeInsert()
    }
  }

def delete(secureFileIdx: Long): Int = {
  DBExec { implicit connection =>
    // Prints correct values
    println(s"table: ${table} pk: ${pk} secureFileIdx: ${secureFileIdx} ")

    // Does not work
    SQL""" 
      DELETE FROM $table WHERE ${pk} = ${secureFileIdx} 
    """.executeUpdate()

    // Works, but unsafe
    val query = s"DELETE FROM ${table} WHERE ${pk} = ${secureFileIdx}" 
    SQL(query).executeUpdate() 
  }
}
....
}

在PostgreSQL日志中,很明显删除语句没有获取正确的值:

2015-01-09 17:23:03 MST ERROR:  syntax error at or near "$1" at character 23
2015-01-09 17:23:03 MST STATEMENT: DELETE FROM $1 WHERE $2 = $3
2015-01-09 17:23:03 MST LOG:  execute S_1: ROLLBACK

我尝试过很多execute,executeUpdate和executeQuery的变种,结果相似。目前,我们正在使用基本的字符串替换,但当然这很糟糕,因为它没有使用PreparedStatements。

2 个答案:

答案 0 :(得分:4)

引入Anorm字符串插值来传递参数(例如SQL"Select * From Test Where id = $x),并根据正确的类型转换在基础$x上设置插值参数(例如PreparedStament)(请参阅{{上的用例} 3}})。

下一个Anorm版本还将使用#$foo语法将参数插值与标准字符串插值混合。这将允许写DELETE FROM #$table WHERE #${pk} = ${secureFileIdx}并将其作为DELETE FROM foo WHERE bar = ?执行(如果文字table"foo"pk"bar"),则使用文字secureFileIdx作为参数传递。请参阅相关的https://www.playframework.com/documentation/2.3.x/ScalaAnorm

在下一版本发布之前,您可以从其主要来源构建Anorm,并从此更改中受益。

答案 1 :(得分:4)

对于坐在这个页面上的任何人都挠头,想知道他们可能会遗漏什么......

SQL("select * from mytable where id = $id") 

不同
SQL"select * from mytable where id = $id" 

前者不进行字符串插值,后者则不进行。

在上述文档中很容易忽略这一点,因为所提供的所有样本恰好都有一个(非相关的)右括号(就像这句话一样)