fix foo/bar/AND/
[id3fs.git] / lib / ID3FS / DB.pm
index 4ff9bfd..86291cf 100644 (file)
@@ -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'";