1 package OpenILS::Application::Storage::CDBI;
2 use base qw/Class::DBI/;
5 use OpenILS::Application::Storage::CDBI::config;
6 use OpenILS::Application::Storage::CDBI::actor;
7 use OpenILS::Application::Storage::CDBI::asset;
8 use OpenILS::Application::Storage::CDBI::biblio;
9 use OpenILS::Application::Storage::CDBI::metabib;
11 use OpenSRF::Utils::Logger;
14 my $log = 'OpenSRF::Utils::Logger';
19 $log->debug("Creating ImaDBI Querys", DEBUG);
20 __PACKAGE__->set_sql( 'OILSFastSearch', <<" SQL", 'Main');
26 __PACKAGE__->set_sql( 'OILSFastOrderedSearchLike', <<" SQL", 'Main');
33 __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<" SQL", 'Main');
40 $log->debug("Calling Driver child_init", DEBUG);
41 $self->SUPER::child_init(@_);
47 $class = ref($class) || $class;
55 if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
56 if (defined($value) and ref($value) and ref($value) eq 'HASH') {
60 $order = { order_by => $class->columns('Primary') }
64 unless (defined $value) {
66 $field = $class->primary_column;
69 unless (defined $field) {
70 $field = $class->primary_column;
73 unless ($order->{order_by}) {
74 $order = { order_by => $class->columns('Primary') }
77 my $fm_class = 'Fieldmapper::'.$class;
78 my $field_list = join ',', $class->columns('All');
82 $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
84 $sth = $class->sql_OILSFastOrderedSearchLike( $field_list, $class->table, $field, $order->{order_by});
86 $sth->execute($value);
92 return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
95 sub fast_fieldmapper {
100 my $class = ref($self) || $self;
101 my $fm_class = 'Fieldmapper::'.$class;
103 $log->debug("fast_fieldmapper() ==> Retrieving $fm_class", INTERNAL);
104 for my $hash ($self->fast_flesh_sth( $col, "$id", { order_by => $col }, $like )->fetchall_hash) {
105 my $fm = $fm_class->new;
106 for my $field ( $fm_class->real_fields ) {
107 $fm->$field( $$hash{$field} );
117 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
120 $log->debug("Retrieving $self with $arg", INTERNAL);
121 my $rec = $self->SUPER::retrieve("$arg");
123 $log->debug("Could not retrieve $self with $arg!", DEBUG);
131 my $class = ref($obj) || $obj;
133 my $fm_class = 'Fieldmapper::'.$class;
134 my $fm = $fm_class->new;
137 for my $field ( $fm->real_fields ) {
138 $fm->$field( $obj->$field );
149 $log->debug("\$arg is $arg (".ref($arg).")",DEBUG);
151 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
152 return $self->create_from_fieldmapper($arg,@_);
155 return $self->SUPER::create($arg,@_);
158 sub create_from_fieldmapper {
163 $log->debug("Creating node of type ".ref($fm), DEBUG);
165 my $class = ref($obj) || $obj;
168 my %hash = map { defined $fm->$_ ?
173 if ($class->find_column( 'last_xact_id' )) {
174 my $xact_id = $class->current_xact_id;
175 throw Error unless ($xact_id);
176 $hash{last_xact_id} = $xact_id;
179 return $class->create( \%hash, @params );
189 my $class = ref($self) || $self;
191 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
192 $self = $self->retrieve($arg);
193 unless (defined $self) {
194 $log->debug("ARG! Couldn't retrieve record ".$arg->id, DEBUG);
195 throw OpenSRF::EX::WARN ("ARG! Couldn't retrieve record ");
199 if ($class->find_column( 'last_xact_id' )) {
200 my $xact_id = $self->current_xact_id;
201 throw Error unless ($xact_id);
202 $self->last_xact_id( $class->current_xact_id );
203 $self->SUPER::update;
206 $self->SUPER::delete;
214 $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
216 if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
217 $self = $self->modify_from_fieldmapper($arg);
218 $log->debug("Modification of $self seems to have failed....", DEBUG);
219 return undef unless (defined $self);
222 $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
223 return $self->SUPER::update if ($self->is_changed);
227 sub modify_from_fieldmapper {
231 $log->debug("Modifying object using fieldmapper", DEBUG);
233 my $class = ref($obj) || $obj;
236 $obj = $class->retrieve($fm);
238 $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
239 throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
244 my %hash = map { defined $fm->$_ ?
249 my $au = $obj->autoupdate;
252 for my $field ( keys %hash ) {
253 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
254 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
257 if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
258 my $xact_id = $obj->current_xact_id;
259 throw Error unless ($xact_id);
260 $obj->last_xact_id( $xact_id );
262 $obj->autoupdate($au)
271 return if ($VERSION);
272 #-------------------------------------------------------------------------------
273 actor::user->has_a( home_ou => 'actor::org_unit' );
274 #actor::org_unit->has_a( address => 'actor::address' );
275 #-------------------------------------------------------------------------------
276 actor::org_unit->has_many( users => 'actor::user' );
277 actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
278 actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
279 #actor::org_unit->has_a( address => 'actor::address' );
280 #-------------------------------------------------------------------------------
282 #-------------------------------------------------------------------------------
283 asset::copy_note->has_a( owning_copy => 'asset::copy' );
284 #-------------------------------------------------------------------------------
285 asset::copy->has_a( call_number => 'asset::call_number' );
286 asset::copy->has_many( notes => 'asset::copy_note' );
287 asset::copy->has_a( creator => 'actor::user' );
288 asset::copy->has_a( editor => 'actor::user' );
289 #asset::copy->might_have( metadata => 'asset::copy_metadata' );
290 #-------------------------------------------------------------------------------
291 asset::call_number_note->has_a( owning_call_number => 'asset::call_number' );
292 #-------------------------------------------------------------------------------
293 asset::call_number->has_a( record => 'biblio::record_entry' );
294 asset::call_number->has_many( copies => 'asset::copy' );
295 asset::call_number->has_many( notes => 'asset::call_number_note' );
296 asset::call_number->has_a( creator => 'actor::user' );
297 asset::call_number->has_a( editor => 'actor::user' );
298 #-------------------------------------------------------------------------------
301 #-------------------------------------------------------------------------------
302 biblio::record_note->has_a( record => 'biblio::record_entry' );
303 #-------------------------------------------------------------------------------
304 biblio::record_mods->is_a( id => 'biblio::record_entry' );
305 #-------------------------------------------------------------------------------
306 biblio::record_marc->is_a( id => 'biblio::record_entry' );
307 #-------------------------------------------------------------------------------
308 biblio::record_entry->has_a( creator => 'actor::user' );
309 biblio::record_entry->has_a( editor => 'actor::user' );
310 biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
311 biblio::record_entry->might_have( marc_entry => 'biblio::record_marc' => qw/marc/ );
312 biblio::record_entry->has_many( notes => 'biblio::record_note' );
313 biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
314 biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
316 # should we have just one field entry per class for each record???? (xslt vs xpath)
317 #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
318 #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
319 #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
320 #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
321 #-------------------------------------------------------------------------------
322 biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
323 #biblio::record_node->has_a(
324 # parent_node => 'biblio::record_node::subnode',
325 # inflate => sub { return biblio::record_node::subnode::_load(@_) }
327 #-------------------------------------------------------------------------------
329 #-------------------------------------------------------------------------------
330 metabib::full_rec->has_a( record => 'biblio::record_entry' );
331 #-------------------------------------------------------------------------------
332 metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
333 metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
334 #-------------------------------------------------------------------------------
335 metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
336 metabib::title_field_entry->has_a( field => 'config::metabib_field' );
337 #-------------------------------------------------------------------------------
338 metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
339 metabib::author_field_entry->has_a( field => 'config::metabib_field' );
340 #-------------------------------------------------------------------------------
341 metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
342 metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
343 #-------------------------------------------------------------------------------
344 metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
345 metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
346 #-------------------------------------------------------------------------------
347 metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
348 metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
349 #-------------------------------------------------------------------------------
352 # should we have just one field entry per class for each record???? (xslt vs xpath)
353 metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
354 metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
355 metabib::title_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
356 #-------------------------------------------------------------------------------
357 metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
358 metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
359 metabib::subject_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
360 #-------------------------------------------------------------------------------
361 metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
362 metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
363 metabib::author_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
364 #-------------------------------------------------------------------------------
365 metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
366 metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
367 metabib::keyword_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
368 #-------------------------------------------------------------------------------