matcha icon indicating copy to clipboard operation
matcha copied to clipboard

Duplicated/un-merged results for nested optionals

Open kirahowe opened this issue 2 years ago • 0 comments

There's a bug where matches of optional clauses seem to return duplicated or unbound vars when they're nested inside a map in a build query.

For example:

;; Given this data:
(def db (matcha/index-triples [[:s1 :p1 :o1]
                               [:s1 :p2 :o2]
                               [:o1 :po1 :oo1]
                               [:o1 :po2 :oo2]]))

;; This works as expected (whether the last clause is optional or not, i.e. both):
(matcha/build [:id ?id]
              {:p1  ?o1
               :po1 ?oo1
               :po2 ?oo2}
              [[?id :p1 ?o1]
               [?id :p2 ?o2]
               [?o1 :po1 ?oo1]
               [?o1 :po2 ?oo2]]
              db)

;; and
(matcha/build [:id ?id]
              {:p1  ?o1
               :po1 ?oo1
               :po2 ?oo2}
              [[?id :p1 ?o1]
               [?id :p2 ?o2]
               [?o1 :po1 ?oo1]
               (matcha/optional [[?o1 :po2 ?oo2]])]
              db)

;; Return, as expected: 
({:id :s1
  :p1 :o1
  :po1 :oo1
  :po2 :oo2})

;; Nesting some of the results under a separate key also works when no clauses are optional:
(matcha/build [:id ?id]
              {:p1  ?o1
               :o1 {:po1 ?oo1
                    :po2 ?oo2}}
              [[?id :p1 ?o1]
               [?id :p2 ?o2]
               [?o1 :po1 ?oo1]
               [?o1 :po2 ?oo2]]
              db)

;; Returns, as expected:
({:id :s1
  :p1 :o1
  :o1 {:po1 :oo1
       :po2 :oo2}})

;; But making one of the clauses optional breaks the result (I would expect the same result as above here, but we get a set instead of a single nested resource):
(matcha/build [:id ?id]
              {:p1  ?o1
               :o1 {:po1 ?oo1
                    :po2 ?oo2}}
              [[?id :p1 ?o1]
               [?id :p2 ?o2]
               [?o1 :po1 ?oo1]
               (matcha/optional [[?o1 :po2 ?oo2]])]
              db)

;; Returns:
({:id :s1
  :p1 :o1
  :o1 #{{:po1 :oo1, :po2 _0}
        {:po1 :oo1, :po2 :oo2}}})

These can be manually fixed/flattened of course, but I think the result given is not the ideal solution.

This may have been introduced when fixing #21.

kirahowe avatar Oct 12 '23 20:10 kirahowe