Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala SQL DSL(内部/外部)_Sql_Scala_Dsl - Fatal编程技术网

Scala SQL DSL(内部/外部)

Scala SQL DSL(内部/外部),sql,scala,dsl,Sql,Scala,Dsl,我一直在研究scala,主要是关于如何构建类似于C#LINQ/SQL的DSL。与C#LINQ查询提供程序合作后,很容易引入我们自己的定制查询提供程序,该程序将LINQ查询转换为我们自己的专有数据存储脚本。我正在寻找类似的东西在scala的eg val query = select Min(Close), Max(Close) from StockPrices where open > 0 首先,这甚至可以在scala中使用内部DSL实现 非常感谢您在这方面的任何想法/想法

我一直在研究scala,主要是关于如何构建类似于C#LINQ/SQL的DSL。与C#LINQ查询提供程序合作后,很容易引入我们自己的定制查询提供程序,该程序将LINQ查询转换为我们自己的专有数据存储脚本。我正在寻找类似的东西在scala的eg

 val query = select Min(Close), Max(Close)
 from   StockPrices 
 where  open > 0 
首先,这甚至可以在scala中使用内部DSL实现

非常感谢您在这方面的任何想法/想法


我还是scala领域的新手,但我开始研究scala元编程&Slick。我对Slick的抱怨是,我想将我的DSL与SQL查询对齐-类似于上面的语法

这是一个令人钦佩的项目,但它已经启动,并且可以在通用版本中使用


当然,我是说。

没有办法让内部DSL(当前版本)看起来与您提供的示例完全相同

使用我仍然拥有的宏,我能得到的最接近的(相对较快)是:

真正的解决方案需要相当长的时间才能创建。如果您愿意这样做,您可以使用macro(不是一个简单的主题)取得很大进展

如果您真的想要完全相同的语法,我建议您使用类似的方法,使用基于eclipse的编辑器“免费”创建DSL

上述示例所需的代码(我没有包括提到的宏):

然后使用它:

import tables._
import StockPrices._

select(Min(StockPrices.Open), Max(StockPrices.Open))
  .from(StockPrices)
  .toString

如果Scala/Java互操作性对您来说不是一个太大的问题,并且如果您愿意使用内部DSL,与您建议的语法相比,它有一些语法上的怪癖,那么它将逐渐成为一种流行的DSL替代方案。下面是一个例子:


用于(r生成的SQL是什么样子的?
Open,Close
Open.Close
的意思是什么?
Open
StockPrices
的属性吗?对不起,这是一个打字错误,我已经修改了我的原始帖子。我将把这个查询翻译成我们专有的脚本语言。不过,我是根据你的代码示例和开始阅读有关宏的内容,让我们看看我离这里有多远。看到宏也会很有趣。我们希望在2014年朝着这样一个方向发展……我用宏回答的问题在答案中有链接,下面是答案的直接链接:谢谢!对不起,我不知道我怎么错过了它
trait SqlElement {
  def toString(): String
}

trait SqlMethod extends SqlElement {
  protected val methodName: String
  protected val arguments: Seq[String]

  override def toString() = {
    val argumentsString = arguments mkString ","
    s"$methodName($argumentsString)"
  }
}

case class Select(elements: Seq[SqlElement]) extends SqlElement {
  override def toString() = s"SELECT ${elements mkString ", "}"
}

case class From(table: Metadata) extends SqlElement {
  private val tableName = table.name
  override def toString() = s"FROM $tableName"
}
case class Min(element: Metadata) extends SqlMethod {
  val methodName = "Min"
  val arguments = Seq(element.name)
}
case class Max(element: Metadata) extends SqlMethod {
  val methodName = "Max"
  val arguments = Seq(element.name)
}

class QueryBuilder(elements: Seq[SqlElement]) {
  def this(element: SqlElement) = this(Seq(element))

  def from(o: Metadata) = new QueryBuilder(elements :+ From(o))
  def where(element: SqlElement) = new QueryBuilder(elements :+ element)
  override def toString() = elements mkString ("\n")
}

def select(args: SqlElement*) = new QueryBuilder(Select(args))

trait Column
object Column extends Column

object tables {

  object StockPrices$ {
    val Open: Column = Column
    val Close: Column = Column
  }
  val StockPrices = StockPrices$
}
import tables._
import StockPrices._

select(Min(StockPrices.Open), Max(StockPrices.Open))
  .from(StockPrices)
  .toString
for (r <- e
    select (
      T_BOOK.ID * T_BOOK.AUTHOR_ID,
      T_BOOK.ID + T_BOOK.AUTHOR_ID * 3 + 4,
      T_BOOK.TITLE || " abc" || " xy"
    )
    from T_BOOK
    leftOuterJoin (
      select (x.ID, x.YEAR_OF_BIRTH)
      from x
      limit 1
      asTable x.getName()
    )
    on T_BOOK.AUTHOR_ID === x.ID
    where (T_BOOK.ID <> 2)
    or (T_BOOK.TITLE in ("O Alquimista", "Brida"))
    fetch
) {
  println(r)
}