packages feed

DSH-0.4: examples/Example1.hs

-- This module is part of the DSH-Compiler package and serves as an example on
-- howto use DSH. It is accompanied by a file ExampleData.sql that contains
-- SQL instructions to setup the database that is used by this example.

-- Quasiquoting has to be enabled to support the list comprehension syntax
{-# LANGUAGE QuasiQuotes #-}

module Main where

-- We hide everything in the prelude as DSH exposes a lot of same combinators.
-- In general we recommend to import the module Database.DSH module qualified.
-- The Database.DSH.Compiler module has to be imported seperately this module
-- contains the machinery necessary to execute the query. This module is part
-- of the DSH-Compiler package, the other module (Database.DSH) is part of
-- DSH-Core. We provide the modules in separate packages so that different
-- backend can be made and used for the DSH query facility.

import Prelude () 
import Database.DSH
import Database.DSH.Compiler

-- For our example we use postgresql, any database will do as long it can be
-- approached through HDBC.
import Database.HDBC.PostgreSQL

-- Setup the connection string. In order for this to work you must provide a
-- username, password, host and database name.
getConn :: IO Connection
getConn = connectPostgreSQL "user = 'postgres' password = 'haskell98' host = 'localhost' dbname = 'ferry'"

-- DSH uses Text instead of string for strings, as a string will be treated as a
-- list of characters.
type Facility = Text
type Cat      = Text
type Feature  = Text
type Meaning  = Text

-- Declare the database tables, note that you *MUST* declare all columns
-- present in a table. And all columns must be in the same order as they are
-- declared in the database. During compilation the types of the columns will
-- be checked against the provided haskell types. When possible the types of
-- columns will be inferred, if they cannot be fully inferred the user has to
-- provide explicit types!

facilities :: Q [(Cat, Facility)]
facilities = table "facilities"
               
features :: Q [(Facility, Feature)]
features = table "features"
          
meanings :: Q [(Feature, Meaning)]
meanings = table "meanings"
            
-- Helper function for the query.
-- Despite the different braces for the comprehension the comprehension body
-- works as normal
descrFacility :: Q Facility -> Q [Meaning]
descrFacility f =  [$qc| mean | (feat,mean) <- meanings, 
                                (fac,feat1) <- features, 
                                feat == feat1 && fac == f|]

-- Main query, use the helper function
query :: Q [(Text , [Text])] 
query = [$qc| tuple (the cat, nub $ concatMap descrFacility fac) 
            | (cat, fac) <- facilities, then group by cat |]


-- Execute the query
main :: IO ()
main = do
  conn   <- getConn           -- Get a connection
  result <- fromQ conn query  -- Execute the query using fromQ
  print result