packages feed

hsparql 0.3.1 → 0.3.2

raw patch · 5 files changed

+394/−289 lines, 5 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 a => Database.HSparql.QueryGenerator.QueryShow [a]
+ Database.HSparql.QueryGenerator: bind :: Expr -> Variable -> Query Pattern
+ Database.HSparql.QueryGenerator: class (TermLike a) => ObjectTermLike a
+ Database.HSparql.QueryGenerator: class (TermLike a) => PredicateTermLike a
+ Database.HSparql.QueryGenerator: class (TermLike a) => SubjectTermLike a
+ Database.HSparql.QueryGenerator: class TermLike a where expr = VarOrTermExpr . varOrTerm
+ Database.HSparql.QueryGenerator: expr :: TermLike a => a -> Expr
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike (Data.Text.Internal.Text, Data.Text.Internal.Text)
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike (Data.Text.Internal.Text, Database.HSparql.QueryGenerator.IRIRef)
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Data.RDF.Types.Node
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Data.Text.Internal.Text
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Database.HSparql.QueryGenerator.BlankNodePattern
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Database.HSparql.QueryGenerator.Expr
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Database.HSparql.QueryGenerator.IRIRef
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Database.HSparql.QueryGenerator.VarOrNode
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike Database.HSparql.QueryGenerator.Variable
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike GHC.Integer.Type.Integer
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.ObjectTermLike GHC.Types.Bool
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.PredicateTermLike Database.HSparql.QueryGenerator.IRIRef
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.PredicateTermLike Database.HSparql.QueryGenerator.Variable
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow Database.HSparql.QueryGenerator.BlankNodePattern
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow Database.HSparql.QueryGenerator.DynamicPredicateObject
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow [Database.HSparql.QueryGenerator.Pattern]
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow [Database.HSparql.QueryGenerator.Prefix]
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow [Database.HSparql.QueryGenerator.VarOrTerm]
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.QueryShow [Database.HSparql.QueryGenerator.Variable]
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.SubjectTermLike Database.HSparql.QueryGenerator.BlankNodePattern
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.SubjectTermLike Database.HSparql.QueryGenerator.IRIRef
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.SubjectTermLike Database.HSparql.QueryGenerator.Variable
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.TermLike Data.RDF.Types.Node
+ Database.HSparql.QueryGenerator: instance Database.HSparql.QueryGenerator.TermLike Database.HSparql.QueryGenerator.BlankNodePattern
+ Database.HSparql.QueryGenerator: instance GHC.Show.Show Database.HSparql.QueryGenerator.DynamicObject
+ Database.HSparql.QueryGenerator: instance GHC.Show.Show Database.HSparql.QueryGenerator.DynamicPredicate
+ Database.HSparql.QueryGenerator: mkPredicateObject :: (PredicateTermLike a, ObjectTermLike b, QueryShow a, QueryShow b, Show a, Show b) => a -> b -> DynamicPredicateObject
+ Database.HSparql.QueryGenerator: type BlankNodePattern = [DynamicPredicateObject]
+ Database.HSparql.QueryGenerator: varOrTerm :: TermLike a => a -> VarOrTerm
- Database.HSparql.QueryGenerator: askTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern
+ Database.HSparql.QueryGenerator: askTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
- Database.HSparql.QueryGenerator: constructTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern
+ Database.HSparql.QueryGenerator: constructTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
- Database.HSparql.QueryGenerator: triple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern
+ Database.HSparql.QueryGenerator: triple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
- Database.HSparql.QueryGenerator: updateTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern
+ Database.HSparql.QueryGenerator: updateTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern

Files

