diff --git a/deps.edn b/deps.edn index 0e0513fd..0476a81a 100644 --- a/deps.edn +++ b/deps.edn @@ -5,7 +5,9 @@ metosin/muuntaja {:mvn/version "0.6.8"} net.cgrand/macrovich {:mvn/version "0.2.1"} net.cgrand/xforms {:mvn/version "0.19.2"} - io.github.OpenGen/GenSQL.inference {:git/sha "689fe740dead93f3ba349a88efa52f2544aa138b"} + io.github.OpenGen/GenSQL.inference + {:git/url "https://github.com/LeifAndersen/GenSQL.inference" + :sha "9decae2d54c8ff37920a2515a9a964398662cdfc"} org.babashka/sci {:mvn/version "0.3.32"} org.clojure/clojure {:mvn/version "1.11.1"} com.google.javascript/closure-compiler-unshaded {:mvn/version "v20230802"} diff --git a/resources/gensql/query/base.bnf b/resources/gensql/query/base.bnf index aac1a3a2..719045e8 100644 --- a/resources/gensql/query/base.bnf +++ b/resources/gensql/query/base.bnf @@ -100,7 +100,8 @@ order-by-clause ::= #'(?i)ORDER' ws #'(?i)BY' ws identifier (ws (asc | desc))? asc ::= #'(?i)ASC' desc ::= #'(?i)DESC' -limit-clause ::= #'(?i)LIMIT' ws int +limit-clause ::= #'(?i)LIMIT' ws int (ws offset-clause)? +offset-clause ::= #'(?i)OFFSET' ws int (* aggregation *) @@ -125,7 +126,8 @@ scalar-expr ::= scalar-expr-0 ::= scalar-expr-4 | expr-binop ::= scalar-expr-5 | expr-addition | expr-subtraction ::= scalar-expr-6 | expr-multiplication | expr-division - ::= scalar-expr-7 | expr-function-call + ::= scalar-expr-7 | expr-exponentiation + ::= scalar-expr-8 | expr-function-call expr-disjunction ::= scalar-expr-0 ws #'(?i)OR' ws scalar-expr-1 expr-conjunction ::= scalar-expr-1 ws #'(?i)AND' ws scalar-expr-2 @@ -140,9 +142,15 @@ expr-subtraction ::= scalar-expr-4 ws? '-' ws? scalar-expr-5 expr-multiplication ::= scalar-expr-5 ws? '*' ws? scalar-expr-6 expr-division ::= scalar-expr-5 ws? '/' ws? scalar-expr-6 +expr-exponentiation ::= scalar-expr-6 ws? '^' ws? scalar-expr-7 + (* currently only log - will likely add more later *) - ::= expr-function-call-log + ::= expr-function-call-log | expr-function-call-sqrt | expr-function-call-sin | expr-function-call-cos | expr-function-call-tan expr-function-call-log ::= 'log(' ws? scalar-expr-6 ws? ')' +expr-function-call-sqrt ::= 'sqrt(' ws? scalar-expr-6 ws? ')' +expr-function-call-sin ::= 'sin(' ws? scalar-expr-6 ws? ')' +expr-function-call-cos ::= 'cos(' ws? scalar-expr-6 ws? ')' +expr-function-call-tan ::= 'tan(' ws? scalar-expr-6 ws? ')' scalar-expr-group ::= '(' ws? scalar-expr ws? ')' diff --git a/resources/gensql/query/permissive.bnf b/resources/gensql/query/permissive.bnf index e0b074fa..f4cc3774 100644 --- a/resources/gensql/query/permissive.bnf +++ b/resources/gensql/query/permissive.bnf @@ -1,5 +1,5 @@ ::= scalar-expr-1 | expr-disjunction | probability-expr | mutual-info-expr - ::= scalar-expr-group | identifier | value + ::= scalar-expr-group | identifier | value (* model-expr *) diff --git a/resources/gensql/query/strict.bnf b/resources/gensql/query/strict.bnf index 4673f718..bd3c0105 100644 --- a/resources/gensql/query/strict.bnf +++ b/resources/gensql/query/strict.bnf @@ -1,4 +1,4 @@ - ::= scalar-expr-group + ::= scalar-expr-group | identifier | value | probability-expr diff --git a/src/gensql/query/db.cljc b/src/gensql/query/db.cljc index 2acc92ad..846a2b56 100644 --- a/src/gensql/query/db.cljc +++ b/src/gensql/query/db.cljc @@ -10,10 +10,21 @@ (defn read-string [s] - (let [sppl-readers {'gensql.gpm.spe/SPE (dynaload/dynaload 'gensql.gpm.sppl/read-string) + (let [object-reader {'object (fn [[class-name _ string-repr]] + (case class-name + java.time.LocalDate + (java.time.LocalDate/parse string-repr), + java.time.LocalDateTime + (java.time.LocalDateTime/parse string-repr), + string-repr))} + sppl-readers {'gensql.gpm.spe/SPE (dynaload/dynaload 'gensql.gpm.sppl/read-string) 'inferenceql.gpm.spe/SPE (dynaload/dynaload 'gensql.gpm.sppl/read-string)} ; for backwards-compatibility - readers (merge gpm/readers sppl-readers)] - (edn/read-string {:readers readers} s))) + readers (merge object-reader gpm/readers sppl-readers)] + (edn/read-string {:readers readers + :default (fn [tag value] + (println "Found unknown tag:" tag "with value:" value) + {:tag tag :value value})} + s))) #?(:clj (defn slurp [x] diff --git a/src/gensql/query/plan.cljc b/src/gensql/query/plan.cljc index 68c31c0b..03b62545 100644 --- a/src/gensql/query/plan.cljc +++ b/src/gensql/query/plan.cljc @@ -92,9 +92,10 @@ ::variables variables}) (defn limit - [op limit] + [op limit offset] {::type :gensql.query.plan.type/limit ::limit limit + ::offset offset ::plan op}) (defn distinct @@ -191,13 +192,13 @@ elsewhere in the parse tree, as is the case with \"SELECT\" subclauses." ([node] (let [pln (with-meta (plan-impl node) - {::parser/node node})] + {::parser/node node})] (tap> #:plan{:node node :plan pln}) pln)) ([node op] (let [pln (if (some? node) (with-meta (plan-impl node op) - {::parser/node node}) + {::parser/node node}) op)] (tap> #:plan{:node node :plan pln :op op}) pln))) @@ -265,9 +266,9 @@ relation." [node] (tree/match [node] - [[:selection "(" child ")"]] (output-attr child) - [[:selection _ [:alias-clause _as id-node]]] (literal/read id-node) - [[:selection child]] (parser/unparse child))) + [[:selection "(" child ")"]] (output-attr child) + [[:selection _ [:alias-clause _as id-node]]] (literal/read id-node) + [[:selection child]] (parser/unparse child))) (defn ^:private selection-plan [node op] @@ -403,9 +404,17 @@ (rename (plan relation-expr) (literal/read identifier)))) (defmethod plan-impl :limit-clause + [node op] + (let [n (eval-literal-in node [:int]) + offset (if-let [offset-clause (tree/get-node node :offset-clause)] + (plan-impl offset-clause op) + 0)] + (limit op n offset))) + +(defmethod plan-impl :offset-clause [node op] (let [n (eval-literal-in node [:int])] - (limit op n))) + (or n 0))) (defmethod plan-impl :distinct-clause [_ op] @@ -557,9 +566,9 @@ (defmethod eval :gensql.query.plan.type/limit [plan env bindings] - (let [{::keys [limit plan]} plan + (let [{::keys [limit offset plan]} plan rel (eval plan env bindings)] - (relation/limit rel limit))) + (relation/limit rel limit offset))) (defmethod eval :gensql.query.plan.type/distinct [plan env bindings] diff --git a/src/gensql/query/relation.cljc b/src/gensql/query/relation.cljc index c141ce3c..35429468 100644 --- a/src/gensql/query/relation.cljc +++ b/src/gensql/query/relation.cljc @@ -80,8 +80,8 @@ (meta rel))) (defn limit - [rel n] - (with-meta (take n (tuples rel)) + [rel n offset] + (with-meta (take n (drop offset (tuples rel))) (meta rel))) (defn distinct diff --git a/src/gensql/query/scalar.cljc b/src/gensql/query/scalar.cljc index 8192fbb0..5454e5b2 100644 --- a/src/gensql/query/scalar.cljc +++ b/src/gensql/query/scalar.cljc @@ -60,8 +60,10 @@ [:expr-subtraction left _ right] `(~'- ~(plan left) ~(plan right)) [:expr-multiplication left _ right] `(~'* ~(plan left) ~(plan right)) [:expr-division left _ right] `(~'/ ~(plan left) ~(plan right)) + [:expr-exponentiation left _ right] `(~'pow ~(plan left) ~(plan right)) [:expr-function-call-log _log child _] `(~'log ~(plan child)) + [:expr-function-call-sqrt _sqrt child _] `(~'sqrt ~(plan child)) [:expr-binop left [:binop [:is _]] right] `(~'= ~(plan left) ~(plan right)) [:expr-binop left [:binop [:is-not & _]] right] `(~'not= ~(plan left) ~(plan right)) @@ -299,7 +301,9 @@ '- (nil-safe (auto-unbox -)) '* (nil-safe (auto-unbox *)) '/ (nil-safe (auto-unbox /)) - 'log (nil-safe (auto-unbox math/log))} + 'pow (nil-safe (auto-unbox math/pow)) + 'log (nil-safe (auto-unbox math/log)) + 'sqrt (nil-safe (auto-unbox math/sqrt))} 'gensql {'safe-get safe-get 'prob prob 'pdf pdf