具有 SQL 插值的 ScalikeJDBC 的未知 SQL 语法错误

Unknown SQL syntax error for ScalikeJDBC with SQL interpolation

为了避免 DRY,我正在尝试创建一个 sql INSERT 语句,其中包含可变列名和通过 ScalikeJDBC 的 sql 插值填充这些列的数据:

case class MySQLInsertMessage(tableName:String, columns:List[String], values:List[String])
def depositMessage(msg: MySQLInsertMessage): Unit = {
      NamedDB('MySQLMsgDepositor) localTx { implicit session =>
        val sqlStmt = sql"INSERT INTO ${msg.tableName} (${msg.columns}) VALUES (${msg.values})"
        println("The sql statement is: " + sqlStmt.statement)
        println("The parameters are: " + sqlStmt.parameters)
        sqlStmt.update().apply()
      }
    }

当我调用它时:

depositMessage(MySQLInsertMessage("My_Table", List("key", "email"), List("42", "user@email.com")))

最终的控制台打印输出是:

The sql statement is: INSERT INTO ? (?, ?) VALUES (?, ?)

The parameters are: List(My_Table, key, email, 42, user@email.com)

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''My_Table' ('key', 'email') VALUES ('42', 'user@emai' at line 1 java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''My_Table' ('key', 'email') VALUES ('42', 'user@emai' at line 1

我试过这样包装 sql"..."sql"""...""",但这似乎没有什么不同。我可以在 MySQL workbench GUI 中很好地执行预期的语句。知道我的语法错误是什么吗?

从@scaisEdge 的提示来看,似乎 ScalikeJDBC 在使用其语法时,总是 在任何参数化值周围放置单引号。从这里判断 - https://github.com/scalikejdbc/scalikejdbc/issues/320 - 这是一个已知问题。

对于 MySQL INSERT 语句(或其他语句),您的 table 名称或列值可能没有单引号,但允许使用反引号。

你可以使用他们的 SQLSyntax.createUnsafely(str:String) 方法,或者,如果我想像上面那样做,而不是使用 sql"...",我可以使用旧方法 SQL(s"INSERT INTO ${msg.tableName} (${msg.columns.mkString(",")})")

注意 - 我相信这两者都会让您容易受到注入攻击。因为,对我来说,这是一个本地 API 并且无论使用它你都必须拥有数据库的用户名和密码,我将采用 createUnsafely 做事的方式,稍微正则表达式 "cleaner" 有点不雅的想法:

def depositMessage(msg: MySQLInsertMessage): Unit = {
      NamedDB('MySQLMsgDepositor) localTx { implicit session =>
        val unsafeSQLRegex = "[`'\"]".r
        val table = SQLSyntax.createUnsafely(s"`${unsafeSQLRegex.replaceAllIn(msg.tableName, "")}`")
        val columns = SQLSyntax.createUnsafely(msg.columns.map(value => unsafeSQLRegex.replaceAllIn(value, "")).mkString("`", "`, `", "`"))
        val sqlStmt = sql"INSERT INTO $table ($columns) VALUES (${msg.values})".update().apply()
      }
    }
  }