datalog: dl-magic-query falls back on built-in/agg/neg goals (222/222)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Bug: dl-magic-query was always trying to seed a magic_<rel>^<adn>
fact for the query goal. For aggregate goals like (count N X (p X))
this produced a non-ground "fact" (magic_count^... N X (p X)) and
dl-add-fact! correctly rejected it, surfacing as an error.
Fix: dl-magic-query now detects built-in / aggregate / negation
goals up front and dispatches to plain dl-query for those cases —
magic-sets only applies to positive non-builtin literals against
rule-defined relations. Other shapes don't benefit from the
rewrite anyway.
1 new test confirms (count N X (p X)) returns the expected
{:N 3} via dl-magic-query.
This commit is contained in:
@@ -376,16 +376,26 @@
|
|||||||
dl-magic-query
|
dl-magic-query
|
||||||
(fn
|
(fn
|
||||||
(db query-goal)
|
(db query-goal)
|
||||||
(let
|
;; Magic-sets only applies to positive non-builtin / non-aggregate
|
||||||
((query-rel (dl-rel-name query-goal))
|
;; literals against rule-defined relations. For other goal shapes
|
||||||
(query-adn (dl-adorn-goal query-goal)))
|
;; (built-ins, aggregates, EDB-only relations) the seed is either
|
||||||
(let
|
;; non-ground or unused; fall back to dl-query.
|
||||||
((query-args (dl-bound-args query-goal query-adn))
|
(cond
|
||||||
(rules (dl-rules db)))
|
((or (dl-builtin? query-goal)
|
||||||
|
(dl-aggregate? query-goal)
|
||||||
|
(and (dict? query-goal) (has-key? query-goal :neg)))
|
||||||
|
(dl-query db query-goal))
|
||||||
|
(else
|
||||||
(let
|
(let
|
||||||
((rewritten (dl-magic-rewrite rules query-rel query-adn query-args))
|
((query-rel (dl-rel-name query-goal))
|
||||||
(mdb (dl-make-db))
|
(query-adn (dl-adorn-goal query-goal)))
|
||||||
(rule-heads (dl-magic-rule-heads rules)))
|
(let
|
||||||
|
((query-args (dl-bound-args query-goal query-adn))
|
||||||
|
(rules (dl-rules db)))
|
||||||
|
(let
|
||||||
|
((rewritten (dl-magic-rewrite rules query-rel query-adn query-args))
|
||||||
|
(mdb (dl-make-db))
|
||||||
|
(rule-heads (dl-magic-rule-heads rules)))
|
||||||
(do
|
(do
|
||||||
;; Copy EDB facts (relations not headed by any caller rule).
|
;; Copy EDB facts (relations not headed by any caller rule).
|
||||||
(for-each
|
(for-each
|
||||||
@@ -400,4 +410,4 @@
|
|||||||
;; Seed + rewritten rules.
|
;; Seed + rewritten rules.
|
||||||
(dl-add-fact! mdb (get rewritten :seed))
|
(dl-add-fact! mdb (get rewritten :seed))
|
||||||
(for-each (fn (r) (dl-add-rule! mdb r)) (get rewritten :rules))
|
(for-each (fn (r) (dl-add-rule! mdb r)) (get rewritten :rules))
|
||||||
(dl-query mdb query-goal)))))))
|
(dl-query mdb query-goal)))))))))
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"lang": "datalog",
|
"lang": "datalog",
|
||||||
"total_passed": 221,
|
"total_passed": 222,
|
||||||
"total_failed": 0,
|
"total_failed": 0,
|
||||||
"total": 221,
|
"total": 222,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
||||||
{"name":"parse","passed":18,"failed":0,"total":18},
|
{"name":"parse","passed":18,"failed":0,"total":18},
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
{"name":"negation","passed":10,"failed":0,"total":10},
|
{"name":"negation","passed":10,"failed":0,"total":10},
|
||||||
{"name":"aggregates","passed":19,"failed":0,"total":19},
|
{"name":"aggregates","passed":19,"failed":0,"total":19},
|
||||||
{"name":"api","passed":20,"failed":0,"total":20},
|
{"name":"api","passed":20,"failed":0,"total":20},
|
||||||
{"name":"magic","passed":23,"failed":0,"total":23},
|
{"name":"magic","passed":24,"failed":0,"total":24},
|
||||||
{"name":"demo","passed":21,"failed":0,"total":21}
|
{"name":"demo","passed":21,"failed":0,"total":21}
|
||||||
],
|
],
|
||||||
"generated": "2026-05-08T10:29:04+00:00"
|
"generated": "2026-05-08T10:31:43+00:00"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# datalog scoreboard
|
# datalog scoreboard
|
||||||
|
|
||||||
**221 / 221 passing** (0 failure(s)).
|
**222 / 222 passing** (0 failure(s)).
|
||||||
|
|
||||||
| Suite | Passed | Total | Status |
|
| Suite | Passed | Total | Status |
|
||||||
|-------|--------|-------|--------|
|
|-------|--------|-------|--------|
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
| negation | 10 | 10 | ok |
|
| negation | 10 | 10 | ok |
|
||||||
| aggregates | 19 | 19 | ok |
|
| aggregates | 19 | 19 | ok |
|
||||||
| api | 20 | 20 | ok |
|
| api | 20 | 20 | ok |
|
||||||
| magic | 23 | 23 | ok |
|
| magic | 24 | 24 | ok |
|
||||||
| demo | 21 | 21 | ok |
|
| demo | 21 | 21 | ok |
|
||||||
|
|||||||
@@ -197,6 +197,18 @@
|
|||||||
6)
|
6)
|
||||||
|
|
||||||
;; dl-magic-query: end-to-end driver, doesn't mutate caller's db.
|
;; dl-magic-query: end-to-end driver, doesn't mutate caller's db.
|
||||||
|
;; dl-magic-query falls back to dl-query for built-in,
|
||||||
|
;; aggregate, and negation goals (the magic seed would
|
||||||
|
;; otherwise be non-ground).
|
||||||
|
(dl-mt-test! "magic-query falls back on aggregate"
|
||||||
|
(let
|
||||||
|
((r (dl-magic-query
|
||||||
|
(dl-program "p(1). p(2). p(3).")
|
||||||
|
(list (quote count) (quote N) (quote X)
|
||||||
|
(list (quote p) (quote X))))))
|
||||||
|
(and (= (len r) 1) (= (get (first r) "N") 3)))
|
||||||
|
true)
|
||||||
|
|
||||||
(dl-mt-test! "magic-query equivalent to dl-query"
|
(dl-mt-test! "magic-query equivalent to dl-query"
|
||||||
(let
|
(let
|
||||||
((db (dl-program
|
((db (dl-program
|
||||||
|
|||||||
Reference in New Issue
Block a user