Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
318a043
Add filter-info function to return data about filter patterns
zonotope Dec 3, 2025
6317bff
move `ensure-vector` to the util ns and improve behavior on nil
zonotope Dec 3, 2025
98fa3e3
rename higher-order-pattern? to vector-pattern?
zonotope Dec 3, 2025
d0d2c33
context aware where clause traversals
zonotope Dec 3, 2025
ae69d9a
Use context aware traversal in the filter inlining loop
zonotope Dec 4, 2025
90a5acc
wip: eliminate redundant compilation and add some tests
zonotope Dec 5, 2025
c59d431
Removed invalid :order clauses
zonotope Dec 5, 2025
64b56fb
Pass parsed where clauses to the -reorder method instead of queries
zonotope Dec 12, 2025
ff93b94
recursively reorder where clauses in optimize ns
zonotope Dec 12, 2025
474ccc7
Add `optimize-where-clause` helper to for where clause optimization
zonotope Dec 12, 2025
70d2036
Separate filters from binding patterns; sort binding patterns alone
zonotope Dec 16, 2025
fdfc1dc
Recursive inline filter optimization for nested where clauses
zonotope Dec 19, 2025
367958e
more accurate names for filter stripping functions
zonotope Dec 19, 2025
d78e27e
Update function names and docstrings for clarity
zonotope Dec 19, 2025
c31f019
push -> append/nest
zonotope Dec 23, 2025
409438b
Merge remote-tracking branch 'origin/main' into feature/inline-multiv…
zonotope Jan 3, 2026
1cbd8d5
cleanup
zonotope Jan 3, 2026
cc914cc
Remove metadata-based filter processing in favor of filter info maps
zonotope Jan 4, 2026
716dae2
inline multivar filters based on variable order in the query, not fn
zonotope Jan 4, 2026
b434293
Merge remote-tracking branch 'origin/main' into feature/inline-multiv…
zonotope Jan 13, 2026
5dda404
Treat exists/not-exists/minus patterns as nonbinding filters
zonotope Jan 14, 2026
2d056dd
Merge remote-tracking branch 'origin/main' into feature/inline-multiv…
zonotope Jan 15, 2026
4c21396
Merge remote-tracking branch 'origin/main' into feature/inline-multiv…
zonotope Jan 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/fluree/db/async_db.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,10 @@
root-db))

optimize/Optimizable
(-reorder [_ parsed-query]
(-reorder [_ where-clause]
(go-try
(let [db (<? db-chan)]
(<? (optimize/-reorder db parsed-query)))))
(<? (optimize/-reorder db where-clause)))))

(-explain [_ parsed-query]
(go-try
Expand Down
9 changes: 5 additions & 4 deletions src/fluree/db/dataset.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,11 @@
nil)))))

optimize/Optimizable
(-reorder [_ds parsed-query]
;; DataSets (federated queries) are not optimized
;; Return query unchanged wrapped in channel
(async/go parsed-query))
(-reorder [_ds where-clause]
;; DataSets (federated queries) are not optimized.
;; Return the clause unchanged wrapped in a channel to maintain the
;; optimizer contract without performing any work.
(async/go where-clause))

(-explain [_ds parsed-query]
;; DataSets (federated queries) cannot be explained
Expand Down
7 changes: 4 additions & 3 deletions src/fluree/db/flake/flake_db.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[fluree.db.flake.index.novelty :as novelty]
[fluree.db.flake.index.storage :as index-storage]
[fluree.db.flake.match :as match]
[fluree.db.flake.optimize :refer [explain-query optimize-query]]
[fluree.db.flake.optimize :refer [explain-query optimize-where]]
[fluree.db.flake.reasoner :as flake.reasoner]
[fluree.db.flake.transact :as flake.transact]
[fluree.db.indexer :as indexer]
Expand Down Expand Up @@ -506,8 +506,9 @@
(reasoner-util/reasoned-facts db))

optimize/Optimizable
(-reorder [db parsed-query]
(async/go (optimize-query db parsed-query)))
(-reorder [db where-clause]
(async/go
(optimize-where db where-clause)))

