2014-01-22 27 views
1

在groovy中使用像dsl這樣的簡單SQL,並且我有一些構建器類來創建select語句。在跨越多行時忽略Groovy中的括號?

例如

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時可選括號的副作用嗎?

在預感上,我把反斜槓放在每一行的末尾,它似乎工作。例如

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

有沒有更好的方法?

回答

2

否。Groovy解析器會假定語句在第一行後完成,在末尾插入一個;,除非它知道該行繼續(例如,當存在左括號或者當您退出EOL時) 。

這是不需要分號的語言的缺點。

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一部分,但我猜你上心