packages feed

hsparql 0.3.4 → 0.3.5

raw patch · 3 files changed

+141/−57 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow Database.HSparql.QueryGenerator.QueryForm
+ Database.HSparql.QueryGenerator: askTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
+ Database.HSparql.QueryGenerator: bind_ :: Expr -> Variable -> Query ()
+ Database.HSparql.QueryGenerator: constructTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
+ Database.HSparql.QueryGenerator: data Prefix
+ Database.HSparql.QueryGenerator: describeIRI_ :: IRIRef -> Query ()
+ Database.HSparql.QueryGenerator: distinct_ :: Query ()
+ Database.HSparql.QueryGenerator: filterExpr_ :: (TermLike a) => a -> Query ()
+ Database.HSparql.QueryGenerator: groupBy_ :: (TermLike a) => a -> Query ()
+ Database.HSparql.QueryGenerator: instance GHC.Classes.Eq Database.HSparql.QueryGenerator.Prefix
+ Database.HSparql.QueryGenerator: limit_ :: Int -> Query ()
+ Database.HSparql.QueryGenerator: optional_ :: Query a -> Query ()
+ Database.HSparql.QueryGenerator: reduced_ :: Query ()
+ Database.HSparql.QueryGenerator: subQuery :: Query SelectQuery -> Query Pattern
+ Database.HSparql.QueryGenerator: subQuery_ :: Query SelectQuery -> Query ()
+ Database.HSparql.QueryGenerator: triple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
+ Database.HSparql.QueryGenerator: union_ :: Query a -> Query b -> Query ()
+ Database.HSparql.QueryGenerator: updateTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()

Files

