'Run a query on the database.
``query_spec``
Queries iterate through specs in the database and return
those that satisfy the supplied ``query_spec``.  If
query_spec is `any`, This will match all specs in the
database.  If it is a spec, we\'ll evaluate
``spec.satisfies(query_spec)``.
The query can be constrained by two additional attributes:
``known``
Possible values: True, False, any
Specs that are "known" are those for which Spack can
locate a ``package.py`` file -- i.e., Spack "knows" how to
install them.  Specs that are unknown may represent
packages that existed in a previous version of Spack, but
have since either changed their name or been removed.
``installed``
Possible values: True, False, any
Specs for which a prefix exists are "installed". A spec
that is NOT installed will be in the database if some
other spec depends on it but its installation has gone
away since Spack installed it.
TODO: Specs are a lot like queries.  Should there be a
wildcard spec object, and should specs have attributes
like installed and known that can be queried?  Or are
these really special cases that only belong here?'

def query(self, query_spec=any, known=any, installed=True, explicit=any):

    with self.read_transaction():
        if (isinstance(query_spec, spack.spec.Spec) and query_spec._concrete):
            hash_key = query_spec.dag_hash()
            if (hash_key in self._data):
                return [self._data[hash_key].spec]
            else:
                return []
        results = []
        for (key, rec) in self._data.items():
            if ((installed is not any) and (rec.installed != installed)):
                continue
            if ((explicit is not any) and (rec.explicit != explicit)):
                continue
            if ((known is not any) and (spack.repo.exists(rec.spec.name) != known)):
                continue
            if ((query_spec is any) or rec.spec.satisfies(query_spec)):
                results.append(rec.spec)
        return sorted(results)
