X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2FID3FS%2FPath.pm;h=406fbdfcd7c120716a2fc0f124059b37a9609e44;hb=f768e5fc4f33962bfac1142c546776cc0e239ec0;hp=e54c7e29735c977b953294a2a9ac5f23d304df78;hpb=3b83e0afa68f15baa1a1ee0fddae969fa5a637c2;p=id3fs.git diff --git a/lib/ID3FS/Path.pm b/lib/ID3FS/Path.pm index e54c7e2..406fbdf 100644 --- a/lib/ID3FS/Path.pm +++ b/lib/ID3FS/Path.pm @@ -48,7 +48,6 @@ sub new $self->{path} =~ s/\/\//\//g; # drop doubled slashes $self->parse(); -# print "STATE: ", $self->state(), "\n"; return $self; } @@ -91,8 +90,6 @@ sub dirents my @dents=(); my @fents=(); my $state=$self->state(); -# print "DIRENTS: STATE: $state\n"; -# print "DIRENTS: FILE: $self->{path}\n"; if($state==$STATE_ALL) { @dents=($self->filter($PATH_ALLTRACKS, $PATH_NOARTIST), $self->artists()); @@ -116,7 +113,7 @@ sub dirents elsif($state==$STATE_BOOLEAN) { my $parent=$self->tail(); - unless($self->is($TYPE_BOOL, $parent) && $parent->{name} eq "NOT") + unless($self->is($TYPE_BOOL, $parent) && $parent->name() eq "NOT") { @dents=("NOT"); } @@ -149,7 +146,6 @@ sub parse return if($self->{path} eq "/"); @{$self->{components}}=split(/\//, $self->{path}); shift @{$self->{components}}; # drop empty field before leading / -# print "PATH: $self->{path}\n"; my @parts=@{$self->{components}}; my($tag, $tagval); $self->{elements}=[]; @@ -158,16 +154,13 @@ sub parse my $tags_seen=0; while(defined(my $name=shift @parts)) { -# print "NAME: $name\n"; my $state=$self->state(); if($state==$STATE_INVALID) { -# print "SM: INVALID: $name\n"; return; } elsif($state==$STATE_ROOT) { -# print "SM: ROOT: $name\n"; if($name eq "ALL") { $self->{in_all}=1; @@ -197,10 +190,8 @@ sub parse elsif($state==$STATE_TAG) { my $tag=$self->tail(); -# print "SM: TAG/TAGVAL($state): $name\n"; if($self->is($TYPE_TAG, $tag) && $self->{db}->tag_has_values($tag->id())) { -# print "Parsing: parent: $tag->id()\n"; my $tagval=ID3FS::Path::Node->new($self->{db}, $TYPE_TAG, $name, $tag->id()); if(defined($tagval)) { @@ -246,11 +237,10 @@ sub parse } elsif($state==$STATE_BOOLEAN) { -# print "SM: BOOLEAN: $name\n"; my $parent=$self->tail(); my $allownot=1; if($self->is($TYPE_BOOL, $parent) && - $parent->{name} eq "NOT") + $parent->name() eq "NOT") { $allownot=0; } @@ -276,7 +266,6 @@ sub parse } elsif($state==$STATE_ALBUMS) { -# print "SM: ALBUM: $name\n"; if($name eq $PATH_ALLTRACKS) { $self->state($STATE_TRACKLIST); @@ -301,7 +290,6 @@ sub parse } elsif($state==$STATE_TRACKLIST) { -# print "SM: TRACKLIST: $name\n"; my $track=ID3FS::Path::Node->new($self->{db}, $TYPE_FILE, $name); if($track) { @@ -315,7 +303,6 @@ sub parse } elsif($state==$STATE_FILE) { -# print "SM: FILE: $name\n"; # Can't have anything after a filename $self->state($STATE_INVALID); } @@ -356,14 +343,17 @@ sub parse { pop @elements; } -# print "\nELEMENTS: ", join(' ', map { $_->name(); } @elements), "\n"; - my @joins=$self->number_joins(@elements); - @joins=qw(INNER) unless(@joins); - $self->{joins}=\@joins; -# print "AFTER: ", join(' ', map { $_->name() . "(" . $_->{table} . ")"; } @elements), "\n"; -# print "JOINS: ", join(', ', @joins), "\n"; + + # calculate joins and assign table numbers to nodes + $self->{joins}=[$self->number_joins(@elements)]; + + # always need at least one join + $self->{joins}=[qw(INNER)] unless(@{$self->{joins}}); + # sort elements by precedence @elements=$self->sort_elements(@elements); + + # convert to binary tree $self->{tagtree}=$self->elements_to_tree(\@elements); } @@ -375,11 +365,11 @@ sub number_joins my $nextjoin=undef; my $lastop=undef; return (@joins) unless(@elements); - while(my $thing=shift @elements) + while(my $node=shift @elements) { - if($thing->type() == $TYPE_BOOL) + if($node->type() == $TYPE_BOOL) { - my $op=$thing->name(); + my $op=$node->name(); if($op eq "AND") { $nextjoin="INNER"; @@ -397,12 +387,17 @@ sub number_joins } else { + $node->hasvals(0); if(@elements) { # if tag has a value, eat the tag, shifting to the value - $thing=shift(@elements) if($elements[0]->type() == $TYPE_TAG); + if($elements[0]->type() == $TYPE_TAG) + { + $node->hasvals(1); + $node=shift(@elements); + } } - elsif($self->{db}->tag_has_values($thing->id())) + elsif($self->{db}->tag_has_values($node->id())) { # if the expression ends in a tag that has a value # (ie we have the tag and want the value) @@ -415,7 +410,7 @@ sub number_joins push(@joins, $nextjoin); $nextjoin=undef; } - $thing->table($table); + $node->table($table); } } return @joins; @@ -438,18 +433,18 @@ sub elements_to_tree my($self, $elements)=@_; return undef unless(@$elements); my ($left, $right, $op)=(undef, undef, undef); - my $thing=pop @$elements; - if($self->is($TYPE_BOOL, $thing)) + my $node=pop @$elements; + if($self->is($TYPE_BOOL, $node)) { $right=$self->elements_to_tree($elements); - if($thing->{name} ne "NOT") + if($node->name() ne "NOT") { $left=$self->elements_to_tree($elements); } - $thing->left($left); - $thing->right($right); + $node->left($left); + $node->right($right); } - return $thing; + return $node; } # Dijkstra's shunting-yard algorithm @@ -458,25 +453,25 @@ sub sort_elements my ($self, @input)=@_; my @opstack=(); my @output=(); - while(my $thing = shift @input) + while(my $node = shift @input) { - if($self->is($TYPE_TAG, $thing)) + if($self->is($TYPE_TAG, $node)) { # Handle tag values by dropping parent if(@input && $self->is($TYPE_TAG, $input[0])) { - $thing=shift @input; + $node=shift @input; } - push(@output, $thing); + push(@output, $node); } - elsif($self->is($TYPE_BOOL, $thing)) + elsif($self->is($TYPE_BOOL, $node)) { while(@opstack && - ($priorities{$thing->{name}} <= $priorities{$opstack[$#opstack]->{name}})) + ($priorities{$node->name()} <= $priorities{$opstack[$#opstack]->name()})) { push(@output, pop(@opstack)); } - push(@opstack, $thing); + push(@opstack, $node); } } while(@opstack) @@ -533,10 +528,10 @@ sub tail sub is { - my($self, $type, $thing)=@_; - return 0 unless($thing); - return 0 unless($thing->type()); - return 1 if($type == $thing->type()); + my($self, $type, $node)=@_; + return 0 unless($node); + return 0 unless($node->type()); + return 1 if($type == $node->type()); return 0; } @@ -557,7 +552,6 @@ sub tags my $sql="SELECT DISTINCT name FROM tags WHERE parents_id='';"; return($self->{db}->cmd_firstcol($sql)); } - my $hasvals=$self->expecting_values(); my $sql="SELECT tags.name FROM "; if($self->want_all_tags()) { @@ -575,7 +569,7 @@ sub tags my $id=$self->trailing_tag_id(); my $parentclause= "tags.parents_id='"; - $parentclause .= $id if($hasvals); + $parentclause .= $id if($self->expecting_values()); $parentclause .= "'"; push(@andclauses, $parentclause); @@ -728,11 +722,8 @@ sub filename sub tags_subselect { my($self)=@_; - my $hasvals=$self->expecting_values(); my $tree=$self->{tagtree}; -# use Data::Dumper; -# print Dumper $tree; - my ($sqlclause, @joins)=$tree->to_sql($hasvals) if($tree); + my ($sqlclause, @joins)=$tree->to_sql() if($tree); my $sql="\tSELECT fxt1.files_id FROM tags t1"; my @crosses=(); my @inners=();