(-explain [db parsed-query]
(async/go (explain-query db parsed-query))))
Expand Down
18 changes: 9 additions & 9 deletions src/fluree/db/flake/optimize.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -484,16 +484,16 @@
{:type :boundary
:pattern (pattern->user-format (:pattern segment) compact-fn)}))

(defn optimize-query
"Optimize a parsed query using statistics if available.
Returns the optimized query with patterns reordered for optimal execution.
Uses fast path - extracts optimized patterns without formatting."
[db parsed-query]
(defn optimize-where
"Optimize a parsed where clause using statistics if available.
Returns the optimized clause in execution order, or the original clause when
statistics are unavailable."
[db where-clause]
(let [stats (:stats db)]
(if (and stats (not-empty stats) (:where parsed-query))
(let [{:keys [optimized]} (optimize-patterns-with-metadata db (:where parsed-query))]
(assoc parsed-query :where optimized))
parsed-query)))
(if (and stats (not-empty stats) (seq where-clause))
(let [{:keys [optimized]} (optimize-patterns-with-metadata db where-clause)]
optimized)
where-clause)))

(defn explain-query
"Generate an execution plan for the query showing optimization details.
Expand Down
9 changes: 5 additions & 4 deletions src/fluree/db/query/exec/where.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -615,8 +615,8 @@

(defn filter-exception
"Reformats raw filter exception to try to provide more useful feedback."
[e f]
(let [fn-str (->> f meta :forms (str/join " "))
[e filter-desc]
(let [fn-str (str/join " " (:forms filter-desc))
ex-msg (or (ex-message e)
;; note: NullPointerException is common but has no ex-message, create one
(let [ex-type (str (type e))] ;; attempt to make JS compatible
Expand Down Expand Up @@ -655,12 +655,13 @@
(defmethod match-pattern :filter
[_ds _tracker solution pattern error-ch]
(go
(let [f (pattern-data pattern)]
(let [desc (pattern-data pattern)
f (:fn desc)]
(try*
(let [result (f solution)]
(when result
solution))
(catch* e (>! error-ch (filter-exception e f)))))))
(catch* e (>! error-ch (filter-exception e desc)))))))

(defn with-constraint
"Return a channel of all solutions from the data set `ds` that extend from the
Expand Down
32 changes: 16 additions & 16 deletions src/fluree/db/query/fql/parse.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,15 @@
[var binding]))))
binds))

(defn higher-order-pattern?
"A non-node where pattern."
(defn vector-pattern?
"True when the where clause pattern is expressed as a vector form rather than a node map."
[pattern]
(and (sequential? pattern) (keyword? (first pattern))))

(defn parse-where-clause
[clause var-config context]
;; a single higher-order where pattern is already sequential, so we need to check if it needs wrapping
(let [clause* (if (higher-order-pattern? clause)
;; a single vector-form where pattern is already sequential, so we need to check if it needs wrapping
(let [clause* (if (vector-pattern? clause)
[clause]
(util/sequential clause))]
(->> clause*
Expand Down Expand Up @@ -577,10 +577,16 @@

(defmethod parse-pattern :filter
[[_ & codes] _var-config context]
(let [parsed-codes (map parse-code codes)
vars (apply set/union (map variables parsed-codes))
f (compile-filter-fn context parsed-codes)]
[(where/->pattern :filter (with-meta f {:forms parsed-codes, :vars vars}))]))
(let [parsed-codes (mapv parse-code codes)
vars (->> parsed-codes
(map variables)
(reduce set/union #{})
not-empty)
f (compile-filter-fn context parsed-codes)
info {:fn f
:forms parsed-codes
:vars vars}]
[(where/->pattern :filter info)]))

(defmethod parse-pattern :union
[[_ & unions] var-config context]
Expand Down Expand Up @@ -778,22 +784,16 @@
(assoc q select-key select))
q))

(defn ensure-vector
[x]
(if (vector? x)
x
[x]))

(defn parse-grouping
[q]
(some->> (:group-by q)
ensure-vector
util/ensure-vector
(mapv parse-var-name)))

(defn parse-ordering
[q]
(some->> (:order-by q)
ensure-vector
util/ensure-vector
(mapv (fn [ord]
(if-let [v (parse-var-name ord)]
[v :asc]
Expand Down
Loading
Loading