Fixes #164 by making CSK dependency direct

This commit is contained in:
Sean Corfield 2021-05-02 19:46:56 -07:00
parent ca5d67f701
commit 800baf3085
7 changed files with 34 additions and 47 deletions

View file

@ -3,6 +3,7 @@
Only accretive/fixative changes will be made from now on. Only accretive/fixative changes will be made from now on.
* 1.1.next in progress * 1.1.next in progress
* Address #164 by making `clj-commons/camel-snake-kebab` an unconditional dependency. _[Being a conditional dependency that could be brought in at runtime caused problems with GraalVM-based native compilation as well as with multi-project monorepos]_
* Add **Tips & Tricks** section about working with PostgreSQL "interval" types (via PR #163 from @snorremd). * Add **Tips & Tricks** section about working with PostgreSQL "interval" types (via PR #163 from @snorremd).
* Address #162 by adding GraalVM to the test matrix (thank you @DeLaGuardo). * Address #162 by adding GraalVM to the test matrix (thank you @DeLaGuardo).
* Update several dependency versions. * Update several dependency versions.

View file

@ -1,6 +1,8 @@
{:paths ["src"] {:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.10.3"} :deps {org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/java.data {:mvn/version "1.0.86"}} org.clojure/java.data {:mvn/version "1.0.86"}
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}}
:aliases :aliases
{:test {:extra-paths ["test"] {:test {:extra-paths ["test"]
:extra-deps {org.clojure/test.check {:mvn/version "1.1.0"} :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}
@ -32,9 +34,7 @@
org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.14.1"} org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-jcl {:mvn/version "2.14.1"} org.apache.logging.log4j/log4j-jcl {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-jul {:mvn/version "2.14.1"} org.apache.logging.log4j/log4j-jul {:mvn/version "2.14.1"}
org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.14.1"} org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.14.1"}}
;; test auto-added snake/kebab builders and options
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}}
:jvm-opts ["-Dlog4j2.configurationFile=log4j2-info.properties"]} :jvm-opts ["-Dlog4j2.configurationFile=log4j2-info.properties"]}
:runner :runner
{:extra-deps {com.cognitect/test-runner {:extra-deps {com.cognitect/test-runner

View file

@ -196,7 +196,7 @@ These quoting functions can be provided to any of the friendly SQL functions abo
(sql/insert! ds :my-table {:some "data"} {:table-fn snake-case}) (sql/insert! ds :my-table {:some "data"} {:table-fn snake-case})
``` ```
If you have [camel-snake-kebab](https://clj-commons.org/camel-snake-kebab/) on your classpath, `next.jdbc` will contain `snake-kebab-opts` and `unqualified-snake-kebab-opts` which are hash maps containing `:column-fn` and `:table-fn` that use the `->snake_case` function from that library which performs a more sophisticated transformation. `next.jdbc` provides `snake-kebab-opts` and `unqualified-snake-kebab-opts` which are hash maps containing `:column-fn` and `:table-fn` that use the `->snake_case` function from the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/) which performs a more sophisticated transformation.
> Note: The entity naming function is passed a string, the result of calling `name` on the keyword passed in. Also note that the default quoting functions do not handle schema-qualified names, such as `dbo.table_name` -- `sql-server` would produce `[dbo.table_name]` from that. Use the `schema` function to wrap the quoting function if you need that behavior, e.g,. `{:table-fn (schema sql-server)}` which would produce `[dbo].[table_name]`. > Note: The entity naming function is passed a string, the result of calling `name` on the keyword passed in. Also note that the default quoting functions do not handle schema-qualified names, such as `dbo.table_name` -- `sql-server` would produce `[dbo.table_name]` from that. Use the `schema` function to wrap the quoting function if you need that behavior, e.g,. `{:table-fn (schema sql-server)}` which would produce `[dbo].[table_name]`.

View file

@ -150,12 +150,10 @@ user=>
> Note: See the `next.jdbc/with-option` examples in the [**Datasources, Connections & Transactions**](#datasources-connections--transactions) below for some caveats around using this function. > Note: See the `next.jdbc/with-option` examples in the [**Datasources, Connections & Transactions**](#datasources-connections--transactions) below for some caveats around using this function.
If you have [camel-snake-kebab](https://clj-commons.org/camel-snake-kebab/) on your classpath, two pre-built option hash maps are available in `next.jdbc`: In addition, two pre-built option hash maps are available in `next.jdbc`, that leverage the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/):
* `snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with qualified `:kebab-case` names from SQL entities that use `snake_case`, * `snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with qualified `:kebab-case` names from SQL entities that use `snake_case`,
* `unqualified-snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with _unqualified_ `:kebab-case` names from SQL entities that use `snake_case`. * `unqualified-snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with _unqualified_ `:kebab-case` names from SQL entities that use `snake_case`.
In addition, `next.jdbc.result-set` will have `as-kebab-maps` and `as-unqualified-kebab-maps` defined.
> Note: Using `camel-snake-kebab` might also be helpful if your database has `camelCase` table and column names, although you'll have to provide `:column-fn` and `:table-fn` yourself as `->camelCase` from that library. Either way, consider relying on the _default_ result set builder first and avoid converting column and table names (see [Advantages of 'snake case': portability and ubiquity](https://vvvvalvalval.github.io/posts/clojure-key-namespacing-convention-considered-harmful.html#advantages_of_'snake_case':_portability_and_ubiquity) for an interesting discussion on kebab-case vs snake_case -- I do not agree with all of the author's points in that article, particularly his position against qualified keywords, but his argument for retaining snake_case around system boundaries is compelling). > Note: Using `camel-snake-kebab` might also be helpful if your database has `camelCase` table and column names, although you'll have to provide `:column-fn` and `:table-fn` yourself as `->camelCase` from that library. Either way, consider relying on the _default_ result set builder first and avoid converting column and table names (see [Advantages of 'snake case': portability and ubiquity](https://vvvvalvalval.github.io/posts/clojure-key-namespacing-convention-considered-harmful.html#advantages_of_'snake_case':_portability_and_ubiquity) for an interesting discussion on kebab-case vs snake_case -- I do not agree with all of the author's points in that article, particularly his position against qualified keywords, but his argument for retaining snake_case around system boundaries is compelling).

View file

@ -34,7 +34,7 @@ An example builder that converts `snake_case` database table/column names to `ke
(result-set/as-modified-maps rs (assoc opts :qualifier-fn kebab :label-fn kebab)))) (result-set/as-modified-maps rs (assoc opts :qualifier-fn kebab :label-fn kebab))))
``` ```
If you have [camel-snake-kebab](https://clj-commons.org/camel-snake-kebab/) on your classpath, two additional builders will be available: `as-kebab-maps` and `as-unqualified-kebab-maps` which use the `->kebab-case` function from that library with `as-modified-maps` and `as-unqualified-modified-maps` respectively. However, a version of `as-kebab-maps` is built-in, as is `as-unqualified-kebab-maps`, which both use the `->kebab-case` function from the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/) with `as-modified-maps` and `as-unqualified-modified-maps` respectively.
And finally there are two styles of adapters for the existing builders that let you override the default way that columns are read from result sets. And finally there are two styles of adapters for the existing builders that let you override the default way that columns are read from result sets.
The first style takes a `column-reader` function, which is called with the `ResultSet`, the `ResultSetMetaData`, and the column index, and is expected to read the raw column value from the result set and return it. The result is then passed through `read-column-by-index` (from `ReadableColumn`, which may be implemented directly via protocol extension or via metadata on the result of the `column-reader` function): The first style takes a `column-reader` function, which is called with the `ResultSet`, the `ResultSetMetaData`, and the column index, and is expected to read the raw column value from the result set and return it. The result is then passed through `read-column-by-index` (from `ReadableColumn`, which may be implemented directly via protocol extension or via metadata on the result of the `column-reader` function):

View file

@ -61,7 +61,8 @@
In addition, wherever a `PreparedStatement` is created, you may specify: In addition, wherever a `PreparedStatement` is created, you may specify:
* `:return-keys` -- either `true` or a vector of key names to return." * `:return-keys` -- either `true` or a vector of key names to return."
(:require [next.jdbc.connection] (:require [camel-snake-kebab.core :refer [->kebab-case ->snake_case]]
[next.jdbc.connection]
[next.jdbc.default-options :as opts] [next.jdbc.default-options :as opts]
[next.jdbc.prepare :as prepare] [next.jdbc.prepare :as prepare]
[next.jdbc.protocols :as p] [next.jdbc.protocols :as p]
@ -367,25 +368,18 @@
[connectable opts] [connectable opts]
(opts/->DefaultOptions connectable opts)) (opts/->DefaultOptions connectable opts))
(defmacro ^:private def-snake-kebab []
(try
(require 'camel-snake-kebab.core)
`(let [kebab-case# (requiring-resolve 'camel-snake-kebab.core/->kebab-case)
snake-case# (requiring-resolve 'camel-snake-kebab.core/->snake_case)]
(def snake-kebab-opts (def snake-kebab-opts
"A hash map of options that will convert Clojure identifiers to "A hash map of options that will convert Clojure identifiers to
snake_case SQL entities (`:table-fn`, `:column-fn`), and will convert snake_case SQL entities (`:table-fn`, `:column-fn`), and will convert
SQL entities to qualified kebab-case Clojure identifiers (`:builder-fn`)." SQL entities to qualified kebab-case Clojure identifiers (`:builder-fn`)."
{:column-fn snake-case# :table-fn snake-case# {:column-fn ->snake_case :table-fn ->snake_case
:label-fn kebab-case# :qualifier-fn kebab-case# :label-fn ->kebab-case :qualifier-fn ->kebab-case
:builder-fn (resolve 'next.jdbc.result-set/as-kebab-maps)}) :builder-fn rs/as-kebab-maps})
(def unqualified-snake-kebab-opts (def unqualified-snake-kebab-opts
"A hash map of options that will convert Clojure identifiers to "A hash map of options that will convert Clojure identifiers to
snake_case SQL entities (`:table-fn`, `:column-fn`), and will convert snake_case SQL entities (`:table-fn`, `:column-fn`), and will convert
SQL entities to unqualified kebab-case Clojure identifiers (`:builder-fn`)." SQL entities to unqualified kebab-case Clojure identifiers (`:builder-fn`)."
{:column-fn snake-case# :table-fn snake-case# {:column-fn ->snake_case :table-fn ->snake_case
:label-fn kebab-case# :qualifier-fn kebab-case# :label-fn ->kebab-case :qualifier-fn ->kebab-case
:builder-fn (resolve 'next.jdbc.result-set/as-unqualified-kebab-maps)})) :builder-fn rs/as-unqualified-kebab-maps})
(catch Throwable _)))
(def-snake-kebab)

View file

@ -17,7 +17,8 @@
See also https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time See also https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time
for implementations of `ReadableColumn` that provide automatic for implementations of `ReadableColumn` that provide automatic
conversion of some SQL data types to Java Time objects." conversion of some SQL data types to Java Time objects."
(:require [clojure.core.protocols :as core-p] (:require [camel-snake-kebab.core :refer [->kebab-case]]
[clojure.core.protocols :as core-p]
[clojure.core.reducers :as r] [clojure.core.reducers :as r]
[clojure.datafy :as d] [clojure.datafy :as d]
[next.jdbc.prepare :as prepare] [next.jdbc.prepare :as prepare]
@ -256,26 +257,19 @@
[rs opts] [rs opts]
(as-unqualified-modified-maps rs (assoc opts :label-fn lower-case))) (as-unqualified-modified-maps rs (assoc opts :label-fn lower-case)))
(defmacro ^:private def-snake-kebab [] (defn as-kebab-maps
(try "Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`
(let [kebab-case (requiring-resolve 'camel-snake-kebab.core/->kebab-case)]
`(do
(defn ~'as-kebab-maps
{:doc "Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`
that produces bare vectors of hash map rows, with kebab-case keys." that produces bare vectors of hash map rows, with kebab-case keys."
:arglists '([~'rs ~'opts])} [rs opts]
[rs# opts#] (as-modified-maps rs (assoc opts
(as-modified-maps rs# (assoc opts# :qualifier-fn ->kebab-case
:qualifier-fn ~kebab-case :label-fn ->kebab-case)))
:label-fn ~kebab-case)))
(defn ~'as-unqualified-kebab-maps (defn as-unqualified-kebab-maps
{:doc "Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder` "Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`
that produces bare vectors of hash map rows, with simple, kebab-case keys." that produces bare vectors of hash map rows, with simple, kebab-case keys."
:arglists '([~'rs ~'opts])} [rs opts]
[rs# opts#] (as-unqualified-modified-maps rs (assoc opts :label-fn ->kebab-case)))
(as-unqualified-modified-maps rs# (assoc opts# :label-fn ~kebab-case)))))
(catch Throwable _)))
(def-snake-kebab)
(defn as-maps-adapter (defn as-maps-adapter
"Given a map builder function (e.g., `as-lower-maps`) and a column reading "Given a map builder function (e.g., `as-lower-maps`) and a column reading