Merge pull request #237 from camsaul/fix-turkish

Fix query generation when user.language is Turkish
This commit is contained in:
Sean Corfield 2019-02-08 21:03:10 -08:00 committed by GitHub
commit 83c307e03a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 3 deletions

View file

@ -71,6 +71,17 @@
(defn- undasherize [s]
(string/replace s "-" "_"))
;; String.toUpperCase() or `string/upper-case` for that matter converts the string to uppercase for the DEFAULT
;; LOCALE. Normally this does what you'd expect but things like `inner join` get converted to `İNNER JOIN` (dot over
;; the I) when user locale is Turkish. This predictably has bad consequences for people who like their SQL queries to
;; work. The fix here is to use String.toUpperCase(Locale/US) instead which always converts things the way we'd expect.
;;
;; Use this function instead of `string/upper-case` as it will always use Locale/US.
(def ^:private ^{:arglists '([s])} upper-case
;; TODO - not sure if there's a JavaScript equivalent here we should be using as well
#?(:clj (fn [s] (.. s toString (toUpperCase (java.util.Locale/US))))
:cljs string/upper-case))
(defn quote-identifier [x & {:keys [style split] :or {split true}}]
(let [name-transform-fn (cond
*name-transform-fn* *name-transform-fn*
@ -453,7 +464,7 @@
(->> args
(remove nil?)
(map format-predicate*)
(string/join (str " " (string/upper-case op-name) " "))
(string/join (str " " (upper-case op-name) " "))
(paren-wrap))
"exists"
@ -494,7 +505,7 @@
(defmethod format-clause :select [[_ fields] sql-map]
(str "SELECT "
(when (:modifiers sql-map)
(str (space-join (map (comp string/upper-case name)
(str (space-join (map (comp upper-case name)
(:modifiers sql-map)))
" "))
(comma-join (map to-sql fields))))
@ -507,7 +518,7 @@
(defn format-join [type table pred]
(str (when type
(str (string/upper-case (name type)) " "))
(str (upper-case (name type)) " "))
"JOIN " (to-sql table)
(when pred
(if (= :using (first pred))

View file

@ -2,6 +2,7 @@
(:refer-clojure :exclude [format])
(:require [#?@(:clj [clojure.test :refer]
:cljs [cljs.test :refer-macros]) [deftest testing is are]]
honeysql.core
[honeysql.types :as sql]
[honeysql.format :refer
[*allow-dashed-names?* quote-identifier format-clause format
@ -228,3 +229,21 @@
(format {:select [(honeysql.core/inline "foo")
(honeysql.core/inline :bar)
(honeysql.core/inline nil)]}))))
;; Make sure if Locale is Turkish we're not generating queries like İNNER JOIN (dot over the I) because
;; `string/upper-case` is converting things to upper-case using the default Locale. Generated query should be the same
;; regardless of system Locale. See #236
#?(:clj
(deftest statements-generated-correctly-with-turkish-locale
(let [format-with-locale (fn [^String language-tag]
(let [original-locale (java.util.Locale/getDefault)]
(try
(java.util.Locale/setDefault (java.util.Locale/forLanguageTag language-tag))
(format {:select [:t2.name]
:from [[:table1 :t1]]
:join [[:table2 :t2] [:= :t1.fk :t2.id]]
:where [:= :t1.id 1]})
(finally
(java.util.Locale/setDefault original-locale)))))]
(is (= (format-with-locale "en")
(format-with-locale "tr"))))))