(ns metabase.legacy-mbql.schema.helpers (:refer-clojure :exclude [distinct]) (:require [clojure.string :as str] [metabase.types] [metabase.util.malli.registry :as mr])) | |
(comment metabase.types/keep-me) | |
--------------------------------------------------- defclause ---------------------------------------------------- | |
True if | (defn mbql-clause?
[x]
(and (sequential? x)
(not (map-entry? x))
(keyword? (first x)))) |
If (is-clause? :count [:count 10]) ; -> true (is-clause? #{:+ :- :* :/} [:+ 10 20]) ; -> true | (defn is-clause?
[k-or-ks x]
(and
(mbql-clause? x)
(if (coll? k-or-ks)
((set k-or-ks) (first x))
(= k-or-ks (first x))))) |
Returns (check-clause :count [:count 10]) ; => [:count 10] (check-clause? #{:+ :- :* :/} [:+ 10 20]) ; -> [:+ 10 20] (check-clause :sum [:count 10]) ; => nil | (defn check-clause
[k-or-ks x]
(when (is-clause? k-or-ks x)
x)) |
(defn- wrap-clause-arg-schema [arg-schema]
[:schema (if (qualified-keyword? arg-schema)
[:ref arg-schema]
arg-schema)]) | |
(defn- clause-arg-schema [arg-schema]
;; for things like optional schemas
(if-not (vector? arg-schema)
(wrap-clause-arg-schema arg-schema)
(let [[option arg-schema :as vector-arg-schema] arg-schema]
(case option
:optional [:? [:maybe (wrap-clause-arg-schema arg-schema)]]
:rest [:* (wrap-clause-arg-schema arg-schema)]
(wrap-clause-arg-schema vector-arg-schema))))) | |
Impl of [[metabase.legacy-mbql.schema.macros/defclause]] macro. Creates a Malli schema. | (defn clause
[tag & arg-schemas]
[:and
{:doc/title [:span [:code (pr-str tag)] " clause"]}
[:fn
{:error/message (str "must be a `" tag "` clause")}
(partial is-clause? tag)]
(into
[:catn
["tag" [:= tag]]]
(for [[arg-name arg-schema] (partition 2 arg-schemas)]
[arg-name (clause-arg-schema arg-schema)]))]) |
(defn- clause-tag [a-clause]
(when (and (vector? a-clause)
(keyword? (first a-clause)))
(first a-clause))) | |
Interal impl of | (defn one-of*
[& tags+schemas]
(into
[:multi {:dispatch clause-tag
:error/message (str "valid instance of one of these MBQL clauses: " (str/join ", " (map first tags+schemas)))
:doc/schema (into
[:or
{:description "valid instance of one of these MBQL clauses:"}]
(map second)
tags+schemas)}]
(for [[tag schema] tags+schemas]
[tag (if (qualified-keyword? schema)
[:ref schema]
schema)]))) |
Schema for any keyword or string. | (def KeywordOrString [:or :keyword :string]) |
Add an addditonal constraint to | (defn non-empty
[schema]
(if (and (sequential? schema)
(= (first schema) :sequential))
(let [[_sequential & args] schema
[options & args] (if (map? (first args))
args
(cons nil args))]
(into [:sequential (assoc options :min 1)] args))
[:and
schema
[:fn
{:error/message "non-empty"}
seq]])) |
True if | (defn empty-or-distinct?
[coll]
(if (seq coll)
(apply distinct? coll)
true)) |
(mr/def ::distinct
[:fn
{:description "values must be distinct"
:error/message "distinct"}
empty-or-distinct?]) | |
Add an additional constraint to | (defn distinct [schema] [:and schema [:ref ::distinct]]) |