Skip to content

fix(#655): search now works again #656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions tagstudio/src/core/library/alchemy/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
TextField,
_FieldID,
)
from .joins import TagSubtag
from .joins import TagEntry, TagSubtag
from .models import Entry, Folder, Preferences, Tag, TagAlias, ValueType
from .visitors import SQLBoolExpressionBuilder

Expand Down Expand Up @@ -558,7 +558,7 @@ def search_library(
statement = select(Entry)

if search.ast:
statement = statement.outerjoin(Entry.tag_box_fields).where(
statement = statement.outerjoin(TagEntry).where(
SQLBoolExpressionBuilder(self).visit(search.ast)
)

Expand Down
31 changes: 15 additions & 16 deletions tagstudio/src/core/library/alchemy/visitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from src.core.query_lang import BaseVisitor
from src.core.query_lang.ast import AST, ANDList, Constraint, ConstraintType, Not, ORList, Property

from .joins import TagField
from .models import Entry, Tag, TagAlias, TagBoxField
from .joins import TagEntry
from .models import Entry, Tag, TagAlias

# workaround to have autocompletion in the Editor
if TYPE_CHECKING:
Expand Down Expand Up @@ -50,19 +50,20 @@ def visit_and_list(self, node: ANDList) -> ColumnExpressionArgument:
# If there is just one tag id, check the normal way
elif len(tag_ids) == 1:
bool_expressions.append(
self.__entry_satisfies_expression(TagField.tag_id == tag_ids[0])
self.__entry_satisfies_expression(TagEntry.tag_id == tag_ids[0])
)

return and_(*bool_expressions)

def visit_constraint(self, node: Constraint) -> ColumnExpressionArgument:
"""Returns a Boolean Expression that is true, if the Entry satisfies the constraint."""
if len(node.properties) != 0:
raise NotImplementedError("Properties are not implemented yet") # TODO TSQLANG

if node.type == ConstraintType.Tag:
return TagBoxField.tags.any(Tag.id.in_(self.__get_tag_ids(node.value)))
return Entry.tags.any(Tag.id.in_(self.__get_tag_ids(node.value)))
elif node.type == ConstraintType.TagID:
return TagBoxField.tags.any(Tag.id == int(node.value))
return Entry.tags.any(Tag.id == int(node.value))
elif node.type == ConstraintType.Path:
return Entry.path.op("GLOB")(node.value)
elif node.type == ConstraintType.MediaType:
Expand All @@ -76,9 +77,7 @@ def visit_constraint(self, node: Constraint) -> ColumnExpressionArgument:
return Entry.suffix.ilike(node.value)
elif node.type == ConstraintType.Special: # noqa: SIM102 unnecessary once there is a second special constraint
if node.value.lower() == "untagged":
return ~Entry.id.in_(
select(Entry.id).join(Entry.tag_box_fields).join(TagBoxField.tags)
)
return ~Entry.id.in_(select(Entry.id).join(TagEntry))

# raise exception if Constraint stays unhandled
raise NotImplementedError("This type of constraint is not implemented yet")
Expand All @@ -105,11 +104,10 @@ def __entry_has_all_tags(self, tag_ids: list[int]) -> BinaryExpression[bool]:
# Relational Division Query
return Entry.id.in_(
select(Entry.id)
.outerjoin(TagBoxField)
.outerjoin(TagField)
.where(TagField.tag_id.in_(tag_ids))
.outerjoin(TagEntry)
.where(TagEntry.tag_id.in_(tag_ids))
.group_by(Entry.id)
.having(func.count(distinct(TagField.tag_id)) == len(tag_ids))
.having(func.count(distinct(TagEntry.tag_id)) == len(tag_ids))
)

def __entry_satisfies_ast(self, partial_query: AST) -> BinaryExpression[bool]:
Expand All @@ -119,7 +117,8 @@ def __entry_satisfies_ast(self, partial_query: AST) -> BinaryExpression[bool]:
def __entry_satisfies_expression(
self, expr: ColumnExpressionArgument
) -> BinaryExpression[bool]:
"""Returns Binary Expression that is true if the Entry satisfies the column expression."""
return Entry.id.in_(
select(Entry.id).outerjoin(Entry.tag_box_fields).outerjoin(TagField).where(expr)
)
"""Returns Binary Expression that is true if the Entry satisfies the column expression.

Executed on: Entry ⟕ TagEntry (Entry LEFT OUTER JOIN TagEntry).
"""
return Entry.id.in_(select(Entry.id).outerjoin(TagEntry).where(expr))
Loading