Exemplo n.º 1
0
def item_name_exists_in_folder(item_id, parent_id, db=None):
    new_item_name = with_row_locks(db.session.query(
        Item.name).filter(Item.id == item_id),
                                   of=Item).first()[0]

    exists_item = with_row_locks(
        db.session.query(Ancestors,
                         Item).join(Item,
                                    Item.id == Ancestors.child_id,
                                    isouter=True).filter(
                                        and_(Ancestors.parent_id == parent_id),
                                        Item.name == new_item_name,
                                        Ancestors.depth == 1)).first()
    return True if exists_item else False
Exemplo n.º 2
0
def delete_item(id, db=None):
    # delete from ancestors table
    # NOTE: must delete before item to avoid fk violation
    # returns children items that need to be deleted
    child_item_ids = Ancestors.delete_item(id=id)

    # delete from file table
    # NOTE: must delete before item to avoid fk violation
    with_row_locks(db.session.query(File).filter(
        File.id.in_(child_item_ids + [id])),
                   of=File).delete(synchronize_session=False)

    # delete from item table
    with_row_locks(db.session.query(Item).filter(
        Item.id.in_(child_item_ids + [id])),
                   of=Item).delete(synchronize_session=False)
Exemplo n.º 3
0
def item_exists_in_folder(item_id, parent_id, db=None):
    if item_id == BASE_DIR_ID:  # don't care about parent_id
        return True

    relationship = with_row_locks(db.session.query(Ancestors).filter(
        and_(Ancestors.child_id == item_id, Ancestors.parent_id == parent_id,
             Ancestors.depth == 1)),
                                  of=Ancestors).first()
    return True if relationship else False
Exemplo n.º 4
0
def item_exists(abs_path, db=None, check_is_dir=False):
    """
    Check if item exists,
    if check_is_dir is passed also checks whether item is a dir

    returns (Bool, Int)
        = (whether item exists + is dir(if check requested), item id of deepest child item in path)
    """
    print("checking if item exists abs_path={}".format(abs_path))
    if abs_path == "/":
        return True, BASE_DIR_ID

    allparts = abs_path.split("/")

    # allparts[0] == ""
    root_item = with_row_locks(
        db.session.query(Item).filter(Item.id == BASE_DIR_ID),
        of=Item).first()

    parent_item = root_item
    # if abs_path contains many subdirectories
    for item_name in allparts[1:]:  # skips root
        # get parent folder contents
        child_item_ids = db.session.query(Ancestors.child_id).filter(
            Ancestors.parent_id == parent_item.id).distinct().all()

        # check if item exists in parent folder
        child_item = with_row_locks(db.session.query(Item).filter(
            and_(Item.id.in_(child_item_ids), Item.name == item_name)),
                                    of=Item).first()
        if not child_item:
            # item does not exist in parent
            return False, BASE_DIR_ID

        # item exists in parent
        # update parent item
        parent_item = child_item

    if check_is_dir and not parent_item.is_dir:  # exists but not a dir
        return False, parent_item.id

    # deepest subdirectory (item) id / current directory id
    return True, parent_item.id
Exemplo n.º 5
0
def get_item(item_name, parent_id, db=None):
    # # get parent folder contents
    # child_item_ids = db.session.query(Ancestors.child_id).filter(
    #     Ancestors.parent_id == parent_id).distinct().all()

    # # check if any of the child items have the same name as item_name
    # # since item names in same directory are distinct -> should only return at most 1 item
    # item = with_row_locks(db.session.query(Item), of=Item).filter(and_(Item.id.in_(child_item_ids),
    #                                                                    Item.name == item_name)).first()
    query = db.session.query(Ancestors,
                             Item).filter(Ancestors.parent_id == parent_id)
    item = with_row_locks(
        query.join(Item, Item.id == Ancestors.child_id,
                   isouter=True).filter(Item.name == item_name)).first()

    return item[1] if item else None
Exemplo n.º 6
0
def get_child_item(parent_id, child_name, db=None):
    """
    given parent id and child name -> return child id else None if doesn't exist

    :param parent_id: [description]
    :type parent_id: [type]
    :param child_name: [description]
    :type child_name: [type]

    """
    r = with_row_locks(
        db.session.query(Ancestors).join(
            Item, Item.id == Ancestors.child_id).filter(
                and_(Ancestors.parent_id == parent_id),
                Item.name == child_name)).first()
    return r.id if r else None
Exemplo n.º 7
0
def to_abs_path_ids(abs_path, db=None):
    item_names = abs_path.split("/")
    item_names[0] = "/"  # replace '' with '/' to enable querying of root

    item_ids = [0] * len(item_names)
    item_ids[0] = BASE_DIR_ID  # id of root('/') = 0

    for i in range(1, len(item_names)):
        item_name = item_names[i]
        parent_id = item_ids[i - 1]

        # get parent folder contents
        child_item_ids = db.session.query(Ancestors.child_id).filter(
            Ancestors.parent_id == parent_id).distinct().all()

        # check if any of the child items have the same name as item_name
        # since item names in same directory are distinct -> should only return at most 1 item
        item = with_row_locks(db.session.query(Item).filter(
            and_(Item.id.in_(child_item_ids), Item.name == item_name)),
                              of=Item).first()
        # convention used when item doesn't exist in parent
        item_ids[i] = item.id if item else -1

    return (item_names, item_ids)
Exemplo n.º 8
0
    def delete_item(id, db=None):
        print("Deleting from file table id={}".format(id))

        with_row_locks(db.session.query(File).filter(File.id == id),
                       of=File).delete()