Database/HSparql/Connection.hs view
@@ -15,7 +15,7 @@ import Text.XML.Light import Database.HSparql.QueryGenerator import Text.RDF.RDF4H.TurtleParser-import Data.RDF+import qualified Data.RDF as RDF import qualified Data.Text as T import qualified Data.Text.Encoding as E import qualified Data.ByteString.Char8 as B@@ -26,9 +26,9 @@ type EndPoint = String  -- |Local representations of incoming XML results.-data BindingValue = Bound Data.RDF.Node    -- ^RDF Node (UNode, BNode, LNode)+data BindingValue = Bound RDF.Node    -- ^RDF Node (UNode, BNode, LNode)                   | Unbound       -- ^Unbound result value-  deriving (Show, Eq)+                  deriving (Show, Eq)  -- |Base 'QName' for results with a SPARQL-result URI specified. sparqlResult :: String -> QName@@ -38,34 +38,34 @@ --  table storing the bindings for each variable in each row. structureContent :: String -> Maybe [[BindingValue]] structureContent s =-    do e <- doc-       return $ map (projectResult $ vars e) $ findElements (sparqlResult "result") e-    where doc :: Maybe Element-          doc = parseXMLDoc s+  do e <- doc+     return $ map (projectResult $ vars e) $ findElements (sparqlResult "result") e+  where doc :: Maybe Element+        doc = parseXMLDoc s -          vars :: Element -> [String]-          vars = mapMaybe (findAttr $ unqual "name") . findElements (sparqlResult "variable")+        vars :: Element -> [String]+        vars = mapMaybe (findAttr $ unqual "name") . findElements (sparqlResult "variable") -          projectResult :: [String] -> Element -> [BindingValue]-          projectResult vs e = map pVar vs-             where pVar v   = maybe Unbound (value . head . elChildren) $ filterElement (pred v) e-                   pred v e = isJust $ do a <- findAttr (unqual "name") e-                                          guard $ a == v+        projectResult :: [String] -> Element -> [BindingValue]+        projectResult vs e = map pVar vs+          where pVar v = maybe Unbound (value . head . elChildren) $ filterElement (pred_ v) e+                pred_ v e' = isJust $ do a <- findAttr (unqual "name") e'+                                         guard $ a == v -          value :: Element -> BindingValue-          value e =-            case qName (elName e) of-              "uri"     -> Bound $ Data.RDF.unode $ (T.pack $ strContent e)-              "literal" -> case findAttr (unqual "datatype") e of-                             Just dt -> Bound $ Data.RDF.lnode $ Data.RDF.typedL (T.pack $ strContent e) (T.pack dt)-                             Nothing -> case findAttr langAttr e of-                                          Just lang -> Bound $ Data.RDF.lnode $ Data.RDF.plainLL (T.pack $ strContent e) (T.pack lang)-                                          Nothing   -> Bound $ Data.RDF.lnode $ Data.RDF.plainL (T.pack $ strContent e)-              -- TODO: what about blank nodes?-              _         -> Unbound+        value :: Element -> BindingValue+        value e =+          case qName (elName e) of+            "uri"     -> Bound $ RDF.unode $ (T.pack $ strContent e)+            "literal" -> case findAttr (unqual "datatype") e of+                           Just dt -> Bound $ RDF.lnode $ RDF.typedL (T.pack $ strContent e) (T.pack dt)+                           Nothing -> case findAttr langAttr e of+                                        Just lang_ -> Bound $ RDF.lnode $ RDF.plainLL (T.pack $ strContent e) (T.pack lang_)+                                        Nothing    -> Bound $ RDF.lnode $ RDF.plainL (T.pack $ strContent e)+            -- TODO: what about blank nodes?+            _         -> Unbound -          langAttr :: QName-          langAttr = blank_name { qName = "lang", qPrefix = Just "xml" }+        langAttr :: QName+        langAttr = blank_name { qName = "lang", qPrefix = Just "xml" }  -- |Parses the response from a SPARQL ASK query. Either "true" or "false" is expected parseAsk :: String -> Bool@@ -73,8 +73,7 @@   | (s' == "true" || s' == "yes") = True   | (s' == "false"|| s' == "no")  = False   | otherwise = error $ "Unexpected Ask response: " ++ s- where-  s' = reverse $ dropWhile (=='\n') $ reverse s+  where s' = reverse $ dropWhile (=='\n') $ reverse s  -- |Parses the response from a SPARQL UPDATE query.  An empty body is expected parseUpdate :: String -> Bool@@ -86,74 +85,71 @@ --  'Variable's in the 'SelectQuery' action. selectQuery :: Database.HSparql.Connection.EndPoint -> Query SelectQuery -> IO (Maybe [[BindingValue]]) selectQuery ep q = do-    let uri      = ep ++ "?" ++ urlEncodeVars [("query", createSelectQuery q)]-        h1 = mkHeader HdrAccept "application/sparql-results+xml"-        h2 = mkHeader HdrUserAgent "hsparql-client"-        request = Request { rqURI = fromJust $ parseURI uri-                          , rqHeaders = [h1,h2]-                          , rqMethod = GET-                          , rqBody = ""-                          }-    response <- simpleHTTP request >>= getResponseBody-    return $ structureContent response+  let uri = ep ++ "?" ++ urlEncodeVars [("query", createSelectQuery q)]+      h1 = mkHeader HdrAccept "application/sparql-results+xml"+      h2 = mkHeader HdrUserAgent "hsparql-client"+      request = Request { rqURI = fromJust $ parseURI uri+                        , rqHeaders = [h1,h2]+                        , rqMethod = GET+                        , rqBody = ""+                        }+  response <- simpleHTTP request >>= getResponseBody+  return $ structureContent response  -- |Connect to remote 'EndPoint' and find all possible bindings for the --  'Variable's in the 'SelectQuery' action. askQuery :: Database.HSparql.Connection.EndPoint -> Query AskQuery -> IO Bool askQuery ep q = do-    let uri = ep ++ "?" ++ urlEncodeVars [("query", createAskQuery q)]-        hdr1 = Header HdrUserAgent "hsparql-client"-        hdr2 = Header HdrAccept "text/plain"-        hdr3 = Header HdrAccept "text/boolean"-        hdr4 = Header HdrAcceptCharset "utf-8"-        request  = insertHeaders [hdr1,hdr2,hdr3,hdr4] (getRequest uri)-    response <- simpleHTTP request >>= getResponseBody-    return $ parseAsk response-+  let uri = ep ++ "?" ++ urlEncodeVars [("query", createAskQuery q)]+      hdr1 = Header HdrUserAgent "hsparql-client"+      hdr2 = Header HdrAccept "text/plain"+      hdr3 = Header HdrAccept "text/boolean"+      hdr4 = Header HdrAcceptCharset "utf-8"+      request  = insertHeaders [hdr1,hdr2,hdr3,hdr4] (getRequest uri)+  response <- simpleHTTP request >>= getResponseBody+  return $ parseAsk response  -- |Connect to remote 'EndPoint' and find all possible bindings for the --  'Variable's in the 'SelectQuery' action. updateQuery :: Database.HSparql.Connection.EndPoint -> Query UpdateQuery -> IO Bool updateQuery ep q = do-    let uri = ep-        body = createUpdateQuery q-        h1 = mkHeader HdrContentLength $ show (length body)-        h2 = mkHeader HdrContentType "application/sparql-update"-        h3 = mkHeader HdrUserAgent "hsparql-client"-        request = Request { rqURI = fromJust $ parseURI uri-                          , rqHeaders = [h1,h2,h3]-                          , rqMethod = POST-                          , rqBody = body-                          }-    response <- simpleHTTP request >>= getResponseBody+  let uri = ep+      body = createUpdateQuery q+      h1 = mkHeader HdrContentLength $ show (length body)+      h2 = mkHeader HdrContentType "application/sparql-update"+      h3 = mkHeader HdrUserAgent "hsparql-client"+      request = Request { rqURI = fromJust $ parseURI uri+                        , rqHeaders = [h1,h2,h3]+                        , rqMethod = POST+                        , rqBody = body+                        }+  response <- simpleHTTP request >>= getResponseBody --    return $ structureContent response-    return $ parseUpdate response-+  return $ parseUpdate response  -- |Connect to remote 'EndPoint' and construct 'TriplesGraph' from given --  'ConstructQuery' action. /Provisional implementation/.-constructQuery :: (Rdf a) => Database.HSparql.Connection.EndPoint -> Query ConstructQuery -> IO (RDF a)+constructQuery :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> Query ConstructQuery -> IO (RDF.RDF a) constructQuery ep q = do-    let uri      = ep ++ "?" ++ urlEncodeVars [("query", createConstructQuery q)]-    rdfGraph <- httpCallForRdf uri-    case rdfGraph of-      Left e -> error $ show e-      Right graph -> return graph-   +  let uri = ep ++ "?" ++ urlEncodeVars [("query", createConstructQuery q)]+  rdfGraph <- httpCallForRdf uri+  case rdfGraph of+    Left e -> error $ show e+    Right graph -> return graph  -- |Connect to remote 'EndPoint' and construct 'TriplesGraph' from given --  'ConstructQuery' action. /Provisional implementation/.-describeQuery :: (Rdf a) => Database.HSparql.Connection.EndPoint -> Query DescribeQuery -> IO (RDF a)+describeQuery :: (RDF.Rdf a) => Database.HSparql.Connection.EndPoint -> Query DescribeQuery -> IO (RDF.RDF a) describeQuery ep q = do-    let uri      = ep ++ "?" ++ urlEncodeVars [("query", createDescribeQuery q)]-    rdfGraph <- httpCallForRdf uri-    case rdfGraph of-      Left e -> error $ show e-      Right graph -> return graph-    +  let uri = ep ++ "?" ++ urlEncodeVars [("query", createDescribeQuery q)]+  rdfGraph <- httpCallForRdf uri+  case rdfGraph of+    Left e -> error $ show e+    Right graph -> return graph+ -- |Takes a generated uri and makes simple HTTP request, -- asking for RDF N3 serialization. Returns either 'ParseFailure' or 'RDF'-httpCallForRdf :: Rdf a => String -> IO (Either ParseFailure (RDF a))+httpCallForRdf :: RDF.Rdf a => String -> IO (Either RDF.ParseFailure (RDF.RDF a)) httpCallForRdf uri = do   let h1 = mkHeader HdrUserAgent "hsparql-client"       h2 = mkHeader HdrAccept "text/turtle"@@ -163,4 +159,4 @@                           , rqBody = ""                           }   response <- simpleHTTP request >>= getResponseBody-  return $ parseString (TurtleParser Nothing Nothing) $ E.decodeUtf8 (B.pack response)+  return $ RDF.parseString (TurtleParser Nothing Nothing) $ E.decodeUtf8 (B.pack response)
Database/HSparql/QueryGenerator.hs view
@@ -1,85 +1,95 @@+{-# LANGUAGE ExistentialQuantification #-}  -- |The query generator DSL for SPARQL, used when connecting to remote --  endpoints. module Database.HSparql.QueryGenerator-    ( -- * Creating Queries-      createSelectQuery-    , createConstructQuery-    , createAskQuery-    , createUpdateQuery-    , createDescribeQuery-    -- * Query Actions-    , prefix-    , var-    , Database.HSparql.QueryGenerator.triple-    , constructTriple-    , askTriple-    , updateTriple-    , describeIRI-    , optional-    , union-    , filterExpr+  ( -- * Creating Queries+    createSelectQuery+  , createConstructQuery+  , createAskQuery+  , createUpdateQuery+  , createDescribeQuery+  -- * Query Actions+  , prefix+  , var+  , Database.HSparql.QueryGenerator.triple+  , mkPredicateObject+  , constructTriple+  , askTriple+  , updateTriple+  , describeIRI+  , optional+  , union+  , filterExpr+  , bind -    -- ** Duplicate handling-    , distinct-    , reduced+  -- ** Duplicate handling+  , distinct+  , reduced -    -- ** Limit handling-    , limit+  -- ** Limit handling+  , limit -    -- ** Order handling-    , orderNext-    , orderNextAsc-    , orderNextDesc+  -- ** Order handling+  , orderNext+  , orderNextAsc+  , orderNextDesc -    -- ** Auxiliary-    , (.:.)-    , iriRef+  -- ** Auxiliary+  , (.:.)+  , iriRef -    -- * Term Manipulation+  -- * Term Manipulation -    -- ** Operations-    , (.+.), (.-.), (.*.), (./.), (.&&.), (.||.)+  -- ** Operations+  , (.+.), (.-.), (.*.), (./.), (.&&.), (.||.) -    -- ** Relations-    , (.==.), (.!=.), (.<.), (.>.), (.<=.), (.>=.)+  -- ** Relations+  , (.==.), (.!=.), (.<.), (.>.), (.<=.), (.>=.) -    -- ** Negation-    , notExpr+  -- ** Negation+  , notExpr -    -- ** Builtin Functions-    , str-    , lang-    , langMatches-    , datatype-    , bound-    , sameTerm-    , isIRI-    , isURI-    , isBlank-    , isLiteral-    , regex, regexOpts+  -- ** Builtin Functions+  , str+  , lang+  , langMatches+  , datatype+  , bound+  , sameTerm+  , isIRI+  , isURI+  , isBlank+  , isLiteral+  , regex, regexOpts -    -- * Printing Queries-    , qshow+  -- * Printing Queries+  , qshow -    -- * Types-    , Query-    , Variable-    , VarOrNode(..)-    , Pattern-    , SelectQuery(..)-    , ConstructQuery(..)-    , AskQuery(..)-    , UpdateQuery(..)-    , DescribeQuery(..)-    )+  -- * Types+  , Query+  , Variable+  , VarOrNode(..)+  , BlankNodePattern+  , Pattern+  , SelectQuery(..)+  , ConstructQuery(..)+  , AskQuery(..)+  , UpdateQuery(..)+  , DescribeQuery(..)++  -- * Classes+  , TermLike (..)+  , SubjectTermLike+  , PredicateTermLike+  , ObjectTermLike+  ) where  import Control.Monad.State import Data.List (intercalate) import qualified Data.Text as T-import Data.RDF+import qualified Data.RDF as RDF  -- State monads @@ -94,50 +104,52 @@ -- |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 = queryVars query , queryType = SelectType }+  where specifyVars :: Query ()+        specifyVars = do+          query <- q+          modify $ \s -> s { vars = queryVars query , queryType = SelectType }  -- |Execute a 'Construct Query' action, returning the 'String' representation of the query. createConstructQuery :: Query ConstructQuery -> String createConstructQuery q = execQuery specifyType qshow-    where specifyType :: Query ()-          specifyType = do-           query <- q-           modify $ \s -> s { constructTriples = queryConstructs query, queryType = ConstructType }+  where specifyType :: Query ()+        specifyType = do+          query <- q+          modify $ \s -> s { constructTriples = queryConstructs query, queryType = ConstructType }  -- |Execute a 'Ask Query' action, returning the 'String' representation of the query. createAskQuery :: Query AskQuery -> String createAskQuery q = execQuery specifyType qshow-    where specifyType :: Query ()-          specifyType = do-           query <- q-           modify $ \s -> s { askTriples = queryAsk query, queryType = AskType }+  where specifyType :: Query ()+        specifyType = do+          query <- q+          modify $ \s -> s { askTriples = queryAsk query, queryType = AskType }  -- |Execute a 'Update Query' action, returning the 'String' representation of the query. createUpdateQuery :: Query UpdateQuery -> String createUpdateQuery q = execQuery specifyType qshow-    where specifyType :: Query ()-          specifyType = do-           query <- q-           modify $ \s -> s { updateTriples = queryUpdate query, queryType = UpdateType }+  where specifyType :: Query ()+        specifyType = do+          query <- q+          modify $ \s -> s { updateTriples = queryUpdate query, queryType = UpdateType }  -- |Execute a 'Describe Query' action, returning the 'String' representation of the query. createDescribeQuery :: Query DescribeQuery -> String createDescribeQuery q = execQuery specifyType qshow-    where specifyType :: Query ()-          specifyType = do-           query <- q-           modify $ \s -> s { describeURI = Just (queryDescribe query), queryType = DescribeType }+  where specifyType :: Query ()+        specifyType = do+          query <- q+          modify $ \s -> s { describeURI = Just (queryDescribe query), queryType = DescribeType }  -- Manipulate data within monad  -- |Add a prefix to the query, given an IRI reference, and return it. prefix :: T.Text -> IRIRef -> Query Prefix prefix pre (AbsoluteIRI node) = do-                let p = Prefix pre node-                modify $ \s -> s { prefixes = p : prefixes s }-                return p+  let p = Prefix pre node+  modify $ \s -> s { prefixes = p : prefixes s }+  return p+prefix _ _ = error "prefix requires an absolute IRI"  -- |Create and return a variable to the query, usable in later expressions. var :: Query Variable@@ -147,35 +159,34 @@  -- |Restrict the query to only results for which values match constants in this --  triple, or for which the variables can be bound.-triple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern+triple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern triple a b c = do-    let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)-    modify $ \s -> s { pattern = appendPattern t (pattern s) }-    return t-+  let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)+  modify $ \s -> s { pattern = appendPattern t (pattern s) }+  return t -constructTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern+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+  let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)+  modify $ \s -> s { constructTriples = appendTriple t (constructTriples s) }+  return t -askTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern+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+  let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c)+  modify $ \s -> s { askTriples = appendTriple t (askTriples s) }+  return t -updateTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern+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+  let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c) -- TODO: should only allow terms+  modify $ \s -> s { updateTriples = appendTriple t (updateTriples s) }+  return t  describeIRI :: IRIRef -> Query IRIRef describeIRI newIri = do-    modify $ \s -> s { describeURI = Just newIri }-    return newIri+  modify $ \s -> s { describeURI = Just newIri }+  return newIri   -- |Add optional constraints on matches. Variable bindings within the optional@@ -183,29 +194,35 @@ --  optional block. optional :: Query a -> Query Pattern 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-    modify $ \s -> s { pattern = appendPattern option (pattern s) }-    return option+  -- 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+  modify $ \s -> s { pattern = appendPattern option (pattern s) }+  return option  -- |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-        union' = UnionGraphPattern p1 p2-    modify $ \s -> s { pattern = appendPattern union' (pattern s) }-    return union'+union q1 q2 = do+  let p1    = execQuery q1 pattern+      p2    = execQuery q2 pattern+      union' = UnionGraphPattern p1 p2+  modify $ \s -> s { pattern = appendPattern union' (pattern s) }+  return union'  -- |Restrict results to only those for which the given expression is true. filterExpr :: (TermLike a) => a -> Query Pattern filterExpr e = do-    let f = Filter (expr e)-    modify $ \s -> s { pattern = appendPattern f (pattern s) }-    return f+  let f = Filter (expr e)+  modify $ \s -> s { pattern = appendPattern f (pattern s) }+  return f +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+ -- Random auxiliary  -- |Form a 'Node', with the 'Prefix' and reference name.@@ -235,7 +252,7 @@  -- |Alias of 'orderNextAsc'. orderNext :: (TermLike a) => a -> Query ()-orderNext = orderNextAsc +orderNext = orderNextAsc  -- |Order the results, after any previous ordering, based on the term, in --  ascending order.@@ -247,8 +264,8 @@ orderNextDesc :: (TermLike a) => a -> Query () orderNextDesc x = modify $ \s -> s { ordering = ordering s ++ [Desc $ expr x] } --- Permit variables and values to seemlessly be put into argument for 'triple'--- and similar functions+-- |Permit variables and values to seemlessly be put into argument for 'triple'+--  and similar functions class TermLike a where   varOrTerm :: a -> VarOrTerm @@ -261,6 +278,13 @@ instance TermLike IRIRef where   varOrTerm = Term . IRIRefTerm +instance TermLike BlankNodePattern where+  varOrTerm [] = Term (BNode Nothing)+  varOrTerm xs = BlankNodePattern' xs++  expr [] = error "FIXME: blank node expression"+  expr _ = error "cannot use a blank node pattern as an expression"+ instance TermLike Expr where   varOrTerm = error "cannot use an expression as a term"   expr = id@@ -270,23 +294,55 @@   expr = NumericExpr . NumericLiteralExpr  instance TermLike T.Text where-  varOrTerm = Term . RDFLiteralTerm . plainL+  varOrTerm = Term . RDFLiteralTerm . RDF.plainL  instance TermLike (T.Text, T.Text) where-  varOrTerm (s, lang') = Term . RDFLiteralTerm $ plainLL s lang'+  varOrTerm (s, lang') = Term . RDFLiteralTerm $ RDF.plainLL s lang'  instance TermLike (T.Text, IRIRef) where-  varOrTerm (s, ref) = Term . RDFLiteralTerm $ typedL s (getFQN ref)+  varOrTerm (s, ref) = Term . RDFLiteralTerm $ RDF.typedL s (getFQN ref)  instance TermLike Bool where   varOrTerm = Term . BooleanLiteralTerm +instance TermLike RDF.Node where+  varOrTerm n@(RDF.UNode _)  = Term . IRIRefTerm . AbsoluteIRI $ n+  varOrTerm (RDF.LNode lv)   = Term . RDFLiteralTerm $ lv+  varOrTerm (RDF.BNode i)    = Term . BNode . Just $ i+  varOrTerm (RDF.BNodeGen i) = Term . BNode . Just . T.pack . mconcat $ ["genid", show i]+ instance TermLike VarOrNode where-  varOrTerm (Var' v)              = Var v-  varOrTerm (RDFNode n@(UNode _)) = (Term . IRIRefTerm . AbsoluteIRI) n-  varOrTerm (RDFNode (LNode lv))  = (Term . RDFLiteralTerm) lv-  -- TODO: non-exhaustive: missing BNode, BNodeGen+  varOrTerm (Var' v) = Var v+  varOrTerm (RDFNode n) = varOrTerm n +-- |Restriction of TermLike to the role of subject.+class (TermLike a) => SubjectTermLike a++instance SubjectTermLike IRIRef+instance SubjectTermLike Variable+instance SubjectTermLike BlankNodePattern++-- |Restriction of TermLike to the role of predicate.+class (TermLike a) => PredicateTermLike a++instance PredicateTermLike IRIRef+instance PredicateTermLike Variable++-- |Restriction of TermLike to the role of object.+class (TermLike a) => ObjectTermLike a++instance ObjectTermLike IRIRef+instance ObjectTermLike Variable+instance ObjectTermLike BlankNodePattern+instance ObjectTermLike Expr+instance ObjectTermLike Integer+instance ObjectTermLike T.Text+instance ObjectTermLike (T.Text, T.Text)+instance ObjectTermLike (T.Text, IRIRef)+instance ObjectTermLike Bool+instance ObjectTermLike VarOrNode+instance ObjectTermLike RDF.Node+ -- Operations operation :: (TermLike a, TermLike b) => Operation -> a -> b -> Expr operation op x y = NumericExpr $ OperationExpr op (expr x) (expr y)@@ -429,7 +485,6 @@     }  - -- Query representation class QueryShow a where   -- |Convert most query-related types to a 'String', most importantly@@ -442,39 +497,57 @@ data Limit = NoLimit | Limit Int            deriving (Show) -data Prefix = Prefix T.Text Node+data Prefix = Prefix T.Text RDF.Node             deriving (Show)  data Variable = Variable Int               deriving (Show) -data IRIRef = AbsoluteIRI Node+data DynamicPredicate = forall a. (PredicateTermLike a, QueryShow a, Show a) => DynamicPredicate a+data DynamicObject = forall a. (ObjectTermLike a, QueryShow a, Show a) => DynamicObject a+type DynamicPredicateObject = (DynamicPredicate, DynamicObject)+type BlankNodePattern = [DynamicPredicateObject]++instance Show DynamicPredicate where+  show (DynamicPredicate a) = show a++instance Show DynamicObject where+  show (DynamicObject a) = show a++mkPredicateObject :: (PredicateTermLike a, ObjectTermLike b, QueryShow a, QueryShow b, Show a, Show b) => a -> b -> DynamicPredicateObject+mkPredicateObject p o = (DynamicPredicate p, DynamicObject o)++data IRIRef = AbsoluteIRI RDF.Node             | PrefixedName Prefix T.Text             deriving (Show)  iriRef :: T.Text -> IRIRef-iriRef uri = AbsoluteIRI $ unode uri+iriRef uri = AbsoluteIRI $ RDF.unode uri  getFQN :: IRIRef -> T.Text-getFQN (AbsoluteIRI (UNode n)) = n-getFQN (PrefixedName (Prefix _ (UNode n)) s) = T.append n s+getFQN (AbsoluteIRI (RDF.UNode n)) = n+getFQN (PrefixedName (Prefix _ (RDF.UNode n)) s) = T.append n s+-- FIXME+getFQN _ = error "getFQN: input not supported" --- Should support numeric literals, too+-- FIXME: Should support numeric literals, too data GraphTerm = IRIRefTerm IRIRef-               | RDFLiteralTerm LValue+               | RDFLiteralTerm RDF.LValue                | NumericLiteralTerm Integer                | BooleanLiteralTerm Bool+               | BNode (Maybe T.Text)                deriving (Show)  data VarOrTerm = Var Variable                | Term GraphTerm+               | BlankNodePattern' BlankNodePattern                deriving (Show)  -- |Enables programmatic construction of triples where it is not known in -- advance which parts of the triple will be variables and which will be -- 'Node's. data VarOrNode = Var' Variable-               | RDFNode Node+               | RDFNode RDF.Node                deriving (Show)  data Operation = Add | Subtract | Multiply | Divide | And | Or@@ -503,8 +576,10 @@  data Pattern = QTriple VarOrTerm VarOrTerm VarOrTerm              | Filter Expr+             | Bind Expr Variable              | OptionalGraphPattern GroupGraphPattern              | UnionGraphPattern GroupGraphPattern GroupGraphPattern+ data GroupGraphPattern = GroupGraphPattern [Pattern]  data OrderBy = Asc Expr@@ -555,9 +630,13 @@   -- QueryShow instances-instance (QueryShow a) => QueryShow [a] where-  qshow xs = unwords $ map qshow xs+instance QueryShow BlankNodePattern where+  qshow [] = "[]"+  qshow xs = intercalate ", " $ fmap qshow xs +instance QueryShow DynamicPredicateObject where+  qshow (DynamicPredicate p, DynamicObject o) = mconcat ["[", qshow p, " ", qshow o, "]"]+ instance QueryShow Duplicates where   qshow NoLimits = ""   qshow Distinct = "DISTINCT"@@ -567,15 +646,29 @@   qshow NoLimit   = ""   qshow (Limit n) = "Limit " ++ show n -instance QueryShow Node where-  qshow (UNode n) = "<" ++ T.unpack n ++ ">"+instance QueryShow RDF.Node where+  qshow (RDF.UNode n) = "<" ++ T.unpack n ++ ">"+  qshow (RDF.BNode n) = "_:" ++ T.unpack n+  qshow (RDF.BNodeGen i) = "_:genid" ++ show i+  qshow (RDF.LNode n) = qshow n +instance QueryShow RDF.LValue where+  qshow (RDF.PlainL lit)       = T.unpack . T.concat $ ["\"", escapeSpecialChar lit, "\""]+  qshow (RDF.PlainLL lit lang_) = T.unpack . T.concat $ ["\"", escapeSpecialChar lit, "\"@", lang_]+  qshow (RDF.TypedL lit dtype) = T.unpack . T.concat $ ["\"", escapeSpecialChar lit, "\"^^<", dtype, ">"]+ instance QueryShow Prefix where   qshow (Prefix pre ref) = "PREFIX " ++ (T.unpack pre) ++ ": " ++ qshow ref +instance QueryShow [Prefix] where+  qshow = unwords . fmap qshow+ instance QueryShow Variable where   qshow (Variable v) = "?x" ++ show v +instance QueryShow [Variable] where+  qshow = unwords . fmap qshow+ instance QueryShow IRIRef where   qshow (AbsoluteIRI n) = qshow n   qshow (PrefixedName (Prefix pre _) s) = (T.unpack pre) ++ ":" ++ (T.unpack s)@@ -584,22 +677,23 @@   qshow (Just r) = qshow r   qshow Nothing = "" -instance QueryShow LValue where-  qshow (PlainL s)        = "\"" ++ (T.unpack $ escapeQuotes s) ++ "\""-  qshow (PlainLL s lang') = "\"" ++ (T.unpack $ escapeQuotes s) ++ "\"@" ++ (T.unpack lang')-  qshow (TypedL s ref)    = "\"" ++ (T.unpack $ escapeQuotes s) ++ "\"^^" ++ "<" ++ (T.unpack ref) ++ ">"- instance QueryShow GraphTerm where   qshow (IRIRefTerm ref)           = qshow ref   qshow (RDFLiteralTerm s)         = qshow s-  qshow (BooleanLiteralTerm True)  = show "true"-  qshow (BooleanLiteralTerm False) = show "false"+  qshow (BooleanLiteralTerm True)  = show ("true" :: String)+  qshow (BooleanLiteralTerm False) = show ("false" :: String)   qshow (NumericLiteralTerm i)     = show i+  qshow (BNode Nothing)            = "[]"+  qshow (BNode (Just i))           = "_:" ++ T.unpack i  instance QueryShow VarOrTerm where   qshow (Var  v) = qshow v   qshow (Term t) = qshow t+  qshow (BlankNodePattern' bn) = qshow bn +instance QueryShow [VarOrTerm] where+  qshow = unwords . fmap qshow+ instance QueryShow Operation where   qshow Add      = "+"   qshow Subtract = "-"@@ -634,22 +728,26 @@   qshow RegexFunc       = "REGEX"  instance QueryShow Expr where-  qshow (VarOrTermExpr vt) = qshow vt-  qshow e = "(" ++ qshow' e ++ ")"-    where qshow' (OrExpr es)        = intercalate " || " $ map qshow es-          qshow' (AndExpr es)       = intercalate " && " $ map qshow es-          qshow' (NegatedExpr e')   = '!' : qshow e'-          qshow' (RelationalExpr rel e1 e2) = qshow e1 ++ qshow rel ++ qshow e2-          qshow' (NumericExpr e')   = qshow e'-          qshow' (BuiltinCall f es) = qshow f ++ "(" ++ intercalate ", " (map qshow es) ++ ")"+  qshow = qshow'+    where qshow' (VarOrTermExpr vt) = qshow vt+          qshow' (OrExpr es)        = wrap $ intercalate " || " $ map qshow es+          qshow' (AndExpr es)       = wrap $ intercalate " && " $ map qshow es+          qshow' (NegatedExpr e')   = wrap $ '!' : qshow e'+          qshow' (RelationalExpr rel e1 e2) = wrap $ qshow e1 ++ qshow rel ++ qshow e2+          qshow' (NumericExpr e')   = wrap $ qshow e'+          qshow' (BuiltinCall f es) = wrap $ qshow f ++ "(" ++ intercalate ", " (map qshow es) ++ ")"+          wrap e = "(" ++ e ++ ")"  instance QueryShow Pattern where-  qshow (QTriple a b c) = qshow [a, b, c] ++ " ."-  qshow (Filter e)     = "FILTER " ++ qshow e ++ " ."-+  qshow (QTriple a b c) = intercalate " " [qshow a, qshow b, qshow c, "."]+  qshow (Filter e)      = "FILTER " ++ qshow e ++ " ."+  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 +instance QueryShow [Pattern] where+  qshow = unwords . fmap qshow+ instance QueryShow GroupGraphPattern where   qshow (GroupGraphPattern ps) = "{" ++ qshow ps ++ "}" @@ -657,20 +755,15 @@   qshow (Asc e)  = "ASC(" ++ qshow e ++ ")"   qshow (Desc e) = "DESC(" ++ qshow e ++ ")" - instance QueryShow QueryForm where-  qshow (SelectForm qd) =  unwords +  qshow (SelectForm qd) =  unwords                         [ "SELECT"-                         , qshow (duplicates qd)-                         , qshow (vars qd)+                        , 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@@ -682,33 +775,43 @@                                       os -> "ORDER BY" : map qshow os                   query = case queryType qd of-                  SelectType -> +                  SelectType ->                    unwords [ qshow (prefixes qd)                            , qshow (SelectForm qd)                            , whereStmt                            , qshow (limits qd)                            ]-                  ConstructType -> +                  ConstructType ->                    unwords [ qshow (prefixes qd)                            , qshow (ConstructForm qd)                            , whereStmt                            ]-                  DescribeType -> +                  DescribeType ->                    unwords [ qshow (prefixes qd)                            , qshow (DescribeForm qd)                            , whereStmt                            ]-                  AskType -> +                  AskType ->                    unwords [ qshow (prefixes qd)                            , qshow (AskForm qd)                            ]-                  UpdateType -> +                  UpdateType ->                    unwords [ qshow (prefixes qd)                            , qshow (UpdateForm qd)                            ]+                  -- FIXME+                  TypeNotSet ->+                    error "instance QueryShow QueryData: TypeNotSet not supported."              in query   -- Internal utilities-escapeQuotes :: T.Text -> T.Text-escapeQuotes = T.replace "\"" "\\\""+escapeSpecialChar :: T.Text -> T.Text+escapeSpecialChar = T.concatMap handleChar+  -- FIXME: probably more cases to handle+  where handleChar '\n' = "\n"+        handleChar '\t' = "\t"+        handleChar '\r' = "\r"+        handleChar '"'  = "\\\""+        handleChar '\\' = "\\\\"+        handleChar c    = T.singleton c
hsparql.cabal view
@@ -1,6 +1,6 @@ Name:          hsparql Homepage:      https://github.com/robstewart57/hsparql-Version:       0.3.1+Version:       0.3.2 Synopsis:      A SPARQL query generator and DSL, and a client to query a SPARQL server. Category:      Database Description:@@ -34,6 +34,7 @@                , text                , network-uri   extensions:  RankNTypes FlexibleInstances OverloadedStrings+  ghc-options: -Wall -Wcompat  test-suite test-hsparql   type:          exitcode-stdio-1.0@@ -53,6 +54,7 @@   hs-source-dirs: Database, tests   other-modules: Database.HSparql.ConnectionTest   extensions:  OverloadedStrings, FlexibleInstances+  ghc-options: -Wall -Wcompat  source-repository head   type:     git
tests/AllTests.hs view
@@ -4,38 +4,38 @@  import Database.HSparql.ConnectionTest -import Control.Concurrent (forkIO,threadDelay)-import Control.Exception.Base (bracket_)-import Network.HTTP.Types (status200, status500)+import Control.Concurrent (forkIO)+import Network.HTTP.Types (status200) import Network.Wai import Network.Wai.Handler.Warp (run) import Test.Framework +main :: IO () main =-  do forkIO $ startServer+  do _ <- forkIO $ startServer      ropts <- interpretArgsOrExit []      defaultMainWithOpts tests ropts      where tests = Database.HSparql.ConnectionTest.testSuite  app :: Application 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%20"-                            -> 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-                        "?query=PREFIX%20example%3A%20%3Chttp%3A%2F%2Fwww.example.com%2F%3E%20PREFIX%20foaf%3A%20%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%3E%20PREFIX%20dbprop%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fproperty%2F%3E%20PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20CONSTRUCT%20%7B%20%3Fx0%20example%3AhasName%20%3Fx1%20.%20%7D%20WHERE%20%7B%3Fx0%20dbprop%3Agenre%20dbpedia%3AWeb_browser%20.%20%3Fx0%20foaf%3Aname%20%3Fx1%20.%7D"-                            -> constructResponse-                        "?query=PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20DESCRIBE%20dbpedia%3AEdinburgh%20WHERE%20%7B%7D"-                            -> describeResponse-                        otherwise-                            -> error $ "Unexpected URI: \n\n" ++ show (rawQueryString 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%20"+                          -> 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+                      "?query=PREFIX%20example%3A%20%3Chttp%3A%2F%2Fwww.example.com%2F%3E%20PREFIX%20foaf%3A%20%3Chttp%3A%2F%2Fxmlns.com%2Ffoaf%2F0.1%2F%3E%20PREFIX%20dbprop%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fproperty%2F%3E%20PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20CONSTRUCT%20%7B%20%3Fx0%20example%3AhasName%20%3Fx1%20.%20%7D%20WHERE%20%7B%3Fx0%20dbprop%3Agenre%20dbpedia%3AWeb_browser%20.%20%3Fx0%20foaf%3Aname%20%3Fx1%20.%7D"+                          -> constructResponse+                      "?query=PREFIX%20dbpedia%3A%20%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2F%3E%20DESCRIBE%20dbpedia%3AEdinburgh%20WHERE%20%7B%7D"+                          -> describeResponse+                      raw_req+                          -> error $ "Unexpected URI: \n\n" ++ show raw_req -       selectResponse = responseFile status200 [("Content-Type", "application/sparql-results+xml")] "tests/fixtures/sparql_select_response.xml" Nothing-       askResponse = responseFile status200 [("Content-Type", "text/plain")] "tests/fixtures/sparql_ask_response.text" Nothing-       constructResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_construct_response.ttl" Nothing-       describeResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_describe_response.ttl" Nothing+     selectResponse = responseFile status200 [("Content-Type", "application/sparql-results+xml")] "tests/fixtures/sparql_select_response.xml" Nothing+     askResponse = responseFile status200 [("Content-Type", "text/plain")] "tests/fixtures/sparql_ask_response.text" Nothing+     constructResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_construct_response.ttl" Nothing+     describeResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_describe_response.ttl" Nothing   startServer :: IO ()
tests/Database/HSparql/ConnectionTest.hs view
@@ -1,16 +1,16 @@ module Database.HSparql.ConnectionTest ( testSuite ) where -import Test.Framework (testGroup)+import Test.Framework (testGroup, Test) import Test.Framework.Providers.HUnit import Test.HUnit  import qualified Data.Map as Map-import qualified Data.Text as T import qualified Data.RDF as RDF  import Database.HSparql.Connection import Database.HSparql.QueryGenerator +testSuite :: [Test.Framework.Test] testSuite = [     testGroup "Database.HSparql.Connection tests" [         testCase "selectQuery" test_selectQuery@@ -20,6 +20,7 @@     ]   ] +test_selectQuery :: IO () test_selectQuery =   let expectedBVars = Just [ [ Bound $ RDF.lnode $ RDF.plainLL "Kazehakase" "en" ]                            , [ Bound $ RDF.lnode $ RDF.plainLL "Netscape Browser" "en" ]@@ -38,33 +39,35 @@               x    <- var               name <- var -              triple x (dbpprop .:. "genre") (resource .:. "Web_browser")-              triple x (foaf .:. "name") name+              _ <- triple x (dbpprop .:. "genre") (resource .:. "Web_browser")+              _ <- triple x (foaf .:. "name") name                return SelectQuery { queryVars = [name] } +test_askQuery :: IO () test_askQuery = do-    bool <- askQuery endPoint query-    assertBool "invalid" bool+  bool <- askQuery endPoint query+  assertBool "invalid" bool -    where endPoint = "http://127.0.0.1:3000"-          query = do-              resource <- prefix "dbpedia" (iriRef "http://dbpedia.org/resource/")-              dbprop  <- prefix "dbprop" (iriRef "http://dbpedia.org/property/")+  where endPoint = "http://127.0.0.1:3000"+        query = do+            resource <- prefix "dbpedia" (iriRef "http://dbpedia.org/resource/")+            dbprop  <- prefix "dbprop" (iriRef "http://dbpedia.org/property/") -              x <- var-              ask <- askTriple x (dbprop .:. "genre") (resource .:. "Web_browser")+            x <- var+            ask <- askTriple x (dbprop .:. "genre") (resource .:. "Web_browser") -              return AskQuery { queryAsk = [ask] }+            return AskQuery { queryAsk = [ask] } +test_constructQuery :: IO () test_constructQuery =-  let expectedGraph :: RDF.TriplesList+  let expectedGraph :: RDF.RDF RDF.TList       expectedGraph = RDF.mkRdf expectedTriples Nothing (RDF.PrefixMappings Map.empty)       expectedTriples = [ RDF.Triple (RDF.unode "http://dbpedia.org/resource/Kazehakase")                                      (RDF.unode "http://www.example.com/hasName")                                      (RDF.lnode $ RDF.plainLL "Kazehakase" "en") ]   in do-    graph <- constructQuery endPoint query :: IO RDF.TriplesList+    graph <- constructQuery endPoint query :: IO (RDF.RDF RDF.TList)     assertBool "RDF does not include the constructed triple" $ RDF.isIsomorphic expectedGraph graph      where endPoint = "http://127.0.0.1:3000"@@ -78,15 +81,16 @@               name <- var                construct <- constructTriple x (example .:. "hasName") name-              triple x (dbpprop .:. "genre") (resource .:. "Web_browser")-              triple x (foaf .:. "name") name+              _ <- triple x (dbpprop .:. "genre") (resource .:. "Web_browser")+              _ <- triple x (foaf .:. "name") name                return ConstructQuery { queryConstructs = [construct] } +test_describeQuery :: IO () test_describeQuery =   let expectedNode = RDF.unode "http://dbpedia.org/resource/Edinburgh"   in do-    graph <- describeQuery endPoint query :: IO RDF.TriplesList+    graph <- describeQuery endPoint query :: IO (RDF.RDF RDF.TList)     assertBool "RDF does not include the required node" $ RDF.rdfContainsNode graph expectedNode      where endPoint = "http://127.0.0.1:3000"