cubicweb/hooks/synccomputed.py
author Philippe Pepiot <ph@itsalwaysdns.eu>
Tue, 31 Mar 2020 18:22:05 +0200
changeset 12966 6cd938c29ca3
parent 12227 dc333e9104c9
permissions -rw-r--r--
[server] Make connection pooler configurable and set better default values Drop the configuration connections-pool-size and add new configurations options: * connections-pool-min-size. Set to 0 by default so we open connections only when needed. This avoid opening min-size*processes connections at startup, which is, it think, a good default. * connections-pool-max-size. Set to 0 (unlimited) by default, so we move the bottleneck to postgresql. * connections-idle-timeout. Set to 10 minutes. I don't have arguments about this except that this is the default in pgbouncer.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     1
# copyright 2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     3
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     4
# This file is part of CubicWeb.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     5
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
     9
# any later version.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    10
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    14
# details.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    15
#
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    18
"""Hooks for synchronizing computed attributes"""
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    19
11767
432f87a63057 flake8 and all
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
    20
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    21
from collections import defaultdict
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    22
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    23
from rql import nodes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    24
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    25
from cubicweb.server import hook
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    26
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    27
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    28
class RecomputeAttributeOperation(hook.DataOperationMixIn, hook.Operation):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    29
    """Operation to recompute caches of computed attribute at commit time,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    30
    depending on what's have been modified in the transaction and avoiding to
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    31
    recompute twice the same attribute
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    32
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    33
    containercls = dict
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    34
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    35
    def add_data(self, computed_attribute, eid=None):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    36
        try:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    37
            self._container[computed_attribute].add(eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    38
        except KeyError:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    39
            self._container[computed_attribute] = set((eid,))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    40
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    41
    def precommit_event(self):
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10395
diff changeset
    42
        for computed_attribute_rdef, eids in self.get_data().items():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    43
            attr = computed_attribute_rdef.rtype
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    44
            formula = computed_attribute_rdef.formula
10395
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    45
            select = self.cnx.repo.vreg.rqlhelper.parse(formula).children[0]
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    46
            xvar = select.get_variable('X')
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    47
            select.add_selected(xvar, index=0)
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    48
            select.add_group_var(xvar, index=0)
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    49
            if None in eids:
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    50
                select.add_type_restriction(xvar, computed_attribute_rdef.subject)
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    51
            else:
10395
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    52
                select.add_eid_restriction(xvar, eids)
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    53
            update_rql = 'SET X %s %%(value)s WHERE X eid %%(x)s' % attr
10395
7e311ee8b5b0 [hooks] manhandle the parsed rql query, not its string representation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10192
diff changeset
    54
            for eid, value in self.cnx.execute(select.as_string()):
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    55
                self.cnx.execute(update_rql, {'value': value, 'x': eid})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    56
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    57
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    58
class EntityWithCACreatedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    59
    """When creating an entity that has some computed attribute, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    60
    attributes have to be computed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    61
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    62
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    63
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    64
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    65
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    66
    events = ('after_add_entity',)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    67
    # list of computed attribute rdefs that have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    68
    computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    69
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    70
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    71
        for rdef in self.computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    72
            RecomputeAttributeOperation.get_instance(self._cw).add_data(
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    73
                rdef, self.entity.eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    74
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    75
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    76
class RelationInvolvedInCAModifiedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    77
    """When some relation used in a computed attribute is updated, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    78
    attributes have to be recomputed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    79
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    80
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    81
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    82
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    83
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    84
    events = ('after_add_relation', 'before_delete_relation')
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    85
    # list of (computed attribute rdef, optimize_on) that have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    86
    optimized_computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    87
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    88
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    89
        for rdef, optimize_on in self.optimized_computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    90
            if optimize_on is None:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    91
                eid = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    92
            else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    93
                eid = getattr(self, optimize_on)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    94
            RecomputeAttributeOperation.get_instance(self._cw).add_data(rdef, eid)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    95
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    96
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    97
class AttributeInvolvedInCAModifiedHook(hook.Hook):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    98
    """When some attribute used in a computed attribute is updated, those
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
    99
    attributes have to be recomputed.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   100
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   101
    Concret class of this hook are generated at registration time by
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   102
    introspecting the schema.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   103
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   104
    __abstract__ = True
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   105
    events = ('after_update_entity',)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   106
    # list of (computed attribute rdef, attributes of this entity type involved)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   107
    # that may have to be recomputed
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   108
    attributes_computed_attributes = None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   109
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   110
    def __call__(self):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   111
        edited_attributes = frozenset(self.entity.cw_edited)
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10395
diff changeset
   112
        for rdef, used_attributes in self.attributes_computed_attributes.items():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   113
            if edited_attributes.intersection(used_attributes):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   114
                # XXX optimize if the modified attributes belong to the same
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   115
                # entity as the computed attribute
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   116
                RecomputeAttributeOperation.get_instance(self._cw).add_data(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   117
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   118
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   119
# code generation at registration time #########################################
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   120
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   121
def _optimize_on(formula_select, rtype):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   122
    """Given a formula and some rtype, tells whether on update of the given
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   123
    relation, formula may be recomputed only for rhe relation's subject
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   124
    ('eidfrom' returned), object ('eidto' returned) or None.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   125
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   126
    Optimizing is only possible when X is used as direct subject/object of this
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   127
    relation, else we may miss some necessary update.
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   128
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   129
    for rel in formula_select.get_nodes(nodes.Relation):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   130
        if rel.r_type == rtype:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   131
            sub = rel.get_variable_parts()[0]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   132
            obj = rel.get_variable_parts()[1]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   133
            if sub.name == 'X':
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   134
                return 'eidfrom'
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   135
            elif obj.name == 'X':
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   136
                return 'eidto'
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   137
            else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   138
                return None
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   139
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   140
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   141
class _FormulaDependenciesMatrix(object):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   142
    """This class computes and represents the dependencies of computed attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   143
    towards relations and attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   144
    """
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   145
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   146
    def __init__(self, schema):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   147
        """Analyzes the schema to compute the dependencies"""
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   148
        # entity types holding some computed attribute {etype: [computed rdefs]}
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   149
        self.computed_attribute_by_etype = defaultdict(list)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   150
        # depending entity types {dep. etype: {computed rdef: dep. etype attributes}}
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   151
        self.computed_attribute_by_etype_attrs = defaultdict(lambda: defaultdict(set))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   152
        # depending relations def {dep. rdef: [computed rdefs]
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   153
        self.computed_attribute_by_relation = defaultdict(list)  # by rdef
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   154
        # Walk through all attributes definitions
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   155
        for rdef in schema.iter_computed_attributes():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   156
            self.computed_attribute_by_etype[rdef.subject.type].append(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   157
            # extract the relations it depends upon - `rdef.formula_select` is
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   158
            # expected to have been set by finalize_computed_attributes
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   159
            select = rdef.formula_select
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   160
            for rel_node in select.get_nodes(nodes.Relation):
10192
365e5a0287d6 [computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9967
diff changeset
   161
                if rel_node.is_types_restriction():
365e5a0287d6 [computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9967
diff changeset
   162
                    continue
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   163
                rschema = schema.rschema(rel_node.r_type)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   164
                lhs, rhs = rel_node.get_variable_parts()
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   165
                for sol in select.solutions:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   166
                    subject_etype = sol[lhs.name]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   167
                    if isinstance(rhs, nodes.VariableRef):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   168
                        object_etypes = set(sol[rhs.name] for sol in select.solutions)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   169
                    else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   170
                        object_etypes = rschema.objects(subject_etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   171
                    for object_etype in object_etypes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   172
                        if rschema.final:
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   173
                            attr_for_computations = self.computed_attribute_by_etype_attrs[
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   174
                                subject_etype]
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   175
                            attr_for_computations[rdef].add(rschema.type)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   176
                        else:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   177
                            depend_on_rdef = rschema.rdefs[subject_etype, object_etype]
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   178
                            self.computed_attribute_by_relation[depend_on_rdef].append(rdef)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   179
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   180
    def generate_entity_creation_hooks(self):
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10395
diff changeset
   181
        for etype, computed_attributes in self.computed_attribute_by_etype.items():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   182
            regid = 'computed_attribute.%s_created' % etype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   183
            selector = hook.is_instance(etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   184
            yield type('%sCreatedHook' % etype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   185
                       (EntityWithCACreatedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   186
                       {'__regid__': regid,
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   187
                        '__select__': hook.Hook.__select__ & selector,
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   188
                        'computed_attributes': computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   189
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   190
    def generate_relation_change_hooks(self):
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10395
diff changeset
   191
        for rdef, computed_attributes in self.computed_attribute_by_relation.items():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   192
            regid = 'computed_attribute.%s_modified' % rdef.rtype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   193
            selector = hook.match_rtype(rdef.rtype.type,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   194
                                        frometypes=(rdef.subject.type,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   195
                                        toetypes=(rdef.object.type,))
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   196
            optimized_computed_attributes = []
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   197
            for computed_rdef in computed_attributes:
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   198
                optimized_computed_attributes.append(
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   199
                    (computed_rdef,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   200
                     _optimize_on(computed_rdef.formula_select, rdef.rtype))
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   201
                )
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   202
            yield type('%sModifiedHook' % rdef.rtype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   203
                       (RelationInvolvedInCAModifiedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   204
                       {'__regid__': regid,
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   205
                        '__select__': hook.Hook.__select__ & selector,
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   206
                        'optimized_computed_attributes': optimized_computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   207
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   208
    def generate_entity_update_hooks(self):
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10395
diff changeset
   209
        for etype, attributes_computed_attributes in self.computed_attribute_by_etype_attrs.items():
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   210
            regid = 'computed_attribute.%s_updated' % etype
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   211
            selector = hook.is_instance(etype)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   212
            yield type('%sModifiedHook' % etype,
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   213
                       (AttributeInvolvedInCAModifiedHook,),
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   214
                       {'__regid__': regid,
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   215
                        '__select__': hook.Hook.__select__ & selector,
9967
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   216
                        'attributes_computed_attributes': attributes_computed_attributes})
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   217
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   218
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   219
def registration_callback(vreg):
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   220
    vreg.register_all(globals().values(), __name__)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   221
    dependencies = _FormulaDependenciesMatrix(vreg.schema)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   222
    for hook_class in dependencies.generate_entity_creation_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   223
        vreg.register(hook_class)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   224
    for hook_class in dependencies.generate_relation_change_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   225
        vreg.register(hook_class)
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   226
    for hook_class in dependencies.generate_entity_update_hooks():
e65873ad0371 [CWEP002] Add support for computed attribute synchronization
Sylvain Thénault
parents:
diff changeset
   227
        vreg.register(hook_class)