start of support for NOT queries
[id3fs.git] / lib / ID3FS / Path / Node.pm
1 package ID3FS::Path::Node;
2
3 use strict;
4 use warnings;
5
6 sub new
7 {
8     my $proto=shift;
9     my $class=ref($proto) || $proto;
10     my $self={};
11     bless($self,$class);
12
13     $self->left(shift);
14     $self->op(shift);
15     $self->right(shift);
16
17     return $self;
18 }
19
20 sub set
21 {
22     my($self, $name, $val)=@_;
23     if(defined($val))
24     {
25         $self->{$name}=$val;
26     }
27     return $self->{$name};
28 }
29
30 sub left  { return shift->set("left",  shift); }
31 sub right { return shift->set("right", shift); }
32 sub op    { return shift->set("op",    shift); }
33
34 sub print
35 {
36     my($self)=@_;
37     my $op=$self->op();
38     my $left=$self->left();
39     my $right=$self->right();
40     return "" unless($left || $right);
41     my $str .= $self->print_node($left);
42     $str .= (" " . $op->{name} . " ") if($op);
43     $str .= $self->print_node($right);
44     if($op || ($left && $right))
45     {
46         $str="(" . $str . ")";
47     }
48     return $str;
49 }
50
51 sub print_node
52 {
53     my($self, $node)=@_;
54     return "" unless(defined($node));
55     return $node->print() if(ref($node) eq "ID3FS::Path::Node");
56     return $node->{name};
57 }
58
59 sub to_sql
60 {
61     my($self, $parent, @joins)=@_;
62     @joins=("INNER") unless(@joins);
63     my @newjoins=();
64     my (@leftjoins, @rightjoins);
65     my ($leftstr, $rightstr);
66     my $op=$self->op();
67     my $left=$self->left();
68     my $right=$self->right();
69     return ("", @joins) unless($left || $right);
70     ($leftstr, @leftjoins) = $self->node_to_sql($left, $parent, @joins);
71 #    print "LEFT: $leftstr\n";
72 #    $andlevel=$self->max($andlevel, $leftandlevel);
73     if(defined($op))
74     {
75         if($op->{name} eq "AND")
76         {
77             push(@newjoins, "INNER");
78         }
79         elsif($op->{name} eq "NOT")
80         {
81             push(@newjoins, "LEFT");
82         }
83     }
84     push(@joins, @newjoins);
85     ($rightstr, @rightjoins) = $self->node_to_sql($right, $parent, @joins);
86 #    print "RIGHT: $rightstr\n";
87     my $str=$leftstr;
88     $str .= (" " . $op->{name} . " ") if($op);
89     $str .= $rightstr;
90     if($op || ($left && $right))
91     {
92         $str="(" . $str . ")";
93     }
94 #    print "LEFTJOINS: ", join(', ', @leftjoins), "\n";
95 #    print "RIGHTJOINS:", join(', ', @rightjoins), "\n";
96 #    print "NEWJOINS: ",  join(', ', @newjoins), "\n";
97 #    print "STR: $str\n";
98 #    return($str, $self->max($leftandlevel, $rightandlevel));
99     my @sidejoins=((scalar(@leftjoins) > scalar(@rightjoins)) ? @leftjoins : @rightjoins);
100     my @alljoins=(@newjoins, @sidejoins);
101     return($str, @alljoins);
102 }
103
104 sub node_to_sql
105 {
106     my($self, $node, $parent, @joins)=@_;
107     return ("", @joins) unless(defined($node));
108     return $node->to_sql($parent, @joins) if(ref($node) eq "ID3FS::Path::Node");
109     my $sql;
110     my $cnt=scalar(@joins)+1;
111     if(defined($node->{parents_id}))
112     {
113         $sql= "(t" . scalar(@joins) . ".parents_id='$node->{parents_id}'";
114         $sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "')";
115     }
116     else
117     {
118         $sql= "(t" . scalar(@joins) .".parents_id=''";
119         $sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "')";
120     }
121     return ($sql, @joins);
122 }
123
124 sub used_tags
125 {
126     my($self)=@_;
127     my @used=(grep { defined; }  ($self->node_used_tags($self->left()),
128                                   $self->node_used_tags($self->right())));
129     return(@used);
130 }
131
132 sub node_used_tags
133 {
134     my($self, $node)=@_;
135     return (undef) unless(defined($node));
136     return $node->used_tags() if(ref($node) eq "ID3FS::Path::Node");
137     if(defined($node->{parents_id}))
138     {
139         return([ $node->{parents_id}, $node->{id} ]);
140     }
141     return $node->{id};
142 }
143
144
145 sub max
146 {
147     my($self, $a, $b)=@_;
148     return(($a > $b) ? $a : $b);
149 }
150
151 1;