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