具有 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()
}
}
}
为了避免 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()
}
}
}