Skip to content

Commit e13b4f1

Browse files
committed
Remove symbol duplicates from op-sets in specification.cljc
The three op-sets (agg/pred/expr) contained both keyword and symbol forms, but the symbol coverage was incomplete and inconsistent vs the keyword side. Symbols are normalized to keywords by the query engine (normalization.clj) before any dispatch — they don't belong in the validation sets. Clean up: keyword-only sets + normalize symbol→keyword in SAggSpec and SPredSpec validators before the contains? check. Symbol input like '(sum :col) and '(< :col 5) still validates and works correctly.
1 parent 8f77607 commit e13b4f1

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

src/stratum/specification.cljc

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,27 @@
6767
;; =============================================================================
6868

6969
(def agg-op-set
70-
"All recognized aggregate operators."
70+
"All recognized aggregate operators (keywords only).
71+
Symbol forms (e.g. 'sum) are normalized to keywords by the query engine before dispatch."
7172
#{:sum :count :count-non-null :avg :min :max :stddev :stddev-pop :variance :variance-pop :corr
72-
:sum-product :count-distinct :median :percentile :approx-quantile
73-
'sum 'count 'count-non-null 'avg 'min 'max 'stddev 'stddev-pop 'variance 'variance-pop 'corr
74-
'sum-product 'count-distinct 'median 'percentile 'approx-quantile})
73+
:sum-product :count-distinct :median :percentile :approx-quantile})
7574

7675
(def pred-op-set
77-
"All recognized predicate operators."
76+
"All recognized predicate operators (keywords only).
77+
Symbol forms (e.g. '< '=) are normalized to keywords by the query engine before dispatch."
7878
#{:< :> :<= :>= := :!= :not= :between :range :not-range
7979
:like :not-like :ilike :not-ilike :contains :starts-with :ends-with
80-
:in :not-in :is-null :is-not-null :or :and :not
81-
'< '> '<= '>= '= 'not= 'between 'range
82-
'like 'in 'not-in 'ilike 'not-ilike 'is-null 'is-not-null 'or 'and 'not})
80+
:in :not-in :is-null :is-not-null :or :and :not})
8381

8482
(def expr-op-set
85-
"All recognized expression operators."
83+
"All recognized expression operators (keywords only).
84+
Symbol forms are normalized to keywords by the query engine before dispatch."
8685
#{:+ :- :* :/ :mod :% :abs :sqrt :log :ln :log10 :exp :pow
8786
:round :floor :ceil :sign :signum
8887
:year :month :day :hour :minute :second :day-of-week :week-of-year
8988
:date-trunc :date-add :date-diff :epoch-days :epoch-seconds
9089
:coalesce :nullif :greatest :least :lower :upper :substr :length :trim :replace :concat
91-
:cast :case
92-
'+ '- '* '/ 'abs 'sqrt 'round 'cast})
90+
:cast :case})
9391

9492
(def SExpr
9593
"Column reference, literal, or expression vector.
@@ -123,7 +121,9 @@
123121
(str "aggregate must start with a known operator: "
124122
":sum :count :count-non-null :avg :min :max :stddev :stddev-pop :variance :variance-pop :corr "
125123
":count-distinct :median :percentile :approx-quantile :as")}
126-
#(contains? (conj agg-op-set :as 'as) (first %))]])
124+
#(let [op (first %)
125+
kw (if (symbol? op) (keyword (name op)) op)]
126+
(contains? (conj agg-op-set :as) kw))]])
127127

128128
;; =============================================================================
129129
;; Predicate Specifications
@@ -146,10 +146,11 @@
146146
(str "predicate must start with an operator: "
147147
":< :> :<= :>= := :!= :between :in :not-in "
148148
":like :ilike :is-null :is-not-null :or :and :not")}
149-
#(let [op (first %)]
150-
(or (contains? pred-op-set op)
149+
#(let [op (first %)
150+
kw (if (symbol? op) (keyword (name op)) op)]
151+
(or (contains? pred-op-set kw)
151152
;; Also allow expression predicates: [:< [:* :a :b] 100]
152-
(contains? expr-op-set op)))]])
153+
(contains? expr-op-set kw)))]])
153154

154155
;; =============================================================================
155156
;; Query Types

0 commit comments

Comments
 (0)