From: Ian Beckwith Date: Mon, 11 Oct 2010 04:35:43 +0000 (+0100) Subject: start of support for NOT queries X-Git-Tag: debian/1.0-1~106 X-Git-Url: http://erislabs.net/gitweb/?p=id3fs.git;a=commitdiff_plain;h=9f98f6108a1d4666fd103a8a75df33d50db6940b start of support for NOT queries --- diff --git a/lib/ID3FS/Path.pm b/lib/ID3FS/Path.pm index 46bac15..319e147 100644 --- a/lib/ID3FS/Path.pm +++ b/lib/ID3FS/Path.pm @@ -338,9 +338,9 @@ sub parse if($self->{tagtree}) { ($self->{sqlconditions}, - $self->{andsneeded}) = $self->{tagtree}->to_sql(); + $self->{joins}) = $self->{tagtree}->to_sql(); # print "TREE: ", $self->{tagtree}->print(), "\n"; -# print("SQL CONDITION(", $self->{andsneeded}, "): ", +# print("SQL CONDITION(", scalar(@{$self->{joins}}), "): ", # $self->{sqlconditions}, "\n"); # use Data::Dumper; # print Dumper $self->{tagtree}; @@ -721,21 +721,24 @@ sub tags_subselect $tag=$self->trailing_tag_id(); # print "Trailing id: $tag\n"; } - my ($sqlclause, $joinsneeded)=(undef, 1); - ($sqlclause, $joinsneeded) = $tree->to_sql($tag) if($tree); -# print "SQL($joinsneeded): $sqlclause\n"; + my ($sqlclause, @joins)=(undef, ()); + ($sqlclause, @joins) = $tree->to_sql($tag) if($tree); + print "JOINS: ", join(", ", @joins), "\n"; +# print "SQL(" . scalar(@joins) .": $sqlclause\n"; my $sql="\tSELECT fxt1.files_id FROM tags t1"; my @crosses=(); my @inners=(); # $joinsneeded++ if($tag); - for(my $i=1; $i <= $joinsneeded; $i++) + for(my $i=0; $i <= $#joins; $i++) { - my $inner=("\tINNER JOIN files_x_tags fxt$i ON " . - "t${i}.id=fxt${i}.tags_id"); - if($i > 1) + my $cnt=$i+1; + my $join=$joins[$i]; + my $inner=("\t$join JOIN files_x_tags fxt$cnt ON " . + "t${cnt}.id=fxt${cnt}.tags_id"); + if($i > 0) { - push(@crosses, "CROSS JOIN tags t$i"); - $inner .= " AND fxt1.files_id=fxt${i}.files_id"; + push(@crosses, "CROSS JOIN tags t$cnt"); + $inner .= " AND fxt1.files_id=fxt${cnt}.files_id"; } push(@inners, $inner); } diff --git a/lib/ID3FS/Path/Node.pm b/lib/ID3FS/Path/Node.pm index 5280478..8362f34 100644 --- a/lib/ID3FS/Path/Node.pm +++ b/lib/ID3FS/Path/Node.pm @@ -58,33 +58,31 @@ sub print_node sub to_sql { - my($self, $parent, $andlevel)=@_; - $andlevel=1 unless(defined($andlevel)); - my ($leftandlevel, $rightandlevel); + my($self, $parent, @joins)=@_; + @joins=("INNER") unless(@joins); + my @newjoins=(); + my (@leftjoins, @rightjoins); my ($leftstr, $rightstr); my $op=$self->op(); my $left=$self->left(); my $right=$self->right(); - return ("", $andlevel) unless($left || $right); - ($leftstr, $leftandlevel) = $self->node_to_sql($left, $parent, $andlevel); + return ("", @joins) unless($left || $right); + ($leftstr, @leftjoins) = $self->node_to_sql($left, $parent, @joins); # print "LEFT: $leftstr\n"; - $andlevel=$self->max($andlevel, $leftandlevel); - if($op) +# $andlevel=$self->max($andlevel, $leftandlevel); + if(defined($op)) { - if(ref($op) eq "ID3FS::PathElement::Boolean") + if($op->{name} eq "AND") { -# print "Op: Bool: ", $op->{name}, "\n"; + push(@newjoins, "INNER"); } - else + elsif($op->{name} eq "NOT") { -# print "Op: $op\n"; + push(@newjoins, "LEFT"); } } - if(defined($op) && (($op->{name} eq "AND") || ($op->{name} eq "NOT"))) - { - $andlevel++; - } - ($rightstr, $rightandlevel) = $self->node_to_sql($right, $parent, $andlevel); + push(@joins, @newjoins); + ($rightstr, @rightjoins) = $self->node_to_sql($right, $parent, @joins); # print "RIGHT: $rightstr\n"; my $str=$leftstr; $str .= (" " . $op->{name} . " ") if($op); @@ -93,39 +91,34 @@ sub to_sql { $str="(" . $str . ")"; } +# print "LEFTJOINS: ", join(', ', @leftjoins), "\n"; +# print "RIGHTJOINS:", join(', ', @rightjoins), "\n"; +# print "NEWJOINS: ", join(', ', @newjoins), "\n"; # print "STR: $str\n"; - return($str, $self->max($leftandlevel, $rightandlevel)); +# return($str, $self->max($leftandlevel, $rightandlevel)); + my @sidejoins=((scalar(@leftjoins) > scalar(@rightjoins)) ? @leftjoins : @rightjoins); + my @alljoins=(@newjoins, @sidejoins); + return($str, @alljoins); } sub node_to_sql { - my($self, $node, $parent, $andlevel)=@_; - return ("", $andlevel) unless(defined($node)); - return $node->to_sql($parent, $andlevel) if(ref($node) eq "ID3FS::Path::Node"); -# if((ref($node->op()) ne "ID3FS::Path::Element") && -# $node->op() eq " + my($self, $node, $parent, @joins)=@_; + return ("", @joins) unless(defined($node)); + return $node->to_sql($parent, @joins) if(ref($node) eq "ID3FS::Path::Node"); my $sql; -# print("Hit node: " . $node->{name}. "(" . -# (defined($node->{parents_id}) ? $node->{parents_id} : "") . -# ")\n"); + my $cnt=scalar(@joins)+1; if(defined($node->{parents_id})) { -# print "HIT PARENTS_ID: $node->{parents_id}\n"; - $sql= "(t$andlevel.parents_id='$node->{parents_id}'"; - $sql .= " AND fxt${andlevel}.tags_id='" . $node->{id} . "')"; + $sql= "(t" . scalar(@joins) . ".parents_id='$node->{parents_id}'"; + $sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "')"; } -# elsif($parent) -# { -# print "HIT \$parent\n"; -# $sql= "(t$andlevel.parents_id='$parent')"; -# } else { -# print "HIT NORMAL\n"; - $sql= "(t$andlevel.parents_id=''"; - $sql .= " AND fxt${andlevel}.tags_id='" . $node->{id} . "')"; + $sql= "(t" . scalar(@joins) .".parents_id=''"; + $sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "')"; } - return ($sql, $andlevel); + return ($sql, @joins); } sub used_tags