From 1e73912219547384bb259904512b8ffa49037e81 Mon Sep 17 00:00:00 2001 From: Ian Beckwith Date: Fri, 15 Oct 2010 01:13:50 +0100 Subject: [PATCH] special-case /NOT --- lib/ID3FS/Path.pm | 40 ++++++++++++++++++++++++++++++++++++++++ lib/ID3FS/Path/Node.pm | 4 ++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/ID3FS/Path.pm b/lib/ID3FS/Path.pm index 0f3241c..39aab39 100644 --- a/lib/ID3FS/Path.pm +++ b/lib/ID3FS/Path.pm @@ -132,6 +132,9 @@ sub parse my @parts=@{$self->{components}}; my($tag, $tagval); $self->{elements}=[]; + $self->{bare_not}=0; + my $root_not=0; + my $tags_seen=0; while(defined(my $name=shift @parts)) { # print "NAME: $name\n"; @@ -150,6 +153,7 @@ sub parse } elsif($name eq "NOT") { + $root_not=1; push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($self->{db}, $name)); $self->state($STATE_BOOLEAN); } @@ -159,6 +163,7 @@ sub parse if($tag) { push(@{$self->{elements}}, $tag); + $tags_seen++; $self->state($STATE_TAG); } else @@ -243,6 +248,7 @@ sub parse if($tag) { push(@{$self->{elements}}, $tag); + $tags_seen++; $self->state($STATE_TAG); } else @@ -326,6 +332,13 @@ sub parse $self->state($STATE_INVALID); } } + + print "ROOT_NOT: $root_not TAGS_SEEN: $tags_seen\n"; + if($root_not && ($tags_seen < 2)) + { + $self->{bare_not}=1; + } + # remove trailing boolean my @elements=@{$self->{elements}}; while(@elements && ref($elements[$#elements]) eq "ID3FS::PathElement::Boolean") @@ -708,6 +721,12 @@ sub filename sub tags_subselect { my($self)=@_; + # we need to specially handle a bare /NOT/tag with no other clauses, + # using a simple WHERE id !='tagid' instead of a LEFT JOIN + if($self->{bare_not}) + { + return $self->bare_not_subselect(); + } my $tree=$self->{tagtree}; my $hasvals=$self->tag_has_values(); my $parent=$self->trailing_tag_parent(); @@ -751,6 +770,27 @@ sub tags_subselect return $sql; } +sub bare_not_subselect +{ + my($self)=@_; + my @tags=grep { ref($_) eq "ID3FS::PathElement::Tag"; } @{$self->{elements}}; + my $sql=("\tSELECT f1.id AS files_id FROM files f1 WHERE f1.id NOT IN (\n" . + "\t\tSELECT fxt1.files_id FROM tags t1\n" . + "\t\tINNER JOIN files_x_tags fxt1 ON t1.id=fxt1.tags_id\n" . + "\t\tWHERE "); + if(scalar(@tags) > 1) + { + $sql .= ("(t1.parents_id='" . $tags[0]->{id} . "' AND t1.id='" . + $tags[1]->{id} . "')"); + } + else + { + $sql .= ("(t1.parents_id='' AND t1.id='" . $tags[0]->{id} . "')"); + } + $sql .= "\n\t\tGROUP BY fxt1.files_id\n\t)\n"; + return($sql); +} + sub tags_subselect_and_not { my($self,@constraints)=@_; diff --git a/lib/ID3FS/Path/Node.pm b/lib/ID3FS/Path/Node.pm index 68515e3..8ce259e 100644 --- a/lib/ID3FS/Path/Node.pm +++ b/lib/ID3FS/Path/Node.pm @@ -85,8 +85,8 @@ sub to_sql $not=1; push(@joins, "LEFT"); push(@outjoins, "LEFT"); - print("LEFT: ", $left->print(), "\n") if ($left); - print("RIGHT: ", $right->print(), "\n") if($right); +# print("LEFT: ", $left->print(), "\n") if ($left); +# print("RIGHT: ", $right->print(), "\n") if($right); } } my ($rightstr, @rightjoins) = $self->node_to_sql($right, $not, @joins); -- 2.11.0