Я пытаюсь создать SQL DSL для Scala. DSL является расширением Querydsl , который является популярным уровнем абстракции Query для Java.
Сейчас я борюсь с очень простыми выражениями вроде следующего
user.firstName == "Bob" || user.firstName == "Ann"
Поскольку Querydsl уже поддерживает модель выражений, которую можно использовать здесь, я решил обеспечить преобразование объектов Proxy в выражения Querydsl. Для использования прокси я создаю такой экземпляр
import com.mysema.query.alias.Alias._
var user = alias(classOf[User])
С помощью следующих неявных преобразований я могу преобразовывать экземпляры прокси и цепочки вызовов свойств прокси в выражения Querydsl
import com.mysema.query.alias.Alias._
import com.mysema.query.types.expr._
import com.mysema.query.types.path._
object Conversions {
def not(b: EBoolean): EBoolean = b.not()
implicit def booleanPath(b: Boolean): PBoolean = $(b);
implicit def stringPath(s: String): PString = $(s);
implicit def datePath(d: java.sql.Date): PDate[java.sql.Date] = $(d);
implicit def dateTimePath(d: java.util.Date): PDateTime[java.util.Date] = $(d);
implicit def timePath(t: java.sql.Time): PTime[java.sql.Time] = $(t);
implicit def comparablePath(c: Comparable[_]): PComparable[_] = $(c);
implicit def simplePath(s: Object): PSimple[_] = $(s);
}
Теперь я могу создавать выражения, подобные этому
import com.mysema.query.alias.Alias._
import com.mysema.query.scala.Conversions._
var user = alias(classOf[User])
var predicate = (user.firstName like "Bob") or (user.firstName like "Ann")
Я борюсь со следующей проблемой.
eq
и ne
уже доступны как методы в Scala, поэтому преобразования не запускаются при их использовании
Эта проблема может быть обобщена следующим образом. При использовании имен методов, которые уже доступны в таких типах Scala, как eq, ne, launchWith и т. Д., Необходимо использовать какой-либо вид экранирования для запуска неявных преобразований.
Я рассматриваю следующее
Прописные буквы
var predicate = (user.firstName LIKE "Bob") OR (user.firstName LIKE "Ann")
Это, например, подход в Circumflex ORM , очень мощной среде ORM для Scala с аналогичными целями DSL. Но этот подход не согласуется с ключевыми словами запроса (выберите, откуда, где и т. Д.), Которые в Querydsl строчные.
Некоторые префиксы
var predicate = (user.firstName :like "Bob") :or (user.firstName :like "Ann")
Контекст использования предиката выглядит примерно так
var user = alias(classOf[User])
query().from(user)
.where(
(user.firstName like "Bob") or (user.firstName like "Ann"))
.orderBy(user.firstName asc)
.list(user);
Видите ли вы лучшие варианты или другой подход для построения SQL DSL для Scala?
Таким образом, вопрос сводится к двум случаям
Можно ли вызвать неявное преобразование типов при использовании метода, который существует в суперклассе (например, eq
)
Если это невозможно, то какой синтаксис Scalaesque наиболее подходит для таких методов, как eq
, ne
.
EDIT
Мы получили поддержку Scala в Querydsl, используя псевдонимы и escape-синтаксис на основе $ -prefix. Вот сообщение в блоге о результатах: http://blog.mysema.com/2010/09/querying-with-scala.html