'Do the search, caching the results. Results are cached only if the
search is on the full library and no virtual field is searched on'

def _do_search(self, sqp, query, search_restriction, dbcache, book_ids=None):

    if isinstance(search_restriction, bytes):
        search_restriction = search_restriction.decode(u'utf-8')
    if isinstance(query, bytes):
        query = query.decode(u'utf-8')
    query = query.strip()
    if ((book_ids is None) and query and (not search_restriction)):
        cached = self.cache.get(query)
        if (cached is not None):
            return cached
    restricted_ids = all_book_ids = dbcache._all_book_ids(type=set)
    if (search_restriction and search_restriction.strip()):
        cached = self.cache.get(search_restriction.strip())
        if (cached is None):
            sqp.all_book_ids = (all_book_ids if (book_ids is None) else book_ids)
            restricted_ids = sqp.parse(search_restriction)
            if ((not sqp.virtual_field_used) and (sqp.all_book_ids is all_book_ids)):
                self.cache.add(search_restriction.strip(), restricted_ids)
        else:
            restricted_ids = cached
            if (book_ids is not None):
                restricted_ids = book_ids.intersection(restricted_ids)
    elif (book_ids is not None):
        restricted_ids = book_ids
    if (not query):
        return restricted_ids
    if (restricted_ids is all_book_ids):
        cached = self.cache.get(query)
        if (cached is not None):
            return cached
    sqp.all_book_ids = restricted_ids
    result = sqp.parse(query)
    if ((not sqp.virtual_field_used) and (sqp.all_book_ids is all_book_ids)):
        self.cache.add(query, result)
    return result
