/api/query.py
Python | 137 lines | 82 code | 3 blank | 52 comment | 2 complexity | 46898dd7003804b6551e9b34debdd094 MD5 | raw file
- """
- Query.py - includes query handlers
- doing query, rest-server expect those params:
- query - The query to be executed. The query may use the namespace prefixes defined for the user.
- queryLn - The language of the query. Can be sparql or prolog. Defaults to sparql.
- infer - A string that determines what kind of reasoning is used when executing the query.
- Default is false, no reasoning. Other options are rdfs++ (same as true),
- and hasvalue.
- context - Can be passed zero or more times. Sets the graph name, or list of graph names,
- that will be used by this query (as in FROM).
- When no context is given, all graphs are used.
- The string null can be used to refer to the default graph of the store.
- namedContext - Also can be given multiple times.
- Behaves like context, except that the named graphs retain their
- names (as in FROM NAMED).
- default-graph-uri - Can be passed any number of times.
- Works like context except that plain-URI values should be given,
- without wrapping < and > characters.
- named-graph-uri - Works like default-graph-uri, except that this specifies the named
- graphs to be used.
- limit - An integer. Can be used to limit the amount of results returned by the query.
- offset - An integer. Can be used to skip a number of results at the start of the query.
- $[varname] - Parameters starting with a $ character can be used to bind query variables
- to fixed value (an N-Triples term) when executing a SPARQL query.
- checkVariables - A boolean that defaults to false, indicating whether an error should be
- raised when a SPARQL query selects variables that are not mentioned in the query body.
- defaultGraphName - Can be used to provide a resource (URL) name for the default graph.
- Any references to that resource will reference the default graph, and in the
- output the resource will be substituted for any references to the default graph.
- Can be given multiple times to have multiple names refer to this graph,
- but only the first one will appear in the output.
- planner - Can be used to control the way the query is planned .
- save - When given, will cause the server to (as well as executing the query normally)
- save the query as a prepared query under the name passed as the value for this parameter. See preparing queries below.
- The result formats supported depends on the query. Prolog queries return tabular data,
- as do SPARQL select queries. describe or construct queries return triples, and ask queries
- return a boolean value.
- Prolog queries are allowed to return nested lists of results, in which case the result
- can only be returned as application/json, and the nested structure (both in the list of
- column names and in the results themselves) will be represented as nested JSON arrays.
- """
- class Param(object):
- """
- This class maps python objects with AllegroGraph params, this class is important
- because Agraph params dont follow any logic,sometimes variables are camelCased and
- another time they separates-variables-with-minus
- """
- #TODO: default decoder to unicode
- def __init__(self, name, value, decoder = lambda x: str(x)):
- self.name = name
- self.value = value #TODO; test different values -utf8
- self.decoder = decoder
- def _unicode(val):
- """decodes strings to unicode"""
- return val
- def __str__(self):
- """serialize object as string, skips param, which value is just None"""
- if self.value:
- val = "%s=%s" % (self.name, self.decoder(self.value))
- else:
- val = ""
- return val
- class AllegroQuery(object):
- """prolog/sparql queries returns tabular data,
- describe/construct - triples
- ask - boolean,
- sparql/update queries need POST method
- """
- def __init__(self, query, **kwargs):
- self.query = Param("query", query, lambda x: str(x))
- self.qlanq = Param("queryLn", kwargs.get("qlang", "sparql"),
- lambda x: str(x)) #'sparql', 'prolog'
- self.infer = Param("infer", kwargs.get("infer", False),
- lambda x: str(x).lower())
- self.context = Param("context", kwargs.get("context", None)) #"null"
- self.named_context = Param("namedContext",kwargs.get("named_context", None))
- self.limit = Param("limit", kwargs.get("limit", None))
- self.offset = Param("offset", kwargs.get("offset", None))
- self.check_variables = Param("checkVariables",
- kwargs.get("check_variables", False),
- lambda x: str(x).lower())
- self.default_graph = Param("defaultGraphName", kwargs.get("default_graph", None))
- self.planner = Param("planner", kwargs.get("planner", None))
- self.save = Param("save", kwargs.get("save", None),
- lambda x: str(x).lower())
- def serialize(self, separator = ","):
- """object to string"""
- result = separator
- for key in self.__dict__.iterkeys():
- val = self.__dict__[key]
- if isinstance(val, Param) and val.value is not None:
- result.join(str(val))
- return result
- def to_dict(self):
- """build dictionary from class"""
- result = {}
- for key in self.__dict__.iterkeys():
- val = self.__dict__[key]
- #add only values which are not None and Param instance, that means will be part
- #of query arguments
- if isinstance(val, Param) and val.value is not None:
- result[val.name] = val.decoder(val.value)
- return result
- #TODO: add execute and save functionality - integrate with Queries
- class PrologQuery(AllegroQuery):
- def __init__(self, query, **kwargs ):
- """
- Args:
- query - query string
- infer - boolean, do you need infer rules
- """
- self.type = "prolog"
- kwargs["qlang"] = self.type
- super(PrologQuery, self).__init__(query, **kwargs)
- class SparqlQuery(AllegroQuery):
- """ """
- def __init__(self, query, **kwargs):
- self.type = "sparql"
- kwargs["qlang"] = self.type
- super(SparqlQuery, self).__init__(query, **kwargs)
- class StatementQuery(object):
- '''object to represent query for asking statements from DB'''
- pass