|
1227 | 1227 | :rels (->> (:rels context) |
1228 | 1228 | (keep #(limit-rel % vars))))) |
1229 | 1229 |
|
| 1230 | +(defn- ctx-bound-vars [context] |
| 1231 | + (set (concat (mapcat #(keys (:attrs %)) (:rels context)) |
| 1232 | + (keys (:consts context))))) |
| 1233 | + |
| 1234 | +(defn all-bound? |
| 1235 | + "True iff every var in `vars` is currently bound in `context`." |
| 1236 | + [context vars] |
| 1237 | + (set/subset? (set vars) (ctx-bound-vars context))) |
| 1238 | + |
| 1239 | +(defn some-bound? |
| 1240 | + "True iff at least one var in `vars` is currently bound in `context`." |
| 1241 | + [context vars] |
| 1242 | + (boolean (seq (set/intersection (set vars) (ctx-bound-vars context))))) |
| 1243 | + |
1230 | 1244 | (defn check-all-bound [context vars form] |
1231 | | - (let [bound (set (concat (mapcat #(keys (:attrs %)) (:rels context)) |
1232 | | - (keys (:consts context))))] |
| 1245 | + (let [bound (ctx-bound-vars context)] |
1233 | 1246 | (when-not (set/subset? vars bound) |
1234 | 1247 | (let [missing (set/difference (set vars) bound)] |
1235 | 1248 | (log/raise "Insufficient bindings: " missing " not bound in " form |
|
1238 | 1251 | :vars missing}))))) |
1239 | 1252 |
|
1240 | 1253 | (defn check-some-bound [context vars form] |
1241 | | - (let [bound (set (concat (mapcat #(keys (:attrs %)) (:rels context)) |
1242 | | - (keys (:consts context))))] |
1243 | | - (when (empty? (set/intersection vars bound)) |
1244 | | - (log/raise "Insufficient bindings: none of " vars " is bound in " form |
1245 | | - {:error :query/where |
1246 | | - :form form})))) |
| 1254 | + (when (empty? (set/intersection vars (ctx-bound-vars context))) |
| 1255 | + (log/raise "Insufficient bindings: none of " vars " is bound in " form |
| 1256 | + {:error :query/where |
| 1257 | + :form form}))) |
1247 | 1258 |
|
1248 | 1259 | (defn resolve-context [context clauses] |
1249 | 1260 | (dt/resolve-clauses resolve-clause context clauses)) |
|
1894 | 1905 | ([context clause orig-clause] |
1895 | 1906 | (condp looks-like? clause |
1896 | 1907 | [[symbol? '*]] ;; predicate [(pred ?a ?b ?c)] |
1897 | | - (do (check-all-bound context (identity (filter free-var? (first clause))) orig-clause) |
1898 | | - (filter-by-pred context clause)) |
| 1908 | + ;; Defer if any input var isn't bound yet — the iterative resolver |
| 1909 | + ;; (datahike.tools/resolve-clauses) will retry once binders fire. |
| 1910 | + ;; If the var is never bound, the resolver raises "Cannot resolve any |
| 1911 | + ;; more clauses" with the full pending list, which is more useful |
| 1912 | + ;; than a misleading single-clause error from this site. |
| 1913 | + (let [vars (filter free-var? (first clause))] |
| 1914 | + (when (all-bound? context vars) |
| 1915 | + (filter-by-pred context clause))) |
1899 | 1916 |
|
1900 | 1917 | [[symbol? '*] '_] ;; function [(fn ?a ?b) ?res] |
1901 | 1918 | (bind-by-fn context clause) |
|
1918 | 1935 |
|
1919 | 1936 | '[or-join [[*] *] *] ;; (or-join [[req-vars] vars] ...) |
1920 | 1937 | (let [[_ [req-vars & vars] & branches] clause] |
1921 | | - (check-all-bound context req-vars orig-clause) |
1922 | | - (recur context (list* 'or-join (concat req-vars vars) branches) clause)) |
| 1938 | + (when (all-bound? context req-vars) |
| 1939 | + (recur context (list* 'or-join (concat req-vars vars) branches) clause))) |
1923 | 1940 |
|
1924 | 1941 | '[or-join [*] *] ;; (or-join [vars] ...) |
1925 | 1942 | ;; TODO required vars |
|
1953 | 1970 |
|
1954 | 1971 | '[not *] ;; (not ...) |
1955 | 1972 | (let [[_ & clauses] clause |
1956 | | - negation-vars (collect-vars clauses) |
1957 | | - _ (check-some-bound context negation-vars orig-clause) |
1958 | | - join-rel (reduce hash-join (:rels context)) |
1959 | | - negation-context (-> context |
1960 | | - (assoc :rels [join-rel]) |
1961 | | - (assoc :stats []) |
1962 | | - (resolve-context clauses)) |
1963 | | - negation-join-rel (reduce hash-join (:rels negation-context)) |
1964 | | - negation (subtract-rel join-rel negation-join-rel)] |
1965 | | - (cond-> (assoc context :rels [negation]) |
1966 | | - (:stats context) (assoc :tmp-stats {:type :not |
1967 | | - :branches (:stats negation-context)}))) |
| 1973 | + negation-vars (collect-vars clauses)] |
| 1974 | + (when (some-bound? context negation-vars) |
| 1975 | + (let [join-rel (reduce hash-join (:rels context)) |
| 1976 | + negation-context (-> context |
| 1977 | + (assoc :rels [join-rel]) |
| 1978 | + (assoc :stats []) |
| 1979 | + (resolve-context clauses)) |
| 1980 | + negation-join-rel (reduce hash-join (:rels negation-context)) |
| 1981 | + negation (subtract-rel join-rel negation-join-rel)] |
| 1982 | + (cond-> (assoc context :rels [negation]) |
| 1983 | + (:stats context) (assoc :tmp-stats {:type :not |
| 1984 | + :branches (:stats negation-context)}))))) |
1968 | 1985 |
|
1969 | 1986 | '[not-join [*] *] ;; (not-join [vars] ...) |
1970 | | - (let [[_ vars & clauses] clause |
1971 | | - _ (check-all-bound context vars orig-clause) |
1972 | | - join-rel (reduce hash-join (:rels context)) |
1973 | | - negation-context (-> context |
1974 | | - (assoc :rels [join-rel]) |
1975 | | - (assoc :stats []) |
1976 | | - (limit-context vars) |
1977 | | - (resolve-context clauses) |
1978 | | - (limit-context vars)) |
1979 | | - negation-join-rel (reduce hash-join (:rels negation-context)) |
1980 | | - negation (subtract-rel join-rel negation-join-rel)] |
1981 | | - (cond-> (assoc context :rels [negation]) |
1982 | | - (:stats context) (assoc :tmp-stats {:type :not |
1983 | | - :branches (:stats negation-context)}))) |
| 1987 | + (let [[_ vars & clauses] clause] |
| 1988 | + (when (all-bound? context vars) |
| 1989 | + (let [join-rel (reduce hash-join (:rels context)) |
| 1990 | + negation-context (-> context |
| 1991 | + (assoc :rels [join-rel]) |
| 1992 | + (assoc :stats []) |
| 1993 | + (limit-context vars) |
| 1994 | + (resolve-context clauses) |
| 1995 | + (limit-context vars)) |
| 1996 | + negation-join-rel (reduce hash-join (:rels negation-context)) |
| 1997 | + negation (subtract-rel join-rel negation-join-rel)] |
| 1998 | + (cond-> (assoc context :rels [negation]) |
| 1999 | + (:stats context) (assoc :tmp-stats {:type :not |
| 2000 | + :branches (:stats negation-context)}))))) |
1984 | 2001 |
|
1985 | 2002 | '[*] ;; pattern |
1986 | 2003 | (let [source rel/*implicit-source* |
|
0 commit comments