From ddb9cbe0dda25dce5fbbd30738e80807d1bd3da1 Mon Sep 17 00:00:00 2001 From: Ian Beckwith Date: Sun, 10 Oct 2010 20:57:23 +0100 Subject: [PATCH] fix foo/bar/AND/ --- lib/ID3FS/DB.pm | 58 ++++++++++++++++++++++++++++++++++++++------------ lib/ID3FS/Path.pm | 34 ++++++++++++++++++----------- lib/ID3FS/Path/Node.pm | 1 - 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/lib/ID3FS/DB.pm b/lib/ID3FS/DB.pm index 4ff9bfd..86291cf 100644 --- a/lib/ID3FS/DB.pm +++ b/lib/ID3FS/DB.pm @@ -184,11 +184,14 @@ sub tags my @constraints=@{$path->{elements}}; if(!@constraints) # / { - # FIXME: add ALL? my $sql="SELECT DISTINCT name FROM tags WHERE parents_id='';"; my $tags=$self->cmd_rows($sql); return(map { $_->[0]; } @$tags); } + my $hasvals=$path->tag_has_values(); + my $parent=$path->trailing_tag_parent(); + print "THASVALS: $hasvals\n"; + print "TPARENT: ", (defined($parent)? $parent : "NO"), "\n"; my @ids=(); my $sql=("SELECT tags.name FROM (\n" . $self->tags_subselect($path) . @@ -201,13 +204,13 @@ sub tags print "tags(): USED: ", join(", ", @used), "\n"; print "tags(): USED_WITH_VALS: ", join(", ", map { "[".$_->[0]. ", ".$_->[1]."]";} @used_with_vals), "\n"; my @orclauses=(); - if($path->tag_has_values()) + my @andclauses=(); + my $id=$path->trailing_tag_id(); + if($hasvals) { print "HAS_VALUES\n"; - my $parent=$path->trailing_tag_id(); - print "parent: $parent\n"; - my @values=map { "'".$_->[1]."'"; } grep { $_->[0] == $parent; } @used_with_vals; - my $clause="(tags.parents_id='$parent'"; + my @values=map { "'".$_->[1]."'"; } grep { $_->[0] == $id; } @used_with_vals; + my $clause="(tags.parents_id='$id'"; if(@values) { $clause .= " AND tags.id NOT IN (" . join(', ', @values) . ")"; @@ -220,16 +223,33 @@ sub tags print "HASNT VALUES\n";; if(@used) { - push(@orclauses, "(tags.parents_id='' AND tags.id NOT IN (" . join(', ', @used) . "))"); + push(@orclauses, "(NOT (tags.parents_id='' AND tags.id IN (" . join(', ', @used) . ")))"); } for my $pair (@used_with_vals) { - push(@orclauses, "(tags.parents_id='" . $pair->[0] . "' AND tags.id!='" . $pair->[1] . "')"); + push(@orclauses, "(NOT (tags.parents_id='" . $pair->[0] . "' AND tags.id='" . $pair->[1] . "'))"); } } + + my $parentclause= "(tags.parents_id='"; + if($hasvals) + { + $parentclause .= $id; + } + elsif($parent) + { + $parentclause .= $parent; + } + $parentclause .= "')"; + push(@andclauses, $parentclause); + if(@orclauses) { - $sql .= "WHERE " . join(' OR ', @orclauses) . "\n"; + push(@andclauses, join(' OR ', @orclauses)); + } + if(@andclauses) + { + $sql .= "WHERE " . join(' AND ', @andclauses) . "\n"; } $sql .= "GROUP BY tags.name;"; print "SQL: $sql\n"; @@ -320,7 +340,6 @@ sub artist_albums sub artist_tracks { my($self, $artist_id, $path)=@_; - my @constraints=@{$path->{elements}}; my $sql=("SELECT files.name FROM (\n" . $self->tags_subselect($path) . "\t) AS subselect\n" . @@ -358,7 +377,14 @@ sub tracks # FIXME: rework PathElements if(ref($constraints[$#constraints]) eq "ID3FS::PathElement::Artist") { - return $self->artist_tracks($constraints[$#constraints]->{id}, @constraints); + my $artist_id=0; + my $artist=$constraints[$#constraints]; + if(defined($artist) && (ref($artist) eq "ID3FS::PathElement::Artist")) + { + # should always happen + $artist_id=$artist->{id}; + } + return $self->artist_tracks($artist_id, $path); } elsif(ref($constraints[$#constraints]) eq "ID3FS::PathElement::Album") { @@ -408,13 +434,17 @@ sub tags_subselect { my($self, $path)=@_; my $tree=$path->{tagtree}; + my $hasvals=$path->tag_has_values(); + my $parent=$path->trailing_tag_parent(); + my $tag=undef; - if($path->tag_has_values()) + if($hasvals) { $tag=$path->trailing_tag_id(); print "Trailing id: $tag\n"; } - my ($sqlclause, $joinsneeded)=$tree->to_sql($tag); + my ($sqlclause, $joinsneeded)=(undef, 1); + ($sqlclause, $joinsneeded) = $tree->to_sql($tag) if($tree); print "SQL($joinsneeded): $sqlclause\n"; my $sql="\tSELECT fxt1.files_id FROM tags t1"; my @crosses=(); @@ -436,7 +466,7 @@ sub tags_subselect } $sql .= ("\n\t" . join(" ", @crosses)) if(@crosses); $sql .= ("\n" . join("\n", @inners)) if(@inners); - $sql .= "\n\tWHERE $sqlclause"; + $sql .= "\n\tWHERE $sqlclause" if($sqlclause); # if($tag) # { # $sql .= " AND t${joinsneeded}.parents_id='$tag'"; diff --git a/lib/ID3FS/Path.pm b/lib/ID3FS/Path.pm index 5c7eacc..370c105 100644 --- a/lib/ID3FS/Path.pm +++ b/lib/ID3FS/Path.pm @@ -300,14 +300,11 @@ sub parse } } # remove trailing boolean - if(@{$self->{elements}} && - ref($self->{elements}->[$#{$self->{elements}}]) eq "ID3FS::PathElement::Boolean") - { - $self->{lastop}=pop @{$self->{elements}}; - } + my @elements=@{$self->{elements}}; + pop @elements if(@elements && ref($elements[$#elements]) eq "ID3FS::PathElement::Boolean"); # sort elements by precedence - @{$self->{elements}}=$self->sort_elements(@{$self->{elements}}); - $self->{tagtree}=$self->elements_to_tree([ @{$self->{elements}} ]); + @elements=$self->sort_elements(@elements); + $self->{tagtree}=$self->elements_to_tree(@elements); if($self->{tagtree}) { ($self->{sqlconditions}, @@ -328,17 +325,17 @@ sub state sub elements_to_tree { - my($self, $elements)=@_; - return undef unless(@$elements); + my($self, @elements)=@_; + return undef unless(@elements); my ($left, $right, $op)=(undef, undef, undef); - my $thing=pop @$elements; + my $thing=pop @elements; if(ref($thing) eq "ID3FS::PathElement::Boolean") { my $op=$thing; - $right=$self->elements_to_tree($elements); + $right=$self->elements_to_tree(@elements); if($op->{name} ne "NOT") { - $left=$self->elements_to_tree($elements); + $left=$self->elements_to_tree(@elements); } return ID3FS::Path::Node->new($left, $op, $right); } @@ -408,6 +405,7 @@ sub tag_has_values { my($self)=@_; my $tail=$self->{elements}->[$#{$self->{elements}}]; + print "TAIL: ", ref($tail), "\n"; if($tail && ref($tail) eq "ID3FS::PathElement::Tag") { return($self->{db}->tag_has_values($tail->{id})); @@ -425,4 +423,16 @@ sub trailing_tag_id return undef; } +sub trailing_tag_parent +{ + my($self)=@_; + my $tail=$self->{elements}->[$#{$self->{elements}}]; + if($tail && ref($tail) eq "ID3FS::PathElement::Tag") + { + return($tail->{parents_id}); + } + return undef; +} + + 1; diff --git a/lib/ID3FS/Path/Node.pm b/lib/ID3FS/Path/Node.pm index f03d040..8adb076 100644 --- a/lib/ID3FS/Path/Node.pm +++ b/lib/ID3FS/Path/Node.pm @@ -113,7 +113,6 @@ sub used_tags my($self)=@_; my @used=(grep { defined; } ($self->node_used_tags($self->left()), $self->node_used_tags($self->right()))); - print "used_tags: ", join(", ", @used), "\n"; return(@used); } -- 2.11.0