From c2c798770a8473d5f10b9dddeeafdff6be90f79a Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 21 Apr 2019 13:00:03 -0700 Subject: [PATCH] Alpha 4; fixes #11 by adding schema meta-quoting function --- doc/friendly_sql_fns.md | 6 ++++-- doc/getting_started.md | 6 +++--- pom.xml | 8 ++++---- src/next/jdbc/quoted.clj | 15 ++++++++++++++- test/next/jdbc/quoted_test.clj | 21 +++++++++++++++++++-- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/doc/friendly_sql_fns.md b/doc/friendly_sql_fns.md index dcb0c42..81877b9 100644 --- a/doc/friendly_sql_fns.md +++ b/doc/friendly_sql_fns.md @@ -121,7 +121,7 @@ Note that in order to override the default primary key column name (of `:id`), y By default, `next.jdbc.sql` constructs SQL strings with the entity names exactly matching the (unqualified) keywords provided. If you are trying to use a table name or column name that is a reserved name in SQL for your database, you will need to tell `next.jdbc.sql` to quote those names. -The namespace `next.jdbc.quoted` provides five functions that cover the most common types of entity quoting: +The namespace `next.jdbc.quoted` provides five functions that cover the most common types of entity quoting, and a modifier function for quoting dot-separated names (e.g., that include schemas): * `ansi` -- wraps entity names in double quotes, * `mysql` -- wraps entity names in back ticks, @@ -129,6 +129,8 @@ The namespace `next.jdbc.quoted` provides five functions that cover the most com * `oracle` -- an alias for `ansi`, * `postgres` -- an alias for `ansi`. +* `schema` -- wraps a quoting function to support `dbo.table` style entity names. + These quoting functions can be provided to any of the friendly SQL functions above using the `:table-fn` and `:column-fn` options, in a hash map provided as the (optional) last argument in any call. If you want to provide your own entity naming function, you can do that: ```clojure @@ -137,6 +139,6 @@ 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}) ``` -Note that 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 [Issue 11](https://github.com/seancorfield/next-jdbc/issues/11). +Note that 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]`. [[Prev: Getting Started|getting_started]] [[Next: Row and Result Set Builders|rs_builders]] diff --git a/doc/getting_started.md b/doc/getting_started.md index cea3f25..12d2d8f 100644 --- a/doc/getting_started.md +++ b/doc/getting_started.md @@ -9,12 +9,12 @@ It is designed to work with Clojure 1.10 or later, supports `datafy`/`nav`, and You can add `next.jdbc` to your project with either: ```clojure -{next.jdbc {:mvn/version "1.0.0-alpha3"}} +{next.jdbc {:mvn/version "1.0.0-alpha4"}} ``` for `deps.edn` or: ```clojure -[next.jdbc "1.0.0-alpha3"] +[next.jdbc "1.0.0-alpha4"] ``` for `project.clj` or `build.boot`. @@ -29,7 +29,7 @@ For the examples in this documentation, we will use a local H2 database on disk, ```clojure ;; deps.edn {:deps {org.clojure/clojure {:mvn/version "1.10.0"} - next.jdbc {:mvn/version "1.0.0-alpha3"} + next.jdbc {:mvn/version "1.0.0-alpha4"} com.h2database/h2 {:mvn/version "1.4.197"}}} ``` diff --git a/pom.xml b/pom.xml index 92cebd4..1714f24 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 seancorfield next.jdbc - 1.0.0-alpha3 + 1.0.0-alpha4 next.jdbc The next generation of clojure.java.jdbc: a new low-level Clojure wrapper for JDBC-based access to databases. @@ -22,9 +22,9 @@ - scm:git:git@github.com:seancorfield/next-jdbc.git - scm:git:git@github.com:seancorfield/next-jdbc.git - git@github.com:seancorfield/next-jdbc.git + https://github.com/seancorfield/next-jdbc + scm:git:git://github.com/seancorfield/next-jdbc.git + scm:git:ssh://git@github.com/seancorfield/next-jdbc.git 856467465373171befe63e0d6bfff98cb22189a5 diff --git a/src/next/jdbc/quoted.clj b/src/next/jdbc/quoted.clj index 4442c5d..773e784 100644 --- a/src/next/jdbc/quoted.clj +++ b/src/next/jdbc/quoted.clj @@ -3,7 +3,8 @@ (ns next.jdbc.quoted "Provides functions for use with the :table-fn and :column-fn options that define how SQL entities should be quoted in strings constructed - from Clojure data.") + from Clojure data." + (:require [clojure.string :as str])) (defn ansi "ANSI \"quoting\"" [s] (str \" s \")) @@ -14,3 +15,15 @@ (def oracle "Oracle \"quoting\" (ANSI)" ansi) (def postgres "PostgreSQL \"quoting\" (ANSI)" ansi) + +(defn schema + "Given a quoting function, return a new quoting function that will + process schema-qualified names by quoting each segment: + + (mysql :foo.bar) ;=> `foo.bar` + ((schema mysql) :foo.bar) ;=> `foo`.`bar`" + [quoting] + (fn [s] + (->> (str/split s #"\.") + (map quoting) + (str/join ".")))) diff --git a/test/next/jdbc/quoted_test.clj b/test/next/jdbc/quoted_test.clj index 8d6a6a5..0c52762 100644 --- a/test/next/jdbc/quoted_test.clj +++ b/test/next/jdbc/quoted_test.clj @@ -3,8 +3,9 @@ (ns next.jdbc.quoted-test "Basic tests for quoting strategies. These are also tested indirectly via the next.jdbc.sql tests." - (:require [clojure.test :refer [deftest are]] - [next.jdbc.quoted :refer :all])) + (:require [clojure.test :refer [deftest are testing]] + [next.jdbc.quoted :refer [ansi mysql sql-server oracle postgres + schema]])) (deftest basic-quoting (are [quote-fn quoted] (= (quote-fn "x") quoted) @@ -13,3 +14,19 @@ sql-server "[x]" oracle "\"x\"" postgres "\"x\"")) + +(deftest schema-quoting + (testing "verify non-schema behavior" + (are [quote-fn quoted] (= (quote-fn "x.y") quoted) + ansi "\"x.y\"" + mysql "`x.y`" + sql-server "[x.y]" + oracle "\"x.y\"" + postgres "\"x.y\"")) + (testing "verify schema behavior" + (are [quote-fn quoted] (= ((schema quote-fn) "x.y") quoted) + ansi "\"x\".\"y\"" + mysql "`x`.`y`" + sql-server "[x].[y]" + oracle "\"x\".\"y\"" + postgres "\"x\".\"y\"")))