1 package OpenILS::Application::Storage::CDBI;
2 use base qw/Class::DBI/;
9 use OpenILS::Application::Storage::CDBI::config;
10 use OpenILS::Application::Storage::CDBI::actor;
11 use OpenILS::Application::Storage::CDBI::asset;
12 use OpenILS::Application::Storage::CDBI::biblio;
13 use OpenILS::Application::Storage::CDBI::metabib;
15 use OpenILS::Utils::Fieldmapper;
16 use OpenSRF::Utils::Logger;
18 my $log = 'OpenSRF::Utils::Logger';
23 __PACKAGE__->set_sql( 'OILSFastSearch', <<" SQL", 'Main');
29 __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<" SQL", 'Main');
36 $self->SUPER::child_init(@_);
42 $class = ref($class) || $class;
48 if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
49 if (defined($value) and ref($order) and ref($order) eq 'HASH') {
52 $field = $class->primary_column;
54 $order = { order_by => 'id' }
58 unless (defined $value) {
60 $field = $class->primary_column;
63 my $fm_class = 'Fieldmapper::'.$class;
64 my $field_list = join ',', $class->columns('All');
66 my $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
67 $sth->execute($value);
73 return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
76 sub fast_fieldmapper {
78 my $class = ref($self) || $self;
79 my $fm_class = 'Fieldmapper::'.$class;
81 for my $hash ($self->fast_flesh_sth(@_)->fetchall_hash) {
82 my $fm = $fm_class->new;
83 for my $field ( keys %$hash ) {
84 $fm->$field( $$hash{$field} );
94 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
97 $log->debug("Retrieving $self with $arg", INTERNAL);
98 my $rec = $self->SUPER::retrieve("$arg");
100 $log->debug("Could not retrieve $self with $arg!", DEBUG);
108 my $class = ref($obj) || $obj;
110 my $fm_class = 'Fieldmapper::'.$class;
111 my $fm = $fm_class->new;
114 for my $field ( $fm->real_fields ) {
115 $fm->$field( $obj->$field );
126 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
127 return $self->create_from_fieldmapper($arg,@_);
130 return $self->SUPER::create($arg,@_);
133 sub create_from_fieldmapper {
138 my $class = ref($obj) || $obj;
141 my %hash = map { defined $fm->$_ ?
146 if ($class->find_column( 'last_xact_id' )) {
147 my $xact_id = $class->current_xact_id;
148 throw Error unless ($xact_id);
149 $hash{last_xact_id} = $xact_id;
152 return $class->create( \%hash, @params );
162 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
163 $self = $self->retrieve($arg);
166 if ($class->find_column( 'last_xact_id' )) {
167 my $xact_id = $self->current_xact_id;
168 throw Error unless ($xact_id);
169 $self->last_xact_id( $self->current_xact_id );
173 $self->SUPER::delete;
181 $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
183 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
184 $self = $self->modify_from_fieldmapper($arg);
185 $log->debug("Modification of $self seems to have failed....", DEBUG);
186 return undef unless (defined $self);
189 $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
190 return $self->SUPER::update;
193 sub modify_from_fieldmapper {
197 $log->debug("Modifying object using fieldmapper", DEBUG);
199 my $class = ref($obj) || $obj;
202 $obj = $class->retrieve($fm);
204 $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
205 throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
210 my %hash = map { defined $fm->$_ ?
215 my $au = $obj->autoupdate;
218 for my $field ( keys %hash ) {
219 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
220 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
223 if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
224 my $xact_id = $obj->current_xact_id;
225 throw Error unless ($xact_id);
226 $hash{last_xact_id} = $xact_id;
228 $obj->autoupdate($au)
237 #-------------------------------------------------------------------------------
238 actor::user->has_a( home_ou => 'actor::org_unit' );
239 #actor::org_unit->has_a( address => 'actor::address' );
240 #-------------------------------------------------------------------------------
241 actor::org_unit->has_many( users => 'actor::user' );
242 actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
243 actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
244 #actor::org_unit->has_a( address => 'actor::address' );
245 #-------------------------------------------------------------------------------
247 #-------------------------------------------------------------------------------
248 asset::copy->has_a( call_number => 'asset::call_number' );
249 #asset::copy->might_have( metadata => 'asset::copy_metadata' );
250 #-------------------------------------------------------------------------------
251 #asset::copy_metadata->might_have( copy => 'asset::copy' );
252 asset::copy_metadata->has_a( circulating_location => 'actor::org_unit');
253 asset::copy_metadata->has_a( hold_radius => 'actor::org_unit_type');
254 #-------------------------------------------------------------------------------
255 asset::call_number->has_a( record => 'biblio::record_entry' );
256 asset::call_number->has_many( copies => 'asset::copy' );
257 #-------------------------------------------------------------------------------
260 #-------------------------------------------------------------------------------
261 biblio::record_note->has_a( record => 'biblio::record_entry' );
262 #-------------------------------------------------------------------------------
263 biblio::record_entry->has_a( creator => 'actor::user' );
264 biblio::record_entry->has_a( editor => 'actor::user' );
265 biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
266 biblio::record_entry->has_many( notes => 'biblio::record_note' );
267 biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
268 biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
270 # should we have just one field entry per class for each record???? (xslt vs xpath)
271 #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
272 #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
273 #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
274 #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
275 #-------------------------------------------------------------------------------
276 biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
277 #biblio::record_node->has_a(
278 # parent_node => 'biblio::record_node::subnode',
279 # inflate => sub { return biblio::record_node::subnode::_load(@_) }
281 #-------------------------------------------------------------------------------
283 #-------------------------------------------------------------------------------
284 metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
285 metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
286 #-------------------------------------------------------------------------------
287 metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
288 metabib::title_field_entry->has_a( field => 'config::metabib_field' );
289 #-------------------------------------------------------------------------------
290 metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
291 metabib::author_field_entry->has_a( field => 'config::metabib_field' );
292 #-------------------------------------------------------------------------------
293 metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
294 metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
295 #-------------------------------------------------------------------------------
296 metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
297 metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
298 #-------------------------------------------------------------------------------
299 metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
300 metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
301 #-------------------------------------------------------------------------------
304 # should we have just one field entry per class for each record???? (xslt vs xpath)
305 metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
306 metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
307 #-------------------------------------------------------------------------------
308 metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
309 metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
310 #-------------------------------------------------------------------------------
311 metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
312 metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
313 #-------------------------------------------------------------------------------
314 metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
315 metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
316 #-------------------------------------------------------------------------------