Initial revision
[OpenSRF.git] / src / perlmods / OpenSRF / DomainObject / oilsMultiSearch.pm
1 package OpenILS::DomainObjectCollection::oilsMultiSearch;
2 use OpenILS::DomainObjectCollection;
3 use OpenILS::DomainObject::oilsPrimitive;
4 use OpenILS::DomainObject::oilsSearch;
5 use OpenILS::DOM::Element::searchCriteria;
6 use OpenILS::DOM::Element::searchCriterium;
7 use base 'OpenILS::DomainObjectCollection::oilsHash';
8
9 sub new {
10         my $class = shift;
11         my %args = @_;
12
13         $class = ref($class) || $class;
14
15         my $self = $class->SUPER::new;
16
17         tie my %hash, 'OpenILS::DomainObjectCollection::oilsHash', $self;
18
19         $self->set( bind_count  => 1 );
20         $self->set( searches    => new OpenILS::DomainObjectCollection::oilsHash );
21         $self->set( relators    => new OpenILS::DomainObjectCollection::oilsArray );
22         $self->set( fields      => new OpenILS::DomainObjectCollection::oilsArray );
23         $self->set( group_by    => new OpenILS::DomainObjectCollection::oilsArray );
24         $self->set( order_by    => new OpenILS::DomainObjectCollection::oilsArray );
25         
26         return $self;
27 }
28
29 sub add_subsearch {
30         my $self = shift;
31         my $alias = shift;
32         my $search = shift;
33         my $relator = shift;
34         
35         $search = OpenILS::DomainObject::oilsSearch->new($search) if (ref($search) eq 'ARRAY');
36
37         $self->searches->set( $alias => $search );
38         
39         if ($self->searches->size > 1) {
40                 throw OpenILS::EX::InvalidArg ('You need to pass a relator searchCriterium')
41                         unless (defined $relator);
42         }
43
44         $relator = OpenILS::DOM::Element::searchCriterium->new( @$relator )
45                 if (ref($relator) eq 'ARRAY');
46
47         $self->relators->push( $relator ) if (defined $relator);
48
49         return $self;
50 }
51
52 sub relators {
53         return $_[0]->_accessor('relators');
54 }
55
56 sub searches {
57         return $_[0]->_accessor('searches');
58 }
59
60 sub fields {
61         my $self = shift;
62         my @parts = @_;
63         if (@parts) {
64                 $self->set( fields => OpenILS::DomainObjectCollection::oilsArray->new(@_) );
65         }
66         return $self->_accessor('fields')->list;
67 }
68
69 sub format {
70         $_[0]->set( format => $_[1] ) if (defined $_[1]);
71         return $_[0]->_accessor('format');
72 }
73
74 sub limit {
75         $_[0]->set( limit => $_[1] ) if (defined $_[1]);
76         return $_[0]->_accessor('limit');
77 }
78
79 sub offset {
80         $_[0]->set( offset => $_[1] ) if (defined $_[1]);
81         return $_[0]->_accessor('offset');
82 }
83
84 sub chunk_key {
85         $_[0]->set( chunk_key => $_[1] ) if (defined $_[1]);
86         return $_[0]->_accessor('chunk_key');
87 }
88
89 sub order_by {
90         my $self = shift;
91         my @parts = @_;
92         if (@parts) {
93                 $self->set( order_by => OpenILS::DomainObjectCollection::oilsArray->new(@_) );
94         }
95         return $self->_accessor('order_by')->list;
96 }
97
98 sub group_by {
99         my $self = shift;
100         my @parts = @_;
101         if (@parts) {
102                 $self->set( group_by => OpenILS::DomainObjectCollection::oilsArray->new(@_) );
103         }
104         return $self->_accessor('group_by')->list;
105 }
106
107 sub SQL_select_list {
108         my $self = shift;
109
110         if (my $sql = $self->_accessor('sql_select_list')) {
111                 return $sql;
112         }
113
114         $self->set( sql_select_list => 'SELECT '.join(', ', $self->fields) ) if defined($self->fields);
115         return $self->_accessor('sql_select_list');
116 }
117
118 sub SQL_group_by {
119         my $self = shift;
120
121         if (my $sql = $self->_accessor('sql_group_by')) {
122                 return $sql;
123         }
124
125         $self->set( sql_group_by => 'GROUP BY '.join(', ', $self->group_by) ) if defined($self->group_by);
126         return $self->_accessor('sql_group_by');
127 }
128
129 sub SQL_order_by {
130         my $self = shift;
131
132         if (my $sql = $self->_accessor('sql_order_by')) {
133                 return $sql;
134         }
135
136         $self->set( sql_order_by => 'ORDER BY '.join(', ', $self->order_by) ) if defined($self->order_by);
137         return $self->_accessor('sql_order_by');
138 }
139
140 sub SQL_offset {
141         my $self = shift;
142
143         if (my $sql = $self->_accessor('sql_offset')) {
144                 return $sql;
145         }
146
147         $self->set( sql_offset => 'OFFSET '.$self->offset ) if defined($self->offset);
148         return $self->_accessor('sql_offset');
149 }
150
151 sub SQL_limit {
152         my $self = shift;
153
154         if (my $sql = $self->_accessor('sql_limit')) {
155                 return $sql;
156         }
157
158         $self->set( sql_limit => 'LIMIT '.$self->limit ) if defined($self->limit);
159         return $self->_accessor('sql_limit');
160 }
161
162 sub toSQL {
163         my $self = shift;
164
165         my $SQL = $self->SQL_select_list.' FROM ';
166
167         my @subselects;
168         for my $search ( $self->searches->keys ) {
169                 push @subselects, '('.$self->searches->_accessor($search)->toSQL.') '.$search;
170         }
171         $SQL .= join(', ', @subselects).' WHERE ';
172
173         my @relators;
174         for my $rel ( $self->relators->list ) {
175                 push @relators, $rel->value->toSQL( no_quote => 1 );
176         }
177         $SQL .= join(' AND ', @relators).' ';
178         $SQL .= join ' ', ($self->SQL_group_by, $self->SQL_order_by, $self->SQL_limit, $self->SQL_offset);
179
180         return $SQL;
181 }
182
183 #this is just to allow DomainObject to "upcast" nicely
184 package OpenILS::DomainObject::oilsMultiSearch;
185 use base OpenILS::DomainObjectCollection::oilsMultiSearch;
186 1;