Example #1
0
def sort_query(query, table, sort_keys, sort_dir=None, sort_dirs=None):

    if 'id' not in sort_keys:
        # TODO(justinsb): If this ever gives a false-positive, check
        # the actual primary key, rather than assuming its id
        LOG.warning(_LW('Id not in sort_keys; is sort_keys unique?'))

    assert (not (sort_dir and sort_dirs))

    # Default the sort direction to ascending
    if sort_dirs is None and sort_dir is None:
        sort_dir = 'asc'

    # Ensure a per-column sort direction
    if sort_dirs is None:
        sort_dirs = [sort_dir for _sort_key in sort_keys]

    assert (len(sort_dirs) == len(sort_keys))

    for current_sort_key, current_sort_dir in \
            six.moves.zip(sort_keys, sort_dirs):
        try:
            sort_dir_func = {
                'asc': sqlalchemy.asc,
                'desc': sqlalchemy.desc,
            }[current_sort_dir]
        except KeyError:
            raise ValueError(
                _("Unknown sort direction, "
                  "must be 'desc' or 'asc'"))
        try:
            sort_key_attr = getattr(table.c, current_sort_key)
        except AttributeError:
            raise utils.InvalidSortKey()
        query = query.order_by(sort_dir_func(sort_key_attr))

    return query, sort_dirs
Example #2
0
def paginate_query(query,
                   table,
                   limit,
                   sort_keys,
                   marker=None,
                   sort_dir=None,
                   sort_dirs=None):
    if 'id' not in sort_keys:
        # TODO(justinsb): If this ever gives a false-positive, check
        # the actual primary key, rather than assuming its id
        LOG.warning(_LW('Id not in sort_keys; is sort_keys unique?'))

    assert (not (sort_dir and sort_dirs))

    # Default the sort direction to ascending
    if sort_dirs is None and sort_dir is None:
        sort_dir = 'asc'

    # Ensure a per-column sort direction
    if sort_dirs is None:
        sort_dirs = [sort_dir for _sort_key in sort_keys]

    assert (len(sort_dirs) == len(sort_keys))

    # Add sorting
    for current_sort_key, current_sort_dir in zip(sort_keys, sort_dirs):
        try:
            sort_dir_func = {
                'asc': sqlalchemy.asc,
                'desc': sqlalchemy.desc,
            }[current_sort_dir]
        except KeyError:
            raise ValueError(
                _("Unknown sort direction, "
                  "must be 'desc' or 'asc'"))
        try:
            sort_key_attr = getattr(table.c, current_sort_key)
        except AttributeError:
            raise utils.InvalidSortKey()
        query = query.order_by(sort_dir_func(sort_key_attr))

    # Add pagination
    if marker is not None:
        marker_values = []
        for sort_key in sort_keys:
            v = marker[sort_key]
            marker_values.append(v)

        # Build up an array of sort criteria as in the docstring
        criteria_list = []
        for i in range(len(sort_keys)):
            crit_attrs = []
            for j in range(i):
                table_attr = getattr(table.c, sort_keys[j])
                crit_attrs.append((table_attr == marker_values[j]))

            table_attr = getattr(table.c, sort_keys[i])
            if sort_dirs[i] == 'desc':
                crit_attrs.append((table_attr < marker_values[i]))
            else:
                crit_attrs.append((table_attr > marker_values[i]))

            criteria = sqlalchemy.sql.and_(*crit_attrs)
            criteria_list.append(criteria)

        f = sqlalchemy.sql.or_(*criteria_list)
        query = query.where(f)

    if limit is not None:
        query = query.limit(limit)

    return query