]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg.pm
beginings of the new transaction infrastructure
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Driver / Pg.pm
1 { # Based on the change to Class::DBI in OpenILS::Application::Storage.  This will
2   # allow us to use TSearch2 via a simple cdbi "search" interface.
3         #-------------------------------------------------------------------------------
4         use Class::DBI;
5         package Class::DBI;
6
7         sub search_fti {
8                 my $self = shift;
9                 my @args = @_;
10                 if (ref($args[-1]) eq 'HASH') {
11                         $args[-1]->{_placeholder} = "to_tsquery('default',?)";
12                 } else {
13                         push @args, {_placeholder => "to_tsquery('default',?)"};
14                 }
15                 $self->_do_search("@@"  => @args);
16         }
17 }
18
19 { # Every driver needs to provide a 'compile()' method to OpenILS::Application::Storage::FTS.
20   # If that driver wants to support FTI, that is...
21         #-------------------------------------------------------------------------------
22         package OpenILS::Application::Storage::FTS;
23         use OpenSRF::Utils::Logger qw/:level/;
24         my $log = 'OpenSRF::Utils::Logger';
25
26         sub compile {
27                 my $self = shift;
28                 my $term = shift;
29
30                 $self = ref($self) || $self;
31                 $self = bless {} => $self;
32
33                 $self->decompose($term);
34
35                 my $newterm = join('&', $self->words);
36
37                 if ($self->nots) {
38                         $newterm = '('.$newterm.')&('. join('|', $self->nots) . ')';
39                 }
40
41                 $newterm = OpenILS::Application::Storage->driver->quote($newterm);
42
43                 $self->{fts_query} = ["to_tsquery('default',$newterm)"];
44                 $self->{fts_query_nots} = [];
45                 $self->{fts_op} = '@@';
46
47                 return $self;
48         }
49 }
50
51
52 { # The driver package itself just needs a db_Main method for Class::DBI to call.
53   # any other fixups can go in here too... Also, the drivers should subclass the
54   # DBI driver that they are wrapping, or provide a 'quote()' method that calls
55   # the DBD::xxx::quote() method on FTI's behalf.
56   #
57   # The dirver MUST be a subclass of Class::DBI and OpenILS::Application::Storage.
58         #-------------------------------------------------------------------------------
59         package OpenILS::Application::Storage::Driver::Pg;
60         use Class::DBI::Replication;
61         use base qw/Class::DBI::Replication OpenILS::Application::Storage/;
62         use DBI;
63         use OpenSRF::EX qw/:try/;
64         use OpenSRF::Utils::Logger qw/:level/;
65         my $log = 'OpenSRF::Utils::Logger';
66
67         __PACKAGE__->set_sql( retrieve_limited => 'SELECT * FROM __TABLE__ ORDER BY id LIMIT ?' );
68
69         my $_db_params;
70         sub child_init {
71                 my $self = shift;
72                 $_db_params = shift;
73
74                 $_db_params = [ $_db_params ] unless (ref($_db_params) eq 'ARRAY');
75
76                 my %attrs = (   %{$self->_default_attributes},
77                                 RootClass => 'DBIx::ContextualFetch',
78                                 ShowErrorStatement => 1,
79                                 RaiseError => 1,
80                                 AutoCommit => 1,
81                                 PrintError => 1,
82                                 Taint => 1,
83                                 pg_enable_utf8 => 1,
84                                 FetchHashKeyName => 'NAME_lc',
85                                 ChopBlanks => 1,
86                 );
87
88                 my ($master,@slaves);
89                 for my $db (@$_db_params) {
90                         if ($db->{type} eq 'master') {
91                                 __PACKAGE__->set_master("dbi:Pg:host=$$db{host};dbname=$$db{db}",$$db{user},$$db{pw}, \%attrs);
92                         }
93                         push @slaves, ["dbi:Pg:host=$$db{host};dbname=$$db{db}",$$db{user},$$db{pw}, \%attrs];
94                 }
95
96                 __PACKAGE__->set_slaves(@slaves);
97
98                 $log->debug("Running child_init inside ".__PACKAGE__, INTERNAL);
99         }
100
101         sub quote {
102                 return __PACKAGE->db_Main->quote(@_)
103         }
104
105         sub tsearch2_trigger {
106                 my $self = shift;
107                 return unless ($self->value);
108                 $self->index_vector(
109                         $self->db_Main->selectrow_array(
110                                 "SELECT to_tsvector('default',?);",
111                                 {},
112                                 $self->value
113                         )
114                 );
115         }
116
117         my $_xact_session;
118         sub db_Slaves { 
119                 my $self = shift;
120
121                 if ($_xact_session && OpenSRF::AppSession->find($_xact_session)) {
122                         return $self->db_Main;
123                 }
124
125                 return $self->SUPER::db_Slaves
126         }
127
128         sub pg_begin_xaction {
129                 my $self = shift;
130                 my $client = shift;
131
132                 $_xact_session = $client->session->session_id;
133
134                 $client->session->register_callback( disconnect => sub { __PACKAGE__->commit_xaction($client); } )
135                         if ($self->api_name =~ /autocommit$/o);
136
137                 $client->session->register_callback( death => sub { __PACKAGE__->rollback_xaction($client); } );
138
139                 return $self->begin_xaction;
140         }
141         __PACKAGE__->register_method(
142                 method          => 'pg_begin_xaction',
143                 api_name        => 'open-ils.storage.transaction.begin',
144                 api_level       => 1,
145                 argc            => 0,
146         );
147         __PACKAGE__->register_method(
148                 method          => 'pg_begin_xaction',
149                 api_name        => 'open-ils.storage.transaction.begin.autocommit',
150                 api_level       => 1,
151                 argc            => 0,
152         );
153
154         sub pg_commit_xaction {
155
156                 $_xact_session = undef;
157                 return $self->commit_xaction(@_);
158         }
159         __PACKAGE__->register_method(
160                 method          => 'pg_commit_xaction',
161                 api_name        => 'open-ils.storage.transaction.commit',
162                 api_level       => 1,
163                 argc            => 0,
164         );
165
166         sub pg_rollback_xaction {
167
168                 $_xact_session = undef;
169                 return $self->rollback_xaction(@_);
170         }
171         __PACKAGE__->register_method(
172                 method          => 'pg_rollback_xaction',
173                 api_name        => 'open-ils.storage.transaction.rollback',
174                 api_level       => 1,
175                 argc            => 0,
176         );
177
178 }
179
180 {
181         #---------------------------------------------------------------------
182         package asset::call_number;
183         
184         asset::call_number->table( 'asset.call_number' );
185         asset::call_number->sequence( 'asset.call_number_id_seq' );
186         
187         #---------------------------------------------------------------------
188         package asset::copy;
189         
190         asset::copy->table( 'asset.copy' );
191         asset::copy->sequence( 'asset.copy_id_seq' );
192         
193         #---------------------------------------------------------------------
194         package biblio::record_entry;
195         
196         biblio::record_entry->table( 'biblio.record_entry' );
197         biblio::record_entry->sequence( 'biblio.record_entry_id_seq' );
198
199         #---------------------------------------------------------------------
200         package biblio::record_node;
201         
202         biblio::record_node->table( 'biblio.record_data' );
203         biblio::record_node->sequence( 'biblio.record_data_id_seq' );
204         
205         #---------------------------------------------------------------------
206         package biblio::record_note;
207         
208         biblio::record_note->table( 'biblio.record_note' );
209         biblio::record_note->sequence( 'biblio.record_note_id_seq' );
210         
211         #---------------------------------------------------------------------
212         package actor::user;
213         
214         actor::user->table( 'actor.usr' );
215         actor::user->sequence( 'actor.usr_id_seq' );
216         
217         #---------------------------------------------------------------------
218         package actor::org_unit_type;
219         
220         actor::org_unit_type->table( 'actor.org_unit_type' );
221         actor::org_unit_type->sequence( 'actor.org_unit_type_id_seq' );
222         
223         #---------------------------------------------------------------------
224         
225         #-------------------------------------------------------------------------------
226         package metabib::metarecord;
227
228         metabib::metarecord->table( 'metabib.metarecord' );
229         metabib::metarecord->sequence( 'metabib.metarecord_id_seq' );
230
231         #-------------------------------------------------------------------------------
232
233         #-------------------------------------------------------------------------------
234         package metabib::title_field_entry;
235
236         metabib::title_field_entry->table( 'metabib.title_field_entry' );
237         metabib::title_field_entry->sequence( 'metabib.title_field_entry_id_seq' );
238         metabib::title_field_entry->columns( Primary => qw/id/ );
239         metabib::title_field_entry->columns( Essential => qw/id/ );
240         metabib::title_field_entry->columns( Others => qw/field index_vector/ );
241         metabib::title_field_entry->columns( TEMP => qw/value/ );
242
243         metabib::title_field_entry->add_trigger(
244                 before_create => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
245         );
246         metabib::title_field_entry->add_trigger(
247                 before_update => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
248         );
249
250         #-------------------------------------------------------------------------------
251
252         #-------------------------------------------------------------------------------
253         package metabib::author_field_entry;
254
255         metabib::author_field_entry->table( 'metabib.author_field_entry' );
256         metabib::author_field_entry->sequence( 'metabib.author_field_entry_id_seq' );
257         metabib::author_field_entry->columns( Primary => qw/id/ );
258         metabib::author_field_entry->columns( Essential => qw/id/ );
259         metabib::author_field_entry->columns( Others => qw/field index_vector/ );
260         metabib::author_field_entry->columns( TEMP => qw/value/ );
261
262         metabib::author_field_entry->add_trigger(
263                 before_create => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
264         );
265         metabib::author_field_entry->add_trigger(
266                 before_update => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
267         );
268
269         #-------------------------------------------------------------------------------
270
271         #-------------------------------------------------------------------------------
272         package metabib::subject_field_entry;
273
274         metabib::subject_field_entry->table( 'metabib.subject_field_entry' );
275         metabib::subject_field_entry->sequence( 'metabib.subject_field_entry_id_seq' );
276         metabib::subject_field_entry->columns( Primary => qw/id/ );
277         metabib::subject_field_entry->columns( Essential => qw/id/ );
278         metabib::subject_field_entry->columns( Others => qw/field index_vector/ );
279         metabib::subject_field_entry->columns( TEMP => qw/value/ );
280
281         metabib::subject_field_entry->add_trigger(
282                 before_create => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
283         );
284         metabib::subject_field_entry->add_trigger(
285                 before_update => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
286         );
287
288         #-------------------------------------------------------------------------------
289
290         #-------------------------------------------------------------------------------
291         package metabib::keyword_field_entry;
292
293         metabib::keyword_field_entry->table( 'metabib.keyword_field_entry' );
294         metabib::keyword_field_entry->sequence( 'metabib.keyword_field_entry_id_seq' );
295         metabib::keyword_field_entry->columns( Primary => qw/id/ );
296         metabib::keyword_field_entry->columns( Essential => qw/id/ );
297         metabib::keyword_field_entry->columns( Others => qw/field index_vector/ );
298         metabib::keyword_field_entry->columns( TEMP => qw/value/ );
299
300         metabib::keyword_field_entry->add_trigger(
301                 before_create => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
302         );
303         metabib::keyword_field_entry->add_trigger(
304                 before_update => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger
305         );
306
307         #-------------------------------------------------------------------------------
308
309         #-------------------------------------------------------------------------------
310         package metabib::title_field_entry_source_map;
311
312         metabib::title_field_entry_source_map->table( 'metabib.title_field_entry_source_map' );
313         metabib::title_field_entry_source_map->table( 'metabib.title_field_entry_source_map_id_seq' );
314
315         #-------------------------------------------------------------------------------
316
317         #-------------------------------------------------------------------------------
318         package metabib::author_field_entry_source_map;
319
320         metabib::author_field_entry_source_map->table( 'metabib.author_field_entry_source_map' );
321         metabib::author_field_entry_source_map->sequence( 'metabib.author_field_entry_source_map_id_seq' );
322
323         #-------------------------------------------------------------------------------
324
325         #-------------------------------------------------------------------------------
326         package metabib::subject_field_entry_source_map;
327
328         metabib::subject_field_entry_source_map->table( 'metabib.subject_field_entry_source_map' );
329         metabib::subject_field_entry_source_map->sequence( 'metabib.subject_field_entry_source_map_id_seq' );
330
331         #-------------------------------------------------------------------------------
332 }
333
334 1;