ClojureQL - 1.0.0 now in beta
bestinclass.dk
bestinclass.dk
Examples on website are quite simplistic. They are far away from real life SQL queries that usually bigger and more complex (not select and join couple of tables). What about "group by", joining 5 or 8 tables etc.? How you are supposed to prototype and test your queries on existing schema (there are many good graphical clients for many RDBMSes)? There are many questions remaining unanswered.
At least Clojre-QL do not try to fit a square peg into round hole like Hibernate. Personally I liked Hibernate for some period, until I sat down and learned to use SQL.
A simple question is "how the hell you use prepared statements with such libraries"? And the answer will be is that the FRAMEWORK need to be extended further in order to support them. In other words once you abandon SQL you will never have the same flexibility that it gives, because of artificial constraints imposed by every framework. And your code will become more and more complex because of all these frameworks that are invented not of the real need but as an programming exercise.
PS: The article that you suggested is written by a guy that tend to speculate over his point of view without taking in account the reality. In all modern RDBMSes queries having (a=b and a=c and b=c) will be simplified by query planners (Oracle and Postrgre do it) so there will not be any difference in performance.
Instead of writing an ad-hoc SQL parser and doing string manipulation, you can write relatively simple Clojure functions to manipulate these lists and generate valid SQL.
2. They are not simple functions. Compare this : (-> (select (table {} {:employees :p})(where (= :name "John")))(join (table {} {:employees :b})(where (= :p.manager :b.id)))to-sql)
to this :
SELECT p.,b. FROM employees p JOIN employees b ON (p.manager = b.id) WHERE (name = 'John')
Which one is more verbose ?
EDIT: SQL examples with "employees" and "departmets" are very misleading and usually oversimplify the reality.
(def users (cql/table db :users))
(def photos (cql/table db :photos))
(def users-and-photos
(cql/join users photos
(cql/where (= :users.id :photos.user_id))))
(def photo-titles
(-> users-and-photos
(cql/project #{:photos.title})))
Note that my queries just keep getting smaller and smaller ;) By writing the mundane portions of your SQL queries again and again by hand you will have more duplication.With SQL it is straight-forward: you prototype your query using some GUI client and then you just embed it in your program. How it can be done with Clojure-QL ?
SELECT p.*,b.* FROM employees p JOIN employees b ON (p.manager = b.id) WHERE (p.name = 'John')
is only 8 characters less than: (join (select (table {:employees :p}) (=* :name "John")) (table {:employees :b}) (=* :p.manager :b.id))
but that isn't the point. the point is composabilty. you can take 8 simple functions (select, project, join, rename, aggregate, take, drop, sort) and build any query you want. these queries can be passed around your code, reused, modified, and refined, in a way that plain SQL strings cannot.Which is why I'm still using Oyako (https://github.com/briancarper/oyako)
Would be fun to see if we could do some kind of SQL templating where users could supply their own templates.
In my brief experience, the idea of a cross-database SQL DSL is a lost cause unless you want to limit yourself to a very small subset of SQL. Funny, for a language that supposedly has a standard.