Skip to content

Instantly share code, notes, and snippets.

@camsaul
Created March 11, 2023 04:53
Show Gist options
  • Save camsaul/719a76b4a5797925d7c1b39017714183 to your computer and use it in GitHub Desktop.
Save camsaul/719a76b4a5797925d7c1b39017714183 to your computer and use it in GitHub Desktop.
MBQL clause decoding with Malli
(mbql-clause/define-tuple-mbql-clause :foo :- :type/Boolean
#_number int?)
(malli.core/validate
:mbql.clause/foo
[:foo {:lib/uuid (str (random-uuid))} 1])
;; => true
(malli.core/validate :mbql.clause/foo [:foo 1])
;; => false
(defmulti decode-mbql-clause
{:arglists '([target-tag clause])}
(fn [target-tag _clause]
target-tag))
(defmethod decode-mbql-clause :default
[_target-tag [tag & args]]
(let [[opts & args] (if (map? (first args))
args
(cons {} args))
opts (if (:lib/uuid opts)
opts
(assoc opts :lib/uuid (str (random-uuid))))]
(into [(keyword tag) opts] args)))
(defmethod decode-mbql-clause :foo
[target-tag clause]
(let [[tag opts n] ((get-method decode-mbql-clause :default) target-tag clause)]
[tag opts (abs n)]))
;;; dummy schema for transformation purposes
(mr/def :mbql.clause
[:tuple
{:mbql/tag :mbql.clause}])
(defmethod decode-mbql-clause :mbql.clause
[_target-tag [tag :as clause]]
(decode-mbql-clause (keyword tag) clause))
(def mbql-clause-transformer
(mtx/transformer
{:name :mbql-clause
:decoders {:tuple {:compile (fn [schema _options]
(partial decode-mbql-clause (:mbql/tag (malli.core/properties schema))))}}}))
(malli.core/decode :mbql.clause ["foo" -1] mbql-clause-transformer)
;; => [:foo {:lib/uuid "d02eeadb-72b6-46b4-ae8a-38417fac962f"} 1]
@camsaul
Copy link
Author

camsaul commented Mar 11, 2023

I should also mention I tweaked define-mbql-clause to include the :mbql/tag in the schema properties map

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment