也许这不是要走的路,但这是我最初的猜测,我愿意接受提示和更正。
我have been writing a parser表示一种简化的查询方言,该查询方言已部分继承并扩展了很多,允许用户编写如下内容:
plant where accession.code='2018.0047'
还没有准备好,但是除了最后一个步骤之外,缺少的中间步骤很清楚:如何执行结果?
我的目标是等效的Ecto.Query.from
查询的引用表示形式。对于上面的示例,就我而言,等效项是:
from(p in "plant",
select: [:id],
join: a in "accession",
on: a.id==p.accession_id,
where: a.code=="2018.0047")
我一直在研究__schema__
函数返回的结构,并且看起来都很可行,我的意思是我知道如何从模块中提取表名,并从关联中提取所有者和相关模块以及键。给定它的名字,让我们假设我的解析器确实返回了这个值:
{:from, [context: Elixir, import: Ecto.Query],
[
{:in, [context: Elixir, import: Kernel], [{:p, [], Elixir}, "plant"]},
[
select: [:id],
join: {:in, [context: Elixir, import: Kernel],
[{:a, [], Elixir}, "accession"]},
on: {:==, [context: Elixir, import: Kernel],
[
{{:., [], [{:a, [], Elixir}, :id]}, [], []},
{{:., [], [{:p, [], Elixir}, :accession_id]}, [], []}
]},
where: {:==, [context: Elixir, import: Kernel],
[{{:., [], [{:a, [], Elixir}, :code]}, [], []}, "2018.0047"]}
]
]}
我如何让Ecto执行它?
或者从yecc解析器生成Elixir代码的最佳方法是什么?
答案 0 :(得分:0)
简短答案:否,我们无法让Elixir执行“引用”代码。
如果我正确理解在elixir论坛上收到的评论,则quoted
格式仅适用于宏,即用于在编译时定义的内容。
回到示例:
from(p in "plant",
select: [:id],
join: a in "accession",
on: a.id==p.accession_id,
where: a.code=="2018.0047")
其结果是一个值,一个Ecto.Query
结构,尽管不是立即看到正在定义的字段,但看看源代码,我发现我可以产生相同的结果逐步说明价值,例如:
q = %Ecto.Query{}
q = %{ q | from: %Ecto.Query.FromExpr{source: {"plant", nil}}}
q = %{ q | select: %Ecto.Query.SelectExpr{
expr: [{{:., [], [{:&, [], [0]}, :id]}, [], []}]}}
q = %{ q | joins: [
%Ecto.Query.JoinExpr{
source: {"accession", nil},
qual: :inner,
on: %Ecto.Query.QueryExpr{
expr: {:==, [], [
{{:., [], [{:&, [], [0]}, :accession_id]}, [], []},
{{:., [], [{:&, [], [1]}, :id]}, [], []}
]}}}]}
q = %{ q | wheres: [
%Ecto.Query.BooleanExpr{
op: :and,
expr: {:==, [], [{{:., [], [{:&, [], [1]}, :code]}, [], []}, "2018.0047"]}}]}
我知道它看起来并不容易,但是我可以在语法作品中使用它。