Add any_writable_field_query to fix bpd search

This commit is contained in:
Šarūnas Nejus 2024-06-16 15:22:52 +01:00
parent be4fdf492a
commit 856585392d
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
3 changed files with 22 additions and 12 deletions

View file

@ -30,6 +30,7 @@ from collections.abc import Generator, Iterable, Iterator, Mapping, Sequence
from sqlite3 import Connection
from typing import TYPE_CHECKING, Any, AnyStr, Callable, Generic, TypeVar, cast
from mediafile import MediaFile
from rich import print
from rich_tables.generic import flexitable
from unidecode import unidecode
@ -356,6 +357,10 @@ class Model(ABC, Generic[D]):
"""Fields in the related table."""
return cls._relation._fields.keys() - cls.shared_db_fields
@cached_classproperty
def writable_db_fields(cls) -> set[str]:
return MediaFile.fields() & cls._relation._fields.keys()
@cached_classproperty
def table_with_flex_attrs(cls) -> str:
"""Return a SQL for entity table which includes aggregated flexible attributes.

View file

@ -406,6 +406,17 @@ class LibModel(dbcore.Model["Library"]):
]
)
@classmethod
def any_writable_field_query(
cls, query_class: Type[dbcore.FieldQuery], pattern: str
) -> dbcore.OrQuery:
return dbcore.OrQuery(
[
cls.field_query(f, pattern, query_class)
for f in cls.writable_db_fields
]
)
@classmethod
def match_all_query(
cls, pattern_by_field: Mapping[str, str]

View file

@ -27,8 +27,6 @@ import time
import traceback
from string import Template
from mediafile import MediaFile
import beets
import beets.ui
from beets import dbcore, vfs
@ -91,8 +89,6 @@ SUBSYSTEMS = [
"partition",
]
ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())
# Gstreamer import error.
class NoGstreamerError(Exception):
@ -1399,7 +1395,7 @@ class Server(BaseServer):
return test_tag, key
raise BPDError(ERROR_UNKNOWN, "no such tagtype")
def _metadata_query(self, query_type, any_query_type, kv):
def _metadata_query(self, query_type, kv, allow_any_query: bool = False):
"""Helper function returns a query object that will find items
according to the library query type provided and the key-value
pairs specified. The any_query_type is used for queries of
@ -1411,11 +1407,9 @@ class Server(BaseServer):
it = iter(kv)
for tag, value in zip(it, it):
if tag.lower() == "any":
if any_query_type:
if allow_any_query:
queries.append(
any_query_type(
value, ITEM_KEYS_WRITABLE, query_type
)
Item.any_writable_field_query(query_type, value)
)
else:
raise BPDError(ERROR_UNKNOWN, "no such tagtype")
@ -1429,14 +1423,14 @@ class Server(BaseServer):
def cmd_search(self, conn, *kv):
"""Perform a substring match for items."""
query = self._metadata_query(
dbcore.query.SubstringQuery, dbcore.query.AnyFieldQuery, kv
dbcore.query.SubstringQuery, kv, allow_any_query=True
)
for item in self.lib.items(query):
yield self._item_info(item)
def cmd_find(self, conn, *kv):
"""Perform an exact match for items."""
query = self._metadata_query(dbcore.query.MatchQuery, None, kv)
query = self._metadata_query(dbcore.query.MatchQuery, kv)
for item in self.lib.items(query):
yield self._item_info(item)
@ -1456,7 +1450,7 @@ class Server(BaseServer):
raise BPDError(ERROR_ARG, 'should be "Album" for 3 arguments')
elif len(kv) % 2 != 0:
raise BPDError(ERROR_ARG, "Incorrect number of filter arguments")
query = self._metadata_query(dbcore.query.MatchQuery, None, kv)
query = self._metadata_query(dbcore.query.MatchQuery, kv)
clause, subvals = query.clause()
statement = (