Fixes #52 by using US-locale lower-case function
This commit is contained in:
parent
175904bcf6
commit
87e44ae6a6
4 changed files with 33 additions and 19 deletions
|
|
@ -6,7 +6,7 @@ Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
The following changes have been committed to the **master** branch since the 1.0.5 release:
|
The following changes have been committed to the **master** branch since the 1.0.5 release:
|
||||||
|
|
||||||
* None.
|
* Fix #52 by replacing `clojure.string/lower-case` with a US-locale function to avoid breakage in locales such as Turkish.
|
||||||
|
|
||||||
## Stable Builds
|
## Stable Builds
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ The default builder for rows and result sets creates qualified keywords that mat
|
||||||
|
|
||||||
The reason behind the default is to a) be a simple transform, b) produce qualified keys in keeping with Clojure's direction (with `clojure.spec` etc), and c) not mess with the data. `as-arrays` is (slightly) faster than `as-maps` since it produces less data (vectors of values instead of vectors of hash maps), but the `lower` options will be slightly slower since they include (conditional) logic to convert strings to lower-case. The `unqualified` options may be slightly faster than their qualified equivalents but make no attempt to keep column names unique if your SQL joins across multiple tables.
|
The reason behind the default is to a) be a simple transform, b) produce qualified keys in keeping with Clojure's direction (with `clojure.spec` etc), and c) not mess with the data. `as-arrays` is (slightly) faster than `as-maps` since it produces less data (vectors of values instead of vectors of hash maps), but the `lower` options will be slightly slower since they include (conditional) logic to convert strings to lower-case. The `unqualified` options may be slightly faster than their qualified equivalents but make no attempt to keep column names unique if your SQL joins across multiple tables.
|
||||||
|
|
||||||
In addition, the following generic builders can take `:label-fn` and `:qualifier-fn` options to control how the label and qualified are processed. The `lower` variants above are implemented in terms of these, passing `clojure.string/lower-case` for both of those options.
|
In addition, the following generic builders can take `:label-fn` and `:qualifier-fn` options to control how the label and qualified are processed. The `lower` variants above are implemented in terms of these, passing a `lower-case` function for both of those options.
|
||||||
|
|
||||||
* `as-modified-maps` -- table-qualified keywords,
|
* `as-modified-maps` -- table-qualified keywords,
|
||||||
* `as-unqualified-modified-maps` -- simple keywords,
|
* `as-unqualified-modified-maps` -- simple keywords,
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
(ns next.jdbc.optional
|
(ns next.jdbc.optional
|
||||||
"Builders that treat NULL SQL values as 'optional' and omit the
|
"Builders that treat NULL SQL values as 'optional' and omit the
|
||||||
corresponding keys from the Clojure hash maps for the rows."
|
corresponding keys from the Clojure hash maps for the rows."
|
||||||
(:require [clojure.string :as str]
|
(:require [next.jdbc.result-set :as rs])
|
||||||
[next.jdbc.result-set :as rs])
|
(:import (java.sql ResultSet)
|
||||||
(:import (java.sql ResultSet)))
|
(java.util Locale)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
|
@ -69,18 +69,25 @@
|
||||||
cols (rs/get-unqualified-modified-column-names rsmeta opts)]
|
cols (rs/get-unqualified-modified-column-names rsmeta opts)]
|
||||||
(->MapResultSetOptionalBuilder rs rsmeta cols)))
|
(->MapResultSetOptionalBuilder rs rsmeta cols)))
|
||||||
|
|
||||||
|
(defn- lower-case
|
||||||
|
"Converts a string to lower case in the US locale to avoid problems in
|
||||||
|
locales where the lower case version of a character is not a valid SQL
|
||||||
|
entity name (e.g., Turkish)."
|
||||||
|
[^String s]
|
||||||
|
(.toLowerCase s (Locale/US)))
|
||||||
|
|
||||||
(defn as-lower-maps
|
(defn as-lower-maps
|
||||||
"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 lower-case keys and nil
|
that produces bare vectors of hash map rows, with lower-case keys and nil
|
||||||
columns omitted."
|
columns omitted."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-modified-maps rs (assoc opts
|
(as-modified-maps rs (assoc opts
|
||||||
:qualifier-fn str/lower-case
|
:qualifier-fn lower-case
|
||||||
:label-fn str/lower-case)))
|
:label-fn lower-case)))
|
||||||
|
|
||||||
(defn as-unqualified-lower-maps
|
(defn as-unqualified-lower-maps
|
||||||
"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, lower-case keys
|
that produces bare vectors of hash map rows, with simple, lower-case keys
|
||||||
and nil columns omitted."
|
and nil columns omitted."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-unqualified-modified-maps rs (assoc opts :label-fn str/lower-case)))
|
(as-unqualified-modified-maps rs (assoc opts :label-fn lower-case)))
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
Also provides the default implemenations for `Executable` and
|
Also provides the default implemenations for `Executable` and
|
||||||
the default `datafy`/`nav` behavior for rows from a result set."
|
the default `datafy`/`nav` behavior for rows from a result set."
|
||||||
(:require [clojure.core.protocols :as core-p]
|
(:require [clojure.core.protocols :as core-p]
|
||||||
[clojure.string :as str]
|
|
||||||
[next.jdbc.prepare :as prepare]
|
[next.jdbc.prepare :as prepare]
|
||||||
[next.jdbc.protocols :as p])
|
[next.jdbc.protocols :as p])
|
||||||
(:import (java.sql PreparedStatement
|
(:import (java.sql PreparedStatement
|
||||||
ResultSet ResultSetMetaData
|
ResultSet ResultSetMetaData
|
||||||
SQLException)))
|
SQLException)
|
||||||
|
(java.util Locale)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
|
@ -60,19 +60,26 @@
|
||||||
(mapv (fn [^Integer i] (keyword ((:label-fn opts) (.getColumnLabel rsmeta i))))
|
(mapv (fn [^Integer i] (keyword ((:label-fn opts) (.getColumnLabel rsmeta i))))
|
||||||
(range 1 (inc (.getColumnCount rsmeta)))))
|
(range 1 (inc (.getColumnCount rsmeta)))))
|
||||||
|
|
||||||
|
(defn- lower-case
|
||||||
|
"Converts a string to lower case in the US locale to avoid problems in
|
||||||
|
locales where the lower case version of a character is not a valid SQL
|
||||||
|
entity name (e.g., Turkish)."
|
||||||
|
[^String s]
|
||||||
|
(.toLowerCase s (Locale/US)))
|
||||||
|
|
||||||
(defn get-lower-column-names
|
(defn get-lower-column-names
|
||||||
"Given `ResultSetMetaData`, return a vector of lower-case column names, each
|
"Given `ResultSetMetaData`, return a vector of lower-case column names, each
|
||||||
qualified by the table from which it came."
|
qualified by the table from which it came."
|
||||||
[rsmeta opts]
|
[rsmeta opts]
|
||||||
(get-modified-column-names rsmeta (assoc opts
|
(get-modified-column-names rsmeta (assoc opts
|
||||||
:qualifier-fn str/lower-case
|
:qualifier-fn lower-case
|
||||||
:label-fn str/lower-case)))
|
:label-fn lower-case)))
|
||||||
|
|
||||||
(defn get-unqualified-lower-column-names
|
(defn get-unqualified-lower-column-names
|
||||||
"Given `ResultSetMetaData`, return a vector of unqualified column names."
|
"Given `ResultSetMetaData`, return a vector of unqualified column names."
|
||||||
[rsmeta opts]
|
[rsmeta opts]
|
||||||
(get-unqualified-modified-column-names rsmeta
|
(get-unqualified-modified-column-names rsmeta
|
||||||
(assoc opts :label-fn str/lower-case)))
|
(assoc opts :label-fn lower-case)))
|
||||||
|
|
||||||
(defprotocol ReadableColumn
|
(defprotocol ReadableColumn
|
||||||
"Protocol for reading objects from the `java.sql.ResultSet`. Default
|
"Protocol for reading objects from the `java.sql.ResultSet`. Default
|
||||||
|
|
@ -184,14 +191,14 @@
|
||||||
that produces bare vectors of hash map rows, with lower-case keys."
|
that produces bare vectors of hash map rows, with lower-case keys."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-modified-maps rs (assoc opts
|
(as-modified-maps rs (assoc opts
|
||||||
:qualifier-fn str/lower-case
|
:qualifier-fn lower-case
|
||||||
:label-fn str/lower-case)))
|
:label-fn lower-case)))
|
||||||
|
|
||||||
(defn as-unqualified-lower-maps
|
(defn as-unqualified-lower-maps
|
||||||
"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, lower-case keys."
|
that produces bare vectors of hash map rows, with simple, lower-case keys."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-unqualified-modified-maps rs (assoc opts :label-fn str/lower-case)))
|
(as-unqualified-modified-maps rs (assoc opts :label-fn lower-case)))
|
||||||
|
|
||||||
(defrecord ArrayResultSetBuilder [^ResultSet rs rsmeta cols]
|
(defrecord ArrayResultSetBuilder [^ResultSet rs rsmeta cols]
|
||||||
RowBuilder
|
RowBuilder
|
||||||
|
|
@ -254,15 +261,15 @@
|
||||||
row values."
|
row values."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-modified-arrays rs (assoc opts
|
(as-modified-arrays rs (assoc opts
|
||||||
:qualifier-fn str/lower-case
|
:qualifier-fn lower-case
|
||||||
:label-fn str/lower-case)))
|
:label-fn lower-case)))
|
||||||
|
|
||||||
(defn as-unqualified-lower-arrays
|
(defn as-unqualified-lower-arrays
|
||||||
"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`
|
"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`
|
||||||
that produces a vector of simple, lower-case column names followed by
|
that produces a vector of simple, lower-case column names followed by
|
||||||
vectors of row values."
|
vectors of row values."
|
||||||
[rs opts]
|
[rs opts]
|
||||||
(as-unqualified-modified-arrays rs (assoc opts :label-fn str/lower-case)))
|
(as-unqualified-modified-arrays rs (assoc opts :label-fn lower-case)))
|
||||||
|
|
||||||
(declare navize-row)
|
(declare navize-row)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue