{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}

-- | 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,
    embeddedTriple,
    Database.HSparql.QueryGenerator.triple,
    triple_,
    mkPredicateObject,
    constructTriple,
    constructTriple_,
    askTriple,
    askTriple_,
    updateTriple,
    updateTriple_,
    describeIRI,
    describeIRI_,
    optional,
    optional_,
    service,
    service_,
    union,
    union_,
    filterExpr,
    filterExpr_,
    filterExists,
    filterExists_,
    filterNotExists,
    filterNotExists_,
    bind,
    bind_,
    subQuery,
    subQuery_,
    select,
    selectVars,
    as,

    -- ** Property paths

    -- | SPARQL 1.1 property paths documentation: https://www.w3.org/TR/sparql11-query/#propertypaths
    a,

    -- *** Binary operators

    -- **** Property path binary operators
    (.//.),
    (.|.),

    -- **** Negative property set binary operators
    (..|..),

    -- *** Unary operators

    -- **** Property path unary operators
    inv,
    (*.),
    (+.),
    (?.),

    -- **** Negative property set unary operators
    neg,
    inv',

    -- ** Duplicate handling
    distinct,
    distinct_,
    reduced,
    reduced_,

    -- ** Limit handling
    limit,
    limit_,

    -- ** Groups handling
    groupBy,
    groupBy_,

    -- ** Order handling
    orderNext,
    orderNextAsc,
    orderNextDesc,

    -- ** Auxiliary
    (.:.),
    iriRef,

    -- * Term Manipulation

    -- ** Operations
    (.+.),
    (.-.),
    (.*.),
    (./.),
    (.&&.),
    (.||.),

    -- ** Relations
    (.==.),
    (.!=.),
    (.<.),
    (.>.),
    (.<=.),
    (.>=.),

    -- ** Negation
    notExpr,

    -- ** Builtin aggregation functions
    count,
    sum_,
    min_,
    max_,
    avg,
    groupConcat,

    -- ** Builtin Functions
    str,
    lang,
    langMatches,
    datatype,
    bound,
    sameTerm,
    isIRI,
    isURI,
    isBlank,
    isLiteral,
    regex,
    regexOpts,
    strlen,
    substr,
    ucase,
    lcase,
    strstarts,
    strends,
    contains,
    strbefore,
    strafter,
    abs_,
    round_,
    ceil,
    floor_,
    concat_,
    replace,
    rand,

    -- * Printing Queries
    qshow,

    -- * Types
    Query,
    Prefix,
    Variable,
    VarOrNode (..),
    BlankNodePattern,
    Pattern,
    SelectQuery (..),
    SelectExpr (..),
    ConstructQuery (..),
    AskQuery (..),
    UpdateQuery (..),
    DescribeQuery (..),

    -- * Classes
    TermLike (..),
    SubjectTermLike,
    PredicateTermLike,
    ObjectTermLike,
  )
where

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.RDF as RDF
import qualified Data.Text as T
import qualified Network.URI as URI

-- State monads

-- | 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 :: QueryData -> Query a -> (QueryData -> b) -> b
execQuery QueryData
qd Query a
q QueryData -> b
f = QueryData -> b
f (QueryData -> b) -> QueryData -> b
forall a b. (a -> b) -> a -> b
$ Query a -> QueryData -> QueryData
forall s a. State s a -> s -> s
execState Query a
q QueryData
qd

-- | Execute a 'Query' action, starting with the empty 'queryData', then process
--  the resulting 'QueryData'.
execQuery0 :: Query a -> (QueryData -> b) -> b
execQuery0 :: Query a -> (QueryData -> b) -> b
execQuery0 = QueryData -> Query a -> (QueryData -> b) -> b
forall a b. QueryData -> Query a -> (QueryData -> b) -> b
execQuery QueryData
queryData

-- | Execute a 'Select Query' action, returning the 'String' representation of the query.
createSelectQuery :: Query SelectQuery -> String
createSelectQuery :: Query SelectQuery -> String
createSelectQuery Query SelectQuery
q = Query () -> (QueryData -> String) -> String
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 (Query SelectQuery -> Query ()
specifyVars Query SelectQuery
q) QueryData -> String
forall a. QueryShow a => a -> String
qshow

specifyVars :: Query SelectQuery -> Query ()
specifyVars :: Query SelectQuery -> Query ()
specifyVars Query SelectQuery
q = do
  SelectQuery
query <- Query SelectQuery
q
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {vars :: [SelectExpr]
vars = SelectQuery -> [SelectExpr]
queryExpr SelectQuery
query, queryType :: QueryType
queryType = QueryType
SelectType}

-- | Execute a 'Construct Query' action, returning the 'String' representation of the query.
createConstructQuery :: Query ConstructQuery -> String
createConstructQuery :: Query ConstructQuery -> String
createConstructQuery Query ConstructQuery
q = Query () -> (QueryData -> String) -> String
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query ()
specifyType QueryData -> String
forall a. QueryShow a => a -> String
qshow
  where
    specifyType :: Query ()
    specifyType :: Query ()
specifyType = do
      ConstructQuery
query <- Query ConstructQuery
q
      (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {constructTriples :: [Pattern]
constructTriples = ConstructQuery -> [Pattern]
queryConstructs ConstructQuery
query, queryType :: QueryType
queryType = QueryType
ConstructType}

-- | Execute a 'Ask Query' action, returning the 'String' representation of the query.
createAskQuery :: Query AskQuery -> String
createAskQuery :: Query AskQuery -> String
createAskQuery Query AskQuery
q = Query () -> (QueryData -> String) -> String
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query ()
specifyType QueryData -> String
forall a. QueryShow a => a -> String
qshow
  where
    specifyType :: Query ()
    specifyType :: Query ()
specifyType = do
      AskQuery
query <- Query AskQuery
q
      (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {askTriples :: [Pattern]
askTriples = AskQuery -> [Pattern]
queryAsk AskQuery
query, queryType :: QueryType
queryType = QueryType
AskType}

-- | Execute a 'Update Query' action, returning the 'String' representation of the query.
createUpdateQuery :: Query UpdateQuery -> String
createUpdateQuery :: Query UpdateQuery -> String
createUpdateQuery Query UpdateQuery
q = Query () -> (QueryData -> String) -> String
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query ()
specifyType QueryData -> String
forall a. QueryShow a => a -> String
qshow
  where
    specifyType :: Query ()
    specifyType :: Query ()
specifyType = do
      UpdateQuery
query <- Query UpdateQuery
q
      (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {updateTriples :: [Pattern]
updateTriples = UpdateQuery -> [Pattern]
queryUpdate UpdateQuery
query, queryType :: QueryType
queryType = QueryType
UpdateType}

-- | Execute a 'Describe Query' action, returning the 'String' representation of the query.
createDescribeQuery :: Query DescribeQuery -> String
createDescribeQuery :: Query DescribeQuery -> String
createDescribeQuery Query DescribeQuery
q = Query () -> (QueryData -> String) -> String
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query ()
specifyType QueryData -> String
forall a. QueryShow a => a -> String
qshow
  where
    specifyType :: Query ()
    specifyType :: Query ()
specifyType = do
      DescribeQuery
query <- Query DescribeQuery
q
      (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {describeURI :: Maybe IRIRef
describeURI = IRIRef -> Maybe IRIRef
forall a. a -> Maybe a
Just (DescribeQuery -> IRIRef
queryDescribe DescribeQuery
query), queryType :: QueryType
queryType = 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 :: Text -> IRIRef -> Query Prefix
prefix Text
pre (AbsoluteIRI Node
node) = do
  let p :: Prefix
p = Text -> Node -> Prefix
Prefix Text
pre Node
node
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {prefixes :: [Prefix]
prefixes = Prefix
p Prefix -> [Prefix] -> [Prefix]
forall a. a -> [a] -> [a]
: QueryData -> [Prefix]
prefixes QueryData
s}
  Prefix -> Query Prefix
forall (m :: * -> *) a. Monad m => a -> m a
return Prefix
p
prefix Text
_ IRIRef
_ = String -> Query Prefix
forall a. HasCallStack => String -> a
error String
"prefix requires an absolute IRI"

-- | Create and return a variable to the query, usable in later expressions.
var :: Query Variable
var :: Query Variable
var = do
  [Int]
qis <- (QueryData -> [Int]) -> StateT QueryData Identity [Int]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (NonEmpty Int -> [Int]
forall a. NonEmpty a -> [a]
NE.init (NonEmpty Int -> [Int])
-> (QueryData -> NonEmpty Int) -> QueryData -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryData -> NonEmpty Int
subQueryIdx)
  Int
n <- (QueryData -> Int) -> StateT QueryData Identity Int
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> Int
varsIdx
  let sqis :: NonEmpty Int
sqis = [Int] -> NonEmpty Int
forall a. [a] -> NonEmpty a
NE.fromList ([Int]
qis [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
Item [Int]
n])
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {varsIdx :: Int
varsIdx = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1}
  Variable -> Query Variable
forall (m :: * -> *) a. Monad m => a -> m a
return (Variable -> Query Variable) -> Variable -> Query Variable
forall a b. (a -> b) -> a -> b
$ NonEmpty Int -> Variable
Variable NonEmpty Int
sqis

-- | Create an embedded triple usable in an expression.
--   See SPARQL* at <https://wiki.blazegraph.com/wiki/index.php/Reification_Done_Right>
--   or <https://arxiv.org/abs/1406.3399>.
embeddedTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> EmbeddedTriple
embeddedTriple :: a -> b -> c -> EmbeddedTriple
embeddedTriple a
a b
b c
c = VarOrTerm -> EmbeddedTriple
EmbeddedTriple (VarOrTerm -> EmbeddedTriple) -> VarOrTerm -> EmbeddedTriple
forall a b. (a -> b) -> a -> b
$ VarOrTerm -> VarOrTerm -> VarOrTerm -> VarOrTerm
EmbeddedTriple' (a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm a
a) (b -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm b
b) (c -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm c
c)

-- | Restrict the query to only results for which values match constants in this
--   triple, or for which the variables can be bound.
triple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
triple :: a -> b -> c -> Query Pattern
triple a
a b
b c
c = do
  let t :: Pattern
t = VarOrTerm -> VarOrTerm -> VarOrTerm -> Pattern
QTriple (a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm a
a) (b -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm b
b) (c -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm c
c)
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
t (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
t

triple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
triple_ :: a -> b -> c -> Query ()
triple_ a
a b
b c
c = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ a -> b -> c -> Query Pattern
forall a b c.
(SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) =>
a -> b -> c -> Query Pattern
triple a
a b
b c
c

constructTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
constructTriple :: a -> b -> c -> Query Pattern
constructTriple a
a b
b c
c = do
  let t :: Pattern
t = VarOrTerm -> VarOrTerm -> VarOrTerm -> Pattern
QTriple (a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm a
a) (b -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm b
b) (c -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm c
c)
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {constructTriples :: [Pattern]
constructTriples = Pattern -> [Pattern] -> [Pattern]
forall a. a -> [a] -> [a]
appendTriple Pattern
t (QueryData -> [Pattern]
constructTriples QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
t

constructTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
constructTriple_ :: a -> b -> c -> Query ()
constructTriple_ a
a b
b c
c = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ a -> b -> c -> Query Pattern
forall a b c.
(SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) =>
a -> b -> c -> Query Pattern
constructTriple a
a b
b c
c

askTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
askTriple :: a -> b -> c -> Query Pattern
askTriple a
a b
b c
c = do
  let t :: Pattern
t = VarOrTerm -> VarOrTerm -> VarOrTerm -> Pattern
QTriple (a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm a
a) (b -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm b
b) (c -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm c
c)
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {askTriples :: [Pattern]
askTriples = Pattern -> [Pattern] -> [Pattern]
forall a. a -> [a] -> [a]
appendTriple Pattern
t (QueryData -> [Pattern]
askTriples QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
t

askTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
askTriple_ :: a -> b -> c -> Query ()
askTriple_ a
a b
b c
c = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ a -> b -> c -> Query Pattern
forall a b c.
(SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) =>
a -> b -> c -> Query Pattern
askTriple a
a b
b c
c

updateTriple :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query Pattern
updateTriple :: a -> b -> c -> Query Pattern
updateTriple a
a b
b c
c = do
  let t :: Pattern
t = VarOrTerm -> VarOrTerm -> VarOrTerm -> Pattern
QTriple (a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm a
a) (b -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm b
b) (c -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm c
c) -- TODO: should only allow terms
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {updateTriples :: [Pattern]
updateTriples = Pattern -> [Pattern] -> [Pattern]
forall a. a -> [a] -> [a]
appendTriple Pattern
t (QueryData -> [Pattern]
updateTriples QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
t

updateTriple_ :: (SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) => a -> b -> c -> Query ()
updateTriple_ :: a -> b -> c -> Query ()
updateTriple_ a
a b
b c
c = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ a -> b -> c -> Query Pattern
forall a b c.
(SubjectTermLike a, PredicateTermLike b, ObjectTermLike c) =>
a -> b -> c -> Query Pattern
updateTriple a
a b
b c
c

describeIRI :: IRIRef -> Query IRIRef
describeIRI :: IRIRef -> Query IRIRef
describeIRI IRIRef
newIri = do
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {describeURI :: Maybe IRIRef
describeURI = IRIRef -> Maybe IRIRef
forall a. a -> Maybe a
Just IRIRef
newIri}
  IRIRef -> Query IRIRef
forall (m :: * -> *) a. Monad m => a -> m a
return IRIRef
newIri

describeIRI_ :: IRIRef -> Query ()
describeIRI_ :: IRIRef -> Query ()
describeIRI_ = Query IRIRef -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query IRIRef -> Query ())
-> (IRIRef -> Query IRIRef) -> IRIRef -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IRIRef -> Query IRIRef
describeIRI

selectVars :: [Variable] -> Query SelectQuery
selectVars :: [Variable] -> Query SelectQuery
selectVars [Variable]
vs = SelectQuery -> Query SelectQuery
forall (m :: * -> *) a. Monad m => a -> m a
return SelectQuery :: [SelectExpr] -> SelectQuery
SelectQuery {queryExpr :: [SelectExpr]
queryExpr = (Variable -> SelectExpr) -> [Variable] -> [SelectExpr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Variable -> SelectExpr
SelectVar [Variable]
vs}

select :: [SelectExpr] -> Query SelectQuery
select :: [SelectExpr] -> Query SelectQuery
select [SelectExpr]
es = SelectQuery -> Query SelectQuery
forall (m :: * -> *) a. Monad m => a -> m a
return SelectQuery :: [SelectExpr] -> SelectQuery
SelectQuery {queryExpr :: [SelectExpr]
queryExpr = [SelectExpr]
es}

-- | Add optional constraints on matches. Variable bindings within the optional
--   action are lost, so variables must always be defined prior to opening the
--   optional block.
optional :: Query a -> Query Pattern
optional :: Query a -> Query Pattern
optional Query a
q = do
  -- Determine the patterns by executing the action on a blank QueryData, and
  -- then pulling the patterns out from there.
  let option :: Pattern
option = Query a -> (QueryData -> Pattern) -> Pattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query a
q ((QueryData -> Pattern) -> Pattern)
-> (QueryData -> Pattern) -> Pattern
forall a b. (a -> b) -> a -> b
$ GroupGraphPattern -> Pattern
OptionalGraphPattern (GroupGraphPattern -> Pattern)
-> (QueryData -> GroupGraphPattern) -> QueryData -> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryData -> GroupGraphPattern
pattern
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
option (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
option

optional_ :: Query a -> Query ()
optional_ :: Query a -> Query ()
optional_ = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (Query a -> Query Pattern) -> Query a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query a -> Query Pattern
forall a. Query a -> Query Pattern
optional

-- | Instruct a federated query processor to invoke the portion of a SPARQL
--  query against a remote SPARQL endpoint.
--
--  For example
--
--  > createQuery $ do
--  >   foaf <- prefix "foaf" (iriRef "http://xmlns.com/foaf/0.1/")
--  >
--  >   person    <- var
--  >   name      <- var
--  >
--  >   triple_ (iriRef "http://example.org/myfoaf/I") (foaf .:. "knows") person
--  >
--  >   _ <- service (iriRef "http://people.example.org/sparql") $ do
--  >     triple_ person (foaf .:. "name") name
--  >
--  >   selectVars [name]
--
--   produces the SPARQL query:
--
--  > PREFIX foaf: <http://xmlns.com/foaf/0.1/>
--  > SELECT ?x1 WHERE {
--  >   <http://example.org/myfoaf/I> foaf:knows ?x0 .
--  >   SERVICE <http://people.example.org/sparql> {
--  >     ?x0 foaf:name ?x1 .
--  >   }
--  > }
service ::
  -- | SPARQL endpoint
  IRIRef ->
  -- | SPARQL query to invoke against a remote SPARQL endpoint
  Query a ->
  Query Pattern
service :: IRIRef -> Query a -> Query Pattern
service IRIRef
endpoint Query a
q = do
  -- Determine the patterns by executing the action on a blank QueryData, and
  -- then pulling the patterns out from there.
  let servicePatternGroup :: Pattern
servicePatternGroup = Query a -> (QueryData -> Pattern) -> Pattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query a
q ((QueryData -> Pattern) -> Pattern)
-> (QueryData -> Pattern) -> Pattern
forall a b. (a -> b) -> a -> b
$ IRIRef -> GroupGraphPattern -> Pattern
ServiceGraphPattern IRIRef
endpoint (GroupGraphPattern -> Pattern)
-> (QueryData -> GroupGraphPattern) -> QueryData -> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryData -> GroupGraphPattern
pattern
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
servicePatternGroup (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
servicePatternGroup

-- | Same as 'service', but without returning the query patterns.
service_ :: IRIRef -> Query a -> Query ()
service_ :: IRIRef -> Query a -> Query ()
service_ IRIRef
q = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (Query a -> Query Pattern) -> Query a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IRIRef -> Query a -> Query Pattern
forall a. IRIRef -> Query a -> Query Pattern
service IRIRef
q

-- | 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 :: Query a -> Query b -> Query Pattern
union Query a
q1 Query b
q2 = do
  let p1 :: GroupGraphPattern
p1 = Query a -> (QueryData -> GroupGraphPattern) -> GroupGraphPattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query a
q1 QueryData -> GroupGraphPattern
pattern
      p2 :: GroupGraphPattern
p2 = Query b -> (QueryData -> GroupGraphPattern) -> GroupGraphPattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query b
q2 QueryData -> GroupGraphPattern
pattern
      union' :: Pattern
union' = GroupGraphPattern -> GroupGraphPattern -> Pattern
UnionGraphPattern GroupGraphPattern
p1 GroupGraphPattern
p2
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
union' (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
union'

union_ :: Query a -> Query b -> Query ()
union_ :: Query a -> Query b -> Query ()
union_ Query a
a Query b
b = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ Query a -> Query b -> Query Pattern
forall a b. Query a -> Query b -> Query Pattern
union Query a
a Query b
b

filterExists :: Query a -> Query Pattern
filterExists :: Query a -> Query Pattern
filterExists Query a
q = do
  let p :: GroupGraphPattern
p = Query a -> (QueryData -> GroupGraphPattern) -> GroupGraphPattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query a
q QueryData -> GroupGraphPattern
pattern
      filterExists' :: Pattern
filterExists' = GroupGraphPattern -> Pattern
FilterExistsPattern GroupGraphPattern
p
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
filterExists' (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
filterExists'

filterExists_ :: Query a -> Query ()
filterExists_ :: Query a -> Query ()
filterExists_ = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (Query a -> Query Pattern) -> Query a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query a -> Query Pattern
forall a. Query a -> Query Pattern
filterExists

filterNotExists :: Query a -> Query Pattern
filterNotExists :: Query a -> Query Pattern
filterNotExists Query a
q = do
  let p :: GroupGraphPattern
p = Query a -> (QueryData -> GroupGraphPattern) -> GroupGraphPattern
forall a b. Query a -> (QueryData -> b) -> b
execQuery0 Query a
q QueryData -> GroupGraphPattern
pattern
      filterNotExists' :: Pattern
filterNotExists' = GroupGraphPattern -> Pattern
FilterNotExistsPattern GroupGraphPattern
p
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
filterNotExists' (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
filterNotExists'

filterNotExists_ :: Query a -> Query ()
filterNotExists_ :: Query a -> Query ()
filterNotExists_ = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (Query a -> Query Pattern) -> Query a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query a -> Query Pattern
forall a. Query a -> Query Pattern
filterNotExists

-- | Restrict results to only those for which the given expression is true.
filterExpr :: (TermLike a) => a -> Query Pattern
filterExpr :: a -> Query Pattern
filterExpr a
e = do
  let f :: Pattern
f = Expr -> Pattern
Filter (a -> Expr
forall a. TermLike a => a -> Expr
expr a
e)
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
f (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
f

filterExpr_ :: (TermLike a) => a -> Query ()
filterExpr_ :: a -> Query ()
filterExpr_ = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (a -> Query Pattern) -> a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Query Pattern
forall a. TermLike a => a -> Query Pattern
filterExpr

-- | Bind the result of an expression to a variable.
bind :: Expr -> Variable -> Query Pattern
bind :: Expr -> Variable -> Query Pattern
bind Expr
e Variable
v = do
  let b :: Pattern
b = Expr -> Variable -> Pattern
Bind (Expr -> Expr
forall a. TermLike a => a -> Expr
expr Expr
e) Variable
v
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
b (QueryData -> GroupGraphPattern
pattern QueryData
s)}
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
b

bind_ :: Expr -> Variable -> Query ()
bind_ :: Expr -> Variable -> Query ()
bind_ Expr
a Variable
b = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ()) -> Query Pattern -> Query ()
forall a b. (a -> b) -> a -> b
$ Expr -> Variable -> Query Pattern
bind Expr
a Variable
b

-- | Perform a subquery.
subQuery :: Query SelectQuery -> Query Pattern
subQuery :: Query SelectQuery -> Query Pattern
subQuery Query SelectQuery
q = do
  -- Manage subquery indexes
  NonEmpty Int
qis <- (QueryData -> NonEmpty Int)
-> StateT QueryData Identity (NonEmpty Int)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> NonEmpty Int
subQueryIdx
  let sqis :: NonEmpty Int
sqis = NonEmpty Int
qis NonEmpty Int -> Int -> NonEmpty Int
forall a. NonEmpty a -> a -> NonEmpty a
|> Int
0
      qis' :: NonEmpty Int
qis' = [Int] -> NonEmpty Int
forall a. [a] -> NonEmpty a
NE.fromList ([Int] -> NonEmpty Int) -> [Int] -> NonEmpty Int
forall a b. (a -> b) -> a -> b
$ NonEmpty Int -> [Int]
forall a. NonEmpty a -> [a]
NE.init NonEmpty Int
qis [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [NonEmpty Int -> Int
forall a. NonEmpty a -> a
NE.last NonEmpty Int
qis Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1]
  -- Execute the subquery action
  let subQueryData0 :: QueryData
subQueryData0 = QueryData
queryData {subQueryIdx :: NonEmpty Int
subQueryIdx = NonEmpty Int
sqis}
      subQueryData :: QueryData
subQueryData = QueryData -> Query () -> (QueryData -> QueryData) -> QueryData
forall a b. QueryData -> Query a -> (QueryData -> b) -> b
execQuery QueryData
subQueryData0 (Query SelectQuery -> Query ()
specifyVars Query SelectQuery
q) QueryData -> QueryData
forall a. a -> a
id
  -- Merge prefixes
  [Prefix]
prefixesParentQuery <- (QueryData -> [Prefix]) -> StateT QueryData Identity [Prefix]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> [Prefix]
prefixes
  let prefixesSubQuery :: [Prefix]
prefixesSubQuery = QueryData -> [Prefix]
prefixes QueryData
subQueryData
      newPrefixes :: [Prefix]
newPrefixes = [Prefix]
prefixesSubQuery [Prefix] -> [Prefix] -> [Prefix]
forall a. Eq a => [a] -> [a] -> [a]
`L.union` [Prefix]
prefixesParentQuery
  -- Create the subquery pattern and remove prefixes from the subquery
  let sq :: Pattern
sq = QueryData -> Pattern
SubQuery (QueryData -> Pattern) -> QueryData -> Pattern
forall a b. (a -> b) -> a -> b
$ QueryData
subQueryData {prefixes :: [Prefix]
prefixes = []}
  -- Append the subquery pattern, update the subquery index and the prefixes.
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s ->
    QueryData
s
      { pattern :: GroupGraphPattern
pattern = Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
sq (QueryData -> GroupGraphPattern
pattern QueryData
s),
        subQueryIdx :: NonEmpty Int
subQueryIdx = NonEmpty Int
qis',
        prefixes :: [Prefix]
prefixes = [Prefix]
newPrefixes
      }
  Pattern -> Query Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
sq

subQuery_ :: Query SelectQuery -> Query ()
subQuery_ :: Query SelectQuery -> Query ()
subQuery_ = Query Pattern -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Pattern -> Query ())
-> (Query SelectQuery -> Query Pattern)
-> Query SelectQuery
-> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query SelectQuery -> Query Pattern
subQuery

-- Random auxiliary

-- | Form a 'Node', with the 'Prefix' and reference name.
(.:.) :: Prefix -> T.Text -> IRIRef
.:. :: Prefix -> Text -> IRIRef
(.:.) = Prefix -> Text -> IRIRef
PrefixedName

-- Duplicate handling

-- | Set duplicate handling to 'Distinct'. By default, there are no reductions.
distinct :: Query Duplicates
distinct :: Query Duplicates
distinct = do
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {duplicates :: Duplicates
duplicates = Duplicates
Distinct}
  (QueryData -> Duplicates) -> Query Duplicates
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> Duplicates
duplicates

distinct_ :: Query ()
distinct_ :: Query ()
distinct_ = Query Duplicates -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Query Duplicates
distinct

-- | Set duplicate handling to 'Reduced'. By default, there are no reductions.
reduced :: Query Duplicates
reduced :: Query Duplicates
reduced = do
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {duplicates :: Duplicates
duplicates = Duplicates
Reduced}
  (QueryData -> Duplicates) -> Query Duplicates
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> Duplicates
duplicates

reduced_ :: Query ()
reduced_ :: Query ()
reduced_ = Query Duplicates -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Query Duplicates
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 :: Int -> Query Limit
limit Int
n = do
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {limits :: Limit
limits = Int -> Limit
Limit Int
n}
  (QueryData -> Limit) -> Query Limit
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> Limit
limits

limit_ :: Int -> Query ()
limit_ :: Int -> Query ()
limit_ = Query Limit -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query Limit -> Query ())
-> (Int -> Query Limit) -> Int -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Query Limit
limit

-- Grouping

-- | Divide the solution into one or more groups.
groupBy :: (TermLike a) => a -> Query [GroupBy]
groupBy :: a -> Query [GroupBy]
groupBy a
e = do
  (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {groups :: [GroupBy]
groups = QueryData -> [GroupBy]
groups QueryData
s [GroupBy] -> [GroupBy] -> [GroupBy]
forall a. [a] -> [a] -> [a]
++ [Expr -> GroupBy
GroupBy (Expr -> GroupBy) -> (a -> Expr) -> a -> GroupBy
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Expr
forall a. TermLike a => a -> Expr
expr (a -> GroupBy) -> a -> GroupBy
forall a b. (a -> b) -> a -> b
$ a
e]}
  (QueryData -> [GroupBy]) -> Query [GroupBy]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets QueryData -> [GroupBy]
groups

groupBy_ :: (TermLike a) => a -> Query ()
groupBy_ :: a -> Query ()
groupBy_ = Query [GroupBy] -> Query ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Query [GroupBy] -> Query ())
-> (a -> Query [GroupBy]) -> a -> Query ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Query [GroupBy]
forall a. TermLike a => a -> Query [GroupBy]
groupBy

-- Order handling

-- | Alias of 'orderNextAsc'.
orderNext :: (TermLike a) => a -> Query ()
orderNext :: a -> Query ()
orderNext = a -> Query ()
forall a. TermLike a => a -> Query ()
orderNextAsc

-- | Order the results, after any previous ordering, based on the term, in
--   ascending order.
orderNextAsc :: (TermLike a) => a -> Query ()
orderNextAsc :: a -> Query ()
orderNextAsc a
x = (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {ordering :: [OrderBy]
ordering = QueryData -> [OrderBy]
ordering QueryData
s [OrderBy] -> [OrderBy] -> [OrderBy]
forall a. [a] -> [a] -> [a]
++ [Expr -> OrderBy
Asc (Expr -> OrderBy) -> Expr -> OrderBy
forall a b. (a -> b) -> a -> b
$ a -> Expr
forall a. TermLike a => a -> Expr
expr a
x]}

-- | Order the results, after any previous ordering, based on the term, in
--   descending order.
orderNextDesc :: (TermLike a) => a -> Query ()
orderNextDesc :: a -> Query ()
orderNextDesc a
x = (QueryData -> QueryData) -> Query ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((QueryData -> QueryData) -> Query ())
-> (QueryData -> QueryData) -> Query ()
forall a b. (a -> b) -> a -> b
$ \QueryData
s -> QueryData
s {ordering :: [OrderBy]
ordering = QueryData -> [OrderBy]
ordering QueryData
s [OrderBy] -> [OrderBy] -> [OrderBy]
forall a. [a] -> [a] -> [a]
++ [Expr -> OrderBy
Desc (Expr -> OrderBy) -> Expr -> OrderBy
forall a b. (a -> b) -> a -> b
$ a -> Expr
forall a. TermLike a => a -> Expr
expr a
x]}

-- | Permit variables and values to seemlessly be put into argument for 'triple'
--   and similar functions
class TermLike a where
  varOrTerm :: a -> VarOrTerm

  expr :: a -> Expr
  expr = VarOrTerm -> Expr
VarOrTermExpr (VarOrTerm -> Expr) -> (a -> VarOrTerm) -> a -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm

instance TermLike Variable where
  varOrTerm :: Variable -> VarOrTerm
varOrTerm = Variable -> VarOrTerm
Var

instance TermLike IRIRef where
  varOrTerm :: IRIRef -> VarOrTerm
varOrTerm = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (IRIRef -> GraphTerm) -> IRIRef -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IRIRef -> GraphTerm
IRIRefTerm

instance TermLike PropertyPathExpr where
  varOrTerm :: PropertyPathExpr -> VarOrTerm
varOrTerm = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (PropertyPathExpr -> GraphTerm) -> PropertyPathExpr -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PropertyPathExpr -> GraphTerm
PropertyPathTerm

instance TermLike EmbeddedTriple where
  varOrTerm :: EmbeddedTriple -> VarOrTerm
varOrTerm (EmbeddedTriple VarOrTerm
v) = VarOrTerm
v

instance TermLike BlankNodePattern where
  varOrTerm :: BlankNodePattern -> VarOrTerm
varOrTerm [] = GraphTerm -> VarOrTerm
Term (Maybe Text -> GraphTerm
BNode Maybe Text
forall a. Maybe a
Nothing)
  varOrTerm BlankNodePattern
xs = BlankNodePattern -> VarOrTerm
BlankNodePattern' BlankNodePattern
xs

  expr :: BlankNodePattern -> Expr
expr [] = String -> Expr
forall a. HasCallStack => String -> a
error String
"FIXME: blank node expression"
  expr BlankNodePattern
_ = String -> Expr
forall a. HasCallStack => String -> a
error String
"cannot use a blank node pattern as an expression"

instance TermLike Expr where
  varOrTerm :: Expr -> VarOrTerm
varOrTerm = String -> Expr -> VarOrTerm
forall a. HasCallStack => String -> a
error String
"cannot use an expression as a term"
  expr :: Expr -> Expr
expr = Expr -> Expr
forall a. a -> a
id

instance TermLike Integer where
  varOrTerm :: Integer -> VarOrTerm
varOrTerm = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (Integer -> GraphTerm) -> Integer -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> GraphTerm
NumericLiteralTerm
  expr :: Integer -> Expr
expr = NumericExpr -> Expr
NumericExpr (NumericExpr -> Expr)
-> (Integer -> NumericExpr) -> Integer -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> NumericExpr
NumericLiteralExpr

instance TermLike T.Text where
  varOrTerm :: Text -> VarOrTerm
varOrTerm = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (Text -> GraphTerm) -> Text -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LValue -> GraphTerm
RDFLiteralTerm (LValue -> GraphTerm) -> (Text -> LValue) -> Text -> GraphTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LValue
RDF.plainL

instance TermLike (T.Text, T.Text) where
  varOrTerm :: (Text, Text) -> VarOrTerm
varOrTerm (Text
s, Text
lang') = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (LValue -> GraphTerm) -> LValue -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LValue -> GraphTerm
RDFLiteralTerm (LValue -> VarOrTerm) -> LValue -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ Text -> Text -> LValue
RDF.plainLL Text
s Text
lang'

instance TermLike (T.Text, IRIRef) where
  varOrTerm :: (Text, IRIRef) -> VarOrTerm
varOrTerm (Text
s, IRIRef
ref) = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (LValue -> GraphTerm) -> LValue -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LValue -> GraphTerm
RDFLiteralTerm (LValue -> VarOrTerm) -> LValue -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ Text -> Text -> LValue
RDF.typedL Text
s (IRIRef -> Text
getFQN IRIRef
ref)

instance TermLike Bool where
  varOrTerm :: Bool -> VarOrTerm
varOrTerm = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (Bool -> GraphTerm) -> Bool -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> GraphTerm
BooleanLiteralTerm

instance TermLike RDF.Node where
  varOrTerm :: Node -> VarOrTerm
varOrTerm n :: Node
n@(RDF.UNode Text
_) = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (Node -> GraphTerm) -> Node -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IRIRef -> GraphTerm
IRIRefTerm (IRIRef -> GraphTerm) -> (Node -> IRIRef) -> Node -> GraphTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> IRIRef
AbsoluteIRI (Node -> VarOrTerm) -> Node -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ Node
n
  varOrTerm (RDF.LNode LValue
lv) = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (LValue -> GraphTerm) -> LValue -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LValue -> GraphTerm
RDFLiteralTerm (LValue -> VarOrTerm) -> LValue -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ LValue
lv
  varOrTerm (RDF.BNode Text
i) = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> (Text -> GraphTerm) -> Text -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> GraphTerm
BNode (Maybe Text -> GraphTerm)
-> (Text -> Maybe Text) -> Text -> GraphTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> VarOrTerm) -> Text -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ Text
i
  varOrTerm (RDF.BNodeGen Int
i) = GraphTerm -> VarOrTerm
Term (GraphTerm -> VarOrTerm)
-> ([String] -> GraphTerm) -> [String] -> VarOrTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> GraphTerm
BNode (Maybe Text -> GraphTerm)
-> ([String] -> Maybe Text) -> [String] -> GraphTerm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text)
-> ([String] -> Text) -> [String] -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> ([String] -> String) -> [String] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> VarOrTerm) -> [String] -> VarOrTerm
forall a b. (a -> b) -> a -> b
$ [Item [String]
"genid", Int -> String
forall a. Show a => a -> String
show Int
i]

instance TermLike VarOrNode where
  varOrTerm :: VarOrNode -> VarOrTerm
varOrTerm (Var' Variable
v) = Variable -> VarOrTerm
Var Variable
v
  varOrTerm (RDFNode Node
n) = Node -> VarOrTerm
forall a. TermLike a => a -> VarOrTerm
varOrTerm Node
n

-- | Restriction of TermLike to the role of subject.
class (TermLike a) => SubjectTermLike a

instance SubjectTermLike IRIRef

instance SubjectTermLike Variable

instance SubjectTermLike EmbeddedTriple

instance SubjectTermLike BlankNodePattern

-- | Restriction of TermLike to the role of predicate.
class (TermLike a) => PredicateTermLike a

instance PredicateTermLike IRIRef

instance PredicateTermLike Variable

instance PredicateTermLike PropertyPathExpr

-- | Restriction of TermLike to the role of object.
class (TermLike a) => ObjectTermLike a

instance ObjectTermLike IRIRef

instance ObjectTermLike Variable

instance ObjectTermLike EmbeddedTriple

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 :: Operation -> a -> b -> Expr
operation Operation
op a
x b
y = NumericExpr -> Expr
NumericExpr (NumericExpr -> Expr) -> NumericExpr -> Expr
forall a b. (a -> b) -> a -> b
$ Operation -> Expr -> Expr -> NumericExpr
OperationExpr Operation
op (a -> Expr
forall a. TermLike a => a -> Expr
expr a
x) (b -> Expr
forall a. TermLike a => a -> Expr
expr b
y)

-- | Add two terms.
(.+.) :: (TermLike a, TermLike b) => a -> b -> Expr
.+. :: a -> b -> Expr
(.+.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
Add

-- | Find the difference between two terms.
(.-.) :: (TermLike a, TermLike b) => a -> b -> Expr
.-. :: a -> b -> Expr
(.-.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
Subtract

-- | Multiply two terms.
(.*.) :: (TermLike a, TermLike b) => a -> b -> Expr
.*. :: a -> b -> Expr
(.*.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
Multiply

-- | Divide two terms.
(./.) :: (TermLike a, TermLike b) => a -> b -> Expr
./. :: a -> b -> Expr
(./.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
Divide

-- | Combine two boolean terms with AND
(.&&.) :: (TermLike a, TermLike b) => a -> b -> Expr
.&&. :: a -> b -> Expr
(.&&.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
And

-- | Combine two boolean terms with OR
(.||.) :: (TermLike a, TermLike b) => a -> b -> Expr
.||. :: a -> b -> Expr
(.||.) = Operation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Operation -> a -> b -> Expr
operation Operation
Or

infixr 2 .||.

infixr 3 .&&.

infixl 7 .*.

infixl 7 ./.

infixl 6 .+.

infixl 6 .-.

-- Relations
relation :: (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation :: Relation -> a -> b -> Expr
relation Relation
rel a
x b
y = Relation -> Expr -> Expr -> Expr
RelationalExpr Relation
rel (a -> Expr
forall a. TermLike a => a -> Expr
expr a
x) (b -> Expr
forall a. TermLike a => a -> Expr
expr b
y)

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their equivalence.
(.==.) :: (TermLike a, TermLike b) => a -> b -> Expr
.==. :: a -> b -> Expr
(.==.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
Equal

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their equivalence.
(.!=.) :: (TermLike a, TermLike b) => a -> b -> Expr
.!=. :: a -> b -> Expr
(.!=.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
NotEqual

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their relative value.
(.<.) :: (TermLike a, TermLike b) => a -> b -> Expr
.<. :: a -> b -> Expr
(.<.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
LessThan

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their relative value.
(.>.) :: (TermLike a, TermLike b) => a -> b -> Expr
.>. :: a -> b -> Expr
(.>.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
GreaterThan

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their relative value.
(.<=.) :: (TermLike a, TermLike b) => a -> b -> Expr
.<=. :: a -> b -> Expr
(.<=.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
LessThanOrEqual

-- | Create an expression which tests the relationship of the two operands,
--   evaluating their relative value.
(.>=.) :: (TermLike a, TermLike b) => a -> b -> Expr
.>=. :: a -> b -> Expr
(.>=.) = Relation -> a -> b -> Expr
forall a b. (TermLike a, TermLike b) => Relation -> a -> b -> Expr
relation Relation
GreaterThanOrEqual

infix 4 .==., .!=., .<., .<=., .>., .>=.

-- Negation

-- | Negate any term-like expression, for use, e.g., in filtering.
notExpr :: (TermLike a) => a -> Expr
notExpr :: a -> Expr
notExpr = Expr -> Expr
NegatedExpr (Expr -> Expr) -> (a -> Expr) -> a -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Expr
forall a. TermLike a => a -> Expr
expr

-- Builtin Functions
type BuiltinFunc0 = Expr

builtinFunc0 :: Function -> BuiltinFunc0
builtinFunc0 :: Function -> Expr
builtinFunc0 Function
f = Function -> [Expr] -> Expr
BuiltinCall Function
f []

type BuiltinFunc1 = forall a. (TermLike a) => a -> Expr

builtinFunc1 :: Function -> BuiltinFunc1
builtinFunc1 :: Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
f a
x = Function -> [Expr] -> Expr
BuiltinCall Function
f [a -> Expr
forall a. TermLike a => a -> Expr
expr a
x]

type BuiltinFunc2 = forall a b. (TermLike a, TermLike b) => a -> b -> Expr

builtinFunc2 :: Function -> BuiltinFunc2
builtinFunc2 :: Function -> BuiltinFunc2
builtinFunc2 Function
f a
x b
y = Function -> [Expr] -> Expr
BuiltinCall Function
f [a -> Expr
forall a. TermLike a => a -> Expr
expr a
x, b -> Expr
forall a. TermLike a => a -> Expr
expr b
y]

type BuiltinFunc3 = forall a b c. (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Expr

builtinFunc3 :: Function -> BuiltinFunc3
builtinFunc3 :: Function -> BuiltinFunc3
builtinFunc3 Function
f a
x b
y c
z = Function -> [Expr] -> Expr
BuiltinCall Function
f [a -> Expr
forall a. TermLike a => a -> Expr
expr a
x, b -> Expr
forall a. TermLike a => a -> Expr
expr b
y, c -> Expr
forall a. TermLike a => a -> Expr
expr c
z]

-- | Aggregate by count
count :: BuiltinFunc1
count :: a -> Expr
count = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
CountFunc

-- | Aggregate by sum
sum_ :: BuiltinFunc1
sum_ :: a -> Expr
sum_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
SumFunc

-- | Aggregate by minimum value
min_ :: BuiltinFunc1
min_ :: a -> Expr
min_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
MinFunc

-- | Aggregate by maximum value
max_ :: BuiltinFunc1
max_ :: a -> Expr
max_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
MaxFunc

-- | Aggregate by average
avg :: BuiltinFunc1
avg :: a -> Expr
avg = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
AvgFunc

-- | Cast as a string
str :: BuiltinFunc1
str :: a -> Expr
str = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
StrFunc

-- | Get the language of this element
lang :: BuiltinFunc1
lang :: a -> Expr
lang = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
LangFunc

-- | strlen ( string ) - get the length of a string
strlen :: BuiltinFunc1
strlen :: a -> Expr
strlen = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
StrLenFunc

-- | substr ( string beginPosition stringLength ) - get a substring
substr :: BuiltinFunc1
substr :: a -> Expr
substr = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
SubStrFunc

-- | ucase ( string ) - convert to upper case
ucase :: BuiltinFunc1
ucase :: a -> Expr
ucase = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
UcaseFunc

-- | lcase ( string ) - convert to lower case
lcase :: BuiltinFunc1
lcase :: a -> Expr
lcase = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
LcaseFunc

-- | strstarts ( string x ) - return true if x matches the beginning of string
strstarts :: BuiltinFunc2
strstarts :: a -> b -> Expr
strstarts = Function -> BuiltinFunc2
builtinFunc2 Function
StrStartsFunc

-- | strends ( string x ) - return true if x matches the end of string
strends :: BuiltinFunc2
strends :: a -> b -> Expr
strends = Function -> BuiltinFunc2
builtinFunc2 Function
StrEndsFunc

-- | contains ( string x ) - return true if x matches anywhere in string
contains :: BuiltinFunc2
contains :: a -> b -> Expr
contains = Function -> BuiltinFunc2
builtinFunc2 Function
ContainsFunc

-- | strbefore ( string x ) - return the string preceding a match to x
strbefore :: BuiltinFunc2
strbefore :: a -> b -> Expr
strbefore = Function -> BuiltinFunc2
builtinFunc2 Function
StrBeforeFunc

-- | strafter ( string x ) - return the string after a match to x
strafter :: BuiltinFunc2
strafter :: a -> b -> Expr
strafter = Function -> BuiltinFunc2
builtinFunc2 Function
StrAfterFunc

-- | concat_ ( x y ) - concatenate strings x and y
concat_ :: BuiltinFunc2
concat_ :: a -> b -> Expr
concat_ = Function -> BuiltinFunc2
builtinFunc2 Function
ConcatFunc

-- | replace ( string p r ) - replace literal p with literal r in string
replace :: BuiltinFunc3
replace :: a -> b -> c -> Expr
replace = Function -> BuiltinFunc3
builtinFunc3 Function
ReplaceFunc

-- | abs_ ( x ) - take the absolute value of number x
abs_ :: BuiltinFunc1
abs_ :: a -> Expr
abs_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
AbsFunc

-- | round ( x ) - round x to the nearest integer
round_ :: BuiltinFunc1
round_ :: a -> Expr
round_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
RoundFunc

-- | ceil ( number ) - round x up to the nearest integer
ceil :: BuiltinFunc1
ceil :: a -> Expr
ceil = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
CeilFunc

-- | floor ( number ) - round x down to the nearest integer
floor_ :: BuiltinFunc1
floor_ :: a -> Expr
floor_ = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
FloorFunc

-- | rand ( ) - produce a random number between 0 and 1
rand :: BuiltinFunc0
rand :: Expr
rand = Function -> Expr
builtinFunc0 Function
RandFunc

-- | Aggregate a column by string concatenation with a separator.
groupConcat :: (TermLike a) => a -> String -> Expr
groupConcat :: a -> String -> Expr
groupConcat a
x String
sep = ParameterizedFunction -> [Expr] -> [(String, String)] -> Expr
ParameterizedCall ParameterizedFunction
GroupConcat [a -> Expr
forall a. TermLike a => a -> Expr
expr a
x] [(String
"separator", String
"\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
sep String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"")]

langMatches :: BuiltinFunc2
langMatches :: a -> b -> Expr
langMatches = Function -> BuiltinFunc2
builtinFunc2 Function
LangMatchesFunc

datatype :: BuiltinFunc1
datatype :: a -> Expr
datatype = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
DataTypeFunc

bound :: Variable -> Expr
bound :: Variable -> Expr
bound Variable
x = Function -> [Expr] -> Expr
BuiltinCall Function
BoundFunc [Variable -> Expr
forall a. TermLike a => a -> Expr
expr Variable
x]

sameTerm :: BuiltinFunc2
sameTerm :: a -> b -> Expr
sameTerm = Function -> BuiltinFunc2
builtinFunc2 Function
SameTermFunc

isIRI :: BuiltinFunc1
isIRI :: a -> Expr
isIRI = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
IsIRIFunc

isURI :: BuiltinFunc1
isURI :: a -> Expr
isURI = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
IsURIFunc

isBlank :: BuiltinFunc1
isBlank :: a -> Expr
isBlank = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
IsBlankFunc

isLiteral :: BuiltinFunc1
isLiteral :: a -> Expr
isLiteral = Function -> forall a. TermLike a => a -> Expr
builtinFunc1 Function
IsLiteralFunc

regex :: BuiltinFunc2
regex :: a -> b -> Expr
regex = Function -> BuiltinFunc2
builtinFunc2 Function
RegexFunc

regexOpts :: BuiltinFunc3
regexOpts :: a -> b -> c -> Expr
regexOpts = Function -> BuiltinFunc3
builtinFunc3 Function
RegexFunc

-- Default QueryData
queryData :: QueryData
queryData :: QueryData
queryData =
  QueryData :: [Prefix]
-> Int
-> [SelectExpr]
-> QueryType
-> NonEmpty Int
-> GroupGraphPattern
-> [Pattern]
-> [Pattern]
-> [Pattern]
-> Maybe IRIRef
-> Duplicates
-> [GroupBy]
-> [OrderBy]
-> Limit
-> QueryData
QueryData
    { prefixes :: [Prefix]
prefixes = [],
      varsIdx :: Int
varsIdx = Int
0,
      vars :: [SelectExpr]
vars = [],
      queryType :: QueryType
queryType = QueryType
TypeNotSet,
      subQueryIdx :: NonEmpty Int
subQueryIdx = [Item (NonEmpty Int)
0],
      pattern :: GroupGraphPattern
pattern = [Pattern] -> GroupGraphPattern
GroupGraphPattern [],
      constructTriples :: [Pattern]
constructTriples = [],
      askTriples :: [Pattern]
askTriples = [],
      updateTriples :: [Pattern]
updateTriples = [],
      describeURI :: Maybe IRIRef
describeURI = Maybe IRIRef
forall a. Maybe a
Nothing,
      duplicates :: Duplicates
duplicates = Duplicates
NoLimits,
      groups :: [GroupBy]
groups = [],
      ordering :: [OrderBy]
ordering = [],
      limits :: Limit
limits = Limit
NoLimit
    }

-- Query representation
class QueryShow a where
  -- | Convert most query-related types to a 'String', most importantly
  --   'QueryData's.
  qshow :: a -> String

data Duplicates = NoLimits | Distinct | Reduced
  deriving (Int -> Duplicates -> String -> String
[Duplicates] -> String -> String
Duplicates -> String
(Int -> Duplicates -> String -> String)
-> (Duplicates -> String)
-> ([Duplicates] -> String -> String)
-> Show Duplicates
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Duplicates] -> String -> String
$cshowList :: [Duplicates] -> String -> String
show :: Duplicates -> String
$cshow :: Duplicates -> String
showsPrec :: Int -> Duplicates -> String -> String
$cshowsPrec :: Int -> Duplicates -> String -> String
Show)

data Limit = NoLimit | Limit Int
  deriving (Int -> Limit -> String -> String
[Limit] -> String -> String
Limit -> String
(Int -> Limit -> String -> String)
-> (Limit -> String) -> ([Limit] -> String -> String) -> Show Limit
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Limit] -> String -> String
$cshowList :: [Limit] -> String -> String
show :: Limit -> String
$cshow :: Limit -> String
showsPrec :: Int -> Limit -> String -> String
$cshowsPrec :: Int -> Limit -> String -> String
Show)

data Prefix = Prefix T.Text RDF.Node
  deriving (Int -> Prefix -> String -> String
[Prefix] -> String -> String
Prefix -> String
(Int -> Prefix -> String -> String)
-> (Prefix -> String)
-> ([Prefix] -> String -> String)
-> Show Prefix
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Prefix] -> String -> String
$cshowList :: [Prefix] -> String -> String
show :: Prefix -> String
$cshow :: Prefix -> String
showsPrec :: Int -> Prefix -> String -> String
$cshowsPrec :: Int -> Prefix -> String -> String
Show, Prefix -> Prefix -> Bool
(Prefix -> Prefix -> Bool)
-> (Prefix -> Prefix -> Bool) -> Eq Prefix
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Prefix -> Prefix -> Bool
$c/= :: Prefix -> Prefix -> Bool
== :: Prefix -> Prefix -> Bool
$c== :: Prefix -> Prefix -> Bool
Eq)

data Variable = Variable (NonEmpty Int)
  deriving (Int -> Variable -> String -> String
[Variable] -> String -> String
Variable -> String
(Int -> Variable -> String -> String)
-> (Variable -> String)
-> ([Variable] -> String -> String)
-> Show Variable
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Variable] -> String -> String
$cshowList :: [Variable] -> String -> String
show :: Variable -> String
$cshow :: Variable -> String
showsPrec :: Int -> Variable -> String -> String
$cshowsPrec :: Int -> Variable -> String -> String
Show)

data EmbeddedTriple = EmbeddedTriple VarOrTerm
  deriving (Int -> EmbeddedTriple -> String -> String
[EmbeddedTriple] -> String -> String
EmbeddedTriple -> String
(Int -> EmbeddedTriple -> String -> String)
-> (EmbeddedTriple -> String)
-> ([EmbeddedTriple] -> String -> String)
-> Show EmbeddedTriple
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [EmbeddedTriple] -> String -> String
$cshowList :: [EmbeddedTriple] -> String -> String
show :: EmbeddedTriple -> String
$cshow :: EmbeddedTriple -> String
showsPrec :: Int -> EmbeddedTriple -> String -> String
$cshowsPrec :: Int -> EmbeddedTriple -> String -> String
Show)

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 -> String
show (DynamicPredicate a
a) = a -> String
forall a. Show a => a -> String
show a
a

instance Show DynamicObject where
  show :: DynamicObject -> String
show (DynamicObject a
a) = a -> String
forall a. Show a => a -> String
show a
a

-- | support for blank nodes.
--
--  Define a convenient alias for `mkPredicateObject`. Note: a
--  pointfree definition leads to the monomorphism restriction @(&) =
--  mkPredicateObject@. An example of its use:
--
--  > p & o = mkPredicateObject p o
--
--  for example
--
--  > q = do
--  >   p <- prefix "" (iriRef "http://example.com/")
--  >   s <- var
--  >   o1 <- var
--  >   o2 <- var
--  >   _ <- triple s (p .:. "p1") [(p .:. "p2") & [(p .:. "p3") & o1], (p .:. "p4") & o2]
--  >   return SelectQuery { queryVars = [s, o1] }
--
--  >>> createSelectQuery q
--  "PREFIX : <http://example.com/> SELECT  ?x0 ?x1 WHERE {?x0 :p1 [:p2 [:p3 ?x1]], [:p4 ?x2] .} "
mkPredicateObject :: (PredicateTermLike a, ObjectTermLike b, QueryShow a, QueryShow b, Show a, Show b) => a -> b -> DynamicPredicateObject
mkPredicateObject :: a -> b -> DynamicPredicateObject
mkPredicateObject a
p b
o = (a -> DynamicPredicate
forall a.
(PredicateTermLike a, QueryShow a, Show a) =>
a -> DynamicPredicate
DynamicPredicate a
p, b -> DynamicObject
forall a.
(ObjectTermLike a, QueryShow a, Show a) =>
a -> DynamicObject
DynamicObject b
o)

data IRIRef
  = AbsoluteIRI RDF.Node
  | PrefixedName Prefix T.Text
  deriving (Int -> IRIRef -> String -> String
[IRIRef] -> String -> String
IRIRef -> String
(Int -> IRIRef -> String -> String)
-> (IRIRef -> String)
-> ([IRIRef] -> String -> String)
-> Show IRIRef
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [IRIRef] -> String -> String
$cshowList :: [IRIRef] -> String -> String
show :: IRIRef -> String
$cshow :: IRIRef -> String
showsPrec :: Int -> IRIRef -> String -> String
$cshowsPrec :: Int -> IRIRef -> String -> String
Show)

iriRef :: T.Text -> IRIRef
iriRef :: Text -> IRIRef
iriRef Text
uri = Node -> IRIRef
AbsoluteIRI (Node -> IRIRef) -> Node -> IRIRef
forall a b. (a -> b) -> a -> b
$ Text -> Node
RDF.unode Text
uri

getFQN :: IRIRef -> T.Text
getFQN :: IRIRef -> Text
getFQN (AbsoluteIRI (RDF.UNode Text
n)) = Text
n
getFQN (PrefixedName (Prefix Text
_ (RDF.UNode Text
n)) Text
s) = Text -> Text -> Text
T.append Text
n Text
s
-- FIXME
getFQN IRIRef
_ = String -> Text
forall a. HasCallStack => String -> a
error String
"getFQN: input not supported"

-- FIXME: Should support numeric literals, too
data GraphTerm
  = IRIRefTerm IRIRef
  | RDFLiteralTerm RDF.LValue
  | NumericLiteralTerm Integer
  | BooleanLiteralTerm Bool
  | BNode (Maybe T.Text)
  | PropertyPathTerm PropertyPathExpr
  deriving (Int -> GraphTerm -> String -> String
[GraphTerm] -> String -> String
GraphTerm -> String
(Int -> GraphTerm -> String -> String)
-> (GraphTerm -> String)
-> ([GraphTerm] -> String -> String)
-> Show GraphTerm
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [GraphTerm] -> String -> String
$cshowList :: [GraphTerm] -> String -> String
show :: GraphTerm -> String
$cshow :: GraphTerm -> String
showsPrec :: Int -> GraphTerm -> String -> String
$cshowsPrec :: Int -> GraphTerm -> String -> String
Show)

data VarOrTerm
  = Var Variable
  | Term GraphTerm
  | EmbeddedTriple' VarOrTerm VarOrTerm VarOrTerm
  | BlankNodePattern' BlankNodePattern
  deriving (Int -> VarOrTerm -> String -> String
[VarOrTerm] -> String -> String
VarOrTerm -> String
(Int -> VarOrTerm -> String -> String)
-> (VarOrTerm -> String)
-> ([VarOrTerm] -> String -> String)
-> Show VarOrTerm
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [VarOrTerm] -> String -> String
$cshowList :: [VarOrTerm] -> String -> String
show :: VarOrTerm -> String
$cshow :: VarOrTerm -> String
showsPrec :: Int -> VarOrTerm -> String -> String
$cshowsPrec :: Int -> VarOrTerm -> String -> String
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 RDF.Node
  deriving (Int -> VarOrNode -> String -> String
[VarOrNode] -> String -> String
VarOrNode -> String
(Int -> VarOrNode -> String -> String)
-> (VarOrNode -> String)
-> ([VarOrNode] -> String -> String)
-> Show VarOrNode
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [VarOrNode] -> String -> String
$cshowList :: [VarOrNode] -> String -> String
show :: VarOrNode -> String
$cshow :: VarOrNode -> String
showsPrec :: Int -> VarOrNode -> String -> String
$cshowsPrec :: Int -> VarOrNode -> String -> String
Show)

data Operation = Add | Subtract | Multiply | Divide | And | Or
  deriving (Int -> Operation -> String -> String
[Operation] -> String -> String
Operation -> String
(Int -> Operation -> String -> String)
-> (Operation -> String)
-> ([Operation] -> String -> String)
-> Show Operation
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Operation] -> String -> String
$cshowList :: [Operation] -> String -> String
show :: Operation -> String
$cshow :: Operation -> String
showsPrec :: Int -> Operation -> String -> String
$cshowsPrec :: Int -> Operation -> String -> String
Show)

data NumericExpr
  = NumericLiteralExpr Integer
  | OperationExpr Operation Expr Expr
  deriving (Int -> NumericExpr -> String -> String
[NumericExpr] -> String -> String
NumericExpr -> String
(Int -> NumericExpr -> String -> String)
-> (NumericExpr -> String)
-> ([NumericExpr] -> String -> String)
-> Show NumericExpr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [NumericExpr] -> String -> String
$cshowList :: [NumericExpr] -> String -> String
show :: NumericExpr -> String
$cshow :: NumericExpr -> String
showsPrec :: Int -> NumericExpr -> String -> String
$cshowsPrec :: Int -> NumericExpr -> String -> String
Show)

data Relation = Equal | NotEqual | LessThan | GreaterThan | LessThanOrEqual | GreaterThanOrEqual
  deriving (Int -> Relation -> String -> String
[Relation] -> String -> String
Relation -> String
(Int -> Relation -> String -> String)
-> (Relation -> String)
-> ([Relation] -> String -> String)
-> Show Relation
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Relation] -> String -> String
$cshowList :: [Relation] -> String -> String
show :: Relation -> String
$cshow :: Relation -> String
showsPrec :: Int -> Relation -> String -> String
$cshowsPrec :: Int -> Relation -> String -> String
Show)

data Function
  = CountFunc
  | SumFunc
  | MinFunc
  | MaxFunc
  | AvgFunc
  | StrFunc
  | LangFunc
  | LangMatchesFunc
  | DataTypeFunc
  | BoundFunc
  | SameTermFunc
  | IsIRIFunc
  | IsURIFunc
  | IsBlankFunc
  | IsLiteralFunc
  | RegexFunc
  | StrLenFunc
  | SubStrFunc
  | UcaseFunc
  | LcaseFunc
  | StrStartsFunc
  | StrEndsFunc
  | ContainsFunc
  | StrBeforeFunc
  | StrAfterFunc
  | ConcatFunc
  | ReplaceFunc
  | AbsFunc
  | RoundFunc
  | CeilFunc
  | FloorFunc
  | RandFunc
  deriving (Int -> Function -> String -> String
[Function] -> String -> String
Function -> String
(Int -> Function -> String -> String)
-> (Function -> String)
-> ([Function] -> String -> String)
-> Show Function
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Function] -> String -> String
$cshowList :: [Function] -> String -> String
show :: Function -> String
$cshow :: Function -> String
showsPrec :: Int -> Function -> String -> String
$cshowsPrec :: Int -> Function -> String -> String
Show)

data ParameterizedFunction = GroupConcat deriving (Int -> ParameterizedFunction -> String -> String
[ParameterizedFunction] -> String -> String
ParameterizedFunction -> String
(Int -> ParameterizedFunction -> String -> String)
-> (ParameterizedFunction -> String)
-> ([ParameterizedFunction] -> String -> String)
-> Show ParameterizedFunction
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [ParameterizedFunction] -> String -> String
$cshowList :: [ParameterizedFunction] -> String -> String
show :: ParameterizedFunction -> String
$cshow :: ParameterizedFunction -> String
showsPrec :: Int -> ParameterizedFunction -> String -> String
$cshowsPrec :: Int -> ParameterizedFunction -> String -> String
Show)

data Expr
  = OrExpr [Expr]
  | AndExpr [Expr]
  | NegatedExpr Expr
  | RelationalExpr Relation Expr Expr
  | NumericExpr NumericExpr
  | BuiltinCall Function [Expr]
  | VarOrTermExpr VarOrTerm
  | ParameterizedCall ParameterizedFunction [Expr] [(String, String)]
  deriving (Int -> Expr -> String -> String
[Expr] -> String -> String
Expr -> String
(Int -> Expr -> String -> String)
-> (Expr -> String) -> ([Expr] -> String -> String) -> Show Expr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Expr] -> String -> String
$cshowList :: [Expr] -> String -> String
show :: Expr -> String
$cshow :: Expr -> String
showsPrec :: Int -> Expr -> String -> String
$cshowsPrec :: Int -> Expr -> String -> String
Show)

data SelectExpr
  = SelectExpr Expr Variable
  | SelectVar Variable
  deriving (Int -> SelectExpr -> String -> String
[SelectExpr] -> String -> String
SelectExpr -> String
(Int -> SelectExpr -> String -> String)
-> (SelectExpr -> String)
-> ([SelectExpr] -> String -> String)
-> Show SelectExpr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [SelectExpr] -> String -> String
$cshowList :: [SelectExpr] -> String -> String
show :: SelectExpr -> String
$cshow :: SelectExpr -> String
showsPrec :: Int -> SelectExpr -> String -> String
$cshowsPrec :: Int -> SelectExpr -> String -> String
Show)

as :: Expr -> Variable -> SelectExpr
Expr
e `as` Variable
v = Expr -> Variable -> SelectExpr
SelectExpr Expr
e Variable
v

data Pattern
  = QTriple VarOrTerm VarOrTerm VarOrTerm
  | Filter Expr
  | FilterExistsPattern GroupGraphPattern
  | FilterNotExistsPattern GroupGraphPattern
  | Bind Expr Variable
  | OptionalGraphPattern GroupGraphPattern
  | ServiceGraphPattern IRIRef GroupGraphPattern
  | UnionGraphPattern GroupGraphPattern GroupGraphPattern
  | SubQuery QueryData
  deriving (Int -> Pattern -> String -> String
[Pattern] -> String -> String
Pattern -> String
(Int -> Pattern -> String -> String)
-> (Pattern -> String)
-> ([Pattern] -> String -> String)
-> Show Pattern
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Pattern] -> String -> String
$cshowList :: [Pattern] -> String -> String
show :: Pattern -> String
$cshow :: Pattern -> String
showsPrec :: Int -> Pattern -> String -> String
$cshowsPrec :: Int -> Pattern -> String -> String
Show)

data GroupGraphPattern = GroupGraphPattern [Pattern]
  deriving (Int -> GroupGraphPattern -> String -> String
[GroupGraphPattern] -> String -> String
GroupGraphPattern -> String
(Int -> GroupGraphPattern -> String -> String)
-> (GroupGraphPattern -> String)
-> ([GroupGraphPattern] -> String -> String)
-> Show GroupGraphPattern
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [GroupGraphPattern] -> String -> String
$cshowList :: [GroupGraphPattern] -> String -> String
show :: GroupGraphPattern -> String
$cshow :: GroupGraphPattern -> String
showsPrec :: Int -> GroupGraphPattern -> String -> String
$cshowsPrec :: Int -> GroupGraphPattern -> String -> String
Show)

newtype GroupBy = GroupBy Expr
  deriving (Int -> GroupBy -> String -> String
[GroupBy] -> String -> String
GroupBy -> String
(Int -> GroupBy -> String -> String)
-> (GroupBy -> String)
-> ([GroupBy] -> String -> String)
-> Show GroupBy
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [GroupBy] -> String -> String
$cshowList :: [GroupBy] -> String -> String
show :: GroupBy -> String
$cshow :: GroupBy -> String
showsPrec :: Int -> GroupBy -> String -> String
$cshowsPrec :: Int -> GroupBy -> String -> String
Show)

data OrderBy
  = Asc Expr
  | Desc Expr
  deriving (Int -> OrderBy -> String -> String
[OrderBy] -> String -> String
OrderBy -> String
(Int -> OrderBy -> String -> String)
-> (OrderBy -> String)
-> ([OrderBy] -> String -> String)
-> Show OrderBy
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [OrderBy] -> String -> String
$cshowList :: [OrderBy] -> String -> String
show :: OrderBy -> String
$cshow :: OrderBy -> String
showsPrec :: Int -> OrderBy -> String -> String
$cshowsPrec :: Int -> OrderBy -> String -> String
Show)

-- Auxiliary, but fairly useful
-- TODO don't add to end
appendPattern :: Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern :: Pattern -> GroupGraphPattern -> GroupGraphPattern
appendPattern Pattern
p (GroupGraphPattern [Pattern]
ps) = [Pattern] -> GroupGraphPattern
GroupGraphPattern ([Pattern]
ps [Pattern] -> [Pattern] -> [Pattern]
forall a. [a] -> [a] -> [a]
++ [Item [Pattern]
Pattern
p])

appendTriple :: a -> [a] -> [a]
appendTriple :: a -> [a] -> [a]
appendTriple a
t [a]
ts = a
t a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
ts

data QueryData = QueryData
  { QueryData -> [Prefix]
prefixes :: [Prefix],
    QueryData -> Int
varsIdx :: Int,
    QueryData -> [SelectExpr]
vars :: [SelectExpr],
    QueryData -> QueryType
queryType :: QueryType,
    QueryData -> NonEmpty Int
subQueryIdx :: NonEmpty Int,
    QueryData -> GroupGraphPattern
pattern :: GroupGraphPattern,
    QueryData -> [Pattern]
constructTriples :: [Pattern], -- QTriple
    QueryData -> [Pattern]
askTriples :: [Pattern],
    QueryData -> [Pattern]
updateTriples :: [Pattern],
    QueryData -> Maybe IRIRef
describeURI :: Maybe IRIRef,
    QueryData -> Duplicates
duplicates :: Duplicates,
    QueryData -> [GroupBy]
groups :: [GroupBy],
    QueryData -> [OrderBy]
ordering :: [OrderBy],
    QueryData -> Limit
limits :: Limit
  }
  deriving (Int -> QueryData -> String -> String
[QueryData] -> String -> String
QueryData -> String
(Int -> QueryData -> String -> String)
-> (QueryData -> String)
-> ([QueryData] -> String -> String)
-> Show QueryData
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [QueryData] -> String -> String
$cshowList :: [QueryData] -> String -> String
show :: QueryData -> String
$cshow :: QueryData -> String
showsPrec :: Int -> QueryData -> String -> String
$cshowsPrec :: Int -> QueryData -> String -> String
Show)

data QueryType = SelectType | ConstructType | AskType | UpdateType | DescribeType | TypeNotSet
  deriving (Int -> QueryType -> String -> String
[QueryType] -> String -> String
QueryType -> String
(Int -> QueryType -> String -> String)
-> (QueryType -> String)
-> ([QueryType] -> String -> String)
-> Show QueryType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [QueryType] -> String -> String
$cshowList :: [QueryType] -> String -> String
show :: QueryType -> String
$cshow :: QueryType -> String
showsPrec :: Int -> QueryType -> String -> String
$cshowsPrec :: Int -> QueryType -> String -> String
Show)

data ConstructQuery = ConstructQuery
  {ConstructQuery -> [Pattern]
queryConstructs :: [Pattern]}

data AskQuery = AskQuery
  {AskQuery -> [Pattern]
queryAsk :: [Pattern]}

data UpdateQuery = UpdateQuery
  {UpdateQuery -> [Pattern]
queryUpdate :: [Pattern]}

data SelectQuery = SelectQuery
  {SelectQuery -> [SelectExpr]
queryExpr :: [SelectExpr]}

data DescribeQuery = DescribeQuery
  {DescribeQuery -> IRIRef
queryDescribe :: IRIRef}

-- QueryShow instances
instance QueryShow BlankNodePattern where
  qshow :: BlankNodePattern -> String
qshow [] = String
"[]"
  qshow BlankNodePattern
xs = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (DynamicPredicateObject -> String) -> BlankNodePattern -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap DynamicPredicateObject -> String
forall a. QueryShow a => a -> String
qshow BlankNodePattern
xs

instance QueryShow DynamicPredicateObject where
  qshow :: DynamicPredicateObject -> String
qshow (DynamicPredicate a
p, DynamicObject a
o) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [Item [String]
"[", a -> String
forall a. QueryShow a => a -> String
qshow a
p, Item [String]
" ", a -> String
forall a. QueryShow a => a -> String
qshow a
o, Item [String]
"]"]

instance QueryShow Duplicates where
  qshow :: Duplicates -> String
qshow Duplicates
NoLimits = String
""
  qshow Duplicates
Distinct = String
"DISTINCT"
  qshow Duplicates
Reduced = String
"REDUCED"

instance QueryShow Limit where
  qshow :: Limit -> String
qshow Limit
NoLimit = String
""
  qshow (Limit Int
n) = String
"Limit " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n

instance QueryShow RDF.Node where
  qshow :: Node -> String
qshow (RDF.UNode Text
n) = String
"<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
">"
  qshow (RDF.BNode Text
n) = String
"_:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
n
  qshow (RDF.BNodeGen Int
i) = String
"_:genid" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
  qshow (RDF.LNode LValue
n) = LValue -> String
forall a. QueryShow a => a -> String
qshow LValue
n

instance QueryShow RDF.LValue where
  qshow :: LValue -> String
qshow (RDF.PlainL Text
lit) = Text -> String
T.unpack (Text -> String) -> ([Text] -> Text) -> [Text] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat ([Text] -> String) -> [Text] -> String
forall a b. (a -> b) -> a -> b
$ [Item [Text]
"\"", Text -> Text
escapeSpecialChar Text
lit, Item [Text]
"\""]
  qshow (RDF.PlainLL Text
lit Text
lang_) = Text -> String
T.unpack (Text -> String) -> ([Text] -> Text) -> [Text] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat ([Text] -> String) -> [Text] -> String
forall a b. (a -> b) -> a -> b
$ [Item [Text]
"\"", Text -> Text
escapeSpecialChar Text
lit, Item [Text]
"\"@", Text
Item [Text]
lang_]
  qshow (RDF.TypedL Text
lit Text
dtype) = Text -> String
T.unpack (Text -> String) -> ([Text] -> Text) -> [Text] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat ([Text] -> String) -> [Text] -> String
forall a b. (a -> b) -> a -> b
$ [Item [Text]
"\"", Text -> Text
escapeSpecialChar Text
lit, Item [Text]
"\"^^<", Text
Item [Text]
dtype, Item [Text]
">"]

instance QueryShow Prefix where
  qshow :: Prefix -> String
qshow (Prefix Text
pre Node
ref) = String
"PREFIX " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Text -> String
T.unpack Text
pre) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Node -> String
forall a. QueryShow a => a -> String
qshow Node
ref

instance QueryShow [Prefix] where
  qshow :: [Prefix] -> String
qshow = [String] -> String
unwords ([String] -> String)
-> ([Prefix] -> [String]) -> [Prefix] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
forall a. [a] -> [a]
reverse ([String] -> [String])
-> ([Prefix] -> [String]) -> [Prefix] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Prefix -> String) -> [Prefix] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Prefix -> String
forall a. QueryShow a => a -> String
qshow

instance QueryShow Variable where
  qshow :: Variable -> String
qshow (Variable NonEmpty Int
vs) = String
"?x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
indexes
    where
      indexes :: String
indexes = [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String)
-> (NonEmpty Int -> [String]) -> NonEmpty Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String] -> [String]
forall a. a -> [a] -> [a]
intersperse String
"_" ([String] -> [String])
-> (NonEmpty Int -> [String]) -> NonEmpty Int -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> String) -> [Int] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> String
forall a. Show a => a -> String
show ([Int] -> [String])
-> (NonEmpty Int -> [Int]) -> NonEmpty Int -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Int -> [Int]
forall a. NonEmpty a -> [a]
NE.toList (NonEmpty Int -> String) -> NonEmpty Int -> String
forall a b. (a -> b) -> a -> b
$ NonEmpty Int
vs

instance QueryShow [Variable] where
  qshow :: [Variable] -> String
qshow = [String] -> String
unwords ([String] -> String)
-> ([Variable] -> [String]) -> [Variable] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Variable -> String) -> [Variable] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Variable -> String
forall a. QueryShow a => a -> String
qshow

instance QueryShow IRIRef where
  qshow :: IRIRef -> String
qshow (AbsoluteIRI Node
n) = Node -> String
forall a. QueryShow a => a -> String
qshow Node
n
  qshow (PrefixedName (Prefix Text
pre Node
_) Text
s) = (Text -> String
T.unpack Text
pre) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String -> String
escape (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
s)
    where
      escape :: String -> String
escape = (Char -> Bool) -> String -> String
URI.escapeURIString Char -> Bool
URI.isUnescapedInURIComponent

instance QueryShow (Maybe IRIRef) where
  qshow :: Maybe IRIRef -> String
qshow (Just IRIRef
r) = IRIRef -> String
forall a. QueryShow a => a -> String
qshow IRIRef
r
  qshow Maybe IRIRef
Nothing = String
""

instance QueryShow GraphTerm where
  qshow :: GraphTerm -> String
qshow (IRIRefTerm IRIRef
ref) = IRIRef -> String
forall a. QueryShow a => a -> String
qshow IRIRef
ref
  qshow (RDFLiteralTerm LValue
s) = LValue -> String
forall a. QueryShow a => a -> String
qshow LValue
s
  qshow (BooleanLiteralTerm Bool
True) = String -> String
forall a. Show a => a -> String
show (String
"true" :: String)
  qshow (BooleanLiteralTerm Bool
False) = String -> String
forall a. Show a => a -> String
show (String
"false" :: String)
  qshow (NumericLiteralTerm Integer
i) = Integer -> String
forall a. Show a => a -> String
show Integer
i
  qshow (BNode Maybe Text
Nothing) = String
"[]"
  qshow (BNode (Just Text
i)) = String
"_:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
i
  qshow (PropertyPathTerm PropertyPathExpr
p) = PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
p

instance QueryShow VarOrTerm where
  qshow :: VarOrTerm -> String
qshow (Var Variable
v) = Variable -> String
forall a. QueryShow a => a -> String
qshow Variable
v
  qshow (Term GraphTerm
t) = GraphTerm -> String
forall a. QueryShow a => a -> String
qshow GraphTerm
t
  qshow (EmbeddedTriple' VarOrTerm
a VarOrTerm
b VarOrTerm
c) = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" " [Item [String]
"<<", VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
a, VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
b, VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
c, Item [String]
">>"]
  qshow (BlankNodePattern' BlankNodePattern
bn) = BlankNodePattern -> String
forall a. QueryShow a => a -> String
qshow BlankNodePattern
bn

instance QueryShow [VarOrTerm] where
  qshow :: [VarOrTerm] -> String
qshow = [String] -> String
unwords ([String] -> String)
-> ([VarOrTerm] -> [String]) -> [VarOrTerm] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VarOrTerm -> String) -> [VarOrTerm] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow

instance QueryShow Operation where
  qshow :: Operation -> String
qshow Operation
Add = String
"+"
  qshow Operation
Subtract = String
"-"
  qshow Operation
Multiply = String
"*"
  qshow Operation
Divide = String
"/"
  qshow Operation
And = String
"&&"
  qshow Operation
Or = String
"||"

instance QueryShow NumericExpr where
  qshow :: NumericExpr -> String
qshow (NumericLiteralExpr Integer
n) = Integer -> String
forall a. Show a => a -> String
show Integer
n
  qshow (OperationExpr Operation
op Expr
x Expr
y) = Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ Operation -> String
forall a. QueryShow a => a -> String
qshow Operation
op String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
y

instance QueryShow Relation where
  qshow :: Relation -> String
qshow Relation
Equal = String
"="
  qshow Relation
NotEqual = String
"!="
  qshow Relation
LessThan = String
"<"
  qshow Relation
GreaterThan = String
">"
  qshow Relation
LessThanOrEqual = String
"<="
  qshow Relation
GreaterThanOrEqual = String
">="

instance QueryShow Function where
  qshow :: Function -> String
qshow Function
CountFunc = String
"COUNT"
  qshow Function
SumFunc = String
"SUM"
  qshow Function
MinFunc = String
"MIN"
  qshow Function
MaxFunc = String
"MAX"
  qshow Function
AvgFunc = String
"AVG"
  qshow Function
StrFunc = String
"STR"
  qshow Function
LangFunc = String
"LANG"
  qshow Function
LangMatchesFunc = String
"LANGMATCHES"
  qshow Function
DataTypeFunc = String
"DATATYPE"
  qshow Function
BoundFunc = String
"BOUND"
  qshow Function
SameTermFunc = String
"sameTerm"
  qshow Function
IsIRIFunc = String
"isIRI"
  qshow Function
IsURIFunc = String
"isURI"
  qshow Function
IsBlankFunc = String
"isBlank"
  qshow Function
IsLiteralFunc = String
"isLiteral"
  qshow Function
RegexFunc = String
"REGEX"
  qshow Function
StrLenFunc = String
"STRLEN"
  qshow Function
SubStrFunc = String
"SUBSTR"
  qshow Function
UcaseFunc = String
"UCASE"
  qshow Function
LcaseFunc = String
"LCASE"
  qshow Function
StrStartsFunc = String
"STRSTARTS"
  qshow Function
StrEndsFunc = String
"STARTENDS"
  qshow Function
ContainsFunc = String
"CONTAINS"
  qshow Function
StrBeforeFunc = String
"STRBEFORE"
  qshow Function
StrAfterFunc = String
"STRAFTER"
  qshow Function
ConcatFunc = String
"CONCAT"
  qshow Function
ReplaceFunc = String
"REPLACE"
  qshow Function
AbsFunc = String
"ABS"
  qshow Function
RoundFunc = String
"ROUND"
  qshow Function
CeilFunc = String
"CEIL"
  qshow Function
FloorFunc = String
"FLOOR"
  qshow Function
RandFunc = String
"RAND"

instance QueryShow ParameterizedFunction where
  qshow :: ParameterizedFunction -> String
qshow ParameterizedFunction
GroupConcat = String
"GROUP_CONCAT"

instance QueryShow Expr where
  qshow :: Expr -> String
qshow = Expr -> String
qshow'
    where
      qshow' :: Expr -> String
qshow' (VarOrTermExpr VarOrTerm
vt) = VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
vt
      qshow' (OrExpr [Expr]
es) = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" || " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (Expr -> String) -> [Expr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> String
forall a. QueryShow a => a -> String
qshow [Expr]
es
      qshow' (AndExpr [Expr]
es) = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" && " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (Expr -> String) -> [Expr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> String
forall a. QueryShow a => a -> String
qshow [Expr]
es
      qshow' (NegatedExpr Expr
e') = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Char
'!' Char -> String -> String
forall a. a -> [a] -> [a]
: Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e'
      qshow' (RelationalExpr Relation
rel Expr
e1 Expr
e2) = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ Relation -> String
forall a. QueryShow a => a -> String
qshow Relation
rel String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e2
      qshow' (NumericExpr NumericExpr
e') = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ NumericExpr -> String
forall a. QueryShow a => a -> String
qshow NumericExpr
e'
      qshow' (BuiltinCall Function
f [Expr]
es) = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Function -> String
forall a. QueryShow a => a -> String
qshow Function
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Expr -> String) -> [Expr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> String
forall a. QueryShow a => a -> String
qshow [Expr]
es) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
      qshow' (ParameterizedCall ParameterizedFunction
f [Expr]
es [(String, String)]
kwargs) = String -> String
wrap (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ ParameterizedFunction -> String
forall a. QueryShow a => a -> String
qshow ParameterizedFunction
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ((Expr -> String) -> [Expr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> String
forall a. QueryShow a => a -> String
qshow [Expr]
es) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ; " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ ((String, String) -> String) -> [(String, String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, String) -> String
pair [(String, String)]
kwargs) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
      wrap :: String -> String
wrap String
e = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
      pair :: (String, String) -> String
pair (String
k, String
v) = String
k String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
v

instance QueryShow SelectExpr where
  qshow :: SelectExpr -> String
qshow (SelectVar Variable
v) = Variable -> String
forall a. QueryShow a => a -> String
qshow Variable
v
  qshow (SelectExpr Expr
e Variable
v) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [Item [String]
"(", Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e, Item [String]
" AS ", Variable -> String
forall a. QueryShow a => a -> String
qshow Variable
v, Item [String]
")"]

instance QueryShow [SelectExpr] where
  qshow :: [SelectExpr] -> String
qshow = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" " ([String] -> String)
-> ([SelectExpr] -> [String]) -> [SelectExpr] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SelectExpr -> String) -> [SelectExpr] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SelectExpr -> String
forall a. QueryShow a => a -> String
qshow

instance QueryShow Pattern where
  qshow :: Pattern -> String
qshow (QTriple VarOrTerm
a VarOrTerm
b VarOrTerm
c) = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" " [VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
a, VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
b, VarOrTerm -> String
forall a. QueryShow a => a -> String
qshow VarOrTerm
c, Item [String]
"."]
  qshow (Filter Expr
e) = String
"FILTER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ."
  qshow (FilterExistsPattern GroupGraphPattern
p) = String
"FILTER EXISTS " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p
  qshow (FilterNotExistsPattern GroupGraphPattern
p) = String
"FILTER NOT EXISTS " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p
  qshow (Bind Expr
e Variable
v) = String
"BIND(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" AS " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Variable -> String
forall a. QueryShow a => a -> String
qshow Variable
v String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  qshow (OptionalGraphPattern GroupGraphPattern
p) = String
"OPTIONAL " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p
  qshow (ServiceGraphPattern IRIRef
endpoint GroupGraphPattern
p) = String
"SERVICE " String -> String -> String
forall a. [a] -> [a] -> [a]
++ IRIRef -> String
forall a. QueryShow a => a -> String
qshow IRIRef
endpoint String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p
  qshow (UnionGraphPattern GroupGraphPattern
p1 GroupGraphPattern
p2) = GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" UNION " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow GroupGraphPattern
p2
  qshow (SubQuery QueryData
qd) = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" " [Item [String]
"{ ", QueryData -> String
forall a. QueryShow a => a -> String
qshow QueryData
qd, Item [String]
" }"]

instance QueryShow [Pattern] where
  qshow :: [Pattern] -> String
qshow = [String] -> String
unwords ([String] -> String)
-> ([Pattern] -> [String]) -> [Pattern] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Pattern -> String) -> [Pattern] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pattern -> String
forall a. QueryShow a => a -> String
qshow

instance QueryShow GroupGraphPattern where
  qshow :: GroupGraphPattern -> String
qshow (GroupGraphPattern [Pattern]
ps) = String
"{ " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Pattern] -> String
forall a. QueryShow a => a -> String
qshow [Pattern]
ps String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" }"

instance QueryShow GroupBy where
  qshow :: GroupBy -> String
qshow (GroupBy Expr
e) = Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e

instance QueryShow [GroupBy] where
  qshow :: [GroupBy] -> String
qshow [] = String
""
  qshow [GroupBy]
gs = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String
"GROUP BY" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (GroupBy -> String) -> [GroupBy] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap GroupBy -> String
forall a. QueryShow a => a -> String
qshow [GroupBy]
gs

instance QueryShow OrderBy where
  qshow :: OrderBy -> String
qshow (Asc Expr
e) = String
"ASC(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  qshow (Desc Expr
e) = String
"DESC(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. QueryShow a => a -> String
qshow Expr
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

instance QueryShow [OrderBy] where
  qshow :: [OrderBy] -> String
qshow [] = String
""
  qshow [OrderBy]
os = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String
"ORDER BY" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (OrderBy -> String) -> [OrderBy] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap OrderBy -> String
forall a. QueryShow a => a -> String
qshow [OrderBy]
os

instance QueryShow QueryData where
  qshow :: QueryData -> String
qshow QueryData
qd = String
query
    where
      prefixDecl :: String
prefixDecl = [Prefix] -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> [Prefix]
prefixes QueryData
qd)
      whereClause :: String
whereClause = [String] -> String
unwords [Item [String]
"WHERE", GroupGraphPattern -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> GroupGraphPattern
pattern QueryData
qd)]
      groupClause :: String
groupClause = [GroupBy] -> String
forall a. QueryShow a => a -> String
qshow ([GroupBy] -> String)
-> (QueryData -> [GroupBy]) -> QueryData -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryData -> [GroupBy]
groups (QueryData -> String) -> QueryData -> String
forall a b. (a -> b) -> a -> b
$ QueryData
qd
      -- TODO: HAVING clause
      orderClause :: String
orderClause = [OrderBy] -> String
forall a. QueryShow a => a -> String
qshow ([OrderBy] -> String)
-> (QueryData -> [OrderBy]) -> QueryData -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryData -> [OrderBy]
ordering (QueryData -> String) -> QueryData -> String
forall a b. (a -> b) -> a -> b
$ QueryData
qd
      -- TODO: Offset
      limitOffsetClauses :: String
limitOffsetClauses = Limit -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> Limit
limits QueryData
qd)
      solutionModifier :: String
solutionModifier = [String] -> String
unwords' [String
Item [String]
groupClause, String
Item [String]
orderClause, String
Item [String]
limitOffsetClauses]
      query :: String
query = case QueryData -> QueryType
queryType QueryData
qd of
        QueryType
SelectType ->
          [String] -> String
unwords'
            [ String
Item [String]
prefixDecl,
              Item [String]
"SELECT",
              Duplicates -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> Duplicates
duplicates QueryData
qd),
              [SelectExpr] -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> [SelectExpr]
