From ea0bfbabc1e779378bb08d4b46601e086ff978c9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 2 Feb 2021 14:50:12 -0800 Subject: [PATCH] Outline of docs for clauses, operators, and special syntax --- doc/clause-reference.md | 38 +++++++++++++++++++++++++ doc/cljdoc.edn | 14 ++++++---- doc/extending-honeysql.md | 26 +++++++++++++++++- doc/operator-reference.md | 58 +++++++++++++++++++++++++++++++++++++++ doc/special-syntax.md | 19 +++++++++++++ src/honey/sql.cljc | 5 +++- 6 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 doc/clause-reference.md create mode 100644 doc/operator-reference.md create mode 100644 doc/special-syntax.md diff --git a/doc/clause-reference.md b/doc/clause-reference.md new file mode 100644 index 0000000..c09efc7 --- /dev/null +++ b/doc/clause-reference.md @@ -0,0 +1,38 @@ +# SQL Clauses Supported + +This section lists all the SQL clauses that HoneySQL +supports out of the box, in the order that they are +processed for formatting. + +Clauses can be specified as keywords or symbols. Use +`-` in the clause name where the formatted SQL would have +a space (e.g., `:left-join` is formatted as `LEFT JOIN`). + +Except as noted, these clauses apply to all the SQL +dialects that HoneySQL supports. + +## nest +## with, with-recursive +## intersect, union, union-all, except, except-all +## select, select-distinct +## insert-into +## update +## delete, delete-from +## truncate +## columns +## set (ANSI) +## from +## using +## join, left-join, right-join, inner-join, outer-join, full-join +## cross-join +## set (MySQL) +## where +## group-by +## having +## order-by +## limit, offset (MySQL) +## for +## lock (MySQL) +## values +## on-conflict, on-constraint, do-nothing, do-update-set +## returning \ No newline at end of file diff --git a/doc/cljdoc.edn b/doc/cljdoc.edn index 9691209..0326f74 100644 --- a/doc/cljdoc.edn +++ b/doc/cljdoc.edn @@ -1,5 +1,9 @@ -{:cljdoc.doc/tree [["Readme" {:file "README.md"}] - ["Changes" {:file "CHANGELOG.md"}] - ["Getting Started" {:file "doc/getting-started.md"} - ["Extending HoneySQL" {:file "doc/extending-honeysql.md"}]] - ["Differences from 1.x" {:file "doc/difference-from-1-x.md"}]]} +{:cljdoc.doc/tree + [["Readme" {:file "README.md"}] + ["Changes" {:file "CHANGELOG.md"}] + ["Getting Started" {:file "doc/getting-started.md"} + ["SQL Clause Reference" {:file "doc/clause-reference.md"}] + ["SQL Operator Reference" {:file "doc/operator-reference.md"}] + ["SQL 'Special Syntax'" {:file "doc/special-syntax.md"}] + ["Extending HoneySQL" {:file "doc/extending-honeysql.md"}]] + ["Differences from 1.x" {:file "doc/difference-from-1-x.md"}]]} diff --git a/doc/extending-honeysql.md b/doc/extending-honeysql.md index 6732325..3894636 100644 --- a/doc/extending-honeysql.md +++ b/doc/extending-honeysql.md @@ -16,6 +16,30 @@ Built in functions (special syntax) include: `:array`, `:case`, ## Registering a New Clause Formatter +`honey.sql/register-clause!` accepts a keyword (or a symbol) +that should be treated as a new clause in a SQL statement, +a "formatter", and a keyword (or a symbol) that identifies +an existing clause that this new one should be ordered before. + +The formatter can either be a function +of two arguments or a previously registered clause (so +that you can easily reuse formatters). + +The formatter function will be called with: +* The function name (always as a keyword), +* The sequence of arguments provided. + +The third argument to `register-clause!` allows you to +insert your new clause formatter so that clauses are +formatted in the correct order for your SQL dialect. +For example, `:select` comes before `:from` which comes +before `:where`. This is the most implementation-specific +part of extending HoneySQL because you'll need to look at +the (private) Var `default-clause-order` in `honey.sql` +for guidance. _[I plan to add a section in the documentation +somewhere that lists built-in clauses in order which this +can link to...]_ + ## Registering a New Operator `honey.sql/register-op!` accepts a keyword (or a symbol) that @@ -58,7 +82,7 @@ and a "formatter". The formatter can either be a function of two arguments or a previously registered "function" (so that you can easily reuse formatters). -The formatter will be called with: +The formatter function will be called with: * The function name (always as a keyword), * The sequence of arguments provided. diff --git a/doc/operator-reference.md b/doc/operator-reference.md new file mode 100644 index 0000000..36e4a58 --- /dev/null +++ b/doc/operator-reference.md @@ -0,0 +1,58 @@ +# SQL Operators Supported + +This section lists the operators that HoneySQL supports +out of the box. There is no operator precedence assumed +because SQL expressions are represented in prefix form, +just like Clojure expressions. + +Operators can be specified as keywords or symbols. Use +`-` in the operator where the formatted SQL would have +a space (e.g., `:not-like` is formatted as `NOT LIKE`). + +## and, or + +Boolean operators. May take any number of expressions +as arguments. `nil` expressions are ignored which can +make it easier to programmatically build conditional +expressions (since an expression that should be omitted +can simply evaluate to `nil` instead). + +```clojure +{... + :where [:and [:= :type "match"] + (when need-status [:in :status [1 5]])] + ...} +;; if need-status is truthy: +;;=> ["...WHERE (type = ?) AND (status IN (?, ?))..." "match" 1 5] +;; or, if need-status is falsey: +;;=> ["...WHERE (type = ?)..." "match"] +{... + :where [:or [:= :id 42] [:= :type "match"]] + ...} +;;=> ["...WHERE (id = ?) OR (type = ?)..." 42 "match"] +``` + +## = <> < > <= >= + +Binary comparison operators. These expect exactly +two arguments. + +The following aliases are also supported: +* `is` -- an alias for `=` +* `is-not`, `not=`, `!=` -- aliases for `<>` + +## mod, xor, + - * / % | & ^ + +Mathematical and bitwise operators. `+` and `*` are +variadic; the rest are strictly binary operators. + +## like, not like, ilike, not ilike, regexp + +Pattern matching binary operators. `regex` is accepted +as an alias for `regexp`. + +`similar-to` and `not-similar-to` are also supported. + +## || + +Variadic string concatenation operator. diff --git a/doc/special-syntax.md b/doc/special-syntax.md new file mode 100644 index 0000000..b52600a --- /dev/null +++ b/doc/special-syntax.md @@ -0,0 +1,19 @@ +# SQL Special Syntax + +This section lists the function-like expressions that +HoneySQL supports out of the box which are formatted +as special syntactic forms. + +## array +## between +## case +## cast +## composite +## default +## inline +## interval +## lift +## nest +## not +## param +## raw diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index 05c0997..ac322e3 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -810,7 +810,8 @@ only clause so far where that would matter is `:set` which differs in MySQL." [clause formatter before] - (let [clause (sym->kw clause)] + (let [clause (sym->kw clause) + before (sym->kw before)] (assert (keyword? clause)) (let [k (sym->kw formatter) f (if (keyword? k) @@ -891,6 +892,8 @@ :pretty true})) ;; while working on the docs (require '[honey.sql :as sql]) + (sql/format {:where [:and [:= :id 42] [:= :type "match"]]}) + (sql/format {:where [:and [:= :type "match"] (when false [:in :status [1 5]])]}) (sql/format {:select [:*] :from [:table] :where [:= :id 1]}) (sql/format {:select [:t/id [:name :item]], :from [[:table :t]], :where [:= :id 1]}) (sql/format '{select [t/id [name item]], from [[table t]], where [= id 1]})