跨越多行时忽略Groovy中的括号?

时间:2014-01-22 16:28:48

标签: groovy dsl builder

在groovy中使用像dsl这样的简单SQL,我有一些构建器类来创建一个select语句。

e.g。

class SelectClause implements Clause {

  final Object[] attrs;
  final ModTupleDSL parent;
  FromClause fromClause;

  public SelectClause(ModTupleDSL parent, Object... attrs) {
    this.parent = parent;
    this.attrs = attrs;
  }

  public FromClause from (Object relation) {
    fromClause = new FromClause(this, relation);
    return fromClause;
  }
}

class FromClause implements Clause {

  final Object relation;
  final SelectClause parent;
  WhereClause whereClause;

  public FromClause(SelectClause parent, Object relation) {
    this.parent = parent;
    this.relation = relation;
  }

  public WhereClause where(Closure predicate) {
    whereClause = new WhereClause(this, predicate);
    return whereClause;
  }
}

等...

在我的剧本中,我现在可以这样说:

select all from foo where {tuple, args -> tuple.get(id) == args[0]};

但是,如果我在其中添加换行符,则表示错误。

select all 
from foo 
where {tuple, args -> tuple.get(id) == args[0]};

groovy.lang.MissingMethodException: 
No signature of method: foo.Foo.from() is applicable for argument types:
 (clojure.lang.Keyword) values: [:foo]|Possible solutions: grep(), find(), 
          find(groovy.lang.Closure), grep(java.lang.Object), wait(), any()

解析Groovy时,这只是可选括号的副作用吗?

在预感中,我在每行的末尾添加了反斜杠,它似乎有效。 e.g。

select all \
from foo \
where {tuple, args -> tuple.get(id) == args[0]};

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

没有。 Groovy解析器将假定语句在第一行之后完成,在末尾插入;,除非它知道该行继续(例如,当有一个打开的括号或当你逃避EOL时)。 / p>

这是一种不需要分号的语言的缺点。

答案 1 :(得分:1)

我猜@Aaron是对的。或者,您可以允许在闭包内调用方法,并将方法调用委托给查询构建器:

class QueryBuilder {

  def projection
  def origin
  def condition

  def call(closure) {
    def hydrated = closure.rehydrate this, this, this
    hydrated()
    "select $projection from $origin"
  }

  def select(projection) {
    this.projection = projection
  }

  def from(origin) {
    this.origin = origin
  }

  def where(closure) {
    condition = closure
  }

  def propertyMissing(String property) { property }
}

def sql = new QueryBuilder().call {
  select all 
  from foo 
  where {tuple, args -> tuple.get(id) == args[0]};
}

assert sql == "select all from foo"

我没有完成where部分,但我想你有了想法