我有以下SQL查询,我想将其映射到Slick
SELECT * FROM rates
WHERE '3113212512' LIKE (prefix || '%') and present = true
ORDER BY prefix DESC
LIMIT 1;
但是,没有为String定义like符号:
case class Rate(grid: String, prefix: String, present: Boolean)
class Rates(tag: Tag) extends Table[Rate](tag, "rates") {
def grid = column[String]("grid", O.PrimaryKey, O.NotNull)
def prefix = column[String]("prefix", O.NotNull)
def present = column[Boolean]("present", O.NotNull)
// Foreign keys
def ratePlan = foreignKey("rate_plan_fk", ratePlanId, RatePlans)(_.grid)
def ratePlanId = column[String]("rate_plan_id", O.NotNull)
def * = (grid, prefix, present) <>(Rate.tupled, Rate.unapply)
}
object Rates extends TableQuery(new Rates(_)) {
def findActiveRateByRatePlanAndPartialPrefix(ratePlan: String, prefix: String) = {
DB withSession {
implicit session: Session =>
Rates.filter(_.ratePlanId === ratePlan)
.filter(_.present === true)
.filter(prefix like _.prefix)
.sortBy(_.prefix.desc).firstOption
}
}
}
显然,这样的事情不起作用是合乎逻辑的:
.filter(prefix like _.prefix)
和:
.filter(_.prefix like prefix)
将呈现不正确的SQL,我现在甚至没有考虑'%'(只有关于前缀的WHERE子句:
(x2."prefix" like '3113212512')
代替:
'3113212512' LIKE (prefix || '%')
当然我可以使用静态查询解决这个问题,但我想知道这是否可行?
为清楚起见,这里是数据库中的一些前缀
31
3113
312532623
31113212
结果预计会有31113212
2 回答
您可以简单地以支持的样式重写查询 . 我认为这应该是等价的:
如果条件更复杂并且您需要Case表达式,请参阅http://slick.typesafe.com/doc/2.1.0/sql-to-slick.html#case
如果你还想要||运算符您可以这样定义它:
...
我没有对SimpleBinaryOperator进行测试 . 如果不起作用,请在github.com/slick/slick上打开一张票 . 可能我们也应该改变它以返回一个类型化的函数 . 我为https://github.com/slick/slick/issues/1073添加了一张票 .
另见http://slick.typesafe.com/doc/2.1.0/userdefined.html#scalar-database-functions
幸运的是,这里甚至不需要SimpleBinaryOperator .
UPDATE 2
实际上一个不需要concat,因为它也可以写成如下:
UPDATE:
在cvogt提示后,这是不使用内部Slick API的最终结果:
完美地给出了:
Alternative:
这似乎是可能的 . 但请注意,以下方法使用Slick的内部API,并且由于API更改,将来可能不兼容(请参阅cvogt的评论)我使用了Slick 2.1.0 .
基本上我创建了一个Slick的扩展,我在其中定义了一个自定义方案来实现所需的结果:
现在可以按如下方式使用:
并将呈现正确的结果:
笔记:
我可能有更好的命名
必须链接||和使用om.column一样
我引入了新的SqlOperator,因为Or运算符渲染或者我需要在Postgres中连接||