spa2rql.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 23 Jul 2009 12:08:39 +0200
changeset 2430 7d9ed6c740ec
parent 2427 3e0ef847a546
child 2431 93c061eac647
permissions -rw-r--r--
cleanup/document/refactor
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     1
"""SPARQL -> RQL translator
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     2
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     4
:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     7
"""
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     8
from logilab.common import make_domains
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     9
from rql import TypeResolverException
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    10
from fyzz.yappsparser import parse
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    11
from fyzz import ast
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    12
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    13
from cubicweb.xy import xy
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    14
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    15
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    16
class UnsupportedQuery(Exception): pass
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    17
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    18
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    19
class QueryInfo(object):
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    20
    """wrapper class containing necessary information to generate a RQL query
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    21
    from a sparql syntax tree
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    22
    """
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    23
    def __init__(self, sparqlst):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    24
        self.sparqlst = sparqlst
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    25
        if sparqlst.selected == ['*']:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    26
            self.selection = [var.upper() for var in sparqlst.variables]
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    27
        else:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    28
            self.selection = [var.name.upper() for var in sparqlst.selected]
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    29
        self.possible_types = {}
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    30
        self.infer_types_info = []
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    31
        self.union_params = []
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    32
        self.restrictions = []
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    33
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    34
    def finalize(self):
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    35
        """return corresponding rql query"""
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    36
        for varname, ptypes in self.possible_types.iteritems():
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    37
            if len(ptypes) == 1:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    38
                self.restrictions.append('%s is %s' % (varname, iter(ptypes).next()))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    39
        unions = []
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    40
        for releq, subjvar, objvar in self.union_params:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    41
            thisunions = []
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    42
            for st, rt, ot in releq:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    43
                thisunions.append(['%s %s %s' % (subjvar, rt, objvar)])
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    44
                if st != '*':
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    45
                    thisunions[-1].append('%s is %s' % (subjvar, st))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    46
                if ot != '*':
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    47
                    thisunions[-1].append('%s is %s' % (objvar, ot))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    48
            if not unions:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    49
                unions = thisunions
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    50
            else:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    51
                unions = zip(*make_domains([unions, thisunions]))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    52
        baserql = 'Any %s WHERE %s' % (', '.join(self.selection),
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    53
                                       ', '.join(self.restrictions))
2427
3e0ef847a546 distinct / reduced support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2422
diff changeset
    54
        if self.sparqlst.distinct:
3e0ef847a546 distinct / reduced support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2422
diff changeset
    55
            baserql = 'DISTINCT ' + baserql
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    56
        if not unions:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    57
            return baserql
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    58
        rqls = ['(%s, %s)' % (baserql, ', '.join(unionrestrs))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    59
                for unionrestrs in unions]
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    60
        return ' UNION '.join(rqls)
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    61
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    62
    def set_possible_types(self, var, varpossibletypes):
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    63
        """set/restrict possible types for the given variable.
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    64
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    65
        :return: True if something changed, else false.
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    66
        :raise: TypeResolverException if no more type allowed
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    67
        """
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    68
        varpossibletypes = set(varpossibletypes)
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    69
        try:
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    70
            ctypes = self.possible_types[var]
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    71
            nbctypes = len(ctypes)
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    72
            ctypes &= varpossibletypes
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    73
            if not ctypes:
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    74
                raise TypeResolverException()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    75
            return len(ctypes) != nbctypes
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    76
        except KeyError:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    77
            self.possible_types[var] = varpossibletypes
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    78
            return True
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    79
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    80
    def infer_types(self):
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    81
        # XXX should use something similar to rql.analyze for proper type inference
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    82
        modified = True
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    83
        # loop to infer types until nothing changed
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    84
        while modified:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    85
            modified = False
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    86
            for yams_predicates, subjvar, obj in self.infer_types_info:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    87
                nbchoices = len(yams_predicates)
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    88
                # get possible types for the subject variable, according to the
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    89
                # current predicate
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    90
                svptypes = set(s for s, r, o in yams_predicates)
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    91
                if not '*' in svptypes:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    92
                    if self.set_possible_types(subjvar, svptypes):
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    93
                        modified = True
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    94
                # restrict predicates according to allowed subject var types
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    95
                if subjvar in self.possible_types:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    96
                    yams_predicates = [(s, r, o) for s, r, o in yams_predicates
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    97
                                       if s == '*' or s in self.possible_types[subjvar]]
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    98
                if isinstance(obj, ast.SparqlVar):
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
    99
                    # make a valid rql var name
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   100
                    objvar = obj.name.upper()
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   101
                    # get possible types for the object variable, according to
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   102
                    # the current predicate
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   103
                    ovptypes = set(o for s, r, o in yams_predicates)
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   104
                    if not '*' in ovptypes:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   105
                        if self.set_possible_types(objvar, ovptypes):
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   106
                            modified = True
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   107
                    # restrict predicates according to allowed object var types
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   108
                    if objvar in self.possible_types:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   109
                        yams_predicates = [(s, r, o) for s, r, o in yams_predicates
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   110
                                           if o == '*' or o in self.possible_types[objvar]]
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   111
                # ensure this still make sense
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   112
                if not yams_predicates:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   113
                    raise TypeResolverException()
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   114
                if len(yams_predicates) != nbchoices:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   115
                    modified = True
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   116
        # now, for each predicate
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   117
        for yams_predicates, subjvar, obj in self.infer_types_info:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   118
            rel = yams_predicates[0]
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   119
            objvar = obj.name.upper()
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   120
            # if there are several yams relation type equivalences, we will have
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   121
            # to generate several unioned rql queries
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   122
            for s, r, o in yams_predicates[1:]:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   123
                if r != rel[1]:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   124
                    self.union_params.append((yams_predicates, subjvar, objvar))
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   125
                    break
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   126
            else:
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   127
                # else we can simply add it to base rql restrictions
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   128
                self.restrictions.append('%s %s %s' % (subjvar, rel[1], objvar))
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   129
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   130
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   131
class Sparql2rqlTranslator(object):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   132
    def __init__(self, yschema):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   133
        self.yschema = yschema
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   134
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   135
    def translate(self, sparql):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   136
        sparqlst = parse(sparql)
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   137
        if sparqlst.type != 'select':
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   138
            raise UnsupportedQuery()
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   139
        qi = QueryInfo(sparqlst)
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   140
        for subj, predicate, obj in sparqlst.where:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   141
            if not isinstance(subj, ast.SparqlVar):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   142
                raise UnsupportedQuery()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   143
            # make a valid rql var name
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   144
            subjvar = subj.name.upper()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   145
            if predicate == ('', 'a'):
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   146
                # special 'is' relation
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   147
                if not isinstance(obj, tuple):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   148
                    raise UnsupportedQuery()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   149
                # restrict possible types for the subject variable
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   150
                qi.set_possible_types(
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   151
                    subjvar, xy.yeq(':'.join(obj), isentity=True))
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   152
            else:
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   153
                # 'regular' relation (eg not 'is')
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   154
                if not isinstance(predicate, tuple):
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   155
                    raise UnsupportedQuery()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   156
                # list of 3-uple
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   157
                #   (yams etype (subject), yams rtype, yams etype (object))
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   158
                # where subject / object entity type may '*' if not specified
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   159
                yams_predicates = xy.yeq(':'.join(predicate))
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   160
                qi.infer_types_info.append((yams_predicates, subjvar, obj))
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   161
                if isinstance(obj, ast.SparqlVar):
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   162
                    # make a valid rql var name
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   163
                    objvar = obj.name.upper()
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   164
                else:
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   165
                    raise UnsupportedQuery()
2430
7d9ed6c740ec cleanup/document/refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2427
diff changeset
   166
        qi.infer_types()
2422
96da7dc42eb5 quick and dirty support from simple sparql queries + base ui
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   167
        return qi