{-# LANGUAGE OverloadedStrings #-} -- | Generate sql queries from JSON. You could use this to query database directly from frontend. Basic sql queries are supported and the resulting sql query is returned in json format. module Data.Serviette ( rawSqlStr , SqlQuery(..) , SqlResponse(..) , SqlResultQuery(..) ) where import Data.ApiDataTypes import Data.Text hiding (concat, foldl, map) import Data.Aeson import TextShow import Data.Maybe import Data.ByteString.Lazy hiding (append, foldl) -- | Extracts the action and appends space extractAction :: Action -> Text extractAction (Action t) = if t == "SELECT" then append t " " else if t == "DELETE" then append t " FROM " else if t == "INSERT" then append t " INTO " else error "Action parameter id wrong" -- | Extracts table name to Text extractTableName :: TableName -> Text extractTableName (TableName t) = t -- | Extracts table column name to Text extractColumnName :: ColumnName -> Text extractColumnName (ColumnName t) = t -- | Extracts Operator to Text extractOperator :: Operator -> Text extractOperator (Operator t) = t -- | Fetches the Action from SqlQuery getActionArg :: SqlQuery -> Action getActionArg q = action q -- | Gets the main table that Action is performed on getSelectTableArg :: SqlQuery -> TableName getSelectTableArg q = selectName q -- | Retrieves the set list from the SqlQuery getSetFieldsArg :: SqlQuery -> Maybe [SetField] getSetFieldsArg q = set q -- | Retrieves the join list from the SqlQuery getJoinTableArg :: SqlQuery -> Maybe [JoinTable] getJoinTableArg q = joinTables q -- | Gets the where condition list getWhereConditionArg :: SqlQuery -> Maybe [WhereCondition] getWhereConditionArg q = whereCondition q -- | Retrieves the result Format getFormatArg :: SqlQuery -> Int getFormatArg q = getFormat $ Format $ format q -- | Formats the join table list formatSetStr :: SetField -> Text formatSetStr j = (foldl append "" (" set " : [(extractColumnName $ columnName j) , " = " , (formatFieldValue $ setFieldValue j) , " ," ])) -- | Formats the join table list formatJoinStr :: JoinTable -> Text formatJoinStr j = foldl append "" (" join " : [(extractTableName $ tablename j) , " on " , (extractColumnName $ field j) , " " ,(extractOperator $ operator j) , " " , (extractTableName $ withTable j) , "." , (extractColumnName $ withField j), " " ]) -- | Fetches field value depending on field type formatFieldValue :: FieldValue -> Text formatFieldValue a = case a of IntField x -> showt x TextField x -> showt x DateField x -> showt x -- | Formats WhereCondition to Text formatWhereConditionStr :: WhereCondition -> Text formatWhereConditionStr j = foldl append " " (" where " : [ (extractTableName $ whereTableName j), "." , (extractColumnName $ whereField j) , " " ,(extractOperator $ whereOperator j) , " " , (formatFieldValue $ whereFieldValue j)]) -- | Creates final SqlResultQuery type formatToSqlResultQueryType sql = SqlResultQuery (getActionArg sql) (getSelectTableArg sql) (getSetFieldsArg sql) (getJoinTableArg sql) (getWhereConditionArg sql) -- | Returns errors for current query getErrors :: SqlQuery -> Text getErrors s = t where t = case action s of Action "SELECT" | isJust (set s) -> " Do not use SET in SELECT query " | Data.Text.null (extractTableName $ selectName s) -> " You are missing the FROM table name in SELECT statement " | otherwise -> "" Action "DELETE" | isJust (joinTables s) -> " Do not use joins in DELETE query " | otherwise -> "" Action "UPDATE" | isJust (joinTables s) -> " Do not use joins in UPDATE query " | otherwise -> "" Action "INSERT" | isJust (joinTables s) -> " Do not use joins in UPDATE query " | otherwise -> "" -- | Returns possible warnings for current query getWarnings :: SqlQuery -> Text getWarnings s = t where t = case action s of Action "SELECT" | isNothing (whereCondition s) -> " You are probably missing WHERE statement " | otherwise -> "" Action "DELETE" | isNothing (whereCondition s) -> " You are probably missing WHERE statement " | otherwise -> "" Action "UPDATE" | isNothing (whereCondition s) -> " You are missing WHERE statement " | otherwise -> "" Action "INSERT" | isNothing (set s) -> " You are missing the SET statement " | otherwise -> "" -- | Returns json with sql query and errors and warnings if any rawSqlStr :: SqlQuery -> ByteString rawSqlStr s = encode $ SqlResponse {response = alltext, errors = getErrors s , warnings = getWarnings s} where alltext = foldl append "" [(extractAction $ getAction sql) ,(extractTableName $ getSelectTable sql) , setFields , joins , whereConditions ] setFields = case getSetFields sql of Just x -> Data.Text.init $ foldl append "" $ fmap formatSetStr x Nothing -> "" joins = case getJoins sql of Just x -> foldl append "" $ fmap formatJoinStr x Nothing -> "" whereConditions = case getWhereCondition sql of Just x -> foldl append "" $ fmap formatWhereConditionStr x Nothing -> "" sql = formatToSqlResultQueryType s