edn-query-language / eql

EQL is a declarative way to make hierarchical (and possibly nested) selections of information about data requirements. This repository contains the base specs and definitions for EQL parsing, AST, etc.
http://edn-query-language.org
MIT License
381 stars 18 forks source link

Meta support on join vector #18

Closed wilkerlucio closed 2 years ago

wilkerlucio commented 2 years ago

Closes #17

lilactown commented 2 years ago

I think another place we want to preserve metadata (that isn't yet supported here) is on union entries:

user> (eql/query->ast [{:foo {:bar ^:union-meta [:baz]}}])
{:type :root,
 :children
 [{:type :join,
   :dispatch-key :foo,
   :key :foo,
   :query {:bar [:baz]},
   :children
   [{:type :union,
     :query {:bar [:baz]},
     :children
     [{:type :union-entry,
       :union-key :bar,
       :query [:baz],
       :children [{:type :prop, :dispatch-key :baz, :key :baz}]}]}]}]} ;; missing metadata
user> (eql/query->ast [{:foo {:bar ^:component [:baz]}}])
{:type :root,
 :children
 [{:type :join,
   :dispatch-key :foo,
   :key :foo,
   :query {:bar [:baz]},
   :children
   [{:type :union,
     :query {:bar [:baz]},
     :children
     [{:type :union-entry,
       :union-key :bar,
       :query [:baz],
       :children [{:type :prop, :dispatch-key :baz, :key :baz}],
       :component true}]}]}]} ;; <---- component is here as desired
wilkerlucio commented 2 years ago

One thing that I'm wondering is when converting the AST back to query again. Currently, it does it at the join map, but if we are now extracting from the vector also, where will it go? An option is copying on both, which will differ from the source.

I was thinking through some options, and it occurred to me that there is a way to get the query currently. Here is a demo:

(-> (eql/query->ast [{:people ^:foo [:person/id :person/name]}])
      :children first :query meta)

I'm thinking considering this is possible to get the meta, we may not make any changes to EQL here. Will this solution work for your case?

wilkerlucio commented 2 years ago

I put my thoughts about some options I've considered for this, will appreciate your thoughts on it: https://docs.google.com/spreadsheets/d/1OZocybiQxm-lo2Ee5dG7D68_v3F6YlgCkwbkg1resCE/edit#gid=0

lilactown commented 2 years ago

That makes sense, I didn't think of that before. That meets my use case.

I think if you want it to be both bidirectional and serializable, then adding additional keys is the way.

Either that or another level of nesting, but that would be a significant breaking change.

Example:

user> (eql/query->ast [{:people ^:foo [:person/id :person/name]}])
{:type :root,
 :children
 [{:type :join,
   :dispatch-key :people,
   :key :people,
   :query [:person/id :person/name],
   :children
   {:type :join-query
    :meta {:foo true}
    :children [{:type :prop, :dispatch-key :person/id, :key :person/id}
               {:type :prop, :dispatch-key :person/name, :key :person/name}}]}]}
wilkerlucio commented 2 years ago

Considering all the conversations I'm gonna close this, we gonna keep as-is.