Я изо всех сил пытаюсь создать SQL DSL для Scala. DSL является расширением Querydsl , популярного уровня абстракции запросов для 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, startWith и т. Д., Необходимо использовать какой-то вид экранирования для запуска неявных преобразований.
Я рассматриваю следующие
прописные буквы
var predicate = (user.firstName LIKE "Bob") OR (user.firstName LIKE "Ann")
Это например, подход в Circumflex ORM , очень мощная структура ORM для Scala с аналогичными целями DSL. Но этот подход несовместим с ключевыми словами запроса (select, from, where и т. Д.), Которые в 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
.
РЕДАКТИРОВАТЬ
Мы получили поддержку Scala в Querydsl, работая с использованием экземпляров псевдонимов и escape-синтаксисом на основе $ -префикса. Вот сообщение в блоге о результатах: http://blog.mysema.com/2010/09/querying-with-scala.html