Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for postgres schemas #98

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 50 additions & 35 deletions src/korma/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
ent)
[ent table alias db opts] (if (string? ent)
[{:table ent} ent nil nil nil]
[ent (:table ent) (:alias ent)
[ent (:table ent) (:alias ent)
(:db ent) (get-in ent [:db :options])])]
{:ent ent
:table table
:db db
:options opts
:alias alias}))

(defn select*
(defn select*
"Create an empty select query. Ent can either be an entity defined by defentity,
or a string of the table name"
[ent]
Expand All @@ -51,7 +51,7 @@
:group []
:results :results}))))

(defn update*
(defn update*
"Create an empty update query. Ent can either be an entity defined by defentity,
or a string of the table name."
[ent]
Expand All @@ -63,7 +63,7 @@
:where []
:results :keys}))))

(defn delete*
(defn delete*
"Create an empty delete query. Ent can either be an entity defined by defentity,
or a string of the table name"
[ent]
Expand All @@ -74,7 +74,7 @@
:where []
:results :keys}))))

(defn insert*
(defn insert*
"Create an empty insert query. Ent can either be an entity defined by defentity,
or a string of the table name"
[ent]
Expand All @@ -89,47 +89,47 @@
;; Query macros
;;*****************************************************

(defmacro select
(defmacro select
"Creates a select query, applies any modifying functions in the body and then
executes it. `ent` is either a string or an entity created by defentity.
ex: (select user

ex: (select user
(fields :name :email)
(where {:id 2}))"
[ent & body]
`(let [query# (-> (select* ~ent)
~@body)]
(exec query#)))

(defmacro update
(defmacro update
"Creates an update query, applies any modifying functions in the body and then
executes it. `ent` is either a string or an entity created by defentity.
ex: (update user
(set-fields {:name \"chris\"})

ex: (update user
(set-fields {:name \"chris\"})
(where {:id 4}))"
[ent & body]
`(let [query# (-> (update* ~ent)
~@body)]
(exec query#)))

(defmacro delete
(defmacro delete
"Creates a delete query, applies any modifying functions in the body and then
executes it. `ent` is either a string or an entity created by defentity.
ex: (delete user

ex: (delete user
(where {:id 7}))"
[ent & body]
`(let [query# (-> (delete* ~ent)
~@body)]
(exec query#)))

(defmacro insert
(defmacro insert
"Creates an insert query, applies any modifying functions in the body and then
executes it. `ent` is either a string or an entity created by defentity. Inserts
return the last inserted id.
ex: (insert user

ex: (insert user
(values [{:name \"chris\"} {:name \"john\"}]))"
[ent & body]
`(let [query# (-> (insert* ~ent)
Expand All @@ -152,9 +152,9 @@
(defn fields
"Set the fields to be selected in a query. Fields can either be a keyword
or a vector of two keywords [field alias]:

(fields query :name [:firstname :first])"
[query & vs]
[query & vs]
(let [aliases (set (map second (filter coll? vs)))]
(-> query
(add-aliases aliases)
Expand Down Expand Up @@ -184,27 +184,27 @@
Available predicates: and, or, =, not=, <, >, <=, >=, in, like, not

Where can also take a map at any point and will create a clause that compares keys
to values. The value can be a vector with one of the above predicate functions
to values. The value can be a vector with one of the above predicate functions
describing how the key is related to the value: (where query {:name [like \"chris\"})"
[query form]
`(let [q# ~query]
(where* q#
(where* q#
(bind-query q#
(eng/pred-map
~(eng/parse-where `~form))))))

(defn order
"Add an ORDER BY clause to a select query. field should be a keyword of the field name, dir
is ASC by default.

(order query :created :asc)"
[query field & [dir]]
(update-in query [:order] conj [field (or dir :ASC)]))

(defn values
"Add records to an insert clause. values can either be a vector of maps or a single
map.

(values query [{:name \"john\"} {:name \"ed\"}])"
[query values]
(update-in query [:values] concat (if (map? values)
Expand All @@ -214,10 +214,10 @@
(defn join* [query type table clause]
(update-in query [:joins] conj [type table clause]))

(defmacro join
(defmacro join
"Add a join clause to a select query, specifying the table name to join and the predicate
to join on.

(join query addresses)
(join query addresses (= :addres.users_id :users.id))
(join query :right addresses (= :address.users_id :users.id))"
Expand Down Expand Up @@ -255,10 +255,10 @@
(defmacro aggregate
"Use a SQL aggregator function, aliasing the results, and optionally grouping by
a field:
(select users

(select users
(aggregate (count :*) :cnt :status))

Aggregates available: count, sum, avg, min, max, first, last"
[query agg alias & [group-by]]
`(let [q# ~query]
Expand Down Expand Up @@ -316,14 +316,14 @@
;;*****************************************************

(defmacro sql-only
"Wrap around a set of queries so that instead of executing, each will return a string of the SQL
"Wrap around a set of queries so that instead of executing, each will return a string of the SQL
that would be used."
[& body]
`(binding [*exec-mode* :sql]
~@body))

(defmacro dry-run
"Wrap around a set of queries to print to the console all SQL that would
"Wrap around a set of queries to print to the console all SQL that would
be run and return dummy values instead of executing them."
[& body]
`(binding [*exec-mode* :dry-run]
Expand Down Expand Up @@ -481,7 +481,7 @@
"Add a has-many relation for the given entity. It is assumed that the foreign key
is on the sub-entity with the format table_id: user.id = email.user_id
Opts can include a key for :fk to explicitly set the foreign key.

(has-many users email {:fk :emailID})"
[ent sub-ent & [opts]]
`(rel ~ent (var ~sub-ent) :has-many ~opts))
Expand All @@ -493,7 +493,7 @@
(update-in ent [:fields] concat (map #(eng/prefix ent %) fields)))

(defn table
"Set the name of the table and an optional alias to be used for the entity.
"Set the name of the table and an optional alias to be used for the entity.
By default the table is the name of entity's symbol."
[ent t & [alias]]
(let [tname (if (or (keyword? t)
Expand Down Expand Up @@ -570,8 +570,8 @@
(let [fk (:fk rel)
pk (get-in query [:ent :pk])
table (keyword (eng/table-alias ent))]
(post-query query
(partial map
(post-query query
(partial map
#(assoc % table
(select ent
(func)
Expand Down Expand Up @@ -612,3 +612,18 @@
`(with* ~query ~ent (fn [q#]
(-> q#
~@body))))

(defn pg-schema
"Sets the search_path variable of Postgres to the given schema
Usage:
(defentity users)

(select users)
=> \"SELECT \"users\".* FROM \"users\"

(set-pg-schema :test)

(select users)
=> \"SELECT \"test.users\".* FROM \"test.users\"\" "
[schema & body]
(exec-raw [(str "SET search_path TO " (name schema) ";")]))