server/msplanner.py
author sylvain.thenault@logilab.fr
Sat, 04 Apr 2009 13:21:56 +0200
changeset 1230 232e16835fff
parent 1229 dd9bdcfc03b6
child 1231 1457a545af03
permissions -rw-r--r--
fix constant handling in sourcesterms + minor cleanup
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     1
"""plan execution of rql queries on multiple sources
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
     3
the best way to understand what are we trying to acheive here is to read the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
     4
unit-tests in unittest_msplanner.py
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     5
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
     6
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
     7
What you need to know
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
     8
~~~~~~~~~~~~~~~~~~~~~
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
     9
1. The system source is expected  to support every entity and relation types
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    10
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    11
2. Given "X relation Y":
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    12
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    13
   * if relation, X and Y types are supported by the external source, we suppose
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    14
     by default that X and Y should both come from the same source as the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    15
     relation. You can specify otherwise by adding relation into the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    16
     "cross_relations" set in the source's mapping file and it that case, we'll
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    17
     consider that we can also find in the system source some relation between
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    18
     X and Y coming from different sources.
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    19
     
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    20
   * if "relation" isn't supported by the external source but X or Y
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    21
     types (or both) are, we suppose by default that can find in the system
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    22
     source some relation where X and/or Y come from the external source. You
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    23
     can specify otherwise by adding relation into the "dont_cross_relations"
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    24
     set in the source's mapping file and it that case, we'll consider that we
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    25
     can only find in the system source some relation between X and Y coming
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    26
     the system source.
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    27
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    28
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    29
Implementation
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    30
~~~~~~~~~~~~~~
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    31
XXX explain algorithm
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    32
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    33
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    34
Exemples of multi-sources query execution
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    35
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    36
For a system source and a ldap user source (only EUser and its attributes
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    37
is supported, no group or such):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    38
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    39
:EUser X:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    40
1. fetch EUser X from both sources and return concatenation of results
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    41
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    42
:EUser X WHERE X in_group G, G name 'users':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    43
* catch 1
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    44
  1. fetch EUser X from both sources, store concatenation of results into a
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    45
     temporary table
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    46
  2. return the result of TMP X WHERE X in_group G, G name 'users' from the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    47
     system source
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    48
* catch 2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    49
  1. return the result of EUser X WHERE X in_group G, G name 'users' from system
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    50
     source, that's enough (optimization of the sql querier will avoid join on
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    51
     EUser, so we will directly get local eids)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    52
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    53
:EUser X,L WHERE X in_group G, X login L, G name 'users':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    54
1. fetch Any X,L WHERE X is EUser, X login L from both sources, store
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    55
   concatenation of results into a temporary table
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    56
2. return the result of Any X, L WHERE X is TMP, X login LX in_group G,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    57
   G name 'users' from the system source
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    58
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    59
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    60
:Any X WHERE X owned_by Y:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    61
* catch 1
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    62
  1. fetch EUser X from both sources, store concatenation of results into a
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    63
     temporary table
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    64
  2. return the result of Any X WHERE X owned_by Y, Y is TMP from the system
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    65
     source
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    66
* catch 2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    67
  1. return the result of Any X WHERE X owned_by Y from system source, that's
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    68
     enough (optimization of the sql querier will avoid join on EUser, so we
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    69
     will directly get local eids)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    70
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    71
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    72
:organization: Logilab
1124
5548b608b7d9 copyright update
sylvain.thenault@logilab.fr
parents: 1120
diff changeset
    73
:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    74
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    75
"""
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    76
__docformat__ = "restructuredtext en"
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    77
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
    78
from copy import deepcopy
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    79
from itertools import imap, ifilterfalse
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    80
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    81
from logilab.common.compat import any
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    82
from logilab.common.decorators import cached
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    83
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    84
from rql.stmts import Union, Select
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    85
from rql.nodes import VariableRef, Comparison, Relation, Constant, Exists, Variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    86
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    87
from cubicweb import server
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    88
from cubicweb.common.utils import make_uid
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    89
from cubicweb.server.utils import cleanup_solutions
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    90
from cubicweb.server.ssplanner import (SSPlanner, OneFetchStep,
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
    91
                                       add_types_restriction)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    92
from cubicweb.server.mssteps import *
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    93
from cubicweb.server.sources import AbstractSource
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    94
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    95
Variable._ms_table_key = lambda x: x.name
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    96
Relation._ms_table_key = lambda x: x.r_type
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    97
# str() Constant.value to ensure generated table name won't be unicode
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    98
Constant._ms_table_key = lambda x: str(x.value)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
    99
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   100
AbstractSource.dont_cross_relations = ()
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   101
AbstractSource.cross_relations = ()
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   102
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   103
def need_aggr_step(select, sources, stepdefs=None):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   104
    """return True if a temporary table is necessary to store some partial
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   105
    results to execute the given query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   106
    """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   107
    if len(sources) == 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   108
        # can do everything at once with a single source
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   109
        return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   110
    if select.orderby or select.groupby or select.has_aggregat:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   111
        # if more than one source, we need a temp table to deal with sort /
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   112
        # groups / aggregat if :
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   113
        # * the rqlst won't be splitted (in the other case the last query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   114
        #   using partial temporary table can do sort/groups/aggregat without
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   115
        #   the need for a later AggrStep)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   116
        # * the rqlst is splitted in multiple steps and there are more than one
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   117
        #   final step
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   118
        if stepdefs is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   119
            return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   120
        has_one_final = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   121
        fstepsolindices = set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   122
        for stepdef in stepdefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   123
            if stepdef[-1]:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   124
                if has_one_final or frozenset(stepdef[2]) != fstepsolindices:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   125
                    return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   126
                has_one_final = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   127
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   128
                fstepsolindices.update(stepdef[2])
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   129
    return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   130
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   131
def select_group_sort(select): # XXX something similar done in rql2sql
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   132
    # add variables used in groups and sort terms to the selection
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   133
    # if necessary
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   134
    if select.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   135
        for vref in select.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   136
            if not vref in select.selection:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   137
                select.append_selected(vref.copy(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   138
    for sortterm in select.orderby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   139
        for vref in sortterm.iget_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   140
            if not vref in select.get_selected_variables():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   141
                # we can't directly insert sortterm.term because it references
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   142
                # a variable of the select before the copy.
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   143
                # XXX if constant term are used to define sort, their value
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   144
                # may necessite a decay
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   145
                select.append_selected(vref.copy(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   146
                if select.groupby and not vref in select.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   147
                    select.add_group_var(vref.copy(select))
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   148
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   149
def allequals(solutions):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   150
    """return true if all solutions are identical"""
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   151
    sol = solutions.next()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   152
    noconstsol = None
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   153
    for sol_ in solutions:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   154
        if sol_ != sol:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   155
            return False
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   156
    return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   157
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   158
# XXX move functions below to rql ##############################################
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   159
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   160
def is_ancestor(n1, n2):
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   161
    p = n1.parent
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   162
    while p is not None:
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   163
        if p is n2:
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   164
            return True
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   165
        p = p.parent
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   166
    return False
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   167
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   168
def copy_node(newroot, node, subparts=()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   169
    newnode = node.__class__(*node.initargs(newroot))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   170
    for part in subparts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   171
        newnode.append(part)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   172
    return newnode
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   173
        
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   174
def same_scope(var):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   175
    """return true if the variable is always used in the same scope"""
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   176
    try:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   177
        return var.stinfo['samescope']
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   178
    except KeyError:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   179
        for rel in var.stinfo['relations']:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   180
            if not rel.scope is var.scope:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   181
                var.stinfo['samescope'] = False
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   182
                return False
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   183
        var.stinfo['samescope'] = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   184
        return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   185
    
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   186
################################################################################
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   187
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   188
class PartPlanInformation(object):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   189
    """regroups necessary information to execute some part of a "global" rql
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   190
    query ("global" means as received by the querier, which may result in
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   191
    several internal queries, e.g. parts, due to security insertions). Actually
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   192
    a PPI is created for each subquery and for each query in a union.
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   193
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   194
    It exposes as well some methods helping in executing this part on a
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   195
    multi-sources repository, modifying its internal structure during the
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   196
    process.
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   197
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   198
    :attr plan:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   199
      the execution plan
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   200
    :attr rqlst:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   201
      the original rql syntax tree handled by this part
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   202
      
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   203
    :attr needsplit:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   204
      bool telling if the query has to be split into multiple steps for
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   205
      execution or if it can be executed at once
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   206
      
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   207
    :attr temptable:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   208
      a SQL temporary table name or None, if necessary to handle aggregate /
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   209
      sorting for this part of the query
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   210
      
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   211
    :attr finaltable:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   212
      a SQL table name or None, if results for this part of the query should be
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   213
      written into a temporary table (usually shared by multiple PPI)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   214
      
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   215
    :attr sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   216
      a dictionary {source : {term: set([solution index, ])}} telling for each
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   217
      source which terms are supported for which solutions. A "term" may be
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   218
      either a rql Variable, Constant or Relation node.
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   219
    """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   220
    def __init__(self, plan, rqlst, rqlhelper=None):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   221
        self.plan = plan
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   222
        self.rqlst = rqlst
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   223
        self.needsplit = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   224
        self.temptable = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   225
        self.finaltable = None
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   226
        self._schema = plan.schema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   227
        self._session = plan.session
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   228
        self._repo = self._session.repo
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   229
        self._solutions = rqlst.solutions
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   230
        self._solindices = range(len(self._solutions))
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   231
        # source : {term: [solution index, ]}
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   232
        self.sourcesterms = self._sourcesterms = {}
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   233
        # source : {relation: set(child variable and constant)}
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   234
        self._crossrelations = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   235
        # dictionary of variables and constants which are linked to each other
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   236
        # using a non final relation supported by multiple sources (crossed or
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   237
        # not).
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   238
        self._linkedterms = {}
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   239
        # processing
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   240
        termssources = self._compute_sourcesterms()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   241
        self._remove_invalid_sources(termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   242
        self._compute_needsplit()
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   243
        # after initialisation, .sourcesterms contains the same thing as
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   244
        # ._sourcesterms though during plan construction, ._sourcesterms will
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   245
        # be modified while .sourcesterms will be kept unmodified
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   246
        self.sourcesterms = {}
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   247
        for k, v in self._sourcesterms.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   248
            self.sourcesterms[k] = {}
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   249
            for k2, v2 in v.iteritems():
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   250
                self.sourcesterms[k][k2] = v2.copy()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   251
        # cleanup linked var
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   252
        for var, linkedrelsinfo in self._linkedterms.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   253
            self._linkedterms[var] = frozenset(x[0] for x in linkedrelsinfo)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   254
        # map output of a step to input of a following step
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   255
        self._inputmaps = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   256
        # record input map conflicts to resolve them on final step generation
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   257
        self._conflicts = []
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   258
        if rqlhelper is not None: # else test
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   259
            self._insert_identity_variable = rqlhelper._annotator.rewrite_shared_optional
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   260
        if server.DEBUG:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   261
            print 'sourcesterms:'
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   262
            for source, terms in self.sourcesterms.items():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   263
                print source, terms
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   264
            
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   265
    def copy_solutions(self, solindices):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   266
        return [self._solutions[solidx].copy() for solidx in solindices]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   267
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   268
    @property
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   269
    @cached
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   270
    def part_sources(self):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   271
        if self._sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   272
            return tuple(sorted(self._sourcesterms))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   273
        return (self._repo.system_source,)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   274
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   275
    @property
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   276
    @cached
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   277
    def _sys_source_set(self):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   278
        return frozenset((self._repo.system_source, solindex)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   279
                         for solindex in self._solindices)        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   280
       
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   281
    @cached
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   282
    def _norel_support_set(self, relation):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   283
        """return a set of (source, solindex) where source doesn't support the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   284
        relation
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   285
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   286
        return frozenset((source, solidx) for source in self._repo.sources
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   287
                         for solidx in self._solindices
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   288
                         if not ((source.support_relation(relation.r_type))
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   289
                                 or relation.r_type in source.dont_cross_relations))
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   290
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   291
    def _compute_sourcesterms(self):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   292
        """compute for each term (variable, rewritten constant, relation) and
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   293
        for each solution in the rqlst which sources support them
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   294
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   295
        repo = self._repo
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   296
        eschema = self._schema.eschema
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   297
        sourcesterms = self._sourcesterms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   298
        # find for each source which variable/solution are supported
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   299
        for varname, varobj in self.rqlst.defined_vars.items():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   300
            # if variable has an eid specified, we can get its source directly
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   301
            # NOTE: use uidrels and not constnode to deal with "X eid IN(1,2,3,4)"
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   302
            if varobj.stinfo['uidrels']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   303
                vrels = varobj.stinfo['relations'] - varobj.stinfo['uidrels']
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   304
                for rel in varobj.stinfo['uidrels']:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   305
                    if rel.neged(strict=True) or rel.operator() != '=':
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   306
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   307
                    for const in rel.children[1].get_nodes(Constant):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   308
                        eid = const.eval(self.plan.args)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   309
                        source = self._session.source_from_eid(eid)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   310
                        if vrels and not any(source.support_relation(r.r_type)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   311
                                             for r in vrels):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   312
                            self._set_source_for_term(repo.system_source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   313
                        else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   314
                            self._set_source_for_term(source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   315
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   316
            rels = varobj.stinfo['relations']
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   317
            if not rels and not varobj.stinfo['typerels']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   318
                # (rare) case where the variable has no type specified nor
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   319
                # relation accessed ex. "Any MAX(X)"
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   320
                self._set_source_for_term(repo.system_source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   321
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   322
            for i, sol in enumerate(self._solutions):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   323
                vartype = sol[varname]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   324
                # skip final variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   325
                if eschema(vartype).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   326
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   327
                for source in repo.sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   328
                    if source.support_entity(vartype):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   329
                        # the source support the entity type, though we will
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   330
                        # actually have to fetch from it only if
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   331
                        # * the variable isn't invariant
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   332
                        # * at least one supported relation specified
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   333
                        if not varobj._q_invariant or \
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   334
                               any(imap(source.support_relation,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   335
                                        (r.r_type for r in rels if r.r_type != 'eid'))):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   336
                            sourcesterms.setdefault(source, {}).setdefault(varobj, set()).add(i)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   337
                        # if variable is not invariant and is used by a relation
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   338
                        # not supported by this source, we'll have to split the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   339
                        # query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   340
                        if not varobj._q_invariant and any(ifilterfalse(
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   341
                            source.support_relation, (r.r_type for r in rels))):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   342
                            self.needsplit = True               
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   343
        # add source for rewritten constants to sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   344
        for vconsts in self.rqlst.stinfo['rewritten'].itervalues():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   345
            const = vconsts[0]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   346
            source = self._session.source_from_eid(const.eval(self.plan.args))
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   347
            if source is repo.system_source:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   348
                for const in vconsts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   349
                    self._set_source_for_term(source, const)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   350
            elif source in self._sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   351
                source_scopes = frozenset(t.scope for t in self._sourcesterms[source])
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   352
                for const in vconsts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   353
                    if const.scope in source_scopes:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   354
                        self._set_source_for_term(source, const)
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   355
                        # if system source is used, add every rewritten constant
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   356
                        # to its supported terms even when associated entity
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   357
                        # doesn't actually comes from it so we get a changes
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   358
                        # that allequals will return True as expected when
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   359
                        # computing needsplit
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   360
                        if repo.system_source in sourcesterms:
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   361
                            self._set_source_for_term(repo.system_source, const)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   362
        # add source for relations
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   363
        rschema = self._schema.rschema
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   364
        termssources = {}
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   365
        for rel in self.rqlst.iget_nodes(Relation):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   366
            # process non final relations only
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   367
            # note: don't try to get schema for 'is' relation (not available
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   368
            # during bootstrap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   369
            if not rel.is_types_restriction() and not rschema(rel.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   370
                # nothing to do if relation is not supported by multiple sources
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   371
                # or if some source has it listed in its cross_relations
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   372
                # attribute
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   373
                #
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   374
                # XXX code below don't deal if some source allow relation
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   375
                #     crossing but not another one
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
   376
                relsources = repo.rel_type_sources(rel.r_type)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   377
                if len(relsources) < 2:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   378
                    # filter out sources being there because they have this
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   379
                    # relation in their dont_cross_relations attribute
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   380
                    relsources = [source for source in relsources
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   381
                                  if source.support_relation(rel.r_type)]
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
   382
                    if relsources:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   383
                        # this means the relation is using a variable inlined as
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   384
                        # a constant and another unsupported variable, in which
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   385
                        # case we put the relation in sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   386
                        self._sourcesterms.setdefault(relsources[0], {})[rel] = set(self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   387
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   388
                lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   389
                lhsv, rhsv = getattr(lhs, 'variable', lhs), getattr(rhs, 'variable', rhs)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   390
                # update dictionary of sources supporting lhs and rhs vars
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   391
                if not lhsv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   392
                    termssources[lhsv] = self._term_sources(lhs)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   393
                if not rhsv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   394
                    termssources[rhsv] = self._term_sources(rhs)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   395
                self._handle_cross_relation(rel, relsources, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   396
                self._linkedterms.setdefault(lhsv, set()).add((rhsv, rel))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   397
                self._linkedterms.setdefault(rhsv, set()).add((lhsv, rel))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   398
        return termssources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   399
            
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   400
    def _handle_cross_relation(self, rel, relsources, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   401
        for source in relsources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   402
            if rel.r_type in source.cross_relations:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   403
                ssource = self._repo.system_source
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   404
                crossvars = set(x.variable for x in rel.get_nodes(VariableRef))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   405
                for const in rel.get_nodes(Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   406
                    if source.uri != 'system' and not const in self._sourcesterms.get(source, ()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   407
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   408
                    crossvars.add(const)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   409
                self._crossrelations.setdefault(source, {})[rel] = crossvars
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   410
                if len(crossvars) < 2:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   411
                    # this means there is a constant in the relation which is
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   412
                    # not supported by the source, so we can stop here
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   413
                    continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   414
                self._sourcesterms.setdefault(ssource, {})[rel] = set(self._solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   415
                for term in crossvars:
1229
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   416
                    if len(termssources[term]) == 1 and iter(termssources[term]).next()[0].uri == 'system':
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   417
                        for ov in crossvars:
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   418
                            if ov is not term and (isinstance(ov, Constant) or ov._q_invariant):
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   419
                                ssset = frozenset((ssource,))
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   420
                                self._remove_sources(ov, termssources[ov] - ssset)
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   421
                        break
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   422
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   423
                    self._sourcesterms.setdefault(source, {})[rel] = set(self._solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   424
    
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   425
    def _remove_invalid_sources(self, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   426
        """removes invalid sources from `sourcesterms` member according to
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   427
        traversed relations and their properties (which sources support them,
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   428
        can they cross sources, etc...)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   429
        """
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   430
        for term in self._linkedterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   431
            self._remove_sources_until_stable(term, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   432
        if len(self._sourcesterms) > 1 and hasattr(self.plan.rqlst, 'main_relations'):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   433
            # the querier doesn't annotate write queries, need to do it here
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   434
            self.plan.annotate_rqlst()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   435
            # insert/update/delete queries, we may get extra information from
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   436
            # the main relation (eg relations to the left of the WHERE
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   437
            if self.plan.rqlst.TYPE == 'insert':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   438
                inserted = dict((vref.variable, etype)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   439
                                for etype, vref in self.plan.rqlst.main_variables)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   440
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   441
                inserted = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   442
            repo = self._repo
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   443
            rschema = self._schema.rschema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   444
            for rel in self.plan.rqlst.main_relations:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   445
                if not rschema(rel.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   446
                    # nothing to do if relation is not supported by multiple sources
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   447
                    if len(repo.rel_type_sources(rel.r_type)) < 2:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   448
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   449
                    lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   450
                    try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   451
                        lhsv = self._extern_term(lhs, termssources, inserted)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   452
                        rhsv = self._extern_term(rhs, termssources, inserted)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   453
                    except KeyError, ex:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   454
                        continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   455
                    self._remove_term_sources(lhsv, rel, rhsv, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   456
                    self._remove_term_sources(rhsv, rel, lhsv, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   457
                                    
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   458
    def _extern_term(self, term, termssources, inserted):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   459
        var = term.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   460
        if var.stinfo['constnode']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   461
            termv = var.stinfo['constnode']
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   462
            termssources[termv] = self._term_sources(termv)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   463
        elif var in inserted:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   464
            termv = var
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   465
            source = self._repo.locate_etype_source(inserted[var])
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   466
            termssources[termv] = set((source, solindex)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   467
                                      for solindex in self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   468
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   469
            termv = self.rqlst.defined_vars[var.name]
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   470
            if not termv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   471
                termssources[termv] = self._term_sources(termv)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   472
        return termv
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   473
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   474
    def _remove_sources_until_stable(self, term, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   475
        sourcesterms = self._sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   476
        for oterm, rel in self._linkedterms.get(term, ()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   477
            if not term.scope is oterm.scope and rel.scope.neged(strict=True):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   478
                # can't get information from relation inside a NOT exists
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   479
                # where terms don't belong to the same scope
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   480
                continue
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   481
            need_ancestor_scope = False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   482
            if not (term.scope is rel.scope and oterm.scope is rel.scope):
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   483
                if rel.ored():
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   484
                    continue
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   485
                if rel.ored(traverse_scope=True):
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   486
                    # if relation has some OR as parent, constraints should only
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   487
                    # propagate from parent scope to child scope, nothing else
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   488
                    need_ancestor_scope = True
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   489
            relsources = self._repo.rel_type_sources(rel.r_type)
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
   490
            if rel.neged(strict=True) and (
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
   491
                len(relsources) < 2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   492
                or not isinstance(oterm, Variable)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   493
                or oterm.valuable_references() != 1
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   494
                or any(sourcesterms[source][term] != sourcesterms[source][oterm]
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
   495
                       for source in relsources
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   496
                       if term in sourcesterms.get(source, ())
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   497
                       and oterm in sourcesterms.get(source, ()))):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   498
                # neged relation doesn't allow to infer term sources unless
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   499
                # we're on a multisource relation for a term only used by this
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   500
                # relation (eg "Any X WHERE NOT X multisource_rel Y" and over is
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   501
                # Y)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   502
                continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   503
            # compute invalid sources for terms and remove them
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   504
            if not need_ancestor_scope or is_ancestor(term.scope, oterm.scope):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   505
                self._remove_term_sources(term, rel, oterm, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   506
            if not need_ancestor_scope or is_ancestor(oterm.scope, term.scope):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   507
                self._remove_term_sources(oterm, rel, term, termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   508
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   509
    def _remove_term_sources(self, term, rel, oterm, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   510
        """remove invalid sources for term according to oterm's sources and the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   511
        relation between those two terms. 
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   512
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   513
        norelsup = self._norel_support_set(rel)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   514
        termsources = termssources[term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   515
        invalid_sources = termsources - (termssources[oterm] | norelsup)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   516
        if invalid_sources and self._repo.can_cross_relation(rel.r_type):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   517
            invalid_sources -= self._sys_source_set
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   518
            if invalid_sources and isinstance(term, Variable) \
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   519
                   and self._need_ext_source_access(term, rel):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   520
                # if the term is a not invariant variable, we should filter out
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   521
                # source where the relation is a cross relation from invalid
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   522
                # sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   523
                invalid_sources = frozenset([(s, solidx) for s, solidx in invalid_sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   524
                                             if not (s in self._crossrelations and
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   525
                                                     rel in self._crossrelations[s])])
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   526
        if invalid_sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   527
            self._remove_sources(term, invalid_sources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   528
            termsources -= invalid_sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   529
            self._remove_sources_until_stable(term, termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   530
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   531
    def _compute_needsplit(self):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   532
        """tell according to sourcesterms if the rqlst has to be splitted for
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   533
        execution among multiple sources
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   534
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   535
        the execution has to be split if
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   536
        * a source support an entity (non invariant) but doesn't support a
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   537
          relation on it
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   538
        * a source support an entity which is accessed by an optional relation
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   539
        * there is more than one source and either all sources'supported        
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   540
          variable/solutions are not equivalent or multiple variables have to
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   541
          be fetched from some source
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   542
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   543
        # NOTE: < 2 since may be 0 on queries such as Any X WHERE X eid 2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   544
        if len(self._sourcesterms) < 2: 
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   545
            self.needsplit = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   546
        elif not self.needsplit:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   547
            if not allequals(self._sourcesterms.itervalues()):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   548
                self.needsplit = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   549
            else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   550
                sample = self._sourcesterms.itervalues().next()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   551
                if len(sample) > 1:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   552
                    for term in sample:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   553
                        # need split if unlinked variable
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   554
                        if isinstance(term, Variable) and not term in self._linkedterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   555
                            self.needsplit = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   556
                            break
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   557
                    else:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   558
                        # need split if there are some cross relation on non
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   559
                        # invariant variable or if the variable is used in
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   560
                        # multi-sources relation
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   561
                        if self._crossrelations:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   562
                            for reldict in self._crossrelations.itervalues():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   563
                                for rel, terms in reldict.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   564
                                    for term in terms:
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   565
                                        if isinstance(term, Variable) \
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   566
                                               and self._need_ext_source_access(term, rel):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   567
                                            self.needsplit = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   568
                                            return
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   569
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   570
    @cached
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   571
    def _need_ext_source_access(self, var, rel):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   572
        if not var._q_invariant:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   573
            return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   574
        if  any(r for x, r in self._linkedterms[var]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   575
                if not r is rel and self._repo.is_multi_sources_relation(r.r_type)):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   576
            return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   577
        return False
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   578
        
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   579
    def _set_source_for_term(self, source, term):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   580
        self._sourcesterms.setdefault(source, {})[term] = set(self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   581
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   582
    def _term_sources(self, term):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   583
        """returns possible sources for terms `term`"""
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   584
        if isinstance(term, Constant):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   585
            source = self._session.source_from_eid(term.eval(self.plan.args))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   586
            return set((source, solindex) for solindex in self._solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   587
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   588
            var = getattr(term, 'variable', term)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   589
            sources = [source for source, varobjs in self.sourcesterms.iteritems()
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   590
                       if var in varobjs]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   591
            return set((source, solindex) for source in sources
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   592
                       for solindex in self.sourcesterms[source][var])
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   593
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   594
    def _remove_sources(self, term, sources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   595
        """removes invalid sources (`sources`) from `sourcesterms`
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   596
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   597
        :param sources: the list of sources to remove
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   598
        :param term: the analyzed term
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   599
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   600
        sourcesterms = self._sourcesterms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   601
        for source, solindex in sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   602
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   603
                sourcesterms[source][term].remove(solindex)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   604
            except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   605
                return # may occur with subquery column alias
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   606
            if not sourcesterms[source][term]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   607
                del sourcesterms[source][term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   608
                if not sourcesterms[source]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   609
                    del sourcesterms[source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   610
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   611
    def crossed_relation(self, source, relation):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   612
        return relation in self._crossrelations.get(source, ())
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   613
    
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   614
    def part_steps(self):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   615
        """precompute necessary part steps before generating actual rql for
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   616
        each step. This is necessary to know if an aggregate step will be
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   617
        necessary or not.
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   618
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   619
        steps = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   620
        select = self.rqlst
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   621
        rschema = self._schema.rschema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   622
        for source in self.part_sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   623
            sourceterms = self._sourcesterms[source]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   624
            while sourceterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   625
                # take a term randomly, and all terms supporting the
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   626
                # same solutions
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   627
                term, solindices = self._choose_term(sourceterms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   628
                if source.uri == 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   629
                    # ensure all variables are available for the latest step
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   630
                    # (missing one will be available from temporary tables
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   631
                    # of previous steps)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   632
                    scope = select
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   633
                    terms = scope.defined_vars.values() + scope.aliases.values()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   634
                    sourceterms.clear()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   635
                    sources = [source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   636
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   637
                    scope = term.scope
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   638
                    # find which sources support the same term and solutions
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   639
                    sources = self._expand_sources(source, term, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   640
                    # no try to get as much terms as possible
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   641
                    terms = self._expand_terms(term, sources, sourceterms,
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   642
                                               scope, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   643
                    if len(terms) == 1 and isinstance(terms[0], Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   644
                        # we can't generate anything interesting with a single
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   645
                        # constant term (will generate an empty "Any" query),
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   646
                        # go to the next iteration directly!
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   647
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   648
                    if not sourceterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   649
                        del self._sourcesterms[source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   650
                # suppose this is a final step until the contrary is proven
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   651
                final = scope is select
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   652
                # set of terms which should be additionaly selected when
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   653
                # possible
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   654
                needsel = set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   655
                # add attribute variables and mark variables which should be
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   656
                # additionaly selected when possible
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   657
                for var in select.defined_vars.itervalues():
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   658
                    if not var in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   659
                        stinfo = var.stinfo
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   660
                        for ovar, rtype in stinfo['attrvars']:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   661
                            if ovar in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   662
                                needsel.add(var.name)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   663
                                terms.append(var)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   664
                                break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   665
                        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   666
                            needsel.add(var.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   667
                            final = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   668
                if final and source.uri != 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   669
                    # check rewritten constants
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   670
                    for vconsts in select.stinfo['rewritten'].itervalues():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   671
                        const = vconsts[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   672
                        eid = const.eval(self.plan.args)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   673
                        _source = self._session.source_from_eid(eid)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   674
                        if len(sources) > 1 or not _source in sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   675
                            # if there is some rewriten constant used by a not
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   676
                            # neged relation while there are some source not
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   677
                            # supporting the associated entity, this step can't
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   678
                            # be final (unless the relation is explicitly in
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   679
                            # `terms`, eg cross relations)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   680
                            for c in vconsts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   681
                                rel = c.relation()
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   682
                                if rel is None or not (rel in terms or rel.neged(strict=True)):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   683
                                    final = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   684
                                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   685
                            break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   686
                # check where all relations are supported by the sources
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   687
                for rel in scope.iget_nodes(Relation):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   688
                    if rel.is_types_restriction():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   689
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   690
                    # take care not overwriting the existing "source" identifier
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   691
                    for _source in sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   692
                        if not _source.support_relation(rel.r_type):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   693
                            for vref in rel.iget_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   694
                                needsel.add(vref.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   695
                            final = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   696
                            break
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   697
                        elif self.crossed_relation(_source, rel) and not rel in terms:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   698
                            final = False
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   699
                            break
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   700
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   701
                        if not scope is select:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   702
                            self._exists_relation(rel, terms, needsel)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   703
                        # if relation is supported by all sources and some of
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   704
                        # its lhs/rhs variable isn't in "terms", and the
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   705
                        # other end *is* in "terms", mark it have to be
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   706
                        # selected
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   707
                        if source.uri != 'system' and not rschema(rel.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   708
                            lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   709
                            try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   710
                                lhsvar = lhs.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   711
                            except AttributeError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   712
                                lhsvar = lhs
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   713
                            try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   714
                                rhsvar = rhs.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   715
                            except AttributeError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   716
                                rhsvar = rhs
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   717
                            if lhsvar in terms and not rhsvar in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   718
                                needsel.add(lhsvar.name)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   719
                            elif rhsvar in terms and not lhsvar in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   720
                                needsel.add(rhsvar.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   721
                if final:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   722
                    self._cleanup_sourcesterms(sources, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   723
                steps.append((sources, terms, solindices, scope, needsel, final)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   724
                             )
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   725
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   726
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   727
    def _exists_relation(self, rel, terms, needsel):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   728
        rschema = self._schema.rschema(rel.r_type)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   729
        lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   730
        try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   731
            lhsvar, rhsvar = lhs.variable, rhs.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   732
        except AttributeError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   733
            pass
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   734
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   735
            # supported relation with at least one end supported, check the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   736
            # other end is in as well. If not this usually means the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   737
            # variable is refed by an outer scope and should be substituted
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   738
            # using an 'identity' relation (else we'll get a conflict of
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   739
            # temporary tables)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   740
            if rhsvar in terms and not lhsvar in terms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   741
                self._identity_substitute(rel, lhsvar, terms, needsel)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   742
            elif lhsvar in terms and not rhsvar in terms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   743
                self._identity_substitute(rel, rhsvar, terms, needsel)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   744
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   745
    def _identity_substitute(self, relation, var, terms, needsel):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   746
        newvar = self._insert_identity_variable(relation.scope, var)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   747
        if newvar is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   748
            # ensure relation is using '=' operator, else we rely on a
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   749
            # sqlgenerator side effect (it won't insert an inequality operator
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   750
            # in this case)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   751
            relation.children[1].operator = '=' 
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   752
            terms.append(newvar)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   753
            needsel.add(newvar.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   754
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   755
    def _choose_term(self, sourceterms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   756
        """pick one term among terms supported by a source, which will be used
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   757
        as a base to generate an execution step
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   758
        """
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   759
        secondchoice = None
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   760
        if len(self._sourcesterms) > 1:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   761
            # priority to variable from subscopes
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   762
            for var in sourceterms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   763
                if not var.scope is self.rqlst:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   764
                    if isinstance(var, Variable):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   765
                        return var, sourceterms.pop(var)
426
e96662444ec6 oops, var shouldn't be poped there
sylvain.thenault@logilab.fr
parents: 393
diff changeset
   766
                    secondchoice = var
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   767
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   768
            # priority to variable outer scope
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   769
            for var in sourceterms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   770
                if var.scope is self.rqlst:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   771
                    if isinstance(var, Variable):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   772
                        return var, sourceterms.pop(var)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   773
                    secondchoice = var
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   774
        if secondchoice is not None:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   775
            return secondchoice, sourceterms.pop(secondchoice)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   776
        # priority to variable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   777
        for var in sourceterms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   778
            if isinstance(var, Variable):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   779
                return var, sourceterms.pop(var)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   780
        # whatever
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   781
        var = iter(sourceterms).next()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   782
        return var, sourceterms.pop(var)
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   783
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   784
    def _expand_sources(self, selected_source, term, solindices):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   785
        """return all sources supporting given term / solindices"""
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   786
        sources = [selected_source]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   787
        sourcesterms = self._sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   788
        for source in sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   789
            if source is selected_source:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   790
                continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   791
            if not (term in sourcesterms[source] and 
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   792
                    solindices.issubset(sourcesterms[source][term])):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   793
                continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   794
            sources.append(source)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   795
            if source.uri != 'system':
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   796
                termsolindices = sourcesterms[source][term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   797
                termsolindices -= solindices
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   798
                if not termsolindices:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   799
                    del sourcesterms[source][term]                
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   800
        return sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   801
            
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   802
    def _expand_terms(self, term, sources, sourceterms, scope, solindices):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   803
        terms = [term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   804
        sources = sorted(sources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   805
        nbunlinked = 1
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   806
        linkedterms = self._linkedterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   807
        # term has to belong to the same scope if there is more
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   808
        # than the system source remaining
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   809
        if len(self._sourcesterms) > 1 and not scope is self.rqlst:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   810
            candidates = (t for t in sourceterms.keys() if scope is t.scope)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   811
        else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   812
            candidates = sourceterms #.iterkeys()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   813
        # we only want one unlinked term in each generated query
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   814
        candidates = [t for t in candidates
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   815
                      if isinstance(t, Constant) or
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   816
                      (solindices.issubset(sourceterms[t]) and t in linkedterms)]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   817
        accept_term = lambda x: (not any(s for s in sources if not x in self._sourcesterms[s])
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   818
                                and any(t for t in terms if t in linkedterms.get(x, ())))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   819
        source_cross_rels = {}
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   820
        for source in sources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   821
            source_cross_rels.update(self._crossrelations.get(source, {}))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   822
        if isinstance(term, Relation) and term in source_cross_rels:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   823
            cross_terms = source_cross_rels.pop(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   824
            base_accept_term = accept_term
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   825
            accept_term = lambda x: (base_accept_term(x) or x in cross_terms)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   826
            for refed in cross_terms:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   827
                if not refed in candidates:
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   828
                    candidates.append(refed)
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   829
        else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   830
            cross_terms = ()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   831
        # repeat until no term can't be added, since addition of a new
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   832
        # term may permit to another one to be added
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   833
        modified = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   834
        while modified and candidates:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   835
            modified = False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   836
            for term in candidates[:]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   837
                if isinstance(term, Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   838
                    relation = term.relation()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   839
                    if sorted(set(x[0] for x in self._term_sources(term))) != sources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   840
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   841
                    terms.append(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   842
                    candidates.remove(term)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   843
                    modified = True
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   844
                    del sourceterms[term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   845
                elif accept_term(term):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   846
                    terms.append(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   847
                    candidates.remove(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   848
                    modified = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   849
                    for source in sources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   850
                        sourceterms = self._sourcesterms[source]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   851
                        # terms should be deleted once all possible solutions
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   852
                        # indices have been consumed
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   853
                        try:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   854
                            sourceterms[term] -= solindices
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   855
                            if not sourceterms[term]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   856
                                del sourceterms[term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   857
                        except KeyError:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   858
                            assert term in cross_terms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   859
        return terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   860
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   861
    def _cleanup_sourcesterms(self, sources, solindices):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   862
        """on final parts, remove solutions so we know they are already processed"""
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   863
        for source in sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   864
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   865
                sourceterms = self._sourcesterms[source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   866
            except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   867
                continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   868
            for term, termsolindices in sourceterms.items():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   869
                if isinstance(term, Relation) and self.crossed_relation(source, term):
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   870
                    continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   871
                termsolindices -= solindices
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   872
                if not termsolindices:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   873
                    del sourceterms[term]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   874
                    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   875
    def merge_input_maps(self, allsolindices):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   876
        """inputmaps is a dictionary with tuple of solution indices as key with
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   877
        an associated input map as value. This function compute for each
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   878
        solution its necessary input map and return them grouped
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   879
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   880
        ex:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   881
        inputmaps = {(0, 1, 2): {'A': 't1.login1', 'U': 't1.C0', 'U.login': 't1.login1'},
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   882
                     (1,): {'X': 't2.C0', 'T': 't2.C1'}}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   883
        return : [([1],  {'A': 't1.login1', 'U': 't1.C0', 'U.login': 't1.login1',
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   884
                           'X': 't2.C0', 'T': 't2.C1'}),                   
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   885
                  ([0,2], {'A': 't1.login1', 'U': 't1.C0', 'U.login': 't1.login1'})]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   886
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   887
        if not self._inputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   888
            return [(allsolindices, None)]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   889
        mapbysol = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   890
        # compute a single map for each solution
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   891
        for solindices, basemap in self._inputmaps.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   892
            for solindex in solindices:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   893
                solmap = mapbysol.setdefault(solindex, {})
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   894
                solmap.update(basemap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   895
                try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   896
                    allsolindices.remove(solindex)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   897
                except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   898
                    continue # already removed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   899
        # group results by identical input map
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   900
        result = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   901
        for solindex, solmap in mapbysol.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   902
            for solindices, commonmap in result:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   903
                if commonmap == solmap:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   904
                    solindices.append(solindex)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   905
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   906
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   907
                result.append( ([solindex], solmap) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   908
        if allsolindices:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   909
            result.append( (list(allsolindices), None) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   910
        return result
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   911
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   912
    def build_final_part(self, select, solindices, inputmap,  sources,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   913
                         insertedvars):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   914
        solutions = [self._solutions[i] for i in solindices]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   915
        if self._conflicts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   916
            for varname, mappedto in self._conflicts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   917
                var = select.defined_vars[varname]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   918
                newvar = select.make_variable()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   919
                # XXX should use var.scope but scope hasn't been computed yet
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   920
                select.add_relation(var, 'identity', newvar)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   921
                for sol in solutions:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   922
                    sol[newvar.name] = sol[varname]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   923
                inputmap[newvar.name] = mappedto
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   924
        rqlst = self.plan.finalize(select, solutions, insertedvars)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   925
        if self.temptable is None and self.finaltable is None:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   926
            return OneFetchStep(self.plan, rqlst, sources, inputmap=inputmap)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   927
        table = self.temptable or self.finaltable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   928
        return FetchStep(self.plan, rqlst, sources, table, True, inputmap)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   929
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   930
    def build_non_final_part(self, select, solindices, sources, insertedvars,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   931
                             table):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   932
        """non final step, will have to store results in a temporary table"""
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   933
        solutions = [self._solutions[i] for i in solindices]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   934
        rqlst = self.plan.finalize(select, solutions, insertedvars)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   935
        step = FetchStep(self.plan, rqlst, sources, table, False)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   936
        # update input map for following steps, according to processed solutions
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   937
        inputmapkey = tuple(sorted(solindices))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   938
        inputmap = self._inputmaps.setdefault(inputmapkey, {})
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   939
        for varname, mapping in step.outputmap.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   940
            if varname in inputmap and \
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   941
                   not (mapping == inputmap[varname] or
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   942
                        self._schema.eschema(solutions[0][varname]).is_final()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   943
                self._conflicts.append((varname, inputmap[varname]))
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   944
        inputmap.update(step.outputmap)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   945
        self.plan.add_step(step)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   946
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   947
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   948
class MSPlanner(SSPlanner):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   949
    """MultiSourcesPlanner: build execution plan for rql queries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   950
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   951
    decompose the RQL query according to sources'schema
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   952
    """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   953
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   954
    def build_select_plan(self, plan, rqlst):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   955
        """build execution plan for a SELECT RQL query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   956
               
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   957
        the rqlst should not be tagged at this point
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   958
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   959
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   960
            print '-'*80
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   961
            print 'PLANNING', rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   962
        for select in rqlst.children:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   963
            if len(select.solutions) > 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   964
                hasmultiplesols = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   965
                break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   966
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   967
            hasmultiplesols = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   968
        # preprocess deals with security insertion and returns a new syntax tree
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   969
        # which have to be executed to fulfill the query: according
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   970
        # to permissions for variable's type, different rql queries may have to
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   971
        # be executed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   972
        plan.preprocess(rqlst)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   973
        ppis = [PartPlanInformation(plan, select, self.rqlhelper)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   974
                for select in rqlst.children]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   975
        steps = self._union_plan(plan, rqlst, ppis)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   976
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   977
            from pprint import pprint
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   978
            for step in plan.steps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   979
                pprint(step.test_repr())
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   980
            pprint(steps[0].test_repr())
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   981
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   982
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   983
    def _ppi_subqueries(self, ppi):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   984
        # part plan info for subqueries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   985
        plan = ppi.plan
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   986
        inputmap = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   987
        for subquery in ppi.rqlst.with_[:]:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   988
            sppis = [PartPlanInformation(plan, select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   989
                     for select in subquery.query.children]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   990
            for sppi in sppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   991
                if sppi.needsplit or sppi.part_sources != ppi.part_sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   992
                    temptable = 'T%s' % make_uid(id(subquery))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   993
                    sstep = self._union_plan(plan, subquery.query, sppis, temptable)[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   994
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   995
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   996
                sstep = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   997
            if sstep is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   998
                ppi.rqlst.with_.remove(subquery)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   999
                for i, colalias in enumerate(subquery.aliases):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1000
                    inputmap[colalias.name] = '%s.C%s' % (temptable, i)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1001
                ppi.plan.add_step(sstep)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1002
        return inputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1003
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1004
    def _union_plan(self, plan, union, ppis, temptable=None):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1005
        tosplit, cango, allsources = [], {}, set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1006
        for planinfo in ppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1007
            if planinfo.needsplit:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1008
                tosplit.append(planinfo)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1009
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1010
                cango.setdefault(planinfo.part_sources, []).append(planinfo)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1011
            for source in planinfo.part_sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1012
                allsources.add(source)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1013
        # first add steps for query parts which doesn't need to splitted
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1014
        steps = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1015
        for sources, cppis in cango.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1016
            byinputmap = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1017
            for ppi in cppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1018
                select = ppi.rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1019
                if sources != (plan.session.repo.system_source,):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1020
                    add_types_restriction(self.schema, select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1021
                # part plan info for subqueries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1022
                inputmap = self._ppi_subqueries(ppi)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1023
                aggrstep = need_aggr_step(select, sources)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1024
                if aggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1025
                    atemptable = 'T%s' % make_uid(id(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1026
                    sunion = Union()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1027
                    sunion.append(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1028
                    selected = select.selection[:]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1029
                    select_group_sort(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1030
                    step = AggrStep(plan, selected, select, atemptable, temptable)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1031
                    step.set_limit_offset(select.limit, select.offset)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1032
                    select.limit = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1033
                    select.offset = 0
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1034
                    fstep = FetchStep(plan, sunion, sources, atemptable, True, inputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1035
                    step.children.append(fstep)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1036
                    steps.append(step)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1037
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1038
                    byinputmap.setdefault(tuple(inputmap.iteritems()), []).append( (select) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1039
            for inputmap, queries in byinputmap.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1040
                inputmap = dict(inputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1041
                sunion = Union()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1042
                for select in queries:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1043
                    sunion.append(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1044
                if temptable:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1045
                    steps.append(FetchStep(plan, sunion, sources, temptable, True, inputmap))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1046
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1047
                    steps.append(OneFetchStep(plan, sunion, sources, inputmap))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1048
        # then add steps for splitted query parts
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1049
        for planinfo in tosplit:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1050
            steps.append(self.split_part(planinfo, temptable))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1051
        if len(steps) > 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1052
            if temptable:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1053
                step = UnionFetchStep(plan)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1054
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1055
                step = UnionStep(plan)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1056
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1057
            return (step,)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1058
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1059
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1060
    # internal methods for multisources decomposition #########################
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1061
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1062
    def split_part(self, ppi, temptable):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1063
        ppi.finaltable = temptable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1064
        plan = ppi.plan
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1065
        select = ppi.rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1066
        subinputmap = self._ppi_subqueries(ppi)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1067
        stepdefs = ppi.part_steps()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1068
        if need_aggr_step(select, ppi.part_sources, stepdefs):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1069
            atemptable = 'T%s' % make_uid(id(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1070
            selection = select.selection[:]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1071
            select_group_sort(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1072
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1073
            atemptable = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1074
            selection = select.selection
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1075
        ppi.temptable = atemptable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1076
        vfilter = TermsFiltererVisitor(self.schema, ppi)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1077
        steps = []
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1078
        for sources, terms, solindices, scope, needsel, final in stepdefs:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1079
            # extract an executable query using only the specified terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1080
            if sources[0].uri == 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1081
                # in this case we have to merge input maps before call to
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1082
                # filter so already processed restriction are correctly
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1083
                # removed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1084
                solsinputmaps = ppi.merge_input_maps(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1085
                for solindices, inputmap in solsinputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1086
                    minrqlst, insertedvars = vfilter.filter(
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1087
                        sources, terms, scope, set(solindices), needsel, final)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1088
                    if inputmap is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1089
                        inputmap = subinputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1090
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1091
                        inputmap.update(subinputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1092
                    steps.append(ppi.build_final_part(minrqlst, solindices, inputmap,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1093
                                                      sources, insertedvars))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1094
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1095
                # this is a final part (i.e. retreiving results for the
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1096
                # original query part) if all term / sources have been
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1097
                # treated or if this is the last shot for used solutions
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1098
                minrqlst, insertedvars = vfilter.filter(
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1099
                    sources, terms, scope, solindices, needsel, final)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1100
                if final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1101
                    solsinputmaps = ppi.merge_input_maps(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1102
                    for solindices, inputmap in solsinputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1103
                        if inputmap is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1104
                            inputmap = subinputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1105
                        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1106
                            inputmap.update(subinputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1107
                        steps.append(ppi.build_final_part(minrqlst, solindices, inputmap,
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1108
                                                          sources, insertedvars))
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1109
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1110
                    table = '_T%s%s' % (''.join(sorted(v._ms_table_key() for v in terms)),
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1111
                                        ''.join(sorted(str(i) for i in solindices)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1112
                    ppi.build_non_final_part(minrqlst, solindices, sources,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1113
                                             insertedvars, table)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1114
        # finally: join parts, deal with aggregat/group/sorts if necessary
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1115
        if atemptable is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1116
            step = AggrStep(plan, selection, select, atemptable, temptable)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1117
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1118
        elif len(steps) > 1:
442
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1119
            if select.need_intersect or any(select.need_intersect
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1120
                                            for step in steps
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1121
                                            for select in step.union.children):
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1122
                if temptable:
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1123
                    step = IntersectFetchStep(plan)
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1124
                else:
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1125
                    step = IntersectStep(plan)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1126
            else:
341
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1127
                if temptable:
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1128
                    step = UnionFetchStep(plan)
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1129
                else:
0a426be2f3a2 fixes for some cases of neged inlined relations, may have to use (new) IntersectStep. XXX: write IntersectFetchStep
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 257
diff changeset
  1130
                    step = UnionStep(plan)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1131
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1132
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1133
            step = steps[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1134
        if select.limit is not None or select.offset:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1135
            step.set_limit_offset(select.limit, select.offset)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1136
        return step
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1137
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1138
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1139
class UnsupportedBranch(Exception):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1140
    pass
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1141
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1142
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1143
class TermsFiltererVisitor(object):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1144
    def __init__(self, schema, ppi):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1145
        self.schema = schema
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1146
        self.ppi = ppi
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1147
        self.skip = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1148
        self.hasaggrstep = self.ppi.temptable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1149
        self.extneedsel = frozenset(vref.name for sortterm in ppi.rqlst.orderby
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1150
                                    for vref in sortterm.iget_nodes(VariableRef))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1151
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1152
    def _rqlst_accept(self, rqlst, node, newroot, terms, setfunc=None):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1153
        try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1154
            newrestr, node_ = node.accept(self, newroot, terms[:])
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1155
        except UnsupportedBranch:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1156
            return rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1157
        if setfunc is not None and newrestr is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1158
            setfunc(newrestr)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1159
        if not node_ is node:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1160
            rqlst = node.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1161
        return rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1162
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1163
    def filter(self, sources, terms, rqlst, solindices, needsel, final):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1164
        if server.DEBUG:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1165
            print 'filter', final and 'final' or '', sources, terms, rqlst, solindices, needsel
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1166
        newroot = Select()
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1167
        self.sources = sorted(sources)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1168
        self.terms = terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1169
        self.solindices = solindices
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1170
        self.final = final
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1171
        # terms which appear in unsupported branches
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1172
        needsel |= self.extneedsel
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1173
        self.needsel = needsel
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1174
        # terms which appear in supported branches
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1175
        self.mayneedsel = set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1176
        # new inserted variables
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1177
        self.insertedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1178
        # other structures (XXX document)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1179
        self.mayneedvar, self.hasvar = {}, {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1180
        self.use_only_defined = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1181
        self.scopes = {rqlst: newroot}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1182
        if rqlst.where:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1183
            rqlst = self._rqlst_accept(rqlst, rqlst.where, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1184
                                       newroot.set_where)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1185
        if isinstance(rqlst, Select):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1186
            self.use_only_defined = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1187
            if rqlst.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1188
                groupby = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1189
                for node in rqlst.groupby:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1190
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1191
                                               groupby.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1192
                if groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1193
                    newroot.set_groupby(groupby)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1194
            if rqlst.having:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1195
                having = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1196
                for node in rqlst.having:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1197
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1198
                                               having.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1199
                if having:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1200
                    newroot.set_having(having)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1201
            if final and rqlst.orderby and not self.hasaggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1202
                orderby = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1203
                for node in rqlst.orderby:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1204
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1205
                                               orderby.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1206
                if orderby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1207
                    newroot.set_orderby(orderby)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1208
            self.process_selection(newroot, terms, rqlst)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1209
        elif not newroot.where:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1210
            # no restrictions have been copied, just select terms and add
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1211
            # type restriction (done later by add_types_restriction)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1212
            for v in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1213
                if not isinstance(v, Variable):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1214
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1215
                newroot.append_selected(VariableRef(newroot.get_variable(v.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1216
        solutions = self.ppi.copy_solutions(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1217
        cleanup_solutions(newroot, solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1218
        newroot.set_possible_types(solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1219
        if final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1220
            if self.hasaggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1221
                self.add_necessary_selection(newroot, self.mayneedsel & self.extneedsel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1222
            newroot.distinct = rqlst.distinct
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1223
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1224
            self.add_necessary_selection(newroot, self.mayneedsel & self.needsel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1225
            # insert vars to fetch constant values when needed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1226
            for (varname, rschema), reldefs in self.mayneedvar.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1227
                for rel, ored in reldefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1228
                    if not (varname, rschema) in self.hasvar:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1229
                        self.hasvar[(varname, rschema)] = None # just to avoid further insertion
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1230
                        cvar = newroot.make_variable()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1231
                        for sol in newroot.solutions:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1232
                            sol[cvar.name] = rschema.objects(sol[varname])[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1233
                        # if the current restriction is not used in a OR branch,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1234
                        # we can keep it, else we have to drop the constant
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1235
                        # restriction (or we may miss some results)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1236
                        if not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1237
                            rel = rel.copy(newroot)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1238
                            newroot.add_restriction(rel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1239
                        # add a relation to link the variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1240
                        newroot.remove_node(rel.children[1])
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1241
                        cmp = Comparison('=')
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1242
                        rel.append(cmp)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1243
                        cmp.append(VariableRef(cvar))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1244
                        self.insertedvars.append((varname, rschema, cvar.name))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1245
                        newroot.append_selected(VariableRef(newroot.get_variable(cvar.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1246
                        # NOTE: even if the restriction is done by this query, we have
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1247
                        # to let it in the original rqlst so that it appears anyway in
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1248
                        # the "final" query, else we may change the meaning of the query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1249
                        # if there are NOT somewhere :
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1250
                        # 'NOT X relation Y, Y name "toto"' means X WHERE X isn't related
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1251
                        # to Y whose name is toto while
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1252
                        # 'NOT X relation Y' means X WHERE X has no 'relation' (whatever Y)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1253
                    elif ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1254
                        newroot.remove_node(rel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1255
        add_types_restriction(self.schema, rqlst, newroot, solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1256
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1257
            print '--->', newroot
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1258
        return newroot, self.insertedvars
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1259
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1260
    def visit_and(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1261
        subparts = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1262
        for i in xrange(len(node.children)):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1263
            child = node.children[i]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1264
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1265
                newchild, child_ = child.accept(self, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1266
                if not child_ is child:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1267
                    node = child_.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1268
                if newchild is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1269
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1270
                subparts.append(newchild)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1271
            except UnsupportedBranch:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1272
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1273
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1274
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1275
        if len(subparts) == 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1276
            return subparts[0], node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1277
        return copy_node(newroot, node, subparts), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1278
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1279
    visit_or = visit_and
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1280
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1281
    def _relation_supported(self, relation):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1282
        rtype = relation.r_type
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1283
        for source in self.sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1284
            if not source.support_relation(rtype) or (
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1285
                rtype in source.cross_relations and not relation in self.terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1286
                return False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1287
        if not self.final and not relation in self.terms:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1288
            rschema = self.schema.rschema(relation.r_type)
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1289
            if not rschema.is_final():
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1290
                for term in relation.get_nodes((VariableRef, Constant)):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1291
                    term = getattr(term, 'variable', term)
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1292
                    termsources = sorted(set(x[0] for x in self.ppi._term_sources(term)))
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1293
                    if termsources and termsources != self.sources:
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1294
                        return False
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1295
        return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1296
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1297
    def visit_relation(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1298
        if not node.is_types_restriction():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1299
            if node in self.skip and self.solindices.issubset(self.skip[node]):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1300
                if not self.schema.rschema(node.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1301
                    # can't really skip the relation if one variable is selected and only
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1302
                    # referenced by this relation
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1303
                    for vref in node.iget_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1304
                        stinfo = vref.variable.stinfo
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1305
                        if stinfo['selected'] and len(stinfo['relations']) == 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1306
                            break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1307
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1308
                        return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1309
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1310
                    return None, node
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1311
            if not self._relation_supported(node):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1312
                raise UnsupportedBranch()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1313
        # don't copy type restriction unless this is the only relation for the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1314
        # rhs variable, else they'll be reinserted later as needed (else we may
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1315
        # copy a type restriction while the variable is not actually used)
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1316
        elif not any(self._relation_supported(rel)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1317
                     for rel in node.children[0].variable.stinfo['relations']):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1318
            rel, node = self.visit_default(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1319
            return rel, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1320
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1321
            raise UnsupportedBranch()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1322
        rschema = self.schema.rschema(node.r_type)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1323
        try:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1324
            res = self.visit_default(node, newroot, terms)[0]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1325
        except Exception, ex:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1326
            raise
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1327
        ored = node.ored()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1328
        if rschema.is_final() or rschema.inlined:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1329
            vrefs = node.children[1].get_nodes(VariableRef)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1330
            if not vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1331
                if not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1332
                    self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1333
                else:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1334
                    self.mayneedvar.setdefault((node.children[0].name, rschema), []).append( (res, ored) )                    
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1335
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1336
                assert len(vrefs) == 1
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1337
                vref = vrefs[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1338
                # XXX check operator ?
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1339
                self.hasvar[(node.children[0].name, rschema)] = vref
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1340
                if self._may_skip_attr_rel(rschema, node, vref, ored, terms, res):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1341
                    self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1342
        elif not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1343
            self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1344
        return res, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1345
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1346
    def _may_skip_attr_rel(self, rschema, rel, vref, ored, terms, res):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1347
        var = vref.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1348
        if ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1349
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1350
        if var.name in self.extneedsel or var.stinfo['selected']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1351
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1352
        if not same_scope(var):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1353
            return False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1354
        if any(v for v,_ in var.stinfo['attrvars'] if not v.name in terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1355
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1356
        return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1357
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1358
    def visit_exists(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1359
        newexists = node.__class__()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1360
        self.scopes = {node: newexists}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1361
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1362
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1363
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1364
        newexists.set_where(subparts[0])
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1365
        return newexists, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1366
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1367
    def visit_not(self, node, newroot, terms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1368
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1369
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1370
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1371
        return copy_node(newroot, node, subparts), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1372
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1373
    def visit_group(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1374
        if not self.final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1375
            return None, node
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1376
        return self.visit_default(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1377
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1378
    def visit_variableref(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1379
        if self.use_only_defined:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1380
            if not node.variable.name in newroot.defined_vars:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1381
                raise UnsupportedBranch(node.name)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1382
        elif not node.variable in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1383
            raise UnsupportedBranch(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1384
        self.mayneedsel.add(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1385
        # set scope so we can insert types restriction properly
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1386
        newvar = newroot.get_variable(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1387
        newvar.stinfo['scope'] = self.scopes.get(node.variable.scope, newroot)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1388
        return VariableRef(newvar), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1389
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1390
    def visit_constant(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1391
        return copy_node(newroot, node), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1392
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1393
    def visit_default(self, node, newroot, terms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1394
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1395
        return copy_node(newroot, node, subparts), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1396
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1397
    visit_comparison = visit_mathexpression = visit_constant = visit_function = visit_default
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1398
    visit_sort = visit_sortterm = visit_default
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1399
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1400
    def _visit_children(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1401
        subparts = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1402
        for i in xrange(len(node.children)):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1403
            child = node.children[i]
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1404
            newchild, child_ = child.accept(self, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1405
            if not child is child_:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1406
                node = child_.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1407
            if newchild is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1408
                subparts.append(newchild)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1409
        return subparts, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1410
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1411
    def process_selection(self, newroot, terms, rqlst):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1412
        if self.final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1413
            for term in rqlst.selection:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1414
                newroot.append_selected(term.copy(newroot))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1415
                for vref in term.get_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1416
                    self.needsel.add(vref.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1417
            return 
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1418
        for term in rqlst.selection:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1419
            vrefs = term.get_nodes(VariableRef)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1420
            if vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1421
                supportedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1422
                for vref in vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1423
                    var = vref.variable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1424
                    if var in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1425
                        supportedvars.append(vref)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1426
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1427
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1428
                        self.needsel.add(vref.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1429
                        break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1430
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1431
                    for vref in vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1432
                        newroot.append_selected(vref.copy(newroot))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1433
                    supportedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1434
                for vref in supportedvars:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1435
                    if not vref in newroot.get_selected_variables():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1436
                        newroot.append_selected(VariableRef(newroot.get_variable(vref.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1437
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1438
    def add_necessary_selection(self, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1439
        selected = tuple(newroot.get_selected_variables())
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1440
        for varname in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1441
            var = newroot.defined_vars[varname]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1442
            for vref in var.references():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1443
                rel = vref.relation()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1444
                if rel is None and vref in selected:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1445
                    # already selected
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1446
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1447
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1448
                selvref = VariableRef(var)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1449
                newroot.append_selected(selvref)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1450
                if newroot.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1451
                    newroot.add_group_var(VariableRef(selvref.variable, noautoref=1))