vars QueryData
qd),
              String
Item [String]
whereClause,
              String
Item [String]
solutionModifier
            ]
        QueryType
ConstructType ->
          [String] -> String
unwords
            [ String
Item [String]
prefixDecl,
              Item [String]
"CONSTRUCT {",
              [Pattern] -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> [Pattern]
constructTriples QueryData
qd),
              Item [String]
"}",
              String
Item [String]
whereClause
            ]
        QueryType
DescribeType ->
          [String] -> String
unwords
            [ String
Item [String]
prefixDecl,
              Item [String]
"DESCRIBE",
              Maybe IRIRef -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> Maybe IRIRef
describeURI QueryData
qd),
              String
Item [String]
whereClause
            ]
        QueryType
AskType ->
          [String] -> String
unwords
            [ String
Item [String]
prefixDecl,
              Item [String]
"ASK {",
              [Pattern] -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> [Pattern]
askTriples QueryData
qd),
              Item [String]
"}"
            ]
        QueryType
UpdateType ->
          [String] -> String
unwords
            [ String
Item [String]
prefixDecl,
              Item [String]
"INSERT DATA {",
              [Pattern] -> String
forall a. QueryShow a => a -> String
qshow (QueryData -> [Pattern]
updateTriples QueryData
qd),
              Item [String]
"}"
            ]
        -- FIXME
        QueryType
TypeNotSet ->
          String -> String
forall a. HasCallStack => String -> a
error String
"instance QueryShow QueryData: TypeNotSet not supported."

-- Internal utilities
escapeSpecialChar :: T.Text -> T.Text
escapeSpecialChar :: Text -> Text
escapeSpecialChar = (Char -> Text) -> Text -> Text
T.concatMap Char -> Text
handleChar
  where
    -- FIXME: probably more cases to handle
    handleChar :: Char -> Text
handleChar Char
'\n' = Text
"\n"
    handleChar Char
'\t' = Text
"\t"
    handleChar Char
'\r' = Text
"\r"
    handleChar Char
'"' = Text
"\\\""
    handleChar Char
'\\' = Text
"\\\\"
    handleChar Char
c = Char -> Text
T.singleton Char
c

-- | Alternative version of 'unwords' that avoid adding spaces on empty strings.
{-# NOINLINE [1] unwords' #-}
unwords' :: [String] -> String
unwords' :: [String] -> String
unwords' [] = String
""
unwords' (String
"" : [String]
ws) = [String] -> String
unwords' [String]
ws
unwords' (String
w : [String]
ws) = String
w String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
go [String]
ws
  where
    go :: [String] -> String
go [] = String
""
    go (String
"" : [String]
vs) = [String] -> String
go [String]
vs
    go (String
v : [String]
vs) = Char
' ' Char -> String -> String
forall a. a -> [a] -> [a]
: (String
v String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
go [String]
vs)

-- | Append a element to a 'NonEmpty' list.
(|>) :: NonEmpty a -> a -> NonEmpty a
NonEmpty a
xs |> :: NonEmpty a -> a -> NonEmpty a
|> a
x = [a] -> NonEmpty a
forall a. [a] -> NonEmpty a
NE.fromList ([a] -> NonEmpty a) -> [a] -> NonEmpty a
forall a b. (a -> b) -> a -> b
$ NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty a
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
Item [a]
x]

-- Property paths

-- | Permit different type of property path expressions to be seemlessly be put
--  into arguments for '(.//.)' and similar functions.
class PropertyPathExprLike a where
  propertyPathExpr :: a -> PropertyPathExpr

-- | Possible expressions in a SPARQL property path.
data PropertyPathExpr
  = -- | Property path of length one expression. Ex. @rdf:type@
    PathLengthOneExpr PathLengthOne
  | -- | Ex. @foaf:knows/foaf:knows@
    SequencePathExpr PropertyPathExpr PropertyPathExpr
  | -- | Ex. @^foaf:knows@
    InversePathExpr PropertyPathExpr
  | -- | Ex. @rdfs:label|foaf:name@
    AlternativePathExpr PropertyPathExpr PropertyPathExpr
  | -- | Ex. @rdf:type/rdfs:subClassOf*@
    ZeroOrMorePathExpr PropertyPathExpr
  | -- | Ex. @foaf:knows+@
    OneOrMorePathExpr PropertyPathExpr
  | -- | Ex. @rdf:type/rdfs:subClassOf?@
    ZeroOrOnePathExpr PropertyPathExpr
  | -- | Ex. @!(rdf:type|^rdf:type)@
    NegativePropertySetExpr NegativePropertySet
  deriving (Int -> PropertyPathExpr -> String -> String
[PropertyPathExpr] -> String -> String
PropertyPathExpr -> String
(Int -> PropertyPathExpr -> String -> String)
-> (PropertyPathExpr -> String)
-> ([PropertyPathExpr] -> String -> String)
-> Show PropertyPathExpr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PropertyPathExpr] -> String -> String
$cshowList :: [PropertyPathExpr] -> String -> String
show :: PropertyPathExpr -> String
$cshow :: PropertyPathExpr -> String
showsPrec :: Int -> PropertyPathExpr -> String -> String
$cshowsPrec :: Int -> PropertyPathExpr -> String -> String
Show)

-- instance PredicateTermLike PropertyPathExpr

-- | Possible expressions in a negated property set.
data NegativePropertySet
  = NegativePropertySetPath PathLengthOne NegativePropertySet
  | NegativePropertySetPathOne PathLengthOne
  deriving (Int -> NegativePropertySet -> String -> String
[NegativePropertySet] -> String -> String
NegativePropertySet -> String
(Int -> NegativePropertySet -> String -> String)
-> (NegativePropertySet -> String)
-> ([NegativePropertySet] -> String -> String)
-> Show NegativePropertySet
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [NegativePropertySet] -> String -> String
$cshowList :: [NegativePropertySet] -> String -> String
show :: NegativePropertySet -> String
$cshow :: NegativePropertySet -> String
showsPrec :: Int -> NegativePropertySet -> String -> String
$cshowsPrec :: Int -> NegativePropertySet -> String -> String
Show)

instance QueryShow NegativePropertySet where
  qshow :: NegativePropertySet -> String
qshow (NegativePropertySetPath PathLengthOne
p NegativePropertySet
ps) = PathLengthOne -> String
forall a. QueryShow a => a -> String
qshow PathLengthOne
p String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"|" String -> String -> String
forall a. [a] -> [a] -> [a]
++ NegativePropertySet -> String
forall a. QueryShow a => a -> String
qshow NegativePropertySet
ps
  qshow (NegativePropertySetPathOne PathLengthOne
p) = PathLengthOne -> String
forall a. QueryShow a => a -> String
qshow PathLengthOne
p

instance Semigroup NegativePropertySet where
  (NegativePropertySetPathOne PathLengthOne
p1) <> :: NegativePropertySet -> NegativePropertySet -> NegativePropertySet
<> NegativePropertySet
p2 = PathLengthOne -> NegativePropertySet -> NegativePropertySet
NegativePropertySetPath PathLengthOne
p1 NegativePropertySet
p2
  (NegativePropertySetPath PathLengthOne
p1 NegativePropertySet
ps) <> NegativePropertySet
p2 = PathLengthOne -> NegativePropertySet -> NegativePropertySet
NegativePropertySetPath PathLengthOne
p1 (NegativePropertySet
ps NegativePropertySet -> NegativePropertySet -> NegativePropertySet
forall a. Semigroup a => a -> a -> a
<> NegativePropertySet
p2)

instance PropertyPathExprLike PropertyPathExpr where
  propertyPathExpr :: PropertyPathExpr -> PropertyPathExpr
propertyPathExpr = PropertyPathExpr -> PropertyPathExpr
forall a. a -> a
id

-- newtype IRIRef = IRIRef Text

-- instance Show IRIRef where
--   show (IRIRef iri) = unpack iri

instance PropertyPathExprLike IRIRef where
  propertyPathExpr :: IRIRef -> PropertyPathExpr
propertyPathExpr = PathLengthOne -> PropertyPathExpr
PathLengthOneExpr (PathLengthOne -> PropertyPathExpr)
-> (IRIRef -> PathLengthOne) -> IRIRef -> PropertyPathExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IRIRef -> PathLengthOne
PathLengthOneIRI

data PathLengthOne
  = PathLengthOneIRI IRIRef
  | PathLengthOneA
  | PathLengthOneInverse PathLengthOne
  deriving (Int -> PathLengthOne -> String -> String
[PathLengthOne] -> String -> String
PathLengthOne -> String
(Int -> PathLengthOne -> String -> String)
-> (PathLengthOne -> String)
-> ([PathLengthOne] -> String -> String)
-> Show PathLengthOne
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PathLengthOne] -> String -> String
$cshowList :: [PathLengthOne] -> String -> String
show :: PathLengthOne -> String
$cshow :: PathLengthOne -> String
showsPrec :: Int -> PathLengthOne -> String -> String
$cshowsPrec :: Int -> PathLengthOne -> String -> String
Show)

instance PropertyPathExprLike PathLengthOne where
  propertyPathExpr :: PathLengthOne -> PropertyPathExpr
propertyPathExpr PathLengthOne
p = PathLengthOne -> PropertyPathExpr
PathLengthOneExpr PathLengthOne
p

instance NegativePropertySetLike PathLengthOne where
  negativePropertySet :: PathLengthOne -> NegativePropertySet
negativePropertySet PathLengthOne
p = PathLengthOne -> NegativePropertySet
NegativePropertySetPathOne PathLengthOne
p

instance QueryShow PropertyPathExpr where
  qshow :: PropertyPathExpr -> String
qshow (PathLengthOneExpr PathLengthOne
p) = PathLengthOne -> String
forall a. QueryShow a => a -> String
qshow PathLengthOne
p
  qshow (SequencePathExpr PropertyPathExpr
pexpr1 PropertyPathExpr
pexpr2) =
    String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr2 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  qshow (InversePathExpr PropertyPathExpr
pexpr) = String
"(^" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  qshow (AlternativePathExpr PropertyPathExpr
pexpr1 PropertyPathExpr
pexpr2) =
    String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"|" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr2 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
  qshow (ZeroOrMorePathExpr PropertyPathExpr
pexpr) = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"*)"
  qshow (OneOrMorePathExpr PropertyPathExpr
pexpr) = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"+)"
  qshow (ZeroOrOnePathExpr PropertyPathExpr
pexpr) = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PropertyPathExpr -> String
forall a. QueryShow a => a -> String
qshow PropertyPathExpr
pexpr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"?)"
  qshow (NegativePropertySetExpr NegativePropertySet
p) = String
"!(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ NegativePropertySet -> String
forall a. QueryShow a => a -> String
qshow NegativePropertySet
p String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

instance QueryShow PathLengthOne where
  qshow :: PathLengthOne -> String
qshow (PathLengthOneIRI IRIRef
iri) = IRIRef -> String
forall a. QueryShow a => a -> String
qshow IRIRef
iri
  qshow PathLengthOne
PathLengthOneA = String
"a"
  qshow (PathLengthOneInverse PathLengthOne
p) = String
"^" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PathLengthOne -> String
forall a. QueryShow a => a -> String
qshow PathLengthOne
p

class NegativePropertySetLike a where
  negativePropertySet :: a -> NegativePropertySet

instance NegativePropertySetLike IRIRef where
  negativePropertySet :: IRIRef -> NegativePropertySet
negativePropertySet IRIRef
iri = PathLengthOne -> NegativePropertySet
NegativePropertySetPathOne (PathLengthOne -> NegativePropertySet)
-> PathLengthOne -> NegativePropertySet
forall a b. (a -> b) -> a -> b
$ IRIRef -> PathLengthOne
PathLengthOneIRI IRIRef
iri

instance NegativePropertySetLike NegativePropertySet where
  negativePropertySet :: NegativePropertySet -> NegativePropertySet
negativePropertySet NegativePropertySet
ps = NegativePropertySet
ps

-- | Creating a property path sequence.
--
--  >>> IRIRef "rdf:type" ./. IRIRef "rdfs:subClassOf" ./. IRIRef "rdfs:subClassOf"
--  rdf:type/rdfs:subClassOf/rdfs:subClassOf
infixl 5 .//.

(.//.) ::
  (PropertyPathExprLike a, PropertyPathExprLike b) =>
  a ->
  b ->
  PropertyPathExpr
a
x .//. :: a -> b -> PropertyPathExpr
.//. b
y = PropertyPathExpr -> PropertyPathExpr -> PropertyPathExpr
SequencePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
x) (b -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr b
y)

-- | Creating an alternative property path.
--
--  >>> IRIRef "rdfs:label" .|. IRIRef "foaf:name" .|. IRIRef "foaf:givenName
--  rdfs:label|foaf:name|foaf:givenName
infixl 4 .|.

(.|.) ::
  (PropertyPathExprLike a, PropertyPathExprLike b) =>
  a ->
  b ->
  PropertyPathExpr
a
x .|. :: a -> b -> PropertyPathExpr
.|. b
y = PropertyPathExpr -> PropertyPathExpr -> PropertyPathExpr
AlternativePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
x) (b -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr b
y)

-- | Creating an alternative property path inside a negative property set.
--
--  >>> neg $ IRIRef "rdfs:label" ..|.. IRIRef "foaf:name" ..|.. IRIRef "foaf:givenName"
--  !(rdfs:label|foaf:name|foaf:givenName)
infixl 4 ..|..

(..|..) ::
  (NegativePropertySetLike a, NegativePropertySetLike b) =>
  a ->
  b ->
  NegativePropertySet
a
p1 ..|.. :: a -> b -> NegativePropertySet
..|.. b
p2 = a -> NegativePropertySet
forall a. NegativePropertySetLike a => a -> NegativePropertySet
negativePropertySet a
p1 NegativePropertySet -> NegativePropertySet -> NegativePropertySet
forall a. Semigroup a => a -> a -> a
<> b -> NegativePropertySet
forall a. NegativePropertySetLike a => a -> NegativePropertySet
negativePropertySet b
p2

-- | Creating an inverse property path.
--
--  >>> inv (IRIRef "foaf:mbox")
--  ^foaf:mbox
inv :: PropertyPathExprLike a => a -> PropertyPathExpr
inv :: a -> PropertyPathExpr
inv a
p = PropertyPathExpr -> PropertyPathExpr
InversePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
p)

-- | Creating an inverse path of length one inside a negative property set.
--
--  >>> neg $ IRIRef "rdfs:label" ..|.. IRIRef "foaf:name" ..|.. (inv' $ IRIRef "foaf:givenName")
--  !(rdfs:label|foaf:name|^foaf:givenName)
inv' :: NegativePropertySetLike a => a -> NegativePropertySet
inv' :: a -> NegativePropertySet
inv' a
p = case a -> NegativePropertySet
forall a. NegativePropertySetLike a => a -> NegativePropertySet
negativePropertySet a
p of
  NegativePropertySetPathOne PathLengthOne
p1 ->
    PathLengthOne -> NegativePropertySet
NegativePropertySetPathOne (PathLengthOne -> PathLengthOne
PathLengthOneInverse PathLengthOne
p1)
  NegativePropertySetPath PathLengthOne
p1 NegativePropertySet
ps ->
    PathLengthOne -> NegativePropertySet -> NegativePropertySet
NegativePropertySetPath (PathLengthOne -> PathLengthOne
PathLengthOneInverse PathLengthOne
p1) NegativePropertySet
ps

-- | Creating a negative property set.
--
--  >>> inv foafMbox
--  ^foaf:mbox
neg :: NegativePropertySet -> PropertyPathExpr
neg :: NegativePropertySet -> PropertyPathExpr
neg = NegativePropertySet -> PropertyPathExpr
NegativePropertySetExpr

-- | Variable "a" representing the @rdf:type@ property.
a :: PathLengthOne
a :: PathLengthOne
a = PathLengthOne
PathLengthOneA

-- | Creating a zero or more path.
--
--  >>> IRIRef "rdf:type" ./. ((IRIRef "rdfs:subClassOf") *.)
--  rdf:type/rdfs:subClassOf*
(*.) :: PropertyPathExprLike a => a -> PropertyPathExpr
*. :: a -> PropertyPathExpr
(*.) a
p = PropertyPathExpr -> PropertyPathExpr
ZeroOrMorePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
p)

-- | Creating a one or more path.
--
--  >>> ((IRIRef "foaf:knows") +.) ./. IRIRef "foaf:name"
--  foaf:knows+/foaf:name
(+.) :: PropertyPathExprLike a => a -> PropertyPathExpr
+. :: a -> PropertyPathExpr
(+.) a
p = PropertyPathExpr -> PropertyPathExpr
OneOrMorePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
p)

-- | Creating a zero or one path.
--
--  >>> rdfType ./. (rdfsSubClassOf ?.)
--  rdf:type/rdfs:subClassOf?
(?.) :: PropertyPathExprLike a => a -> PropertyPathExpr
?. :: a -> PropertyPathExpr
(?.) a
p = PropertyPathExpr -> PropertyPathExpr
ZeroOrOnePathExpr (a -> PropertyPathExpr
forall a. PropertyPathExprLike a => a -> PropertyPathExpr
propertyPathExpr a
p)