packages feed

DSH-0.8.2.1: examples/Example03.hs

{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE MonadComprehensions   #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE RebindableSyntax      #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE UndecidableInstances  #-}
{-# LANGUAGE ViewPatterns          #-}

module Main where

import qualified Prelude as P
import Database.DSH
import Database.DSH.Compiler

import Database.HDBC.PostgreSQL

data Employee = Prof  { name            :: Text
                      , chair           :: Text
                      , advisedStudents :: [Text]
                      }
              | Stud  { name    :: Text
                      , topic   :: Text
                      , advisor :: Text
                      }
              deriving (Eq,Ord,Show)

deriveDSH ''Employee

students :: Q [(Integer,Text,Text,Text)]
students = toQ  [ (1,"J","P","T")
                , (2,"A","Q","T")
                ]

professors :: Q [(Integer,Text,Text)]
professors = toQ  [ (0,"T","DB")]

employment :: Q [(Integer,Text,Text,Integer)]
employment = toQ  [ (0,"DB","professor",2008)
                  , (1,"DB","student",2010)
                  , (2,"DB","student",2011)
                  , (3,"PL","student",2012)
                  ]

salaries :: Q [(Integer,Integer)]
salaries = toQ  [ (0,4096)
                , (1,2048)
                , (2,2048)
                ]

employeesBySeniority :: Q [Employee]
employeesBySeniority = concat
  [ if eStatus == "student"
       then  [ stud sName sTopic sAdvisor
             | (view -> (sID, sName, sTopic, sAdvisor)) <- students
             , eID == sID
             ]
       else  [  prof pName pChair sAdvised
             |  (view -> (pID, pName, pChair)) <- professors
             ,  eID == pID
             ,  let sAdvised = [ sName
                               | (view -> (_, sName, _, sAdvisor)) <- students
                               , sAdvisor == pName
                               ]
             ]
  | (view -> (eID, _, eStatus, _)) <- sortWith (\(view -> (_, _, _, d)) -> d) employment
  ]

safeMinimum :: (Ord a, QA a) => Q [a] -> Q (Maybe a)
safeMinimum as = if null as then nothing else just (minimum as) 

salPerDept :: Q [(Text, [Integer])]
salPerDept =
  [ pair dept [ salary
              | (view -> (sID,salary)) <- salaries
              , (view -> (dID,_,_,_)) <- deptMembers
              , sID == dID
              ]
  | (view -> (dept, deptMembers)) <- groupWithKey (\(view -> (_,d,_,_)) -> d) employment
  ]

minSalPerDept :: Q [(Text, Integer)]
minSalPerDept =  [ pair dept (elim (safeMinimum sals)
                                   0
                                   (\minSal -> minSal))
                 | (view -> (dept, sals)) <- salPerDept
                 ]

getConn :: IO Connection
getConn = connectPostgreSQL "user = 'giorgidz' password = '' host = 'localhost' dbname = 'giorgidz'"

runQ :: (Show a,QA a) => Q a -> IO ()
runQ q = getConn P.>>= \conn -> (fromQ conn q P.>>= P.print) P.>> disconnect conn

main :: IO ()
main = sequence_  [ runQ employeesBySeniority
                  , runQ salPerDept
                  , runQ minSalPerDept
                  ]