]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm
new magic fieldmapper and updated SQL stuff
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / CDBI.pm
1 package OpenILS::Application::Storage::CDBI;
2 use vars qw/@ISA/;
3 use Class::DBI;
4 use base qw/Class::DBI/;
5
6 use OpenILS::Utils::Fieldmapper;
7
8 our $VERSION = 1;
9
10
11 use OpenILS::Application::Storage::CDBI::config;
12 use OpenILS::Application::Storage::CDBI::actor;
13 use OpenILS::Application::Storage::CDBI::asset;
14 use OpenILS::Application::Storage::CDBI::biblio;
15 use OpenILS::Application::Storage::CDBI::metabib;
16
17 sub child_init {
18         my $self = shift;
19
20         __PACKAGE__->set_sql( 'OILSFastSearch', <<"     SQL", 'Main');
21                 SELECT  %s
22                   FROM  %s
23                   WHERE %s = ?
24         SQL
25
26         __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<"      SQL", 'Main');
27                 SELECT  %s
28                   FROM  %s
29                   WHERE %s = ?
30                   ORDER BY %s
31         SQL
32
33         $self->SUPER::child_init(@_);
34
35 }
36
37 sub fast_flesh_sth {
38         my $class = shift;
39         $class = ref($class) || $class;
40
41         my $field = shift;
42         my $value = shift;
43         my $order = shift;
44
45         if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
46                 if (defined($value) and ref($order) and ref($order) eq 'HASH') {
47                         $order = $value;
48                         $value = $field;
49                         $field = $class->primary_column;
50                 } else {
51                         $order = { order_by => 'id' }
52                 }
53         }
54
55         unless (defined $value) {
56                 $value = $field;
57                 $field = $class->primary_column;
58         }
59
60         my $fm_class = 'Fieldmapper::'.$class;
61         my $field_list = join ',', $class->columns('All');
62         
63         my $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
64         $sth->execute($value);
65         return $sth;
66 }
67
68 sub fast_flesh {
69         my $self = shift;
70         return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
71 }
72
73 sub fast_fieldmapper {
74         my $self = shift;
75         my $class = ref($self) || $self;
76         my $fm_class = 'Fieldmapper::'.$class;
77         my @fms;
78         for my $hash ($self->fast_flesh_sth(@_)->fetchall_hash) {
79                 my $fm = $fm_class->new;
80                 for my $field ( keys %$hash ) {
81                         $fm->$field( $$hash{$field} );
82                 }
83                 push @fms, $fm;
84         }
85         return @fms;
86 }
87
88 sub retrieve {
89         my $self = shift;
90         my $arg = shift;
91         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
92                 $arg = $arg->id;
93         }
94         return $self->SUPER::retrieve("$arg");
95 }
96
97 sub to_fieldmapper {
98         my $obj = shift;
99         my $class = ref($obj) || $obj;
100
101         my $fm_class = 'Fieldmapper::'.$class;
102         my $fm = $fm_class->new;
103
104         if (ref($obj)) {
105                 for my $field ( $fm->real_fields ) {
106                         $fm->$field( $obj->$field );
107                 }
108         }
109
110         return $fm;
111 }
112
113 sub create {
114         my $self = shift;
115         my $arg = shift;
116
117         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
118                 return $self->create_from_fieldmapper($arg,@_);
119         }
120
121         return $self->SUPER::create($arg,@_);
122 }
123
124 sub create_from_fieldmapper {
125         my $obj = shift;
126         my $fm = shift;
127         my @params = @_;
128
129         my $class = ref($obj) || $obj;
130
131         if (ref $fm) {
132                 my %hash = map { defined $fm->$_ ?
133                                         ($_ => $fm->$_) :
134                                         ()
135                                 } $fm->real_fields;
136
137                 if ($class->find_column( 'last_xact_id' )) {
138                         my $xact_id = $class->current_xact_id;
139                         throw Error unless ($xact_id);
140                         $hash{last_xact_id} = $xact_id;
141                 }
142
143                 return $class->create( \%hash, @params );
144         } else {
145                 return undef;
146         }
147 }
148
149 sub update {
150         my $self = shift;
151         my $arg = shift;
152
153         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
154                 $self = $self->modify_from_fieldmapper($arg);
155         }
156
157         $self->SUPER::update;
158         return $self;
159 }
160
161 sub delete {
162         my $self = shift;
163         my $arg = shift;
164
165         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
166                 $self = $self->retrieve($arg);
167         }
168
169         if ($class->find_column( 'last_xact_id' )) {
170                 my $xact_id = $self->current_xact_id;
171                 throw Error unless ($xact_id);
172                 $self->last_xact_id( $self->current_xact_id );
173                 $self->update;
174         }
175
176         $self->SUPER::delete;
177         return $arg;
178 }
179
180 sub modify_from_fieldmapper {
181         my $obj = shift;
182         my $fm = shift;
183
184         my $class = ref($obj) || $obj;
185
186         if (!ref($obj)) {
187                 $obj = $class->retieve($fm);
188                 return undef unless ($obj);
189         }
190
191         my %hash = map { defined $fm->$_ ?
192                                 ($_ => $fm->$_) :
193                                 ()
194                         } $fm->real_fields;
195
196         if ($class->find_column( 'last_xact_id' )) {
197                 my $xact_id = $obj->current_xact_id;
198                 throw Error unless ($xact_id);
199                 $hash{last_xact_id} = $xact_id;
200         }
201
202         my $au = $obj->autoupdate;
203         $obj->autoupdate(0);
204         
205         for my $field ( keys %hash ) {
206                 $obj->$field( $hash{$field} );
207         }
208
209         $obj->autoupdate($au);
210
211         return $obj;
212 }
213
214
215
216
217 #-------------------------------------------------------------------------------
218 actor::user->has_a( home_ou => 'actor::org_unit' );
219 #actor::org_unit->has_a( address => 'actor::address' );
220 #-------------------------------------------------------------------------------
221 actor::org_unit->has_many( users => 'actor::user' );
222 actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
223 actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
224 #actor::org_unit->has_a( address => 'actor::address' );
225 #-------------------------------------------------------------------------------
226
227 #-------------------------------------------------------------------------------
228 asset::copy->has_a( call_number => 'asset::call_number' );
229 #asset::copy->might_have( metadata => 'asset::copy_metadata' );
230 #-------------------------------------------------------------------------------
231 #asset::copy_metadata->might_have( copy => 'asset::copy' );
232 asset::copy_metadata->has_a( circulating_location => 'actor::org_unit');
233 asset::copy_metadata->has_a( hold_radius => 'actor::org_unit_type');
234 #-------------------------------------------------------------------------------
235 asset::call_number->has_a( record => 'biblio::record_entry' );
236 asset::call_number->has_many( copies => 'asset::copy' );
237 #-------------------------------------------------------------------------------
238
239
240 #-------------------------------------------------------------------------------
241 biblio::record_note->has_a( record => 'biblio::record_entry' );
242 #-------------------------------------------------------------------------------
243 biblio::record_entry->has_a( creator => 'actor::user' );
244 biblio::record_entry->has_a( editor => 'actor::user' );
245 biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
246 biblio::record_entry->has_many( notes => 'biblio::record_note' );
247 biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
248 biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
249
250 # should we have just one field entry per class for each record???? (xslt vs xpath)
251 #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
252 #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
253 #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
254 #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
255 #-------------------------------------------------------------------------------
256 biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
257 #biblio::record_node->has_a(
258 #       parent_node     => 'biblio::record_node::subnode',
259 #       inflate         => sub { return biblio::record_node::subnode::_load(@_) }
260 #);
261 #-------------------------------------------------------------------------------
262
263 #-------------------------------------------------------------------------------
264 metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
265 metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
266 #-------------------------------------------------------------------------------
267 metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
268 #metabib::title_field_entry->has_a( field => 'config::metabib_field_map' );
269 #-------------------------------------------------------------------------------
270 metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
271 #metabib::author_field_entry->has_a( field => 'config::metabib_field_map' );
272 #-------------------------------------------------------------------------------
273 metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
274 #metabib::subject_field_entry->has_a( field => 'config::metabib_field_map' );
275 #-------------------------------------------------------------------------------
276 metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
277 #metabib::keyword_field_entry->has_a( field => 'config::metabib_field_map' );
278 #-------------------------------------------------------------------------------
279 metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
280 metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
281 #-------------------------------------------------------------------------------
282
283
284 # should we have just one field entry per class for each record???? (xslt vs xpath)
285 metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
286 metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
287 #-------------------------------------------------------------------------------
288 metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
289 metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
290 #-------------------------------------------------------------------------------
291 metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
292 metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
293 #-------------------------------------------------------------------------------
294 metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
295 metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
296 #-------------------------------------------------------------------------------
297
298
299 1;