Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue454]: Add validation that queries provide the correct parameters #455

Merged
merged 2 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ This is a history of changes to clara-rules.
# 0.21.0 SNAPSHOT
* Add names to anonymous functions generated by rule compilation, see [issue 261](https://github.com/cerner/clara-rules/issues/261) and [issue 291](https://github.com/cerner/clara-rules/issues/291)
* Add alpha node types, see [issue 237](https://github.com/cerner/clara-rules/issues/237)
* BREAKING: Validate parameters provided to queries exist on query and compilation. see [issue 454](https://github.com/cerner/clara-rules/issues/454)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better to not just call it breaking. It is in a sense, but previously you’d get no result basically. Perhaps mention? Or is the issue link enough I guess?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For something like this where giving the now-breaking parameters would never have given meaningful result this might be a bit too much, but not really a big deal either way IMO. Maybe a phrase like "Throw exception on invalid..." to make clear that if users are giving correct input that they won't be impacted.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to the changes in b559d93


# 0.20.0
* Add a flag to omit compilation context (used by the durability layer) after Session compilation to save space when not needed. Defaults to true. [issue 422](https://github.com/cerner/clara-rules/issues/422)
Expand Down
25 changes: 18 additions & 7 deletions src/main/clojure/clara/rules/compiler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -1292,15 +1292,26 @@
beta-with-nodes))

;; No more conditions to add, so connect the production.
(add-node beta-graph
parent-ids
(create-id-fn)
(if (:rhs production)
(if (:rhs production)
;; if its a production node simply add it
(add-node beta-graph
parent-ids
(create-id-fn)
{:node-type :production
:production production
:bindings ancestor-bindings}
{:node-type :query
:query production}))))))
:bindings ancestor-bindings})
;; else its a query node and we need to validate that the query has at least the bindings
;; specified in the parameters
(if (every? ancestor-bindings (:params production))
(add-node beta-graph
parent-ids
(create-id-fn)
{:node-type :query
:query production})
(throw (ex-info "QueryNode does not contain bindings specified in parameters."
{:expected-bindings (:params production)
:available-bindings ancestor-bindings
:query (:name production)}))))))))


(sc/defn to-beta-graph :- schema/BetaGraph
Expand Down
3 changes: 3 additions & 0 deletions src/main/clojure/clara/rules/engine.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1986,6 +1986,9 @@
(let [query-node (get-in rulebase [:query-nodes query])]
(when (= nil query-node)
(platform/throw-error (str "The query " query " is invalid or not included in the rule base.")))
(when-not (= (into #{} (keys params)) ;; nil params should be equivalent to #{}
(:param-keys query-node))
(platform/throw-error (str "The query " query " was not provided with the correct parameters, expected: " (:param-keys query-node) ", provided: " (set (keys params)))))

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit : Really long line?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this was resolved by the changes in b559d93

(->> (mem/get-tokens memory query-node params)

Expand Down
26 changes: 23 additions & 3 deletions src/test/clojure/clara/test_compiler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
[clara.rules.engine :as eng]
[clojure.string :as str]
[clara.rules.accumulators :as acc]
[clojure.main :as m])
[clojure.main :as m]
[clara.rules.compiler :as com])
(:import [clara.rules.engine
AlphaNode
TestNode
Expand All @@ -14,7 +15,8 @@
ProductionNode
NegationWithJoinFilterNode
ExpressionJoinNode
RootJoinNode]))
RootJoinNode]
[clojure.lang ExceptionInfo]))

;; See https://github.com/cerner/clara-rules/pull/451 for more info
(tu/def-rules-test test-nodes-have-named-fns
Expand Down Expand Up @@ -55,4 +57,22 @@
"-"
(:id node)))
(-> node-fn str m/demunge (str/split #"/") last)))
(str "For node: " node " and node-fn: " node-fn)))))
(str "For node: " node " and node-fn: " node-fn)))))

;; See https://github.com/cerner/clara-rules/issues/454 for more info
(deftest test-query-node-requires-bindings-exist
(let [;; (defquery a-query
;; [:?b]
;; [?c <- ::a-fact-type])
query {:lhs [{:type ::a-fact-type
:constraints []
:args []
:fact-binding :?c}]
:params #{:?b}
:name "a-query"}]
(try (com/mk-session [[query]])
(catch ExceptionInfo exc
(is (= (ex-data exc)
{:expected-bindings #{:?b}
:available-bindings #{:?c}
:query "a-query"}))))))
30 changes: 30 additions & 0 deletions src/test/common/clara/test_simple_rules.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,33 @@
(is (has-fact? (:cold @side-effect-holder) (->Temperature -10 "MCI") ))

(is (has-fact? (:subzero @side-effect-holder) (->Temperature -10 "MCI")))))

(def-rules-test test-query-failure-when-provided-invalid-parameters

{:queries [temp-query [[:?t] [[Temperature (= ?t temperature)]]]]

:sessions [empty-session [temp-query] {}]}

(let [session (-> empty-session
(insert (->Temperature 10 "MCI"))
;; Ensure retracting a nonexistent item has no ill effects.
(retract (->Temperature 15 "MCI"))
fire-rules)

expected-msg #"was not provided with the correct parameters"]

;; passivity test
(is (= #{{:?t 10}}
(set (query session temp-query :?t 10))))

(is (thrown-with-msg? #?(:clj IllegalArgumentException :cljs js/Error)
expected-msg
(query session temp-query :?another-param 42)))

(is (thrown-with-msg? #?(:clj IllegalArgumentException :cljs js/Error)
expected-msg
(query session temp-query)))

(is (thrown-with-msg? #?(:clj IllegalArgumentException :cljs js/Error)
expected-msg
(query session temp-query :?t 42 :?another-param 42)))))