diff --git a/CHANGELOG.md b/CHANGELOG.md index 71cf762..b0d982d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Only accretive/fixative changes will be made from now on. * 1.3.next in progress * Fix [#222](https://github.com/seancorfield/next-jdbc/issues/222) by correcting implementation of `.cons` on a row. + * Address [#221](https://github.com/seancorfield/next-jdbc/issues/221) by supporting `:column-fn` a top-level option in `plan`-related functions to transform keys used in reducing function contexts. Also corrects handling of column names in schema `nav`igation (which previously only supported `:table-fn` and incorrectly applied it to columns as well). * Address [#218](https://github.com/seancorfield/next-jdbc/issues/218) by moving `:extend-via-metadata true` after the protocols' docstrings. * Document `:useBulkCopyForBatchInsert` for Microsoft SQL Server via PR [#216](https://github.com/seancorfield/next-jdbc/issues/216) -- [danskarda](https://github.com/danskarda). * Address [#215](https://github.com/seancorfield/next-jdbc/issues/215) by dropping official support for JDK 8 and updating various JDBC drivers in the testing matrix. diff --git a/doc/all-the-options.md b/doc/all-the-options.md index f73b0ef..8eef0dc 100644 --- a/doc/all-the-options.md +++ b/doc/all-the-options.md @@ -39,8 +39,8 @@ If you need additional options set on a connection, you can either use Java inte Except for `query` (which is simply an alias for `execute!`), all the "friendly" SQL functions accept the following options (in addition to all the options that `plan`, `execute!`, and `execute-one!` can accept): -* `:table-fn` -- the quoting function to be used on the string that identifies the table name, if provided, -* `:column-fn` -- the quoting function to be used on any string that identifies a column name, if provided. +* `:table-fn` -- the quoting function to be used on the string that identifies the table name, if provided; this also applies to assumed table names when `nav`igating schemas, +* `:column-fn` -- the quoting function to be used on any string that identifies a column name, if provided; this also applies to the reducing function context over `plan` and to assumed foreign key column names when `nav`igating schemas. They also support a `:suffix` argument which can be used to specify a SQL string that should be appended to the generated SQL string before executing it, e.g., `:suffix "FOR UPDATE"`. diff --git a/doc/getting-started.md b/doc/getting-started.md index 55978cf..1f99797 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -191,6 +191,8 @@ user=> (reduce The call to `jdbc/plan` returns an `IReduceInit` object but does not actually run the SQL. Only when the returned object is reduced is the connection obtained from the data source, the SQL executed, and the computation performed. The connection is closed automatically when the reduction is complete. The `row` in the reduction is an abstraction over the underlying (mutable) `ResultSet` object -- it is not a Clojure data structure. Because of that, you can simply access the columns via their SQL labels as shown -- you do not need to use the column-qualified name, and you do not need to worry about the database returning uppercase column names (SQL labels are not case sensitive). +> Note: if you want a column name transformation to be applied here, specify `:column-fn` as an option to the `plan` call. + Here's the same computation rewritten using `transduce`: ```clojure diff --git a/src/next/jdbc/result_set.clj b/src/next/jdbc/result_set.clj index 65e9fdd..36bab87 100644 --- a/src/next/jdbc/result_set.clj +++ b/src/next/jdbc/result_set.clj @@ -485,7 +485,8 @@ realize the full row explicitly before performing other (metadata-preserving) operations on it." [^ResultSet rs opts] - (let [builder (delay ((get opts :builder-fn as-maps) rs opts))] + (let [builder (delay ((get opts :builder-fn as-maps) rs opts)) + name-fn (get opts :column-fn name)] (reify MapifiedResultSet @@ -511,15 +512,15 @@ clojure.lang.Associative (containsKey [this k] (try - (.getObject rs (name k)) + (.getObject rs (name-fn k)) true (catch SQLException _ false))) (entryAt [this k] (try (clojure.lang.MapEntry. k (read-column-by-label - (.getObject rs (name k)) - (name k))) + (.getObject rs (name-fn k)) + (name-fn k))) (catch SQLException _))) clojure.lang.Counted @@ -542,14 +543,14 @@ (if (number? k) (let [^Integer i (inc k)] (read-column-by-index (.getObject rs i) (:rsmeta @builder) i)) - (read-column-by-label (.getObject rs (name k)) (name k))) + (read-column-by-label (.getObject rs (name-fn k)) (name-fn k))) (catch SQLException _))) (valAt [this k not-found] (try (if (number? k) (let [^Integer i (inc k)] (read-column-by-index (.getObject rs i) (:rsmeta @builder) i)) - (read-column-by-label (.getObject rs (name k)) (name k))) + (read-column-by-label (.getObject rs (name-fn k)) (name-fn k))) (catch SQLException _ not-found))) @@ -1082,8 +1083,8 @@ cardinality is `:one`. Rows are looked up using `-execute-all` or `-execute-one`, and the `:table-fn` - option, if provided, is applied to both the assumed table name and the - assumed foreign key column name." + option, if provided, is applied to the assumed table name and `:column-fn` if + provided to the assumed foreign key column name." [connectable opts] (fn [row] (vary-meta @@ -1095,15 +1096,16 @@ (expand-schema k (or (get-in opts [:schema k]) (default-schema k)))] (if (and fk connectable) - (let [entity-fn (:table-fn opts identity) + (let [table-fn (:table-fn opts identity) + column-fn (:column-fn opts identity) exec-fn! (if (= :many cardinality) p/-execute-all p/-execute-one)] (exec-fn! connectable [(str "SELECT * FROM " - (entity-fn (name table)) + (table-fn (name table)) " WHERE " - (entity-fn (name fk)) + (column-fn (name fk)) " = ?") v] opts)) @@ -1128,8 +1130,8 @@ cardinality is `:one`. Rows are looked up using `-execute-all` or `-execute-one`, and the `:table-fn` - option, if provided, is applied to both the assumed table name and the - assumed foreign key column name." + option, if provided, is applied to the assumed table name and `:column-fn` if + provided to the assumed foreign key column name." [connectable opts] (fn [_ k v] (try @@ -1137,15 +1139,16 @@ (expand-schema k (or (get-in opts [:schema k]) (default-schema k)))] (if (and fk connectable) - (let [entity-fn (:table-fn opts identity) + (let [table-fn (:table-fn opts identity) + column-fn (:column-fn opts identity) exec-fn! (if (= :many cardinality) p/-execute-all p/-execute-one)] (exec-fn! connectable [(str "SELECT * FROM " - (entity-fn (name table)) + (table-fn (name table)) " WHERE " - (entity-fn (name fk)) + (column-fn (name fk)) " = ?") v] opts))