haskell-relational-record/quickstart.md

2.9 KiB

layout title
default Quick start

Preparing HRR

To start using Haskell Relational Record (HRR), you need to install:

  1. Glasgow Haskell Compiler (GHC) + the "cabal" command
  2. The Haskell "relational-record" library
  3. Relational database system
    • In this quickstart, we assume that SQLite version 3 has been installed

To install the Haskell "relational-record" library, run the following commands:

% cabal update
% cabal install relational-record

The first relation

Let's define our first relation. Copy the following to "hello.hs":

{% highlight haskell %} import Data.Int (Int32) import Database.Relational.Query

hello :: Relation () (Int32, String) hello = relation $ return (value 0 >< value "Hello")

main :: IO () main = putStrLn $ show hello ++ ";" {% endhighlight %}

hello defines our first relation. This "SELECT"s a constant tuple value (0,"Hello") from the (virtual) empty table. In other words, this relation just returns (0,"Hello").

Let's run the above Haskell code to show what kind of SQL statement is generated:

{% highlight sql %} % runghc hello.hs SELECT ALL 0 AS f0, 'Hello' AS f1; {% endhighlight %}

OK. Next, let's execute the SQL produced above in SQLite:

% runghc hello.hs | sqlite3 dummy.db
0|Hello

We got "0|Hello"! Note that "dummy.db" is just a dummy file.

Composing relations

Next, let's compose relations. Copy the following to "helloworld.hs":

{% highlight haskell %} import Data.Int (Int32) import Database.Relational.Query

hello :: Relation () (Int32, String) hello = relation $ return (value 0 >< value "Hello")

world :: Relation () (Int32, String) world = relation $ return (value 0 >< value "World!")

helloWorld :: Relation () (Int32, (String, String)) helloWorld = relation $ do h <- query hello w <- query world on $ h ! fst' .=. w ! fst' return $ h ! fst' >< (h ! snd' >< w ! snd')

main :: IO () main = putStrLn $ show helloWorld ++ ";" {% endhighlight %}

This code defines queries called hello and world. And helloworld composes them by joining them on the first element of the tuples.

This code generates the following SQL statement:

{% highlight sql %} % runghc helloworld.hs SELECT ALL T0.f0 AS f0, T0.f1 AS f1, T1.f1 AS f2 FROM (SELECT ALL 0 AS f0, 'Hello' AS f1) T0 INNER JOIN (SELECT ALL 0 AS f0, 'World!' AS f1) T1 ON (T0.f0 = T1.f0); {% endhighlight %}

Finally, let's execute it in SQLite:

% runghc helloworld.hs | sqlite3 dummy.db
0|Hello|World!

Now we understand that relations are composable. Raw SQL does NOT have this feature. Moreover, relations are type safe. If our HRR code can be compiled by GHC, it always generates valid SQL statements.

The next step is to read the HRR tutorial.