module QueryParser (
QueryExpr(..),
queryExpr,
makeSelect,evaluateQuery) where
import Text.Parsec.String (Parser)
import Text.ParserCombinators.Parsec.Char
import Text.ParserCombinators.Parsec.Combinator
import Text.Parsec (parse , ParseError , try)
import Control.Applicative ((<*),(<$>), (*>), (<|>),(<$),(<*>))
import Control.Monad
import qualified Text.ParserCombinators.Parsec.Expr as E
import Data.Maybe ()
import Funcs
import ExpressionParser
import Database
data QueryExpr = Select
{qeSelectList :: [(ValueExpr,Maybe String)]
,qefromClause :: ValueExpr
,qeWhere :: Maybe ValueExpr
,qeGroupBy :: [ValueExpr]
,qeHaving :: Maybe ValueExpr
,qeOrderBy :: [ValueExpr]
} deriving (Eq,Show)
makeSelect :: QueryExpr
makeSelect = Select {qeSelectList = []
,qefromClause = Iden ""
,qeWhere = Nothing
,qeGroupBy = []
,qeHaving = Nothing
,qeOrderBy = []}
selectList :: Parser [(ValueExpr, Maybe String)]
selectList = keyword_ "select" *> commaSep1 selectItem
selectItem :: Parser (ValueExpr, Maybe String)
selectItem = (,) <$> valueExpr [] <*> optionMaybe (try alias)
where alias = optional (keyword_ "as") *> identifierBlacklist ["from","where","group","having","order"]
fromClause :: Parser ValueExpr
fromClause = keyword_ "from" *> iden ["from","where","group","having","order"]
whereClause :: Parser ValueExpr
whereClause = keyword_ "where" *> valueExpr []
groupByClause :: Parser [ValueExpr]
groupByClause = keyword_ "group" *> keyword_ "by"
*> commaSep1 (valueExpr [])
having :: Parser ValueExpr
having = keyword_ "having" *> (valueExpr [])
orderByClause :: Parser [ValueExpr]
orderByClause = keyword_ "order" *> keyword_ "by"
*> commaSep1 (valueExpr [])
queryExpr :: Parser QueryExpr
queryExpr = Select
<$> selectList
<*> fromClause
<*> optionMaybe whereClause
<*> option [] groupByClause
<*> optionMaybe having
<*> option [] orderByClause
eval :: ValueExpr -> String
eval (Iden s) = s
evalWhere :: Maybe ValueExpr -> Maybe Database -> String -> [[(Int,String, Datatype, String)]]
evalWhere (Just expr) db tname = find (Right expr) db tname
evalWhere (Nothing) db tname = find (Right (BoolLit True)) db tname
evalOrderBy :: [ValueExpr]-> [[(Int,String, Datatype, String)]] -> [[(Int,String, Datatype, String)]]
evalOrderBy [] out = out
evalOrderBy (x : xs) out = evalOrderBy xs (orderBy (Right x) out)
evalSelect :: [(ValueExpr, Maybe String)] -> [(String,String)]
evalSelect [(Star,Nothing)] = []
evalSelect [] = []
evalSelect (x : xs) = do
case (snd x) of
Nothing -> (eval (fst x),eval (fst x)) : evalSelect xs
Just y -> (eval (fst x),y) : evalSelect xs
evaluateQuery :: Either ParseError QueryExpr -> Maybe Database -> [[(Int,String, Datatype, String)]]
evaluateQuery (Right expr) db = do
let out1 = evalWhere (qeWhere expr) db (eval (qefromClause expr))
let out2 = evalOrderBy (qeOrderBy expr) out1
select (evalSelect (qeSelectList expr)) out2