diff --git a/beets/library.py b/beets/library.py index 71ef84993..6393fe78e 100644 --- a/beets/library.py +++ b/beets/library.py @@ -188,16 +188,30 @@ class Item(object): -class QueryElement(object): - """A building block for library queries.""" +class Query(object): + """An abstract class representing a query into the item database.""" def clause(self): """Returns (clause, subvals) where clause is a valid sqlite WHERE - clause implementing the query element and subvals is a list of items - to be substituted for ?s in the clause.""" + clause implementing the query and subvals is a list of items to be + substituted for ?s in the clause.""" raise NotImplementedError + + def statement(self, columns='*'): + """Returns (query, subvals) where clause is a sqlite SELECT statement + to enact this query and subvals is a list of values to substitute in + for ?s in the query.""" + clause, subvals = self.clause() + return ('select ' + columns + ' from items where ' + clause, subvals) + + def execute(self, library): + """Runs the query in the specified library, returning an + ItemResultIterator.""" + cursor = library.conn.cursor() + cursor.execute(*self.statement()) + return ResultIterator(cursor) -class SubstringQueryElement(QueryElement): - """A query element that matches a substring in a specific item field.""" +class SubstringQuery(Query): + """A query that matches a substring in a specific item field.""" def __init__(self, field, pattern): if field not in item_keys: @@ -212,8 +226,8 @@ class SubstringQueryElement(QueryElement): subvals = [search] return (clause, subvals) -class AnySubstringQueryElement(QueryElement): - """A query element that matches a substring in any item field.""" +class AnySubstringQuery(Query): + """A query that matches a substring in any item field.""" def __init__(self, pattern): self.pattern = pattern @@ -222,16 +236,16 @@ class AnySubstringQueryElement(QueryElement): clause_parts = [] subvals = [] for field in item_keys: - el_clause, el_subvals = (SubstringQueryElement(field, self.pattern) + el_clause, el_subvals = (SubstringQuery(field, self.pattern) .clause()) clause_parts.append('(' + el_clause + ')') subvals += el_subvals clause = ' or '.join(clause_parts) return clause, subvals -class AndQueryElement(QueryElement): - """A conjunction of a list of other query elements. Can be indexed like a - list to access the sub-elements.""" +class AndQuery(Query): + """A conjunction of a list of other queries. Can be indexed like a list to + access the sub-queries.""" def __init__(self, elements = None): if elements is None: @@ -259,11 +273,11 @@ class AndQueryElement(QueryElement): @classmethod def from_dict(cls, matches): - """Construct a query element from a dictionary, matches, whose keys - are item field names and whose values are substring patterns.""" + """Construct a query from a dictionary, matches, whose keys are item + field names and whose values are substring patterns.""" elements = [] for key, pattern in matches.iteritems(): - elements.append(SubstringQueryElement(key, pattern)) + elements.append(SubstringQuery(key, pattern)) return cls(elements) @@ -277,7 +291,7 @@ class AndQueryElement(QueryElement): r'(?