Project

General

Profile

Revision 24589c11

ID24589c115a6c82bf24bb1434987d49bda8b9c056
Parent 05432195
Child cfed65e0

Added by Francois POIROTTE almost 13 years ago

Suppression d'une requête IN coûteuse (#772)

Suppression d'une requête IN coûteuse dans VigiGraph.
Il n'en reste plus que 3...

Change-Id: I67bf1c21798cf0bb0cd0312fce7587ad64a7ab50
Refs: #772.
Reviewed-on: https://vigilo-dev.si.c-s.fr/review/271
Tested-by: Build system <>
Reviewed-by: Aurelien BOMPARD <>

View differences:

vigigraph/controllers/rpc.py
24 24
from formencode import validators, schema
25 25
from sqlalchemy import or_
26 26
from sqlalchemy.sql.expression import literal_column
27
from sqlalchemy.orm import aliased, lazyload
27 28

  
28 29
from vigilo.turbogears.controllers import BaseController
29 30
from vigilo.turbogears.helpers import get_current_user
30
from vigilo.turbogears.controllers.proxy import get_through_proxy

31
from vigilo.turbogears.controllers.proxy import get_through_proxy
31 32

  
32 33
from vigilo.models.session import DBSession
33
from vigilo.models.tables import Host
34
from vigilo.models.tables import SupItemGroup
35
from vigilo.models.tables import PerfDataSource
36
from vigilo.models.tables import Graph, GraphGroup
34
from vigilo.models.tables import Host, SupItemGroup, PerfDataSource
35
from vigilo.models.tables import Graph, GraphGroup, Change, UserGroup
36
from vigilo.models.tables import DataPermission
37
from vigilo.models.tables.group import Group
37 38
from vigilo.models.tables.grouphierarchy import GroupHierarchy
38
from vigilo.models.tables import Change
39 39

  
40 40
from vigilo.models.tables.secondary_tables import SUPITEM_GROUP_TABLE
41 41
from vigilo.models.tables.secondary_tables import GRAPH_GROUP_TABLE
42 42
from vigilo.models.tables.secondary_tables import GRAPH_PERFDATASOURCE_TABLE
43
from vigilo.models.tables.secondary_tables import USER_GROUP_TABLE
43 44
from vigilo.models.functions import sql_escape_like
44 45

  
45 46
LOGGER = logging.getLogger(__name__)
......
118 119
        # correspondant au motif, quel que soit l'hôte.
119 120
        if search_form_graph:
120 121
            if not search_form_host:
121
                search_form_host = '*'
122
                search_form_host = u'*'
122 123

  
123 124
            search_form_host = sql_escape_like(search_form_host)
124 125
            search_form_graph = sql_escape_like(search_form_graph)
......
358 359
            if len(set(hostgroups).intersection(set(supitemgroups))) < 1:
359 360
                message = _('Access denied to host "%s"') % host
360 361
                LOGGER.warning(message)
361
                raise http_exc.HTTPForbidden(message) 
362
                raise http_exc.HTTPForbidden(message)
362 363

  
363 364
        # Récupération de la liste des noms des graphes associés à l'hôte.
364 365
        graphs = DBSession.query(
......
407 408
            ).join(
408 409
                (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
409 410
                    Host.idhost),
410
            ).filter(Host.name.like(query + '%')
411
            ).filter(Host.name.like(query + u'%')
411 412
            ).order_by(
412 413
                Host.name.asc(),
413 414
            )
......
462 463
        if not is_manager:
463 464
            direct_access = False
464 465
            user = get_current_user()
465
            user_groups = dict(user.supitemgroups())
466
            # On regarde d'abord si le groupe fait partie de ceux
467
            # auquels l'utilisateur a explicitement accès, ou s'il
468
            # est un parent des groupes auxquels l'utilisateur a accès
469
            if parent_id in user_groups.keys():
470
                direct_access = user_groups[parent_id]
471
            # Dans le cas contraire, on vérifie si le groupe est un
472
            # sous-groupe des groupes auxquels l'utilisateur a accès
473
            else:
474
                id_list = [ug for ug in user_groups.keys() if user_groups[ug]]
475
                child_groups = DBSession.query(SupItemGroup.idgroup
476
                    ).distinct(
466

  
467
            # On calcule la distance de ce groupe par rapport aux groupes
468
            # sur lesquels l'utilisateur a explicitement les permissions.
469
            #
470
            # La distance est définie ainsi :
471
            # 0 : l'utilisateur a des droits explicites sur ce groupe.
472
            # > 0 : l'utilisateur a accès implicitement au groupe.
473
            # < 0 : l'utilisateur n'a pas d'accès (il peut juste parcourir
474
            #       ce groupe)
475
            #
476
            # Il faut 2 étapes pour trouver la distance. La 1ère essaye
477
            # de trouver une distance >= 0, la 2ème une distance <= 0.
478

  
479
            # Distance positive.
480
            distance = DBSession.query(
481
                    GroupHierarchy.hops
482
                ).join(
483
                    (Group, Group.idgroup == GroupHierarchy.idparent),
484
                    (DataPermission, DataPermission.idgroup == Group.idgroup),
485
                    (UserGroup, UserGroup.idgroup == DataPermission.idusergroup),
486
                    (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \
487
                        UserGroup.idgroup),
488
                ).filter(USER_GROUP_TABLE.c.username == user.user_name
489
                ).filter(Group._grouptype == u'supitemgroup'
490
                ).filter(GroupHierarchy.idchild == parent_id
491
                ).order_by(GroupHierarchy.hops.desc()).scalar()
492

  
493
            if distance is None:
494
                # Distance négative.
495
                distance = DBSession.query(
496
                        GroupHierarchy.hops
477 497
                    ).join(
478
                        (GroupHierarchy,
479
                            GroupHierarchy.idchild == SupItemGroup.idgroup),
480
                    ).filter(GroupHierarchy.idparent.in_(id_list)
481
                    ).filter(GroupHierarchy.hops > 0
482
                    ).all()
483
                for ucg in child_groups:
484
                    if ucg.idgroup == parent_id:
485
                        direct_access = True
486
                        break
487
                # Sinon, l'utilisateur n'a pas accès à ce groupe
488
                else:
489
                    return dict(groups = [], items = [])
498
                        (Group, Group.idgroup == GroupHierarchy.idchild),
499
                        (DataPermission, DataPermission.idgroup == Group.idgroup),
500
                        (UserGroup, UserGroup.idgroup == DataPermission.idusergroup),
501
                        (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \
502
                            UserGroup.idgroup),
503
                    ).filter(USER_GROUP_TABLE.c.username == user.user_name
504
                    ).filter(Group._grouptype == u'supitemgroup'
505
                    ).filter(GroupHierarchy.idparent == parent_id
506
                    ).order_by(GroupHierarchy.hops.desc()).scalar()
507
                if distance is not None:
508
                    distance = -distance
509

  
510
            if distance is None:
511
                # Pas d'accès à ce groupe.
512
                return dict(groups = [], items = [])
513

  
514
            direct_access = distance >= 0
490 515

  
491 516
        limit = int(config.get("max_menu_entries", 20))
492 517
        result = {"groups": [], "items": []}
......
494 519
        if not onlytype or onlytype == "group":
495 520
            # On récupère la liste des groupes dont
496 521
            # l'identifiant du parent est passé en paramètre
522
            gh1 = aliased(GroupHierarchy, name='gh1')
523
            gh2 = aliased(GroupHierarchy, name='gh2')
524

  
497 525
            db_groups = DBSession.query(
498 526
                SupItemGroup
527
            ).options(lazyload('_path_obj')
528
            ).distinct(
499 529
            ).join(
500
                (GroupHierarchy, GroupHierarchy.idchild == \
501
                    SupItemGroup.idgroup),
502
            ).filter(GroupHierarchy.hops == 1
503
            ).filter(GroupHierarchy.idparent == parent_id
530
                (gh1, gh1.idchild == SupItemGroup.idgroup),
531
            ).filter(gh1.hops == 1
532
            ).filter(gh1.idparent == parent_id
504 533
            ).order_by(SupItemGroup.name.asc())
534

  
505 535
            if not is_manager and not direct_access:
506
                id_list = [ug for ug in user_groups.keys()]
536
                # On ne doit afficher que les fils du groupe <parent_id>
537
                # tels que l'utilisateur a accès explicitement à l'un
538
                # des fils de l'un de ces groupes.
539
                db_groups = db_groups.join(
540
                        (gh2, gh2.idparent == gh1.idchild),
541
                        (DataPermission, DataPermission.idgroup == gh2.idchild),
542
                        (UserGroup, UserGroup.idgroup == DataPermission.idusergroup),
543
                        (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == UserGroup.idgroup),
544
                    ).filter(USER_GROUP_TABLE.c.username == user.user_name)
507 545

  
508
                db_groups = db_groups.filter(
509
                    SupItemGroup.idgroup.in_(id_list))
510 546
            num_children_left = db_groups.count() - offset
511 547
            if offset:
512 548
                result["continued_from"] = offset
......
770 806
    @expose('json')
771 807
    def external_links(self):
772 808
        return dict(links=config['external_links'])
773

  

Also available in: Unified diff