Database/HSparql/QueryGenerator.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ExistentialQuantification, OverloadedLists #-}  -- |The query generator DSL for SPARQL, used when connecting to remote --  endpoints.@@ -12,29 +12,30 @@   -- * Query Actions   , prefix   , var-  , Database.HSparql.QueryGenerator.triple+  , Database.HSparql.QueryGenerator.triple, triple_   , mkPredicateObject-  , constructTriple-  , askTriple-  , updateTriple-  , describeIRI-  , optional-  , union-  , filterExpr-  , bind+  , constructTriple, constructTriple_+  , askTriple, askTriple_+  , updateTriple, updateTriple_+  , describeIRI, describeIRI_+  , optional, optional_+  , union, union_+  , filterExpr, filterExpr_+  , bind, bind_+  , subQuery, subQuery_   , select   , selectVars   , as    -- ** Duplicate handling-  , distinct-  , reduced+  , distinct, distinct_+  , reduced, reduced_    -- ** Limit handling-  , limit+  , limit, limit_    -- ** Groups handling-  , groupBy+  , groupBy, groupBy_    -- ** Order handling   , orderNext@@ -81,6 +82,7 @@    -- * Types   , Query+  , Prefix   , Variable   , VarOrNode(..)   , BlankNodePattern@@ -100,8 +102,11 @@   ) where -import Control.Monad.State-import Data.List (intercalate)+import           Control.Monad.State+import           Data.List (intercalate, intersperse)+import qualified Data.List as L+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NE import qualified Data.Text as T import qualified Data.RDF as RDF @@ -110,22 +115,28 @@ -- |The 'State' monad applied to 'QueryData'. type Query a = State QueryData a +-- |Execute a 'Query' action, starting with initial 'QueryData', then process+-- the resulting 'QueryData'.+execQuery :: QueryData -> Query a -> (QueryData -> b) -> b+execQuery qd q f = f $ execState q qd+ -- |Execute a 'Query' action, starting with the empty 'queryData', then process -- the resulting 'QueryData'.-execQuery :: Query a -> (QueryData -> b) -> b-execQuery q f = f $ execState q queryData+execQuery0 :: Query a -> (QueryData -> b) -> b+execQuery0 = execQuery queryData  -- |Execute a 'Select Query' action, returning the 'String' representation of the query. createSelectQuery :: Query SelectQuery -> String-createSelectQuery q = execQuery specifyVars qshow-  where specifyVars :: Query ()-        specifyVars = do-          query <- q-          modify $ \s -> s { vars = queryExpr query, queryType = SelectType }+createSelectQuery q = execQuery0 (specifyVars q) qshow +specifyVars :: Query SelectQuery -> Query ()+specifyVars q = do+  query <- q+  modify $ \s -> s { vars = queryExpr query, queryType = SelectType }+ -- |Execute a 'Construct Query' action, returning the 'String' representation of the query. createConstructQuery :: Query ConstructQuery -> String-createConstructQuery q = execQuery specifyType qshow+createConstructQuery q = execQuery0 specifyType qshow   where specifyType :: Query ()         specifyType = do           query <- q@@ -133,7 +144,7 @@  -- |Execute a 'Ask Query' action, returning the 'String' representation of the query. createAskQuery :: Query AskQuery -> String-createAskQuery q = execQuery specifyType qshow+createAskQuery q = execQuery0 specifyType qshow   where specifyType :: Query ()         specifyType = do           query <- q@@ -141,7 +152,7 @@  -- |Execute a 'Update Query' action, returning the 'String' representation of the query. createUpdateQuery :: Query UpdateQuery -> String-createUpdateQuery q = execQuery specifyType qshow+createUpdateQuery q = execQuery0 specifyType qshow   where specifyType :: Query ()         specifyType = do           query <- q@@ -149,7 +160,7 @@  -- |Execute a 'Describe Query' action, returning the 'String' representation of the query. createDescribeQuery :: Query DescribeQuery -> String-createDescribeQuery q = execQuery specifyType qshow+createDescribeQuery q = execQuery0 specifyType qshow   where specifyType :: Query ()         specifyType = do           query <- q@@ -167,9 +178,11 @@  -- |Create and return a variable to the query, usable in later expressions. var :: Query Variable-var = do n <- gets varsIdx+var = do qis <- gets (NE.init . subQueryIdx)+         n <- gets varsIdx+         let sqis = NE.fromList (qis ++ [n])          modify $ \s -> s { varsIdx = n + 1 }-         return $ Variable n+         return $ Variable sqis  -- |Restrict the query to only results for which values match constants in this --  triple, or for which the variables can be bound.@@ -179,29 +192,44 @@   modify $ \s -> s { pattern = appendPattern t (pattern s) }   return t +triple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()+triple_ a b c = void $ triple a b c+ constructTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern constructTriple a b c = do   let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)   modify $ \s -> s { constructTriples = appendTriple t (constructTriples s) }   return t +constructTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()+constructTriple_ a b c = void $ constructTriple a b c+ askTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern askTriple a b c = do   let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)   modify $ \s -> s { askTriples = appendTriple t (askTriples s) }   return t +askTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()+askTriple_ a b c = void $ askTriple a b c+ updateTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern updateTriple a b c = do   let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c) -- TODO: should only allow terms   modify $ \s -> s { updateTriples = appendTriple t (updateTriples s) }   return t +updateTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()+updateTriple_ a b c = void $ updateTriple a b c+ describeIRI :: IRIRef -> Query IRIRef describeIRI newIri = do   modify $ \s -> s { describeURI = Just newIri }   return newIri +describeIRI_ :: IRIRef -> Query ()+describeIRI_ = void . describeIRI+ selectVars :: [Variable] -> Query SelectQuery selectVars vs = return SelectQuery { queryExpr = fmap SelectVar vs } @@ -215,20 +243,26 @@ optional q = do   -- Determine the patterns by executing the action on a blank QueryData, and   -- then pulling the patterns out from there.-  let option  = execQuery q $ OptionalGraphPattern . pattern+  let option  = execQuery0 q $ OptionalGraphPattern . pattern   modify $ \s -> s { pattern = appendPattern option (pattern s) }   return option +optional_ :: Query a -> Query ()+optional_ = void . optional+ -- |Add a union structure to the query pattern. As with 'optional' blocks, --  variables must be defined prior to the opening of any block. union :: Query a -> Query b -> Query Pattern union q1 q2 = do-  let p1    = execQuery q1 pattern-      p2    = execQuery q2 pattern+  let p1    = execQuery0 q1 pattern+      p2    = execQuery0 q2 pattern       union' = UnionGraphPattern p1 p2   modify $ \s -> s { pattern = appendPattern union' (pattern s) }   return union' +union_ :: Query a -> Query b -> Query ()+union_ a b = void $ union a b+ -- |Restrict results to only those for which the given expression is true. filterExpr :: (TermLike a) => a -> Query Pattern filterExpr e = do@@ -236,12 +270,44 @@   modify $ \s -> s { pattern = appendPattern f (pattern s) }   return f +filterExpr_ :: (TermLike a) => a -> Query ()+filterExpr_ = void . filterExpr++-- |Bind the result of an expression to a variable. bind :: Expr -> Variable -> Query Pattern bind e v = do   let b = Bind (expr e) v   modify $ \s -> s { pattern = appendPattern b (pattern s) }   return b +bind_ :: Expr -> Variable -> Query ()+bind_ a b = void $ bind a b++-- |Perform a subquery.+subQuery :: Query SelectQuery -> Query Pattern+subQuery q = do+  -- Manage subquery indexes+  qis <- gets subQueryIdx+  let sqis = qis |> 0+      qis' = NE.fromList $ NE.init qis ++ [NE.last qis + 1]+  -- Execute the subquery action+  let subQueryData0 = queryData { subQueryIdx = sqis }+      subQueryData = execQuery subQueryData0 (specifyVars q) id+  -- Merge prefixes+  prefixesParentQuery <- gets prefixes+  let prefixesSubQuery = prefixes subQueryData+      newPrefixes = prefixesParentQuery `L.union` prefixesSubQuery+  -- Create the subquery pattern and remove prefixes from the subquery+  let sq = SubQuery $ subQueryData { prefixes = [] }+  -- Append the subquery pattern, update the subquery index and the prefixes.+  modify $ \s -> s { pattern = appendPattern sq (pattern s)+                   , subQueryIdx = qis'+                   , prefixes = newPrefixes  }+  return sq++subQuery_ :: Query SelectQuery -> Query ()+subQuery_ = void . subQuery+ -- Random auxiliary  -- |Form a 'Node', with the 'Prefix' and reference name.@@ -256,17 +322,26 @@ distinct = do modify $ \s -> s { duplicates = Distinct }               gets duplicates +distinct_ :: Query ()+distinct_ = void distinct+ -- |Set duplicate handling to 'Reduced'. By default, there are no reductions. reduced :: Query Duplicates reduced = do modify $ \s -> s { duplicates = Reduced }              gets duplicates +reduced_ :: Query ()+reduced_ = void reduced+ -- |Set limit handling to the given value.  By default, there are no limits. --  Note: negative numbers cause no query results to be returned. limit :: Int -> Query Limit limit n = do modify $ \s -> s { limits = Limit n }              gets limits +limit_ :: Int -> Query ()+limit_ = void . limit+ -- Grouping  -- |Divide the solution into one or more groups.@@ -275,6 +350,9 @@   modify $ \s -> s { groups = groups s ++ [GroupBy . expr $ e] }   gets groups +groupBy_ :: (TermLike a) => a -> Query ()+groupBy_ = void . groupBy+ -- Order handling  -- |Alias of 'orderNextAsc'.@@ -518,6 +596,7 @@     , varsIdx    = 0     , vars       = []     , queryType  = TypeNotSet+    , subQueryIdx = [0]     , pattern    = GroupGraphPattern []     , constructTriples = []     , askTriples = []@@ -543,9 +622,9 @@            deriving (Show)  data Prefix = Prefix T.Text RDF.Node-            deriving (Show)+            deriving (Show, Eq) -data Variable = Variable Int+data Variable = Variable (NonEmpty Int)               deriving (Show)  data DynamicPredicate = forall a. (PredicateTermLike a, QueryShow a, Show a) => DynamicPredicate a@@ -653,6 +732,7 @@              | Bind Expr Variable              | OptionalGraphPattern GroupGraphPattern              | UnionGraphPattern GroupGraphPattern GroupGraphPattern+             | SubQuery QueryData  data GroupGraphPattern = GroupGraphPattern [Pattern] @@ -674,6 +754,7 @@     , varsIdx    :: Int     , vars       :: [SelectExpr]     , queryType  :: QueryType+    , subQueryIdx :: NonEmpty Int     , pattern    :: GroupGraphPattern     , constructTriples :: [Pattern] -- QTriple     , askTriples :: [Pattern]@@ -688,8 +769,6 @@  data QueryType = SelectType | ConstructType | AskType | UpdateType | DescribeType | TypeNotSet -data QueryForm = SelectForm QueryData | ConstructForm QueryData | AskForm QueryData | UpdateForm QueryData | DescribeForm QueryData- data ConstructQuery = ConstructQuery     { queryConstructs :: [Pattern] } @@ -740,7 +819,8 @@   qshow = unwords . fmap qshow  instance QueryShow Variable where-  qshow (Variable v) = "?x" ++ show v+  qshow (Variable vs) = "?x" ++ indexes+    where indexes = mconcat . intersperse "_" . fmap show . NE.toList $ vs  instance QueryShow [Variable] where   qshow = unwords . fmap qshow@@ -832,6 +912,7 @@   qshow (Bind e v)      = "BIND(" ++ qshow e ++ " AS " ++ qshow v ++ ")"   qshow (OptionalGraphPattern p)  = "OPTIONAL " ++ qshow p   qshow (UnionGraphPattern p1 p2) = qshow p1 ++ " UNION " ++ qshow p2+  qshow (SubQuery qd)   = intercalate " " ["{", qshow qd, "}"]  instance QueryShow [Pattern] where   qshow = unwords . fmap qshow@@ -854,17 +935,6 @@   qshow [] = ""   qshow os = unwords $ "ORDER BY" : fmap qshow os -instance QueryShow QueryForm where-  qshow (SelectForm qd) =  unwords-                        [ "SELECT"-                        , qshow (duplicates qd)-                        , qshow (vars qd)-                        ]-  qshow (ConstructForm qd) = "CONSTRUCT { " ++ qshow (constructTriples qd) ++ " }"-  qshow (AskForm qd) = "ASK { " ++ qshow (askTriples qd) ++ " }"-  qshow (UpdateForm qd) = "INSERT DATA { " ++ qshow (updateTriples qd) ++ " }"-  qshow (DescribeForm qd) = "DESCRIBE " ++ qshow (describeURI qd)- instance QueryShow QueryData where   qshow qd = query     where prefixDecl = qshow (prefixes qd)@@ -878,27 +948,36 @@           query = case queryType qd of             SelectType ->              unwords' [ prefixDecl-                      , qshow (SelectForm qd)+                      , "SELECT"+                      , qshow (duplicates qd)+                      , qshow (vars qd)                       , whereClause                       , solutionModifier                       ]             ConstructType ->              unwords [ prefixDecl-                     , qshow (ConstructForm qd)+                     , "CONSTRUCT {"+                     , qshow (constructTriples qd)+                     , "}"                      , whereClause                      ]             DescribeType ->              unwords [ prefixDecl-                     , qshow (DescribeForm qd)+                     , "DESCRIBE"+                     , qshow (describeURI qd)                      , whereClause                      ]             AskType ->              unwords [ prefixDecl-                     , qshow (AskForm qd)+                     , "ASK {"+                     , qshow (askTriples qd)+                     , "}"                      ]             UpdateType ->              unwords [ prefixDecl-                     , qshow (UpdateForm qd)+                     , "INSERT DATA {"+                     , qshow (updateTriples qd)+                     , "}"                      ]             -- FIXME             TypeNotSet ->@@ -919,9 +998,14 @@ -- | Alternative version of 'unwords' that avoid adding spaces on empty strings. {-# NOINLINE [1] unwords' #-} unwords'        :: [String] -> String-unwords' []     =  ""-unwords' (w:ws) = w ++ go ws+unwords' []      =  ""+unwords' ("":ws) = unwords' ws+unwords' (w:ws)  = w ++ go ws   where     go []      = ""     go ("":vs) = go vs     go (v:vs)  = ' ' : (v ++ go vs)++-- | Append a element to a 'NonEmpty' list.+(|>) :: NonEmpty a -> a -> NonEmpty a+xs |> x = NE.fromList $ NE.toList xs ++ [x]
hsparql.cabal view
@@ -1,6 +1,6 @@ Name:          hsparql Homepage:      https://github.com/robstewart57/hsparql-Version:       0.3.4+Version:       0.3.5 Synopsis:      A SPARQL query generator and DSL, and a client to query a SPARQL server. Category:      Database Description:
tests/AllTests.hs view
@@ -21,7 +21,7 @@ app req respond = respond $ response req    where      response req_ = case rawQueryString req_ of-                      "?query=PREFIX%20foaf%3A%20%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%3E%20PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fproperty%2F%3E%20PREFIX%20dbprop%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20SELECT%20%20%3Fx1%20WHERE%20%7B%3Fx0%20dbpedia%3Agenre%20dbprop%3AWeb_browser%20.%20%3Fx0%20foaf%3Aname%20%3Fx1%20.%7D"+                      "?query=PREFIX%20foaf%3A%20%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%3E%20PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fproperty%2F%3E%20PREFIX%20dbprop%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20SELECT%20%3Fx1%20WHERE%20%7B%3Fx0%20dbpedia%3Agenre%20dbprop%3AWeb_browser%20.%20%3Fx0%20foaf%3Aname%20%3Fx1%20.%7D"                           -> selectResponse                       "?query=PREFIX%20dbprop%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fproperty%2F%3E%20PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20ASK%20%7B%20%3Fx0%20dbprop%3Agenre%20dbpedia%3AWeb_browser%20.%20%7D"                           -> askResponse