adding hold verification support per copy_location
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Driver / Pg.pm
1
2 { # The driver package itself just needs a db_Main method (or db_Slaves if
3   #Class::DBI::Replication is in use) for Class::DBI to call.
4   #
5   # Any other fixups can go in here too... Also, the drivers should subclass the
6   # DBI driver that they are wrapping, or provide a 'quote()' method that calls
7   # the DBD::xxx::quote() method on FTI's behalf.
8   #
9   # The dirver MUST be a subclass of Class::DBI(::Replication) and
10   # OpenILS::Application::Storage.
11   #-------------------------------------------------------------------------------
12         package OpenILS::Application::Storage::Driver::Pg;
13         use OpenILS::Application::Storage::Driver::Pg::cdbi;
14         use OpenILS::Application::Storage::Driver::Pg::fts;
15         use OpenILS::Application::Storage::Driver::Pg::storage;
16         use OpenILS::Application::Storage::Driver::Pg::dbi;
17         use Class::DBI;
18         use base qw/Class::DBI OpenILS::Application::Storage/;
19         use DBI;
20         use OpenSRF::EX qw/:try/;
21         use OpenSRF::DomainObject::oilsResponse;
22         use OpenSRF::Utils::Logger qw/:level/;
23         my $log = 'OpenSRF::Utils::Logger';
24
25         __PACKAGE__->set_sql( retrieve_limited => 'SELECT * FROM __TABLE__ ORDER BY id LIMIT ?' );
26         __PACKAGE__->set_sql( copy_start => 'COPY %s (%s) FROM STDIN;' );
27         __PACKAGE__->set_sql( copy_end => '\.' );
28
29         my $master_db;
30         my @slave_dbs;
31         my $_db_params;
32
33         sub db_Handles {
34                 return ($master_db, @slave_dbs);
35         }
36
37         sub child_init {
38                 my $self = shift;
39                 $_db_params = shift;
40
41                 $log->debug("Running child_init inside ".__PACKAGE__, INTERNAL);
42
43                 $_db_params = [ $_db_params ] unless (ref($_db_params) eq 'ARRAY');
44
45                 my %attrs = (   %{$self->_default_attributes},
46                                 RootClass => 'DBIx::ContextualFetch',
47                                 ShowErrorStatement => 1,
48                                 RaiseError => 1,
49                                 AutoCommit => 1,
50                                 PrintError => 1,
51                                 Taint => 1,
52                                 #TraceLevel => "1|SQL",
53                                 pg_enable_utf8 => 1,
54                                 pg_server_prepare => 0,
55                                 FetchHashKeyName => 'NAME_lc',
56                                 ChopBlanks => 1,
57                 );
58
59                 my $master = shift @$_db_params;
60                 $$master{port} ||= '5432';
61                 $$master{host} ||= 'localhost';
62                 $$master{db} ||= 'openils';
63
64                 $log->debug("Attempting to connect to $$master{db} at $$master{host}", INFO);
65
66                 try {
67                         $master_db = DBI->connect(
68                                 "dbi:Pg:".
69                                         "host=$$master{host};".
70                                         "port=$$master{port};".
71                                         "dbname=$$master{db}",
72                                 $$master{user},
73                                 $$master{pw},
74                                 \%attrs)
75                         || do { sleep(1);
76                                 DBI->connect(
77                                         "dbi:Pg:".
78                                                 "host=$$master{host};".
79                                                 "port=$$master{port};".
80                                                 "dbname=$$master{db}",
81                                         $$master{user},
82                                         $$master{pw},
83                                         \%attrs) }
84                         || throw OpenSRF::EX::ERROR
85                                 ("Couldn't connect to $$master{db}".
86                                  " on $$master{host}::$$master{port}".
87                                  " as $$master{user}!!");
88                 } catch Error with {
89                         my $e = shift;
90                         $log->debug("Error connecting to database:\n\t$e\n\t$DBI::errstr", ERROR);
91                         throw $e;
92                 };
93
94                 $log->debug("Connected to MASTER db $$master{db} at $$master{host}", INFO);
95                 
96                 $master_db->do("SET NAMES '$$master{client_encoding}';") if ($$master{client_encoding});
97
98                 for my $db (@$_db_params) {
99                         try {
100                                 push @slave_dbs, DBI->connect("dbi:Pg:host=$$db{host};port=$$db{port};dbname=$$db{db}",$$db{user},$$db{pw}, \%attrs)
101                                         || do { sleep(1); DBI->connect("dbi:Pg:host=$$db{host};port=$$db{port};dbname=$$db{db}",$$db{user},$$db{pw}, \%attrs) }
102                                         || throw OpenSRF::EX::ERROR
103                                                 ("Couldn't connect to $$db{db}".
104                                                 " on $$db{host}::$$db{port}".
105                                                 " as $$db{user}!!");
106                         } catch Error with {
107                                 my $e = shift;
108                                 $log->debug("Error connecting to database:\n\t$e\n\t$DBI::errstr", ERROR);
109                                 throw $e;
110                         };
111
112                         $slave_dbs[-1]->do("SET NAMES '$$db{client_encoding}';") if ($$master{client_encoding});
113
114                         $log->debug("Connected to MASTER db '$$master{db} at $$master{host}", INFO);
115                 }
116
117                 $log->debug("All is well on the western front", INTERNAL);
118         }
119
120         sub db_Main {
121                 my $self = shift;
122                 return $master_db if ($self->current_xact_session || $OpenILS::Application::Storage::WRITE);
123                 return $master_db unless (@slave_dbs);
124                 return ($master_db, @slave_dbs)[rand(scalar(@slave_dbs))];
125         }
126
127         sub quote {
128                 my $self = shift;
129                 return $self->db_Main->quote(@_)
130         }
131
132 #       sub tsearch2_trigger {
133 #               my $self = shift;
134 #               return unless ($self->value);
135 #               $self->index_vector(
136 #                       $self->db_Slaves->selectrow_array(
137 #                               "SELECT to_tsvector('default',?);",
138 #                               {},
139 #                               $self->value
140 #                       )
141 #               );
142 #       }
143
144         my $_xact_session;
145
146         sub current_xact_session {
147                 my $self = shift;
148                 if (defined($_xact_session)) {
149                         return $_xact_session;
150                 }
151                 return undef;
152         }
153
154         sub current_xact_is_auto {
155                 my $self = shift;
156                 my $auto = shift;
157                 if (defined($_xact_session) and ref($_xact_session)) {
158                         if (defined $auto) {
159                                 $_xact_session->session_data(autocommit => $auto);
160                         }
161                         return $_xact_session->session_data('autocommit'); 
162                 }
163         }
164
165         sub current_xact_id {
166                 my $self = shift;
167                 if (defined($_xact_session) and ref($_xact_session)) {
168                         return $_xact_session->session_id;
169                 }
170                 return undef;
171         }
172
173         sub set_xact_session {
174                 my $self = shift;
175                 my $ses = shift;
176                 if (!defined($ses)) {
177                         return undef;
178                 }
179                 $_xact_session = $ses;
180                 return $_xact_session;
181         }
182
183         sub unset_xact_session {
184                 my $self = shift;
185                 my $ses = $_xact_session;
186                 undef $_xact_session;
187                 return $ses;
188         }
189
190 }
191
192 1;