Merge pull request #517 from dancek/create-index
Implement CREATE INDEX
This commit is contained in:
commit
1c499ac8a7
5 changed files with 64 additions and 3 deletions
|
|
@ -98,7 +98,7 @@ names: the "from" and the "to" names.
|
||||||
|
|
||||||
> Note: `:modify-column` is MySQL-specific and should be considered legacy and deprecated. `:alter-column` will produce `MODIFY COLUMN` when the MySQL dialect is selected.
|
> Note: `:modify-column` is MySQL-specific and should be considered legacy and deprecated. `:alter-column` will produce `MODIFY COLUMN` when the MySQL dialect is selected.
|
||||||
|
|
||||||
### add-index, drop-index
|
### add-index, drop-index, create-index
|
||||||
|
|
||||||
Used with `:alter-table`,
|
Used with `:alter-table`,
|
||||||
`:add-index` accepts a single (function) expression
|
`:add-index` accepts a single (function) expression
|
||||||
|
|
@ -125,6 +125,22 @@ user=> (-> (h/alter-table :fruit)
|
||||||
["ALTER TABLE fruit ADD PRIMARY KEY(id)"]
|
["ALTER TABLE fruit ADD PRIMARY KEY(id)"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Some databases treat the standalone `:create-index` differently (e.g. PostgreSQL) while some treat it as an alias to `:alter-table` `:add-index` (e.g. MySQL). It accepts a pair of index specification and column specification:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
user=> (sql/format {:create-index [:my-idx [:fruit :appearance]]})
|
||||||
|
["CREATE INDEX my_idx ON fruit (appearance)"]
|
||||||
|
user=> (sql/format {:create-index [[:unique :another-idx] [:fruit :color :appearance]]})
|
||||||
|
["CREATE UNIQUE INDEX another_idx ON fruit (color, appearance)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
PostgreSQL supports IF NOT EXISTS and expressions instead of columns. This may make `:create-index` more useful than `:add-index`:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
user=> (sql/format (h/create-index [:unique :another-idx :if-not-exists] [:fruit :color :%lower.appearance]))
|
||||||
|
["CREATE UNIQUE INDEX IF NOT EXISTS another_idx ON fruit (color, LOWER(appearance))"]
|
||||||
|
```
|
||||||
|
|
||||||
### rename-table
|
### rename-table
|
||||||
|
|
||||||
Used with `:alter-table`,
|
Used with `:alter-table`,
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
:create-extension
|
:create-extension
|
||||||
:drop-table :drop-view :drop-materialized-view :drop-extension
|
:drop-table :drop-view :drop-materialized-view :drop-extension
|
||||||
:refresh-materialized-view
|
:refresh-materialized-view
|
||||||
|
:create-index
|
||||||
;; then SQL clauses in priority order:
|
;; then SQL clauses in priority order:
|
||||||
:raw :nest :with :with-recursive :intersect :union :union-all :except :except-all
|
:raw :nest :with :with-recursive :intersect :union :union-all :except :except-all
|
||||||
:table
|
:table
|
||||||
|
|
@ -1255,6 +1256,17 @@
|
||||||
(into more)
|
(into more)
|
||||||
(conj (when as (sql-kw as))))))]))
|
(conj (when as (sql-kw as))))))]))
|
||||||
|
|
||||||
|
(defn- format-create-index [k clauses]
|
||||||
|
(let [[index-spec [table & exprs]] clauses
|
||||||
|
[pre entity ine & more] (destructure-ddl-item index-spec (str (sql-kw k) " options"))
|
||||||
|
[sqls params] (format-expr-list exprs)]
|
||||||
|
(into [(str/join " " (remove empty?
|
||||||
|
(-> ["CREATE" pre "INDEX" ine entity
|
||||||
|
"ON" (format-entity table)
|
||||||
|
(str "(" (str/join ", " sqls) ")")]
|
||||||
|
(into more))))]
|
||||||
|
params)))
|
||||||
|
|
||||||
(defn- format-with-data [_ data]
|
(defn- format-with-data [_ data]
|
||||||
(let [data (if (sequential? data) (first data) data)]
|
(let [data (if (sequential? data) (first data) data)]
|
||||||
[(str/join " " (remove nil?
|
[(str/join " " (remove nil?
|
||||||
|
|
@ -1433,6 +1445,7 @@
|
||||||
:drop-view #'format-drop-items
|
:drop-view #'format-drop-items
|
||||||
:drop-materialized-view #'format-drop-items
|
:drop-materialized-view #'format-drop-items
|
||||||
:refresh-materialized-view (fn [_ x] (format-create :refresh :materialized-view x nil))
|
:refresh-materialized-view (fn [_ x] (format-create :refresh :materialized-view x nil))
|
||||||
|
:create-index #'format-create-index
|
||||||
:raw (fn [_ x] (raw-render x))
|
:raw (fn [_ x] (raw-render x))
|
||||||
:nest (fn [_ x]
|
:nest (fn [_ x]
|
||||||
(let [[sql & params] (format-dsl x {:nested true})]
|
(let [[sql & params] (format-dsl x {:nested true})]
|
||||||
|
|
|
||||||
|
|
@ -375,6 +375,20 @@
|
||||||
[& views]
|
[& views]
|
||||||
(generic :refresh-materialized-view views))
|
(generic :refresh-materialized-view views))
|
||||||
|
|
||||||
|
(defn create-index
|
||||||
|
"Accepts an index spexification and a column specification. The column
|
||||||
|
specification consists of table name and one or more columns.
|
||||||
|
|
||||||
|
(create-index :name-of-idx [:table :col])
|
||||||
|
(create-index :name-of-idx [:table :col1 :col2])
|
||||||
|
(create-index [:unique :name-of-idx] [:table :col])
|
||||||
|
|
||||||
|
PostgreSQL also supports :if-not-exists and expressions instead of columns.
|
||||||
|
|
||||||
|
(create-index [:name-of-idx :if-not-exists] [:table :%lower.col])"
|
||||||
|
[& args]
|
||||||
|
(generic :create-index args))
|
||||||
|
|
||||||
(defn with
|
(defn with
|
||||||
"Accepts one or more CTE definitions.
|
"Accepts one or more CTE definitions.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
[honey.sql.helpers :as h
|
[honey.sql.helpers :as h
|
||||||
:refer [add-column add-index alter-table columns create-table create-table-as create-view
|
:refer [add-column add-index alter-table columns create-table create-table-as create-view
|
||||||
create-materialized-view drop-view drop-materialized-view
|
create-materialized-view drop-view drop-materialized-view
|
||||||
|
create-index
|
||||||
bulk-collect-into
|
bulk-collect-into
|
||||||
cross-join do-update-set drop-column drop-index drop-table
|
cross-join do-update-set drop-column drop-index drop-table
|
||||||
filter from full-join
|
filter from full-join
|
||||||
|
|
@ -962,3 +963,21 @@
|
||||||
(is (= '{}
|
(is (= '{}
|
||||||
(-> '{}
|
(-> '{}
|
||||||
(where))))))
|
(where))))))
|
||||||
|
|
||||||
|
(deftest test-create-index
|
||||||
|
(testing "create index, commonly supported features"
|
||||||
|
(is (= ["CREATE INDEX my_column_idx ON my_table (my_column)"]
|
||||||
|
(sql/format {:create-index [:my-column-idx [:my-table :my-column]]})))
|
||||||
|
(is (= ["CREATE INDEX my_column_idx ON my_table (my_column)"]
|
||||||
|
(sql/format (create-index :my-column-idx [:my-table :my-column]))))
|
||||||
|
(is (= ["CREATE UNIQUE INDEX my_column_idx ON my_table (my_column)"]
|
||||||
|
(sql/format (create-index [:unique :my-column-idx] [:my-table :my-column]))))
|
||||||
|
(is (= ["CREATE INDEX my_column_idx ON my_table (my_column, my_other_column)"]
|
||||||
|
(sql/format (create-index :my-column-idx [:my-table :my-column :my-other-column])))))
|
||||||
|
(testing "PostgreSQL extensions (IF NOT EXISTS and expressions)"
|
||||||
|
(is (= ["CREATE INDEX IF NOT EXISTS my_column_idx ON my_table (my_column)"]
|
||||||
|
(sql/format (create-index [:my-column-idx :if-not-exists] [:my-table :my-column]))))
|
||||||
|
(is (= ["CREATE UNIQUE INDEX IF NOT EXISTS my_column_idx ON my_table (my_column)"]
|
||||||
|
(sql/format (create-index [:unique :my-column-idx :if-not-exists] [:my-table :my-column]))))
|
||||||
|
(is (= ["CREATE INDEX my_column_idx ON my_table (LOWER(my_column))"]
|
||||||
|
(sql/format (create-index :my-column-idx [:my-table :%lower.my-column]))))))
|
||||||
|
|
|
||||||
|
|
@ -1311,5 +1311,4 @@ ORDER BY id = ? DESC
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
;; partial workaround for #407:
|
;; partial workaround for #407:
|
||||||
(sut/format {:select :f.* :from [[:foo [:f :for :system-time]]] :where [:= :f.id 1]})
|
(sut/format {:select :f.* :from [[:foo [:f :for :system-time]]] :where [:= :f.id 1]}))
|
||||||
)
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue