server/msplanner.py
author sylvain.thenault@logilab.fr
Thu, 16 Apr 2009 18:31:53 +0200
changeset 1382 618f6aee8d52
parent 1237 c836bdb3b17b
child 1263 01152fffd593
permissions -rw-r--r--
use adbh.func_sqlname for more backend compat
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
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   226
        # shortcuts
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   227
        self._schema = plan.schema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   228
        self._session = plan.session
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   229
        self._repo = self._session.repo
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   230
        self._solutions = rqlst.solutions
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   231
        self._solindices = range(len(self._solutions))
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   232
        self.system_source = self._repo.system_source
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   233
        # source : {term: [solution index, ]}
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   234
        self.sourcesterms = self._sourcesterms = {}
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   235
        # source : {relation: set(child variable and constant)}
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   236
        self._crossrelations = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   237
        # 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
   238
        # 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
   239
        # not).
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   240
        self._linkedterms = {}
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   241
        # processing
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   242
        termssources = self._compute_sourcesterms()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   243
        self._remove_invalid_sources(termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   244
        self._compute_needsplit()
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   245
        # after initialisation, .sourcesterms contains the same thing as
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   246
        # ._sourcesterms though during plan construction, ._sourcesterms will
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   247
        # be modified while .sourcesterms will be kept unmodified
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   248
        self.sourcesterms = {}
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   249
        for k, v in self._sourcesterms.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   250
            self.sourcesterms[k] = {}
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   251
            for k2, v2 in v.iteritems():
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   252
                self.sourcesterms[k][k2] = v2.copy()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   253
        # cleanup linked var
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   254
        for var, linkedrelsinfo in self._linkedterms.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   255
            self._linkedterms[var] = frozenset(x[0] for x in linkedrelsinfo)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   256
        # 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
   257
        self._inputmaps = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   258
        # 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
   259
        self._conflicts = []
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   260
        if rqlhelper is not None: # else test
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   261
            self._insert_identity_variable = rqlhelper._annotator.rewrite_shared_optional
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   262
        if server.DEBUG:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   263
            print 'sourcesterms:'
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   264
            for source, terms in self.sourcesterms.items():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   265
                print source, terms
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   266
            
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   267
    def copy_solutions(self, solindices):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   268
        return [self._solutions[solidx].copy() for solidx in solindices]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   269
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   270
    @property
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   271
    @cached
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   272
    def part_sources(self):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   273
        if self._sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   274
            return tuple(sorted(self._sourcesterms))
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   275
        return (self.system_source,)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   276
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   277
    @property
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   278
    @cached
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   279
    def _sys_source_set(self):
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   280
        return frozenset((self.system_source, solindex)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   281
                         for solindex in self._solindices)        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   282
       
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   283
    @cached
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   284
    def _norel_support_set(self, relation):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   285
        """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
   286
        relation
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   287
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   288
        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
   289
                         for solidx in self._solindices
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   290
                         if not ((source.support_relation(relation.r_type))
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   291
                                 or relation.r_type in source.dont_cross_relations))
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   292
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   293
    def _compute_sourcesterms(self):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   294
        """compute for each term (variable, rewritten constant, relation) and
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   295
        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
   296
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   297
        repo = self._repo
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   298
        eschema = self._schema.eschema
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   299
        sourcesterms = self._sourcesterms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   300
        # find for each source which variable/solution are supported
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   301
        for varname, varobj in self.rqlst.defined_vars.items():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   302
            # 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
   303
            # 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
   304
            if varobj.stinfo['uidrels']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   305
                vrels = varobj.stinfo['relations'] - varobj.stinfo['uidrels']
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   306
                for rel in varobj.stinfo['uidrels']:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   307
                    if rel.neged(strict=True) or rel.operator() != '=':
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   308
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   309
                    for const in rel.children[1].get_nodes(Constant):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   310
                        eid = const.eval(self.plan.args)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   311
                        source = self._session.source_from_eid(eid)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   312
                        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
   313
                                             for r in vrels):
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   314
                            self._set_source_for_term(self.system_source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   315
                        else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   316
                            self._set_source_for_term(source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   317
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   318
            rels = varobj.stinfo['relations']
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   319
            if not rels and not varobj.stinfo['typerels']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   320
                # (rare) case where the variable has no type specified nor
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   321
                # relation accessed ex. "Any MAX(X)"
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   322
                self._set_source_for_term(self.system_source, varobj)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   323
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   324
            for i, sol in enumerate(self._solutions):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   325
                vartype = sol[varname]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   326
                # skip final variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   327
                if eschema(vartype).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   328
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   329
                for source in repo.sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   330
                    if source.support_entity(vartype):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   331
                        # the source support the entity type, though we will
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   332
                        # actually have to fetch from it only if
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   333
                        # * the variable isn't invariant
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   334
                        # * at least one supported relation specified
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   335
                        if not varobj._q_invariant or \
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   336
                               any(imap(source.support_relation,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   337
                                        (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
   338
                            sourcesterms.setdefault(source, {}).setdefault(varobj, set()).add(i)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   339
                        # 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
   340
                        # 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
   341
                        # query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   342
                        if not varobj._q_invariant and any(ifilterfalse(
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   343
                            source.support_relation, (r.r_type for r in rels))):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   344
                            self.needsplit = True               
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   345
        # add source for rewritten constants to sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   346
        for vconsts in self.rqlst.stinfo['rewritten'].itervalues():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   347
            const = vconsts[0]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   348
            source = self._session.source_from_eid(const.eval(self.plan.args))
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   349
            if source is self.system_source:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   350
                for const in vconsts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   351
                    self._set_source_for_term(source, const)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   352
            elif source in self._sourcesterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   353
                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
   354
                for const in vconsts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   355
                    if const.scope in source_scopes:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   356
                        self._set_source_for_term(source, const)
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   357
                        # 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
   358
                        # to its supported terms even when associated entity
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   359
                        # 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
   360
                        # that allequals will return True as expected when
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   361
                        # computing needsplit
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   362
                        if self.system_source in sourcesterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   363
                            self._set_source_for_term(self.system_source, const)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   364
        # add source for relations
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   365
        rschema = self._schema.rschema
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   366
        termssources = {}
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   367
        for rel in self.rqlst.iget_nodes(Relation):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   368
            # process non final relations only
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   369
            # 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
   370
            # during bootstrap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   371
            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
   372
                # nothing to do if relation is not supported by multiple sources
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   373
                # or if some source has it listed in its cross_relations
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   374
                # attribute
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   375
                #
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   376
                # XXX code below don't deal if some source allow relation
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   377
                #     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
   378
                relsources = repo.rel_type_sources(rel.r_type)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   379
                if len(relsources) < 2:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   380
                    # filter out sources being there because they have this
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   381
                    # relation in their dont_cross_relations attribute
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   382
                    relsources = [source for source in relsources
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   383
                                  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
   384
                    if relsources:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   385
                        # this means the relation is using a variable inlined as
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   386
                        # a constant and another unsupported variable, in which
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   387
                        # case we put the relation in sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   388
                        self._sourcesterms.setdefault(relsources[0], {})[rel] = set(self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   389
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   390
                lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   391
                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
   392
                # update dictionary of sources supporting lhs and rhs vars
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   393
                if not lhsv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   394
                    termssources[lhsv] = self._term_sources(lhs)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   395
                if not rhsv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   396
                    termssources[rhsv] = self._term_sources(rhs)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   397
                self._handle_cross_relation(rel, relsources, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   398
                self._linkedterms.setdefault(lhsv, set()).add((rhsv, rel))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   399
                self._linkedterms.setdefault(rhsv, set()).add((lhsv, rel))
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   400
        return termssources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   401
            
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   402
    def _handle_cross_relation(self, rel, relsources, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   403
        for source in relsources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   404
            if rel.r_type in source.cross_relations:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   405
                ssource = self.system_source
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   406
                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
   407
                for const in rel.get_nodes(Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   408
                    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
   409
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   410
                    crossvars.add(const)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   411
                self._crossrelations.setdefault(source, {})[rel] = crossvars
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   412
                if len(crossvars) < 2:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   413
                    # 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
   414
                    # not supported by the source, so we can stop here
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   415
                    continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   416
                self._sourcesterms.setdefault(ssource, {})[rel] = set(self._solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   417
                for term in crossvars:
1229
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   418
                    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
   419
                        for ov in crossvars:
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   420
                            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
   421
                                ssset = frozenset((ssource,))
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   422
                                self._remove_sources(ov, termssources[ov] - ssset)
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   423
                        break
dd9bdcfc03b6 cleanup _handle_cross_relation
sylvain.thenault@logilab.fr
parents: 1228
diff changeset
   424
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   425
                    self._sourcesterms.setdefault(source, {})[rel] = set(self._solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   426
    
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   427
    def _remove_invalid_sources(self, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   428
        """removes invalid sources from `sourcesterms` member according to
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   429
        traversed relations and their properties (which sources support them,
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   430
        can they cross sources, etc...)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   431
        """
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   432
        for term in self._linkedterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   433
            self._remove_sources_until_stable(term, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   434
        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
   435
            # 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
   436
            self.plan.annotate_rqlst()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   437
            # insert/update/delete queries, we may get extra information from
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   438
            # 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
   439
            if self.plan.rqlst.TYPE == 'insert':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   440
                inserted = dict((vref.variable, etype)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   441
                                for etype, vref in self.plan.rqlst.main_variables)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   442
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   443
                inserted = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   444
            repo = self._repo
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   445
            rschema = self._schema.rschema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   446
            for rel in self.plan.rqlst.main_relations:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   447
                if not rschema(rel.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   448
                    # nothing to do if relation is not supported by multiple sources
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   449
                    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
   450
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   451
                    lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   452
                    try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   453
                        lhsv = self._extern_term(lhs, termssources, inserted)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   454
                        rhsv = self._extern_term(rhs, termssources, inserted)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   455
                    except KeyError, ex:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   456
                        continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   457
                    self._remove_term_sources(lhsv, rel, rhsv, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   458
                    self._remove_term_sources(rhsv, rel, lhsv, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   459
                                    
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   460
    def _extern_term(self, term, termssources, inserted):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   461
        var = term.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   462
        if var.stinfo['constnode']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   463
            termv = var.stinfo['constnode']
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   464
            termssources[termv] = self._term_sources(termv)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   465
        elif var in inserted:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   466
            termv = var
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   467
            source = self._repo.locate_etype_source(inserted[var])
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   468
            termssources[termv] = set((source, solindex)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   469
                                      for solindex in self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   470
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   471
            termv = self.rqlst.defined_vars[var.name]
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   472
            if not termv in termssources:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   473
                termssources[termv] = self._term_sources(termv)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   474
        return termv
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   475
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   476
    def _remove_sources_until_stable(self, term, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   477
        sourcesterms = self._sourcesterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   478
        for oterm, rel in self._linkedterms.get(term, ()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   479
            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
   480
                # 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
   481
                # where terms don't belong to the same scope
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   482
                continue
1120
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   483
            need_ancestor_scope = False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   484
            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
   485
                if rel.ored():
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   486
                    continue
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   487
                if rel.ored(traverse_scope=True):
1c24cde4bf72 fix ms planning w/ relation constraint propagation
sylvain.thenault@logilab.fr
parents: 442
diff changeset
   488
                    # 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
   489
                    # 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
   490
                    need_ancestor_scope = True
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   491
            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
   492
            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
   493
                len(relsources) < 2
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   494
                or not isinstance(oterm, Variable)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   495
                or oterm.valuable_references() != 1
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   496
                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
   497
                       for source in relsources
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   498
                       if term in sourcesterms.get(source, ())
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   499
                       and oterm in sourcesterms.get(source, ()))):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   500
                # neged relation doesn't allow to infer term sources unless
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   501
                # 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
   502
                # 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
   503
                # Y)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   504
                continue
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   505
            # compute invalid sources for terms and remove them
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   506
            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
   507
                self._remove_term_sources(term, rel, oterm, termssources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   508
            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
   509
                self._remove_term_sources(oterm, rel, term, termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   510
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   511
    def _remove_term_sources(self, term, rel, oterm, termssources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   512
        """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
   513
        relation between those two terms. 
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   514
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   515
        norelsup = self._norel_support_set(rel)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   516
        termsources = termssources[term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   517
        invalid_sources = termsources - (termssources[oterm] | norelsup)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   518
        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
   519
            invalid_sources -= self._sys_source_set
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   520
            if invalid_sources and isinstance(term, Variable) \
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   521
                   and self._need_ext_source_access(term, rel):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   522
                # 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
   523
                # source where the relation is a cross relation from invalid
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   524
                # sources
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   525
                invalid_sources = frozenset((s, solidx) for s, solidx in invalid_sources
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   526
                                            if not (s in self._crossrelations and
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   527
                                                    rel in self._crossrelations[s]))
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   528
        if invalid_sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   529
            self._remove_sources(term, invalid_sources)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   530
            termsources -= invalid_sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   531
            self._remove_sources_until_stable(term, termssources)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   532
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   533
    def _compute_needsplit(self):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   534
        """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
   535
        execution among multiple sources
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   536
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   537
        the execution has to be split if
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   538
        * 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
   539
          relation on it
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   540
        * 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
   541
        * 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
   542
          variable/solutions are not equivalent or multiple variables have to
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   543
          be fetched from some source
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   544
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   545
        # 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
   546
        if len(self._sourcesterms) < 2: 
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   547
            self.needsplit = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   548
        elif not self.needsplit:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   549
            if not allequals(self._sourcesterms.itervalues()):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   550
                self.needsplit = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   551
            else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   552
                sample = self._sourcesterms.itervalues().next()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   553
                if len(sample) > 1:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   554
                    for term in sample:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   555
                        # need split if unlinked variable
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   556
                        if isinstance(term, Variable) and not term in self._linkedterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   557
                            self.needsplit = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   558
                            break
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   559
                    else:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   560
                        # need split if there are some cross relation on non
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   561
                        # invariant variable or if the variable is used in
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   562
                        # multi-sources relation
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   563
                        if self._crossrelations:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   564
                            for reldict in self._crossrelations.itervalues():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   565
                                for rel, terms in reldict.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   566
                                    for term in terms:
1230
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   567
                                        if isinstance(term, Variable) \
232e16835fff fix constant handling in sourcesterms + minor cleanup
sylvain.thenault@logilab.fr
parents: 1229
diff changeset
   568
                                               and self._need_ext_source_access(term, rel):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   569
                                            self.needsplit = True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   570
                                            return
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   571
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   572
    @cached
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   573
    def _need_ext_source_access(self, var, rel):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   574
        if not var._q_invariant:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   575
            return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   576
        if  any(r for x, r in self._linkedterms[var]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   577
                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
   578
            return True
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   579
        return False
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   580
        
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   581
    def _set_source_for_term(self, source, term):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   582
        self._sourcesterms.setdefault(source, {})[term] = set(self._solindices)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   583
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   584
    def _term_sources(self, term):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   585
        """returns possible sources for terms `term`"""
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   586
        if isinstance(term, Constant):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   587
            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
   588
            return set((source, solindex) for solindex in self._solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   589
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   590
            var = getattr(term, 'variable', term)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   591
            sources = [source for source, varobjs in self.sourcesterms.iteritems()
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   592
                       if var in varobjs]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   593
            return set((source, solindex) for source in sources
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   594
                       for solindex in self.sourcesterms[source][var])
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   595
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   596
    def _remove_sources(self, term, sources):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   597
        """removes invalid sources (`sources`) from `sourcesterms`
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   598
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   599
        :param sources: the list of sources to remove
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   600
        :param term: the analyzed term
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   601
        """
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   602
        sourcesterms = self._sourcesterms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   603
        for source, solindex in sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   604
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   605
                sourcesterms[source][term].remove(solindex)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   606
            except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   607
                return # may occur with subquery column alias
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   608
            if not sourcesterms[source][term]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   609
                del sourcesterms[source][term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   610
                if not sourcesterms[source]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   611
                    del sourcesterms[source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   612
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   613
    def crossed_relation(self, source, relation):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   614
        return relation in self._crossrelations.get(source, ())
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   615
    
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   616
    def part_steps(self):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   617
        """precompute necessary part steps before generating actual rql for
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   618
        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
   619
        necessary or not.
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   620
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   621
        steps = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   622
        select = self.rqlst
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   623
        rschema = self._schema.rschema
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   624
        for source in self.part_sources:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   625
            try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   626
                sourceterms = self._sourcesterms[source]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   627
            except KeyError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   628
                continue # already proceed
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   629
            while sourceterms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   630
                # take a term randomly, and all terms supporting the
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   631
                # same solutions
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   632
                term, solindices = self._choose_term(sourceterms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   633
                if source.uri == 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   634
                    # ensure all variables are available for the latest step
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   635
                    # (missing one will be available from temporary tables
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   636
                    # of previous steps)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   637
                    scope = select
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   638
                    terms = scope.defined_vars.values() + scope.aliases.values()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   639
                    sourceterms.clear()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   640
                    sources = [source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   641
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   642
                    scope = term.scope
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   643
                    # find which sources support the same term and solutions
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   644
                    sources = self._expand_sources(source, term, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   645
                    # no try to get as much terms as possible
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   646
                    terms = self._expand_terms(term, sources, sourceterms,
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   647
                                               scope, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   648
                    if len(terms) == 1 and isinstance(terms[0], Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   649
                        # we can't generate anything interesting with a single
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   650
                        # constant term (will generate an empty "Any" query),
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   651
                        # go to the next iteration directly!
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   652
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   653
                    if not sourceterms:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   654
                         try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   655
                             del self._sourcesterms[source]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   656
                         except KeyError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   657
                             # XXX already cleaned
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   658
                             pass
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   659
                # set of terms which should be additionaly selected when
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   660
                # possible
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   661
                needsel = set()
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   662
                if not self._sourcesterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   663
                    terms += scope.defined_vars.values() + scope.aliases.values()
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   664
                    final = True
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   665
                else:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   666
                    # suppose this is a final step until the contrary is proven
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   667
                    final = scope is select
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   668
                    # add attribute variables and mark variables which should be
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   669
                    # additionaly selected when possible
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   670
                    for var in select.defined_vars.itervalues():
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   671
                        if not var in terms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   672
                            stinfo = var.stinfo
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   673
                            for ovar, rtype in stinfo['attrvars']:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   674
                                if ovar in terms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   675
                                    needsel.add(var.name)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   676
                                    terms.append(var)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   677
                                    break
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   678
                            else:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   679
                                needsel.add(var.name)
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   680
                                final = False
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   681
                    # check where all relations are supported by the sources
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   682
                    for rel in scope.iget_nodes(Relation):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   683
                        if rel.is_types_restriction():
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   684
                            continue
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   685
                        # take care not overwriting the existing "source" identifier
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   686
                        for _source in sources:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   687
                            if not _source.support_relation(rel.r_type) or (
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   688
                                self.crossed_relation(_source, rel) and not rel in terms):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   689
                                for vref in rel.iget_nodes(VariableRef):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   690
                                    needsel.add(vref.name)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   691
                                final = False
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   692
                                break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   693
                        else:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   694
                            if not scope is select:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   695
                                self._exists_relation(rel, terms, needsel)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   696
                            # if relation is supported by all sources and some of
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   697
                            # its lhs/rhs variable isn't in "terms", and the
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   698
                            # other end *is* in "terms", mark it have to be
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   699
                            # selected
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   700
                            if source.uri != 'system' and not rschema(rel.r_type).is_final():
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   701
                                lhs, rhs = rel.get_variable_parts()
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   702
                                try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   703
                                    lhsvar = lhs.variable
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   704
                                except AttributeError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   705
                                    lhsvar = lhs
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   706
                                try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   707
                                    rhsvar = rhs.variable
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   708
                                except AttributeError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   709
                                    rhsvar = rhs
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   710
                                if lhsvar in terms and not rhsvar in terms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   711
                                    needsel.add(lhsvar.name)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   712
                                elif rhsvar in terms and not lhsvar in terms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   713
                                    needsel.add(rhsvar.name)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   714
                if final and source.uri != 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   715
                    # check rewritten constants
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   716
                    for vconsts in select.stinfo['rewritten'].itervalues():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   717
                        const = vconsts[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   718
                        eid = const.eval(self.plan.args)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   719
                        _source = self._session.source_from_eid(eid)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   720
                        if len(sources) > 1 or not _source in sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   721
                            # if there is some rewriten constant used by a not
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   722
                            # neged relation while there are some source not
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   723
                            # supporting the associated entity, this step can't
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   724
                            # be final (unless the relation is explicitly in
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   725
                            # `terms`, eg cross relations)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   726
                            for c in vconsts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   727
                                rel = c.relation()
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   728
                                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
   729
                                    final = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   730
                                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   731
                            break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   732
                if final:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   733
                    self._cleanup_sourcesterms(sources, solindices)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   734
                steps.append((sources, terms, solindices, scope, needsel, final)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   735
                             )
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   736
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   737
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   738
    def _exists_relation(self, rel, terms, needsel):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   739
        rschema = self._schema.rschema(rel.r_type)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   740
        lhs, rhs = rel.get_variable_parts()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   741
        try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   742
            lhsvar, rhsvar = lhs.variable, rhs.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   743
        except AttributeError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   744
            pass
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   745
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   746
            # supported relation with at least one end supported, check the
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   747
            # 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
   748
            # 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
   749
            # 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
   750
            # temporary tables)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   751
            if rhsvar in terms and not lhsvar in terms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   752
                self._identity_substitute(rel, lhsvar, terms, needsel)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   753
            elif lhsvar in terms and not rhsvar in terms:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   754
                self._identity_substitute(rel, rhsvar, terms, needsel)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   755
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   756
    def _identity_substitute(self, relation, var, terms, needsel):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   757
        newvar = self._insert_identity_variable(relation.scope, var)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   758
        if newvar is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   759
            # ensure relation is using '=' operator, else we rely on a
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   760
            # sqlgenerator side effect (it won't insert an inequality operator
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   761
            # in this case)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   762
            relation.children[1].operator = '=' 
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   763
            terms.append(newvar)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   764
            needsel.add(newvar.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   765
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   766
    def _choose_term(self, sourceterms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   767
        """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
   768
        as a base to generate an execution step
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   769
        """
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   770
        secondchoice = None
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   771
        if len(self._sourcesterms) > 1:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   772
            # priority to variable from subscopes
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   773
            for term in sourceterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   774
                if not term.scope is self.rqlst:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   775
                    if isinstance(term, Variable):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   776
                        return term, sourceterms.pop(term)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   777
                    secondchoice = term
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   778
        else:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   779
            # priority to variable from outer scope
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   780
            for term in sourceterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   781
                if term.scope is self.rqlst:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   782
                    if isinstance(term, Variable):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   783
                        return term, sourceterms.pop(term)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   784
                    secondchoice = term
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   785
        if secondchoice is not None:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   786
            return secondchoice, sourceterms.pop(secondchoice)
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   787
        # priority to variable with the less solutions supported and with the
1237
c836bdb3b17b more test predictability
Sylvain <syt@logilab.fr>
parents: 1231
diff changeset
   788
        # most valuable refs. Add variable name for test predictability
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   789
        variables = sorted([(var, sols) for (var, sols) in sourceterms.items()
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   790
                            if isinstance(var, Variable)],
1237
c836bdb3b17b more test predictability
Sylvain <syt@logilab.fr>
parents: 1231
diff changeset
   791
                           key=lambda (v, s): (len(s), -v.valuable_references(), v.name))
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   792
        if variables:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   793
            var = variables[0][0]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   794
            return var, sourceterms.pop(var)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   795
        # priority to constant
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   796
        for term in sourceterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   797
            if isinstance(term, Constant):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   798
                return term, sourceterms.pop(term)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   799
        # whatever (relation)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   800
        term = iter(sourceterms).next()
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   801
        return term, sourceterms.pop(term)
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   802
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   803
    def _expand_sources(self, selected_source, term, solindices):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   804
        """return all sources supporting given term / solindices"""
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   805
        sources = [selected_source]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   806
        sourcesterms = self._sourcesterms
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   807
        for source in sourcesterms.keys():
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   808
            if source is selected_source:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   809
                continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   810
            if not (term in sourcesterms[source] and 
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   811
                    solindices.issubset(sourcesterms[source][term])):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   812
                continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   813
            sources.append(source)
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   814
            if source.uri != 'system' or not (isinstance(term, Variable) and not term in self._linkedterms):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   815
                termsolindices = sourcesterms[source][term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   816
                termsolindices -= solindices
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   817
                if not termsolindices:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   818
                    del sourcesterms[source][term]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   819
                    if not sourcesterms[source]:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   820
                        del sourcesterms[source]
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   821
        return sources
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   822
            
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   823
    def _expand_terms(self, term, sources, sourceterms, scope, solindices):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   824
        terms = [term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   825
        sources = sorted(sources)
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   826
        sourcesterms = self._sourcesterms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   827
        nbunlinked = 1
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   828
        linkedterms = self._linkedterms
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   829
        # 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
   830
        # than the system source remaining
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   831
        if len(sourcesterms) > 1 and not scope is self.rqlst:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   832
            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
   833
        else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   834
            candidates = sourceterms #.iterkeys()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   835
        # we only want one unlinked term in each generated query
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   836
        candidates = [t for t in candidates
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   837
                      if isinstance(t, (Constant, Relation)) or
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   838
                      (solindices.issubset(sourceterms[t]) and t in linkedterms)]
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   839
        cross_rels = {}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   840
        for source in sources:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   841
            cross_rels.update(self._crossrelations.get(source, {}))
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   842
        exclude = {}
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   843
        for rel, crossvars in cross_rels.iteritems():
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   844
            vars = [t for t in crossvars if isinstance(t, Variable)]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   845
            try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   846
                exclude[vars[0]] = vars[1]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   847
                exclude[vars[1]] = vars[0]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   848
            except IndexError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   849
                pass
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   850
        accept_term = lambda x: (not any(s for s in sources if not x in sourcesterms.get(s, ()))
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   851
                                 and any(t for t in terms if t in linkedterms.get(x, ()))
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   852
                                 and not exclude.get(x) in terms)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   853
        if isinstance(term, Relation) and term in cross_rels:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   854
            cross_terms = cross_rels.pop(term)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   855
            base_accept_term = accept_term
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   856
            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
   857
            for refed in cross_terms:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
   858
                if not refed in candidates:
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   859
                    terms.append(refed)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   860
        # 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
   861
        # term may permit to another one to be added
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   862
        modified = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   863
        while modified and candidates:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   864
            modified = False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   865
            for term in candidates[:]:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   866
                if isinstance(term, Constant):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   867
                    relation = term.relation()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   868
                    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
   869
                        continue
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   870
                    terms.append(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   871
                    candidates.remove(term)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   872
                    modified = True
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   873
                    del sourceterms[term]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   874
                elif accept_term(term):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   875
                    terms.append(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   876
                    candidates.remove(term)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   877
                    modified = True
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   878
                    self._cleanup_sourcesterms(sources, solindices, term)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   879
        return terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   880
    
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   881
    def _cleanup_sourcesterms(self, sources, solindices, term=None):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   882
        """remove solutions so we know they are already processed"""
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   883
        for source in sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   884
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   885
                sourceterms = self._sourcesterms[source]
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   886
            except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   887
                continue
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   888
            if term is None:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   889
                for term, termsolindices in sourceterms.items():
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   890
                    if isinstance(term, Relation) and self.crossed_relation(source, term):
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   891
                        continue
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   892
                    termsolindices -= solindices
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   893
                    if not termsolindices:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   894
                        del sourceterms[term]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   895
            else:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   896
                try:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   897
                    sourceterms[term] -= solindices
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   898
                    if not sourceterms[term]:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   899
                        del sourceterms[term]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   900
                except KeyError:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   901
                    pass
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   902
                    #assert term in cross_terms
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   903
            if not sourceterms:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   904
                del self._sourcesterms[source]
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
   905
                
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   906
    def merge_input_maps(self, allsolindices):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   907
        """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
   908
        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
   909
        solution its necessary input map and return them grouped
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   910
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   911
        ex:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   912
        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
   913
                     (1,): {'X': 't2.C0', 'T': 't2.C1'}}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   914
        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
   915
                           'X': 't2.C0', 'T': 't2.C1'}),                   
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   916
                  ([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
   917
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   918
        if not self._inputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   919
            return [(allsolindices, None)]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   920
        mapbysol = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   921
        # compute a single map for each solution
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   922
        for solindices, basemap in self._inputmaps.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   923
            for solindex in solindices:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   924
                solmap = mapbysol.setdefault(solindex, {})
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   925
                solmap.update(basemap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   926
                try:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   927
                    allsolindices.remove(solindex)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   928
                except KeyError:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   929
                    continue # already removed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   930
        # group results by identical input map
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   931
        result = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   932
        for solindex, solmap in mapbysol.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   933
            for solindices, commonmap in result:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   934
                if commonmap == solmap:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   935
                    solindices.append(solindex)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   936
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   937
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   938
                result.append( ([solindex], solmap) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   939
        if allsolindices:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   940
            result.append( (list(allsolindices), None) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   941
        return result
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   942
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   943
    def build_final_part(self, select, solindices, inputmap,  sources,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   944
                         insertedvars):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   945
        solutions = [self._solutions[i] for i in solindices]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   946
        if self._conflicts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   947
            for varname, mappedto in self._conflicts:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   948
                var = select.defined_vars[varname]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   949
                newvar = select.make_variable()
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   950
                # 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
   951
                select.add_relation(var, 'identity', newvar)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   952
                for sol in solutions:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   953
                    sol[newvar.name] = sol[varname]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   954
                inputmap[newvar.name] = mappedto
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   955
        rqlst = self.plan.finalize(select, solutions, insertedvars)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   956
        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
   957
            return OneFetchStep(self.plan, rqlst, sources, inputmap=inputmap)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   958
        table = self.temptable or self.finaltable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   959
        return FetchStep(self.plan, rqlst, sources, table, True, inputmap)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   960
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   961
    def build_non_final_part(self, select, solindices, sources, insertedvars,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   962
                             table):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   963
        """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
   964
        solutions = [self._solutions[i] for i in solindices]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   965
        rqlst = self.plan.finalize(select, solutions, insertedvars)
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   966
        step = FetchStep(self.plan, rqlst, sources, table, False)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   967
        # update input map for following steps, according to processed solutions
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   968
        inputmapkey = tuple(sorted(solindices))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   969
        inputmap = self._inputmaps.setdefault(inputmapkey, {})
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   970
        for varname, mapping in step.outputmap.iteritems():
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   971
            if varname in inputmap and \
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   972
                   not (mapping == inputmap[varname] or
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   973
                        self._schema.eschema(solutions[0][varname]).is_final()):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   974
                self._conflicts.append((varname, inputmap[varname]))
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   975
        inputmap.update(step.outputmap)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
   976
        self.plan.add_step(step)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   977
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   978
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   979
class MSPlanner(SSPlanner):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   980
    """MultiSourcesPlanner: build execution plan for rql queries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   981
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   982
    decompose the RQL query according to sources'schema
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   983
    """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   984
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   985
    def build_select_plan(self, plan, rqlst):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   986
        """build execution plan for a SELECT RQL query
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   987
               
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   988
        the rqlst should not be tagged at this point
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   989
        """
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   990
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   991
            print '-'*80
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   992
            print 'PLANNING', rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   993
        for select in rqlst.children:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   994
            if len(select.solutions) > 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   995
                hasmultiplesols = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   996
                break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   997
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   998
            hasmultiplesols = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
   999
        # 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
  1000
        # which have to be executed to fulfill the query: according
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1001
        # 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
  1002
        # be executed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1003
        plan.preprocess(rqlst)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1004
        ppis = [PartPlanInformation(plan, select, self.rqlhelper)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1005
                for select in rqlst.children]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1006
        steps = self._union_plan(plan, rqlst, ppis)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1007
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1008
            from pprint import pprint
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1009
            for step in plan.steps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1010
                pprint(step.test_repr())
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1011
            pprint(steps[0].test_repr())
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1012
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1013
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1014
    def _ppi_subqueries(self, ppi):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1015
        # part plan info for subqueries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1016
        plan = ppi.plan
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1017
        inputmap = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1018
        for subquery in ppi.rqlst.with_[:]:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1019
            sppis = [PartPlanInformation(plan, select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1020
                     for select in subquery.query.children]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1021
            for sppi in sppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1022
                if sppi.needsplit or sppi.part_sources != ppi.part_sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1023
                    temptable = 'T%s' % make_uid(id(subquery))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1024
                    sstep = self._union_plan(plan, subquery.query, sppis, temptable)[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1025
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1026
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1027
                sstep = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1028
            if sstep is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1029
                ppi.rqlst.with_.remove(subquery)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1030
                for i, colalias in enumerate(subquery.aliases):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1031
                    inputmap[colalias.name] = '%s.C%s' % (temptable, i)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1032
                ppi.plan.add_step(sstep)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1033
        return inputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1034
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1035
    def _union_plan(self, plan, union, ppis, temptable=None):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1036
        tosplit, cango, allsources = [], {}, set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1037
        for planinfo in ppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1038
            if planinfo.needsplit:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1039
                tosplit.append(planinfo)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1040
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1041
                cango.setdefault(planinfo.part_sources, []).append(planinfo)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1042
            for source in planinfo.part_sources:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1043
                allsources.add(source)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1044
        # 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
  1045
        steps = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1046
        for sources, cppis in cango.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1047
            byinputmap = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1048
            for ppi in cppis:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1049
                select = ppi.rqlst
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1050
                if sources != (ppi.system_source,):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1051
                    add_types_restriction(self.schema, select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1052
                # part plan info for subqueries
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1053
                inputmap = self._ppi_subqueries(ppi)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1054
                aggrstep = need_aggr_step(select, sources)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1055
                if aggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1056
                    atemptable = 'T%s' % make_uid(id(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1057
                    sunion = Union()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1058
                    sunion.append(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1059
                    selected = select.selection[:]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1060
                    select_group_sort(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1061
                    step = AggrStep(plan, selected, select, atemptable, temptable)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1062
                    step.set_limit_offset(select.limit, select.offset)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1063
                    select.limit = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1064
                    select.offset = 0
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1065
                    fstep = FetchStep(plan, sunion, sources, atemptable, True, inputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1066
                    step.children.append(fstep)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1067
                    steps.append(step)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1068
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1069
                    byinputmap.setdefault(tuple(inputmap.iteritems()), []).append( (select) )
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1070
            for inputmap, queries in byinputmap.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1071
                inputmap = dict(inputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1072
                sunion = Union()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1073
                for select in queries:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1074
                    sunion.append(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1075
                if temptable:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1076
                    steps.append(FetchStep(plan, sunion, sources, temptable, True, inputmap))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1077
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1078
                    steps.append(OneFetchStep(plan, sunion, sources, inputmap))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1079
        # then add steps for splitted query parts
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1080
        for planinfo in tosplit:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1081
            steps.append(self.split_part(planinfo, temptable))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1082
        if len(steps) > 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1083
            if temptable:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1084
                step = UnionFetchStep(plan)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1085
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1086
                step = UnionStep(plan)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1087
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1088
            return (step,)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1089
        return steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1090
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1091
    # internal methods for multisources decomposition #########################
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1092
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1093
    def split_part(self, ppi, temptable):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1094
        ppi.finaltable = temptable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1095
        plan = ppi.plan
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1096
        select = ppi.rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1097
        subinputmap = self._ppi_subqueries(ppi)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1098
        stepdefs = ppi.part_steps()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1099
        if need_aggr_step(select, ppi.part_sources, stepdefs):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1100
            atemptable = 'T%s' % make_uid(id(select))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1101
            selection = select.selection[:]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1102
            select_group_sort(select)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1103
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1104
            atemptable = None
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1105
            selection = select.selection
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1106
        ppi.temptable = atemptable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1107
        vfilter = TermsFiltererVisitor(self.schema, ppi)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1108
        steps = []
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1109
        for sources, terms, solindices, scope, needsel, final in stepdefs:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1110
            # extract an executable query using only the specified terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1111
            if sources[0].uri == 'system':
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1112
                # 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
  1113
                # filter so already processed restriction are correctly
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1114
                # removed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1115
                solsinputmaps = ppi.merge_input_maps(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1116
                for solindices, inputmap in solsinputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1117
                    minrqlst, insertedvars = vfilter.filter(
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1118
                        sources, terms, scope, set(solindices), needsel, final)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1119
                    if inputmap is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1120
                        inputmap = subinputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1121
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1122
                        inputmap.update(subinputmap)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1123
                    steps.append(ppi.build_final_part(minrqlst, solindices, inputmap,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1124
                                                      sources, insertedvars))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1125
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1126
                # 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
  1127
                # original query part) if all term / sources have been
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1128
                # 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
  1129
                minrqlst, insertedvars = vfilter.filter(
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1130
                    sources, terms, scope, solindices, needsel, final)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1131
                if final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1132
                    solsinputmaps = ppi.merge_input_maps(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1133
                    for solindices, inputmap in solsinputmaps:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1134
                        if inputmap is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1135
                            inputmap = subinputmap
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1136
                        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1137
                            inputmap.update(subinputmap)
1231
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1138
                        if inputmap and len(sources) > 1:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1139
                            sources.remove(ppi.system_source)
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1140
                            steps.append(ppi.build_final_part(minrqlst, solindices, None,
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1141
                                                              sources, insertedvars))
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1142
                            steps.append(ppi.build_final_part(minrqlst, solindices, inputmap,
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1143
                                                              [ppi.system_source], insertedvars))
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1144
                        else:
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1145
                            steps.append(ppi.build_final_part(minrqlst, solindices, inputmap,
1457a545af03 more fix of cross relation handling
sylvain.thenault@logilab.fr
parents: 1230
diff changeset
  1146
                                                              sources, insertedvars))
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1147
                else:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1148
                    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
  1149
                                        ''.join(sorted(str(i) for i in solindices)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1150
                    ppi.build_non_final_part(minrqlst, solindices, sources,
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1151
                                             insertedvars, table)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1152
        # finally: join parts, deal with aggregat/group/sorts if necessary
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1153
        if atemptable is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1154
            step = AggrStep(plan, selection, select, atemptable, temptable)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1155
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1156
        elif len(steps) > 1:
442
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1157
            if select.need_intersect or any(select.need_intersect
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1158
                                            for step in steps
b1cf7611f8b3 fix need intersect detection
sylvain.thenault@logilab.fr
parents: 433
diff changeset
  1159
                                            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
  1160
                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
  1161
                    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
  1162
                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
  1163
                    step = IntersectStep(plan)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1164
            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
  1165
                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
  1166
                    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
  1167
                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
  1168
                    step = UnionStep(plan)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1169
            step.children = steps
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1170
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1171
            step = steps[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1172
        if select.limit is not None or select.offset:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1173
            step.set_limit_offset(select.limit, select.offset)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1174
        return step
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1175
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1176
    
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1177
class UnsupportedBranch(Exception):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1178
    pass
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1179
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1180
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1181
class TermsFiltererVisitor(object):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1182
    def __init__(self, schema, ppi):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1183
        self.schema = schema
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1184
        self.ppi = ppi
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1185
        self.skip = {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1186
        self.hasaggrstep = self.ppi.temptable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1187
        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
  1188
                                    for vref in sortterm.iget_nodes(VariableRef))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1189
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1190
    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
  1191
        try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1192
            newrestr, node_ = node.accept(self, newroot, terms[:])
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1193
        except UnsupportedBranch:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1194
            return rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1195
        if setfunc is not None and newrestr is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1196
            setfunc(newrestr)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1197
        if not node_ is node:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1198
            rqlst = node.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1199
        return rqlst
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1200
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1201
    def filter(self, sources, terms, rqlst, solindices, needsel, final):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1202
        if server.DEBUG:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1203
            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
  1204
        newroot = Select()
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1205
        self.sources = sorted(sources)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1206
        self.terms = terms
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1207
        self.solindices = solindices
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1208
        self.final = final
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1209
        # terms which appear in unsupported branches
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1210
        needsel |= self.extneedsel
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1211
        self.needsel = needsel
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1212
        # terms which appear in supported branches
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1213
        self.mayneedsel = set()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1214
        # new inserted variables
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1215
        self.insertedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1216
        # other structures (XXX document)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1217
        self.mayneedvar, self.hasvar = {}, {}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1218
        self.use_only_defined = False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1219
        self.scopes = {rqlst: newroot}
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1220
        if rqlst.where:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1221
            rqlst = self._rqlst_accept(rqlst, rqlst.where, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1222
                                       newroot.set_where)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1223
        if isinstance(rqlst, Select):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1224
            self.use_only_defined = True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1225
            if rqlst.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1226
                groupby = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1227
                for node in rqlst.groupby:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1228
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1229
                                               groupby.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1230
                if groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1231
                    newroot.set_groupby(groupby)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1232
            if rqlst.having:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1233
                having = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1234
                for node in rqlst.having:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1235
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1236
                                               having.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1237
                if having:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1238
                    newroot.set_having(having)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1239
            if final and rqlst.orderby and not self.hasaggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1240
                orderby = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1241
                for node in rqlst.orderby:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1242
                    rqlst = self._rqlst_accept(rqlst, node, newroot, terms,
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1243
                                               orderby.append)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1244
                if orderby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1245
                    newroot.set_orderby(orderby)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1246
            self.process_selection(newroot, terms, rqlst)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1247
        elif not newroot.where:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1248
            # 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
  1249
            # type restriction (done later by add_types_restriction)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1250
            for v in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1251
                if not isinstance(v, Variable):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1252
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1253
                newroot.append_selected(VariableRef(newroot.get_variable(v.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1254
        solutions = self.ppi.copy_solutions(solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1255
        cleanup_solutions(newroot, solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1256
        newroot.set_possible_types(solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1257
        if final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1258
            if self.hasaggrstep:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1259
                self.add_necessary_selection(newroot, self.mayneedsel & self.extneedsel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1260
            newroot.distinct = rqlst.distinct
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1261
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1262
            self.add_necessary_selection(newroot, self.mayneedsel & self.needsel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1263
            # insert vars to fetch constant values when needed
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1264
            for (varname, rschema), reldefs in self.mayneedvar.iteritems():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1265
                for rel, ored in reldefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1266
                    if not (varname, rschema) in self.hasvar:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1267
                        self.hasvar[(varname, rschema)] = None # just to avoid further insertion
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1268
                        cvar = newroot.make_variable()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1269
                        for sol in newroot.solutions:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1270
                            sol[cvar.name] = rschema.objects(sol[varname])[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1271
                        # 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
  1272
                        # 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
  1273
                        # restriction (or we may miss some results)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1274
                        if not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1275
                            rel = rel.copy(newroot)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1276
                            newroot.add_restriction(rel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1277
                        # add a relation to link the variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1278
                        newroot.remove_node(rel.children[1])
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1279
                        cmp = Comparison('=')
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1280
                        rel.append(cmp)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1281
                        cmp.append(VariableRef(cvar))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1282
                        self.insertedvars.append((varname, rschema, cvar.name))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1283
                        newroot.append_selected(VariableRef(newroot.get_variable(cvar.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1284
                        # 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
  1285
                        # 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
  1286
                        # 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
  1287
                        # if there are NOT somewhere :
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1288
                        # '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
  1289
                        # to Y whose name is toto while
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1290
                        # '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
  1291
                    elif ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1292
                        newroot.remove_node(rel)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1293
        add_types_restriction(self.schema, rqlst, newroot, solutions)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1294
        if server.DEBUG:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1295
            print '--->', newroot
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1296
        return newroot, self.insertedvars
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1297
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1298
    def visit_and(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1299
        subparts = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1300
        for i in xrange(len(node.children)):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1301
            child = node.children[i]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1302
            try:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1303
                newchild, child_ = child.accept(self, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1304
                if not child_ is child:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1305
                    node = child_.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1306
                if newchild is None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1307
                    continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1308
                subparts.append(newchild)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1309
            except UnsupportedBranch:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1310
                continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1311
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1312
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1313
        if len(subparts) == 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1314
            return subparts[0], node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1315
        return copy_node(newroot, node, subparts), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1316
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1317
    visit_or = visit_and
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1318
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1319
    def _relation_supported(self, relation):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1320
        rtype = relation.r_type
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1321
        for source in self.sources:
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1322
            if not source.support_relation(rtype) or (
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1323
                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
  1324
                return False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1325
        if not self.final and not relation in self.terms:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1326
            rschema = self.schema.rschema(relation.r_type)
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1327
            if not rschema.is_final():
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1328
                for term in relation.get_nodes((VariableRef, Constant)):
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1329
                    term = getattr(term, 'variable', term)
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1330
                    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
  1331
                    if termsources and termsources != self.sources:
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1332
                        return False
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1333
        return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1334
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1335
    def visit_relation(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1336
        if not node.is_types_restriction():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1337
            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
  1338
                if not self.schema.rschema(node.r_type).is_final():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1339
                    # 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
  1340
                    # referenced by this relation
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1341
                    for vref in node.iget_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1342
                        stinfo = vref.variable.stinfo
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1343
                        if stinfo['selected'] and len(stinfo['relations']) == 1:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1344
                            break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1345
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1346
                        return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1347
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1348
                    return None, node
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1349
            if not self._relation_supported(node):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1350
                raise UnsupportedBranch()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1351
        # 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
  1352
        # 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
  1353
        # copy a type restriction while the variable is not actually used)
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1354
        elif not any(self._relation_supported(rel)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1355
                     for rel in node.children[0].variable.stinfo['relations']):
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1356
            rel, node = self.visit_default(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1357
            return rel, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1358
        else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1359
            raise UnsupportedBranch()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1360
        rschema = self.schema.rschema(node.r_type)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1361
        try:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1362
            res = self.visit_default(node, newroot, terms)[0]
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1363
        except Exception, ex:
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1364
            raise
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1365
        ored = node.ored()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1366
        if rschema.is_final() or rschema.inlined:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1367
            vrefs = node.children[1].get_nodes(VariableRef)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1368
            if not vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1369
                if not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1370
                    self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1371
                else:
393
45a675515427 cross_relations support
sylvain.thenault@logilab.fr
parents: 392
diff changeset
  1372
                    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
  1373
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1374
                assert len(vrefs) == 1
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1375
                vref = vrefs[0]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1376
                # XXX check operator ?
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1377
                self.hasvar[(node.children[0].name, rschema)] = vref
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1378
                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
  1379
                    self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1380
        elif not ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1381
            self.skip.setdefault(node, set()).update(self.solindices)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1382
        return res, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1383
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1384
    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
  1385
        var = vref.variable
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1386
        if ored:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1387
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1388
        if var.name in self.extneedsel or var.stinfo['selected']:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1389
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1390
        if not same_scope(var):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1391
            return False
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1392
        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
  1393
            return False
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1394
        return True
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1395
        
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1396
    def visit_exists(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1397
        newexists = node.__class__()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1398
        self.scopes = {node: newexists}
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1399
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1400
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1401
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1402
        newexists.set_where(subparts[0])
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1403
        return newexists, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1404
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1405
    def visit_not(self, node, newroot, terms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1406
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1407
        if not subparts:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1408
            return None, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1409
        return copy_node(newroot, node, 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 visit_group(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1412
        if not self.final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1413
            return None, node
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1414
        return self.visit_default(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1415
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1416
    def visit_variableref(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1417
        if self.use_only_defined:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1418
            if not node.variable.name in newroot.defined_vars:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1419
                raise UnsupportedBranch(node.name)
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1420
        elif not node.variable in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1421
            raise UnsupportedBranch(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1422
        self.mayneedsel.add(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1423
        # set scope so we can insert types restriction properly
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1424
        newvar = newroot.get_variable(node.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1425
        newvar.stinfo['scope'] = self.scopes.get(node.variable.scope, newroot)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1426
        return VariableRef(newvar), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1427
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1428
    def visit_constant(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1429
        return copy_node(newroot, node), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1430
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1431
    def visit_default(self, node, newroot, terms):
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1432
        subparts, node = self._visit_children(node, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1433
        return copy_node(newroot, node, subparts), node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1434
        
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1435
    visit_comparison = visit_mathexpression = visit_constant = visit_function = visit_default
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1436
    visit_sort = visit_sortterm = visit_default
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 _visit_children(self, node, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1439
        subparts = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1440
        for i in xrange(len(node.children)):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1441
            child = node.children[i]
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1442
            newchild, child_ = child.accept(self, newroot, terms)
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1443
            if not child is child_:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1444
                node = child_.parent
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1445
            if newchild is not None:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1446
                subparts.append(newchild)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1447
        return subparts, node
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1448
    
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1449
    def process_selection(self, newroot, terms, rqlst):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1450
        if self.final:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1451
            for term in rqlst.selection:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1452
                newroot.append_selected(term.copy(newroot))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1453
                for vref in term.get_nodes(VariableRef):
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1454
                    self.needsel.add(vref.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1455
            return 
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1456
        for term in rqlst.selection:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1457
            vrefs = term.get_nodes(VariableRef)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1458
            if vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1459
                supportedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1460
                for vref in vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1461
                    var = vref.variable
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1462
                    if var in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1463
                        supportedvars.append(vref)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1464
                        continue
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1465
                    else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1466
                        self.needsel.add(vref.name)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1467
                        break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1468
                else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1469
                    for vref in vrefs:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1470
                        newroot.append_selected(vref.copy(newroot))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1471
                    supportedvars = []
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1472
                for vref in supportedvars:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1473
                    if not vref in newroot.get_selected_variables():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1474
                        newroot.append_selected(VariableRef(newroot.get_variable(vref.name)))
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1475
            
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1476
    def add_necessary_selection(self, newroot, terms):
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1477
        selected = tuple(newroot.get_selected_variables())
1228
91ae10ffb611 * refactor ms planner (renaming, reorganization)
sylvain.thenault@logilab.fr
parents: 1124
diff changeset
  1478
        for varname in terms:
257
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1479
            var = newroot.defined_vars[varname]
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1480
            for vref in var.references():
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1481
                rel = vref.relation()
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1482
                if rel is None and vref in selected:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1483
                    # already selected
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1484
                    break
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1485
            else:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1486
                selvref = VariableRef(var)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1487
                newroot.append_selected(selvref)
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1488
                if newroot.groupby:
4c7d3af7e94d restore multi-sources capabilities
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
diff changeset
  1489
                    newroot.add_group_var(VariableRef(selvref.variable, noautoref=1))