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