1 package OpenILS::Application::Storage::CDBI;
2 use base qw/Class::DBI/;
4 use Class::DBI::AbstractSearch;
6 use OpenILS::Application::Storage::CDBI::actor;
7 use OpenILS::Application::Storage::CDBI::action;
8 use OpenILS::Application::Storage::CDBI::asset;
9 use OpenILS::Application::Storage::CDBI::biblio;
10 use OpenILS::Application::Storage::CDBI::config;
11 use OpenILS::Application::Storage::CDBI::metabib;
12 use OpenILS::Application::Storage::CDBI::money;
13 use OpenILS::Application::Storage::CDBI::permission;
15 use OpenSRF::Utils::Logger;
16 use OpenSRF::EX qw/:try/;
19 my $log = 'OpenSRF::Utils::Logger';
24 $log->debug("Creating ImaDBI Querys", DEBUG);
25 __PACKAGE__->set_sql( 'OILSFastSearch', <<" SQL", 'Main');
31 __PACKAGE__->set_sql( 'OILSFastOrderedSearchLike', <<" SQL", 'Main');
38 __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<" SQL", 'Main');
45 $log->debug("Calling Driver child_init", DEBUG);
46 $self->SUPER::child_init(@_);
52 $class = ref($class) || $class;
60 if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
61 if (defined($value) and ref($value) and ref($value) eq 'HASH') {
65 $order = { order_by => $class->columns('Primary') }
69 unless (defined $value) {
71 ($field) = $class->columns('Primary');
74 unless (defined $field) {
75 ($field) = $class->columns('Primary');
78 unless ($order->{order_by}) {
79 $order = { order_by => $class->columns('Primary') }
82 my $fm_class = 'Fieldmapper::'.$class;
83 my $field_list = join ',', $class->columns('All');
87 $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
89 $sth = $class->sql_OILSFastOrderedSearchLike( $field_list, $class->table, $field, $order->{order_by});
91 $sth->execute($value);
97 return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
100 sub fast_fieldmapper {
106 my $class = ref($self) || $self;
107 my $fm_class = 'Fieldmapper::'.$class;
109 $log->debug("fast_fieldmapper() ==> Retrieving $fm_class", INTERNAL);
111 for my $hash ($self->fast_flesh_sth( $col, "$id", { order_by => $col }, $like )->fetchall_hash) {
112 my $fm = $fm_class->new;
113 for my $field ( $fm_class->real_fields ) {
114 $fm->$field( $$hash{$field} );
119 my $search_type = 'search';
121 $search_type = 'search_fts'
122 } elsif ($like == 3) {
123 $search_type = 'search_regex'
126 for my $obj ($class->$search_type({ $col => $id}, $options)) {
127 push @fms, $obj->to_fieldmapper;
136 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
137 my ($col) = $self->primary_column;
138 $log->debug("Using field $col as the primary key", INTERNAL);
141 $log->debug("Retrieving $self with $arg", INTERNAL);
144 $rec = $self->SUPER::retrieve("$arg");
146 $log->debug("Could not retrieve $self with $arg! -- ".shift(), DEBUG);
154 my $class = ref($obj) || $obj;
156 my $fm_class = 'Fieldmapper::'.$class;
157 my $fm = $fm_class->new;
160 for my $field ( $fm->real_fields ) {
161 $fm->$field( $obj->$field );
173 delete $$arg{$_} for (keys %$search);
176 @objs = $self->search_where($search) unless (ref $self);
179 return $objs[0]->update($arg);
180 } elsif (@objs == 0) {
181 return $self->create({%$search,%$arg});
183 throw OpenSRF::EX::WARN ("Non-unique search key for merge. Perhaps you meant to use remote_update?");
192 delete $$arg{$_} for (keys %$search);
194 my @objs = $self->search_where($search);
196 throw OpenSRF::EX::WARN ("No objects found for remote_update. Perhaps you meant to use merge?");
198 $_->update($arg) for (@objs);
199 return scalar(@objs);
207 $log->debug("\$arg is $arg (".ref($arg).")",DEBUG);
209 if (ref($arg) && UNIVERSAL::isa($arg => 'Fieldmapper')) {
210 return $self->create_from_fieldmapper($arg,@_);
213 return $self->SUPER::create($arg,@_);
216 sub create_from_fieldmapper {
221 $log->debug("Creating node of type ".ref($fm), DEBUG);
223 my $class = ref($obj) || $obj;
224 my ($primary) = $class->columns('Primary');
226 if (ref($fm) &&UNIVERSAL::isa($fm => 'Fieldmapper')) {
227 my %hash = map { defined $fm->$_ ?
230 } grep { $_ ne $primary } $class->columns('All');
232 if ($class->find_column( 'last_xact_id' )) {
233 my $xact_id = $class->current_xact_id;
234 throw Error unless ($xact_id);
235 $hash{last_xact_id} = $xact_id;
238 return $class->create( \%hash, @params );
248 my $class = ref($self) || $self;
250 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
251 $self = $self->retrieve($arg);
252 unless (defined $self) {
253 $log->debug("ARG! Couldn't retrieve record ".$arg->id, DEBUG);
254 throw OpenSRF::EX::WARN ("ARG! Couldn't retrieve record ");
258 if ($class->find_column( 'last_xact_id' )) {
259 my $xact_id = $self->current_xact_id;
260 throw Error unless ($xact_id);
261 $self->last_xact_id( $class->current_xact_id );
262 $self->SUPER::update;
265 $self->SUPER::delete;
273 $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
276 $self = $self->modify_from_fieldmapper($arg);
277 $log->debug("Modification of $self seems to have failed....", DEBUG);
278 return undef unless (defined $self);
281 $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
282 return $self->SUPER::update if ($self->is_changed);
286 sub modify_from_fieldmapper {
290 $log->debug("Modifying object using fieldmapper", DEBUG);
292 my $class = ref($obj) || $obj;
293 my ($primary) = $class->columns('Primary');
296 $obj = $class->retrieve($fm);
298 $log->debug("Retrieve of $class using $fm (".$fm->id.") failed! -- ".shift(), ERROR);
299 throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
305 if (ref($fm) and UNIVERSAL::isa($fm => 'Fieldmapper')) {
306 %hash = map { defined $fm->$_ ?
309 } grep { $_ ne $primary } $class->columns('All');
314 my $au = $obj->autoupdate;
317 for my $field ( keys %hash ) {
318 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
319 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
322 if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
323 my $xact_id = $obj->current_xact_id;
324 throw Error unless ($xact_id);
325 $obj->last_xact_id( $xact_id );
327 $obj->autoupdate($au)
335 #-------------------------------------------------------------------------------
336 actor::user->has_a( home_ou => 'actor::org_unit' );
337 actor::user->has_a( card => 'actor::card' );
338 actor::user->has_a( standing => 'config::standing' );
339 actor::user->has_a( profile => 'actor::profile' );
340 actor::user->has_a( mailing_address => 'actor::user_address' );
341 actor::user->has_a( billing_address => 'actor::user_address' );
342 actor::user->has_a( ident_type => 'config::identification_type' );
343 actor::user->has_a( ident_type2 => 'config::identification_type' );
344 actor::user->has_a( net_access_level => 'config::net_access_level' );
346 actor::user_address->has_a( usr => 'actor::user' );
348 actor::card->has_a( usr => 'actor::user' );
350 actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
351 actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
352 #actor::org_unit->has_a( address => 'actor::org_address' );
354 actor::stat_cat_entry->has_a( stat_cat => 'actor::stat_cat' );
355 actor::stat_cat->has_many( entries => 'actor::stat_cat_entry' );
356 actor::stat_cat_entry_user_map->has_a( stat_cat => 'actor::stat_cat' );
357 actor::stat_cat_entry_user_map->has_a( stat_cat_entry => 'actor::stat_cat_entry' );
358 actor::stat_cat_entry_user_map->has_a( target_usr => 'actor::user' );
360 asset::stat_cat_entry->has_a( stat_cat => 'asset::stat_cat' );
361 asset::stat_cat->has_many( entries => 'asset::stat_cat_entry' );
362 asset::stat_cat_entry_copy_map->has_a( stat_cat => 'asset::stat_cat' );
363 asset::stat_cat_entry_copy_map->has_a( stat_cat_entry => 'asset::stat_cat_entry' );
364 asset::stat_cat_entry_copy_map->has_a( owning_copy => 'asset::copy' );
366 action::survey_response->has_a( usr => 'actor::user' );
367 action::survey_response->has_a( survey => 'action::survey' );
368 action::survey_response->has_a( question => 'action::survey_question' );
369 action::survey_response->has_a( answer => 'action::survey_answer' );
371 action::survey_question->has_a( survey => 'action::survey' );
373 action::survey_answer->has_a( question => 'action::survey' );
375 asset::copy_note->has_a( owning_copy => 'asset::copy' );
377 actor::user->has_many( stat_cat_entries => [ 'actor::stat_cat_entry_user_map' => 'stat_cat_entry' ] );
378 actor::user->has_many( stat_cat_entry_user_maps => 'actor::stat_cat_entry_user_map' );
380 asset::copy->has_many( stat_cat_entries => [ 'asset::stat_cat_entry_copy_map' => 'stat_cat_entry' ] );
381 asset::copy->has_many( stat_cat_entry_copy_maps => 'asset::stat_cat_entry_copy_map' );
383 asset::copy->has_a( call_number => 'asset::call_number' );
384 asset::copy->has_a( creator => 'actor::user' );
385 asset::copy->has_a( editor => 'actor::user' );
386 asset::copy->has_a( status => 'config::copy_status' );
387 asset::copy->has_a( location => 'asset::copy_location' );
388 asset::copy->has_a( circ_lib => 'actor::org_unit' );
390 asset::call_number_note->has_a( call_number => 'asset::call_number' );
392 asset::call_number->has_a( record => 'biblio::record_entry' );
393 asset::call_number->has_a( creator => 'actor::user' );
394 asset::call_number->has_a( editor => 'actor::user' );
396 biblio::record_note->has_a( record => 'biblio::record_entry' );
398 biblio::record_entry->has_a( creator => 'actor::user' );
399 biblio::record_entry->has_a( editor => 'actor::user' );
401 metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
403 metabib::record_descriptor->has_a( record => 'biblio::record_entry' );
405 metabib::full_rec->has_a( record => 'biblio::record_entry' );
407 metabib::title_field_entry->has_a( source => 'biblio::record_entry' );
408 metabib::title_field_entry->has_a( field => 'config::metabib_field' );
410 metabib::author_field_entry->has_a( source => 'biblio::record_entry' );
411 metabib::author_field_entry->has_a( field => 'config::metabib_field' );
413 metabib::subject_field_entry->has_a( source => 'biblio::record_entry' );
414 metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
416 metabib::keyword_field_entry->has_a( source => 'biblio::record_entry' );
417 metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
419 metabib::series_field_entry->has_a( source => 'biblio::record_entry' );
420 metabib::series_field_entry->has_a( field => 'config::metabib_field' );
422 metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
423 metabib::metarecord_source_map->has_a( source => 'biblio::record_entry' );
425 action::circulation->has_a( usr => 'actor::user' );
426 action::circulation->has_a( target_copy => 'asset::copy' );
427 action::circulation->has_a( circ_lib => 'actor::org_unit' );
429 money::billable_transaction->has_a( usr => 'actor::user' );
432 #-------------------------------------------------------------------------------
433 actor::user->has_many( survey_responses => 'action::survey_response' );
434 actor::user->has_many( addresses => 'actor::user_address' );
435 actor::user->has_many( cards => 'actor::card' );
437 actor::org_unit->has_many( users => 'actor::user' );
438 actor::profile->has_many( users => 'actor::user' );
440 action::survey->has_many( questions => 'action::survey_question' );
441 action::survey->has_many( responses => 'action::survey_response' );
443 action::survey_question->has_many( answers => 'action::survey_answer' );
444 action::survey_question->has_many( responses => 'action::survey_response' );
446 action::survey_answer->has_many( responses => 'action::survey_response' );
448 asset::copy->has_many( notes => 'asset::copy_note' );
449 asset::call_number->has_many( copies => 'asset::copy' );
450 asset::call_number->has_many( notes => 'asset::call_number_note' );
452 biblio::record_entry->has_many( record_descriptor => 'metabib::record_descriptor' );
453 biblio::record_entry->has_many( notes => 'biblio::record_note' );
454 biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
455 biblio::record_entry->has_many( full_record_entries => 'metabib::full_rec' );
456 biblio::record_entry->has_many( title_field_entries => 'metabib::title_field_entry' );
457 biblio::record_entry->has_many( author_field_entries => 'metabib::author_field_entry' );
458 biblio::record_entry->has_many( subject_field_entries => 'metabib::subject_field_entry' );
459 biblio::record_entry->has_many( keyword_field_entries => 'metabib::keyword_field_entry' );
460 biblio::record_entry->has_many( series_field_entries => 'metabib::series_field_entry' );
462 metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source'] );
464 money::billable_transaction->has_many( billings => 'money::billing' );
465 money::billable_transaction->has_many( payments => 'money::payment' );
467 money::billing->has_a( xact => 'money::billable_transaction' );
468 money::payment->has_a( xact => 'money::billable_transaction' );
470 money::cash_payment->has_a( xact => 'money::billable_transaction' );
471 money::cash_payment->has_a( accepting_usr => 'actor::user' );
473 money::check_payment->has_a( xact => 'money::billable_transaction' );
474 money::check_payment->has_a( accepting_usr => 'actor::user' );
476 money::credit_card_payment->has_a( xact => 'money::billable_transaction' );
477 money::credit_card_payment->has_a( accepting_usr => 'actor::user' );
479 money::forgive_payment->has_a( xact => 'money::billable_transaction' );
480 money::forgive_payment->has_a( accepting_usr => 'actor::user' );
482 money::work_payment->has_a( xact => 'money::billable_transaction' );
483 money::work_payment->has_a( accepting_usr => 'actor::user' );
485 money::credit_payment->has_a( xact => 'money::billable_transaction' );
486 money::credit_payment->has_a( accepting_usr => 'actor::user' );
488 permission::grp_tree->has_a( parent => 'permission::grp_tree' );
490 permission::grp_perm_map->has_a( grp => 'permission::grp_tree' );
491 permission::grp_perm_map->has_a( perm => 'permission::perm_list' );
492 permission::grp_perm_map->has_a( depth => 'actor::org_unit_type' );
494 permission::usr_perm_map->has_a( usr => 'actor::user' );
495 permission::usr_perm_map->has_a( perm => 'permission::perm_list' );
496 permission::usr_perm_map->has_a( depth => 'actor::org_unit_type' );
498 permission::usr_grp_map->has_a( usr => 'actor::user' );
499 permission::usr_grp_map->has_a( grp => 'permission::grp_tree' );
501 action::hold_notification->has_a( hold => 'action::hold_request' );
503 action::hold_copy_map->has_a( hold => 'action::hold_request' );
504 action::hold_copy_map->has_a( target_copy => 'asset::copy' );
506 action::hold_request->has_a( current_copy => 'asset::copy' );
507 action::hold_request->has_a( requestor => 'actor::user' );
508 action::hold_request->has_a( usr => 'actor::user' );
509 action::hold_request->has_a( pickup_lib => 'actor::org_unit' );
511 action::hold_request->has_many( notifications => 'action::hold_notification' );
512 action::hold_request->has_many( copy_maps => 'action::hold_copy_map' );
514 asset::copy->has_many( hold_maps => 'action::hold_copy_map' );