Exemplo n.º 9
0
def _resolve_path(item_name_list, item_id_list, begin_indx=1, db=None):
    _item_names = item_name_list[:]
    _item_ids = item_id_list[:]

    # process from begin_indx -> second last arr element
    for i in range(begin_indx, len(_item_names) - 1):
        parent_id = _item_ids[i - 1]
        item_name = _item_names[i]
        if item_name == "*":
            # will give at most 1 match if intermediate dirs since unique names in same directory
            # using  parent_id  and child_item_name of item to find a match
            # depth between parent_id and child_item of item == 2:
            # parent -> child (no constraint on item_name)
            # child -> child items (item_name constraint = item_names[i+1])
            child_ids = with_row_locks(db.session.query(
                Ancestors.child_id).filter(
                    and_(Ancestors.parent_id == parent_id,
                         Ancestors.depth == 2)),
                                       of=Ancestors).all()

            ancestors_and_item = with_row_locks(
                db.session.query(Ancestors, Item).join(
                    Item, Item.id == Ancestors.child_id).filter(
                        and_(Ancestors.depth == 1,
                             Ancestors.child_id.in_(child_ids),
                             Item.name == _item_names[i + 1]))).all()
            if len(ancestors_and_item):
                res = []

                for _ancestor, _item in ancestors_and_item:
                    _new_item_names = _item_names[:]
                    _found_item_name = with_row_locks(db.session.query(
                        Item.name).filter(Item.id == _ancestor.parent_id),
                                                      of=Item).first()
                    _new_item_names[i] = _found_item_name[0]

                    _new_item_ids = _item_ids[:]
                    _new_item_ids[i] = _ancestor.parent_id
                    res.extend(
                        _resolve_path(_new_item_names, _new_item_ids, i + 1))

                return res
            else:
                raise InvalidCmdError(
                    'unable to resolve asterisks(*) to a valid path : {}'.
                    format("/".join(_item_names)))
        else:
            item = get_item(item_name=item_name, parent_id=parent_id)

            # convention used when item doesn't exist in parent
            _item_ids[i] = item.id if item else -1

    # process last part of the path

    res = []

    # may yield mutiple items if last item in path = '*'
    # get child items of depth = 1
    if _item_names[-1] == '*':
        query = db.session.query(Ancestors, Item).filter(
            Ancestors.parent_id == _item_ids[-2], Ancestors.depth == 1)
        child_items = query.join(Item, Item.id == Ancestors.child_id).all()

        for _, item in child_items:
            _item_names = _item_names[:-1] + [item.name]
            _item_ids = _item_ids[:-1] + [item.id]

            res.append((_item_names, _item_ids))
    else:
        item = get_item(item_name=_item_names[-1], parent_id=_item_ids[-2])

        #  convention used when item doesn't exist in parent
        _item_ids[-1] = item.id if item else -1

        res.append((_item_names, _item_ids))

    return res
Exemplo n.º 10
0
def move_item(id, new_parent_id, db=None):
    # before moving check if item name already exists in parent_folder
    if item_name_exists_in_folder(id, new_parent_id):
        raise InvalidCmdError(
            message="mv: an item with the same name already exists in the dest"
        )
    # cannot move if dest = file and source = folder
    if Item.is_a_dir(id) and not Item.is_a_dir(new_parent_id):
        raise InvalidCmdError(message="mv: dest is a file but src is folder")
    # old_parent
    old_parent_id = with_row_locks(db.session.query(
        Ancestors.parent_id).filter(
            and_(Ancestors.child_id == id, Ancestors.depth == 1)),
                                   of=Ancestors).first()

    # define subtree as id + all childs of id
    childs = with_row_locks(
        db.session.query(Ancestors).filter(Ancestors.parent_id == id),
        of=Ancestors).all()
    subtree_ids = [item.child_id for item in childs]
    subtree = with_row_locks(db.session.query(Ancestors), of=Ancestors).filter(
        Ancestors.parent_id.in_(subtree_ids)).all()

    # delete relationships between upper tree of the tree + subtree
    with_row_locks(db.session.query(Ancestors).filter(
        and_(Ancestors.child_id.in_(subtree_ids),
             not_(Ancestors.parent_id.in_(subtree_ids)))),
                   of=Ancestors).delete(synchronize_session=False)

    # add relationships between (new parent + upper tree of new_parent) + subtree
    new_parent_upper_tree = with_row_locks(db.session.query(Ancestors).filter(
        Ancestors.child_id == new_parent_id),
                                           of=Ancestors).all()
    for new_upper_item in new_parent_upper_tree:
        upper_parent_id = new_upper_item.parent_id

        # distance from (upper_tree_item -> new_parent_id) = upper_tree_depth
        # from (new_parent -> item_id) = 1
        # from (item_id -> child_id) = subtree_item_depth
        upper_tree_depth = new_upper_item.depth
        upper_tree_rank = new_upper_item.rank

        for subtree_item in childs:
            new_rel = Ancestors(parent_id=upper_parent_id,
                                child_id=subtree_item.child_id,
                                depth=upper_tree_depth + subtree_item.depth +
                                1,
                                rank=f'{upper_tree_rank},{subtree_item.rank}')
            db.session.add(new_rel)

    # updating old_parent size + updated_at(if dir)
    # updating new_parent size + updated_at(if dir)
    new_parent = with_row_locks(
        db.session.query(Item).filter(Item.id == new_parent_id),
        of=Item).first()
    old_parent = with_row_locks(
        db.session.query(Item).filter(Item.id == old_parent_id),
        of=Item).first()

    if new_parent.is_dir:
        new_parent.updated_at = datetime.now()
        new_parent.size += 1

    if old_parent.is_dir:
        old_parent.updated_at = datetime.now()
        old_parent.size -= 1

    db.session.add(new_parent)
    db.session.add(old_parent)