This page describes the original version of HaskellDb
, available from http://www.haskell.org/haskellDB/index.html
There is a newer version at http://haskelldb.sourceforge.net/
which works with GHC and supports more backends.
Examples are available at http://www.haskell.org/haskellDB/example.html
. Here are some snippets:
SELECT X.first_name, X.last_name FROM Authors AS X
names = do x <- table authors
project (first_name = x!first_name, last_name = x!last_name )
The "!" operator selects an attribute from a relation (like "." in StructuredQueryLanguage
). The result is bound to names
Since it's plain HaskellLanguage
code one can use any sort of combinators he want to use (e.g. ExtensibleMarkupLanguage
combinators to create reports).
What command(s) actually go to the database engine? Or, is the implementation done in Haskell? If so, what would it look like if other languages wanted to access the same data?
defines some relational algebra combinators (e.g. project, restrict, order) and you use them to declare your query. The constructed query object is eventually given to a particular database driver and it'll then be automatically transformed in a statement string. So you write code like:
samecity = do x <- table authors
y <- table authors
restrict (x!au_id .<>. y!au_id)
restrict (x!city .==. y!city)
project (au_fname = x!au_fname, au_lname = x!au_lname, city = x!city)
And it becomes:
SELECT DISTINCT au_fname1 as au_fname, au_lname1 as au_lname, city1 as city
FROM (SELECT DISTINCT au_id as au_id2 ,city as city2 FROM authors as T1) as T1,
(SELECT DISTINCT au_fname as au_fname1, au_id as au_id1, au_lname as au_lname1, city as city1
FROM authors as T1) as T2
WHERE (au_id1 <> au_id2) AND (city1 = city2)
Which is stupid-translator-ese for:
SELECT DISTINCT t1.au_fname as au_fname, t1.au_lname as au_lname, t1.city as city
FROM authors as t1, authors as t2
WHERE (t1.au_id <> t2.au_id) AND (t1.city = t2.city)
The truly great thing about HaskellDB is that it's strongly typed, which means you can't express a query that's illogical, e.g. joining a string column to a date column. This means databases (and DB programmers) that play fast and loose with type conversions will have to explicitly cast at the DB side if they want to match incompatible types. Of course, strong typing is probably why you're using Haskell in the first place...
has a similar sort of thing called Mnesia where they use list comprehension syntax to query databases.