Skip to content

Instantly share code, notes, and snippets.

Created October 2, 2011 05:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1257106 to your computer and use it in GitHub Desktop.
Save anonymous/1257106 to your computer and use it in GitHub Desktop.
30 mins of orm-iness
(ns korma.core
(:require [clojure.string :as string]))
(comment
(defentity user
(has-many address)
(has-one blah {:include :always
:pk "blah_woot"}))
(select user
(where {:id 3}))
(select-first user
(with blah)
(where {:email "chris@test.com"})
(order :created :desc)
(order :timestamp :desc))
)
(defn empty-query [ent]
{:ent ent
:table (:table ent)
:fields []
:where {}
:order []
:group []})
(defn sql-query-type [query]
(let [clauses (if-not (seq (:fields query))
["*"]
(map name (:fields query)))
clauses-str (string/join ", " clauses)
neue-sql (str "SELECT " clauses-str " FROM " (:table query))]
[neue-sql query]))
(defn join-clause [join-type table sub-table]
(let [join-type (string/upper-case (name join-type))
join (str " " join-type " JOIN " sub-table " ON ")
on-clause (str table "." sub-table "_id = " sub-table ".id")]
(str join on-clause)))
(defn sql-joins [[sql query]]
(let [sub-ents (-> query :ent :has-one)
clauses (for [{:keys [table]} sub-ents]
(join-clause :left (:table query) table))
clauses-str (string/join " " clauses)]
[(str sql clauses-str) query]))
(defn sql-where [[sql query]]
(let [clauses (for [[k v] (:where query)]
(str (name k) " = '" v "'"))
clauses-str (string/join ", " clauses)
neue-sql (str " WHERE " clauses-str)]
[(str sql neue-sql) query]))
(defn sql-order [[sql query]]
(let [clauses (for [[k dir] (:order query)]
(str (name k) " " (string/upper-case (name dir))))
clauses-str (string/join ", " clauses)
neue-sql (str " ORDER BY " clauses-str)]
[(str sql neue-sql) query]))
(defn sql-limit-offset [[sql {:keys [limit offset] :as query}]]
(let [limit-sql (when limit
(str " LIMIT " limit))
offset-sql (when offset
(str " OFFSET " offset))]
[(str sql limit-sql offset-sql) query]))
(defn ->sql [query]
(-> query
(sql-query-type)
(sql-joins)
(sql-where)
(sql-order)
(sql-limit-offset)))
(defmacro defentity [ent & body]
`(let [e# (-> {:table ~(name ent)}
~@body)]
(def ~ent e#)))
(defmacro select [ent & body]
`(let [query# (-> (empty-query ~ent)
~@body)]
(->sql query#)
))
(defn fields [query & vs]
(update-in query [:fields] concat vs))
(defn where [query vs]
(update-in query [:where] merge vs))
(defn order [query k & [dir]]
(update-in query [:order] conj [k (or dir :desc)]))
(defn limit [query v]
(assoc query :limit v))
(defn offset [query v]
(assoc query :offset v))
(defn has-one [ent sub-ent]
(update-in ent [:has-one] conj sub-ent))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment