Example #1
0
    def delete_branch(cls, resource_id=None, db_session=None, *args, **kwargs):
        """
        This deletes whole branch with children starting from resource_id

        :param resource_id:
        :param db_session:
        :return:
        """
        tablename = cls.model.__table__.name

        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id, db_session=db_session)
        parent_id = resource.parent_id
        ordering = resource.ordering
        raw_q = """
            WITH RECURSIVE subtree AS (
                    SELECT res.resource_id
                    FROM {tablename} AS res WHERE res.resource_id = :resource_id
                  UNION ALL
                    SELECT res_u.resource_id
                    FROM {tablename} res_u, subtree st
                    WHERE res_u.parent_id = st.resource_id
            )
            DELETE FROM resources where resource_id in (select * from subtree);
        """.format(tablename=tablename)
        db_session = get_db_session(db_session)
        text_obj = sa.text(raw_q)
        db_session.execute(text_obj, params={'resource_id': resource_id})
        cls.shift_ordering_down(parent_id, ordering, db_session=db_session)
        return True
Example #2
0
    def set_position(cls,
                     resource_id,
                     to_position,
                     db_session=None,
                     *args,
                     **kwargs):
        """
        Sets node position for new node in the tree

        :param resource_id: resource to move
        :param to_position: new position
        :param db_session:
        :return:def count_children(cls, resource_id, db_session=None):
        """
        db_session = get_db_session(db_session)
        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id, db_session=db_session)
        cls.check_node_position(resource.parent_id,
                                to_position,
                                on_same_branch=True,
                                db_session=db_session)
        cls.shift_ordering_up(resource.parent_id,
                              to_position,
                              db_session=db_session)
        db_session.flush()
        db_session.expire(resource)
        resource.ordering = to_position
        return True
Example #3
0
    def check_node_parent(cls,
                          resource_id,
                          new_parent_id,
                          db_session=None,
                          *args,
                          **kwargs):
        """
        Checks if parent destination is valid for node

        :param resource_id:
        :param new_parent_id:
        :param db_session:
        :return:
        """
        db_session = get_db_session(db_session)
        new_parent = ResourceService.lock_resource_for_update(
            resource_id=new_parent_id, db_session=db_session)
        # we are not moving to "root" so parent should be found
        if not new_parent and new_parent_id is not None:
            raise ZigguratResourceTreeMissingException(
                'New parent node not found')
        else:
            result = cls.path_upper(new_parent_id, db_session=db_session)
            path_ids = [r.resource_id for r in result]
            if resource_id in path_ids:
                raise ZigguratResourceTreePathException(
                    'Trying to insert node into itself')
    def check_node_parent(cls, resource_id, new_parent_id, db_session=None,
                          *args, **kwargs):
        """
        Checks if parent destination is valid for node

        :param resource_id:
        :param new_parent_id:
        :param db_session:
        :return:
        """
        db_session = get_db_session(db_session)
        new_parent = ResourceService.lock_resource_for_update(
            resource_id=new_parent_id,
            db_session=db_session)
        # we are not moving to "root" so parent should be found
        if not new_parent and new_parent_id is not None:
            raise ZigguratResourceTreeMissingException(
                'New parent node not found')
        else:
            result = cls.path_upper(new_parent_id,
                                    db_session=db_session)
            path_ids = [r.resource_id for r in result]
            if resource_id in path_ids:
                raise ZigguratResourceTreePathException(
                    'Trying to insert node into itself')
    def delete_branch(cls, resource_id=None, db_session=None, *args, **kwargs):
        """
        This deletes whole branch with children starting from resource_id

        :param resource_id:
        :param db_session:
        :return:
        """
        tablename = cls.model.__table__.name

        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id,
            db_session=db_session)
        parent_id = resource.parent_id
        ordering = resource.ordering
        raw_q = """
            WITH RECURSIVE subtree AS (
                    SELECT res.resource_id
                    FROM {tablename} AS res WHERE res.resource_id = :resource_id
                  UNION ALL
                    SELECT res_u.resource_id
                    FROM {tablename} res_u, subtree st
                    WHERE res_u.parent_id = st.resource_id
            )
            DELETE FROM resources where resource_id in (select * from subtree);
        """.format(tablename=tablename)
        db_session = get_db_session(db_session)
        text_obj = sa.text(raw_q)
        db_session.execute(text_obj, params={'resource_id': resource_id})
        cls.shift_ordering_down(parent_id, ordering, db_session=db_session)
        return True
    def set_position(cls, resource_id, to_position, db_session=None, *args,
                     **kwargs):
        """
        Sets node position for new node in the tree

        :param resource_id: resource to move
        :param to_position: new position
        :param db_session:
        :return:def count_children(cls, resource_id, db_session=None):
        """
        db_session = get_db_session(db_session)
        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id,
            db_session=db_session)
        cls.check_node_position(
            resource.parent_id, to_position, on_same_branch=True,
            db_session=db_session)
        cls.shift_ordering_up(resource.parent_id, to_position,
                              db_session=db_session)
        db_session.flush()
        db_session.expire(resource)
        resource.ordering = to_position
        return True
Example #7
0
    def move_to_position(cls,
                         resource_id,
                         to_position,
                         new_parent_id=noop,
                         db_session=None,
                         *args,
                         **kwargs):
        """
        Moves node to new location in the tree

        :param resource_id: resource to move
        :param to_position: new position
        :param new_parent_id: new parent id
        :param db_session:
        :return:
        """
        db_session = get_db_session(db_session)
        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id, db_session=db_session)
        parent = ResourceService.lock_resource_for_update(
            resource_id=resource.parent_id, db_session=db_session)
        same_branch = False

        # reset if parent is same as old
        if new_parent_id == resource.parent_id:
            new_parent_id = noop

        if new_parent_id is not noop:
            cls.check_node_parent(resource_id,
                                  new_parent_id,
                                  db_session=db_session)
        else:
            same_branch = True

        if new_parent_id is noop:
            # it is not guaranteed that parent exists
            parent_id = resource.parent_id if resource else None
        else:
            parent_id = new_parent_id

        cls.check_node_position(parent_id,
                                to_position,
                                on_same_branch=same_branch,
                                db_session=db_session)
        # move on same branch
        if new_parent_id is noop:
            order_range = list(sorted((resource.ordering, to_position)))
            move_down = resource.ordering > to_position

            query = db_session.query(cls.model)
            query = query.filter(cls.model.parent_id == parent_id)
            query = query.filter(cls.model.ordering.between(*order_range))
            if move_down:
                query.update({cls.model.ordering: cls.model.ordering + 1},
                             synchronize_session=False)
            else:
                query.update({cls.model.ordering: cls.model.ordering - 1},
                             synchronize_session=False)
            db_session.flush()
            db_session.expire(resource)
            resource.ordering = to_position
        # move between branches
        else:
            cls.shift_ordering_down(resource.parent_id,
                                    resource.ordering,
                                    db_session=db_session)
            cls.shift_ordering_up(new_parent_id,
                                  to_position,
                                  db_session=db_session)
            db_session.expire(resource)
            resource.parent_id = new_parent_id
            resource.ordering = to_position
            db_session.flush()
        return True
    def move_to_position(cls, resource_id, to_position,
                         new_parent_id=noop, db_session=None, *args,
                         **kwargs):
        """
        Moves node to new location in the tree

        :param resource_id: resource to move
        :param to_position: new position
        :param new_parent_id: new parent id
        :param db_session:
        :return:
        """
        db_session = get_db_session(db_session)
        # lets lock rows to prevent bad tree states
        resource = ResourceService.lock_resource_for_update(
            resource_id=resource_id,
            db_session=db_session)
        parent = ResourceService.lock_resource_for_update(
            resource_id=resource.parent_id,
            db_session=db_session)
        same_branch = False

        # reset if parent is same as old
        if new_parent_id == resource.parent_id:
            new_parent_id = noop

        if new_parent_id is not noop:
            cls.check_node_parent(resource_id, new_parent_id,
                                  db_session=db_session)
        else:
            same_branch = True

        if new_parent_id is noop:
            # it is not guaranteed that parent exists
            parent_id = resource.parent_id if resource else None
        else:
            parent_id = new_parent_id

        cls.check_node_position(
            parent_id, to_position, on_same_branch=same_branch,
            db_session=db_session)
        # move on same branch
        if new_parent_id is noop:
            order_range = list(sorted((resource.ordering, to_position)))
            move_down = resource.ordering > to_position

            query = db_session.query(cls.model)
            query = query.filter(cls.model.parent_id == parent_id)
            query = query.filter(cls.model.ordering.between(*order_range))
            if move_down:
                query.update({cls.model.ordering: cls.model.ordering + 1},
                             synchronize_session=False)
            else:
                query.update({cls.model.ordering: cls.model.ordering - 1},
                             synchronize_session=False)
            db_session.flush()
            db_session.expire(resource)
            resource.ordering = to_position
        # move between branches
        else:
            cls.shift_ordering_down(resource.parent_id, resource.ordering,
                                    db_session=db_session)
            cls.shift_ordering_up(new_parent_id, to_position,
                                  db_session=db_session)
            db_session.expire(resource)
            resource.parent_id = new_parent_id
            resource.ordering = to_position
            db_session.flush()
        return True