/[cvs]/nfo/perl/libs/Data/Storage/Handler/DBI.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Storage/Handler/DBI.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (show annotations)
Tue Apr 8 23:06:45 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.12: +9 -4 lines
renamed core database helper functions

1 #################################
2 #
3 # $Id: DBI.pm,v 1.12 2003/01/30 22:28:21 joko Exp $
4 #
5 # $Log: DBI.pm,v $
6 # Revision 1.12 2003/01/30 22:28:21 joko
7 # + implemented new concrete methods
8 #
9 # Revision 1.11 2002/12/19 16:31:05 joko
10 # + sub dropDb
11 # + sub rebuildDb
12 #
13 # Revision 1.10 2002/12/15 02:02:22 joko
14 # + fixed logging-message
15 #
16 # Revision 1.9 2002/12/05 07:58:20 joko
17 # + now using Tie::SecureHash as a base for the COREHANDLE
18 # + former public COREHANDLE becomes private _COREHANDLE now
19 #
20 # Revision 1.8 2002/12/01 22:20:43 joko
21 # + sub createDb (from Storage.pm)
22 #
23 # Revision 1.7 2002/12/01 07:09:09 joko
24 # + sub getListFiltered (dummy redirecting to getListUnfiltered)
25 #
26 # Revision 1.6 2002/12/01 04:46:01 joko
27 # + sub eraseAll
28 #
29 # Revision 1.5 2002/11/29 05:00:26 joko
30 # + sub getListUnfiltered
31 # + sub sendQuery
32 #
33 # Revision 1.4 2002/11/17 08:46:42 jonen
34 # + wrapped eval around DBI->connect to prevent deaths
35 #
36 # Revision 1.3 2002/11/17 06:34:39 joko
37 # + locator metadata can now be reached via ->{locator}
38 # - sub hash2sql now taken from libdb
39 #
40 # Revision 1.2 2002/10/25 11:43:27 joko
41 # + enhanced robustness
42 # + more logging for debug-levels
43 #
44 # Revision 1.1 2002/10/10 03:44:07 cvsjoko
45 # + new
46 #
47 #
48 #################################
49
50 package Data::Storage::Handler::DBI;
51
52 use strict;
53 use warnings;
54
55 use base ("Data::Storage::Handler::Abstract");
56
57
58 use DBI;
59 use Data::Dumper;
60 use shortcuts::db qw( hash2sql dsn2dbname );
61 use Data::Storage::Result::DBI;
62
63
64 # get logger instance
65 my $logger = Log::Dispatch::Config->instance;
66
67
68 sub getMetaInfo {
69 my $self = shift;
70 $logger->debug( __PACKAGE__ . "->getMetaInfo()" );
71 return {
72 'disconnectMethod' => 'disconnect',
73 };
74 }
75
76 sub connect {
77
78 my $self = shift;
79
80 # create handle
81 if ( my $dsn = $self->{locator}->{dbi}->{dsn} ) {
82 #if ( my $dsn = $self->{locator}->{dsn} ) {
83 $logger->debug( __PACKAGE__ . "->connect( dsn $dsn )" );
84
85 # HACK:
86 # set errorhandler before actually calling DBI->connect
87 # in order to catch errors from the very beginning
88 #DBI->{HandleError} = $self->{dbi}->{HandleError};
89
90 #use Data::Dumper; print Dumper($self->{dbi});
91
92 eval {
93 $self->{_COREHANDLE} = DBI->connect( $dsn, '', '', $self->{locator}->{dbi} );
94 if (!$self->{_COREHANDLE}) {
95 $logger->warning( __PACKAGE__ . "->connect failed: " . DBI::errstr );
96 return;
97 }
98 };
99 $logger->warning( __PACKAGE__ . "->connect failed: " . $@ ) if $@;
100
101 }
102 $self->configureCOREHANDLE();
103
104 $self->{locator}->{status}->{connected} = 1;
105
106 return 1;
107
108 }
109
110 sub configureCOREHANDLE {
111
112 my $self = shift;
113
114 $logger->debug( __PACKAGE__ . "->configureCOREHANDLE" );
115
116 return if !$self->{_COREHANDLE};
117
118 # apply configured modifications to DBI-handle
119 if (exists $self->{locator}->{dbi}->{trace_level} && exists $self->{locator}->{dbi}->{trace_file}) {
120 $self->{_COREHANDLE}->trace($self->{locator}->{dbi}->{trace_level}, $self->{locator}->{dbi}->{trace_file});
121 }
122 if (exists $self->{locator}->{dbi}->{RaiseError}) {
123 $self->{_COREHANDLE}->{RaiseError} = $self->{locator}->{dbi}->{RaiseError};
124 }
125 if (exists $self->{locator}->{dbi}->{PrintError}) {
126 $self->{_COREHANDLE}->{PrintError} = $self->{locator}->{dbi}->{PrintError};
127 }
128 if (exists $self->{locator}->{dbi}->{HandleError}) {
129 $self->{_COREHANDLE}->{HandleError} = $self->{locator}->{dbi}->{HandleError};
130 }
131
132 }
133
134 sub _sendSql {
135 my $self = shift;
136 my $sql = shift;
137
138 # two-level handling for implicit connect:
139 # if there's no corehandle ...
140 if (!$self->{_COREHANDLE}) {
141 # ... try to connect, but ...
142 $self->connect();
143 # ... if this still fails, there's something wrong probably, so we won't continue
144 if (!$self->{_COREHANDLE}) {
145 return;
146 }
147 }
148
149 #print "prepare sql: $sql\n";
150
151 my $sth = $self->{_COREHANDLE}->prepare($sql);
152 $sth->execute();
153 return $sth;
154 }
155
156 sub sendCommand {
157 my $self = shift;
158 my $command = shift;
159 # TODO: when tracing: yes, do actually log this
160 #$logger->debug( __PACKAGE__ . "->sendCommand( command $command )" );
161 my $cmdHandle = $self->_sendSql($command);
162 my $result = Data::Storage::Result::DBI->new( RESULTHANDLE => $cmdHandle );
163 return $result;
164 }
165
166 sub getChildNodes {
167 my $self = shift;
168 my @nodes;
169 $logger->debug( __PACKAGE__ . "->getChildNodes()" );
170 my $locator = $self->{locator};
171 #print Dumper($locator); exit;
172 if (my $result = $self->sendCommand( 'SHOW TABLES;' ) ) {
173 my $dbname = dsn2dbname($self->{locator}->{dbi}->{dsn});
174 my $key = "Tables_in_$dbname";
175 while ( my $row = $result->getNextEntry() ) {
176 push @nodes, $row->{$key};
177 }
178 }
179 return \@nodes;
180 }
181
182 sub getListUnfiltered {
183 my $self = shift;
184 my $nodename = shift;
185 my @list;
186 $logger->debug( __PACKAGE__ . "->getListUnfiltered( nodename => '" . $nodename . "' )" );
187 # get list of rows from rdbms by table name
188 my $result = $self->sendCommand("SELECT * FROM $nodename");
189 while ( my $row = $result->getNextEntry() ) {
190 push @list, $row;
191 }
192 return \@list;
193 }
194
195 sub sendQuery {
196 my $self = shift;
197 my $query = shift;
198
199 $logger->debug( __PACKAGE__ . "->sendQuery" );
200
201 #my $sql = "SELECT cs FROM $self->{metainfo}->{$descent}->{node} WHERE $self->{metainfo}->{$descent}->{IdentProvider}->{arg}='$self->{entry}->{source}->{ident}';";
202 #my $result = $self->{metainfo}->{$descent}->{storage}->sendCommand($sql);
203 my @crits;
204 foreach (@{$query->{criterias}}) {
205 my $op = '';
206 $op = '=' if lc $_->{op} eq 'eq';
207 push @crits, "$_->{key}$op'$_->{val}'";
208 }
209 my $subnodes = {};
210 map { $subnodes->{$_}++ } @{$query->{subnodes}};
211 # HACK: this is hardcoded ;( expand possibilities!
212 my $crit = join(' AND ', @crits);
213 my $sql = hash2sql($query->{node}, $subnodes, 'SELECT', $crit);
214 return $self->sendCommand($sql);
215 }
216
217 sub eraseAll {
218 my $self = shift;
219 my $classname = shift;
220 $logger->debug( __PACKAGE__ . "->eraseAll" );
221 my $sql = "DELETE FROM $classname";
222 $self->sendCommand($sql);
223 }
224
225 # TODO: actually implement the filtering functionality using $this->sendQuery
226 sub getListFiltered {
227 my $self = shift;
228 my $nodename = shift;
229 return $self->getListUnfiltered($nodename);
230 }
231
232 # TODO: do this via a parametrized "$self->connect(<connect just to database server - don't select database>)"
233 sub createDb {
234
235 my $self = shift;
236
237 # get dsn from Data::Storage::Locator instance
238 my $dsn = $self->{locator}->{dbi}->{dsn};
239
240 $logger->debug( __PACKAGE__ . "->createDb( dsn $dsn )" );
241
242 # remove database setting from dsn-string
243 $dsn =~ s/database=(.+?);//;
244
245 # remember extracted database name to know what actually to create right now
246 my $database_name = $1;
247
248 # flag to indicate goodness
249 my $ok;
250
251 # connect to database server - don't select/use any specific database
252 #if ( my $dbh = DBI->connect($dsn, '', '', { PrintError => 0 } ) ) {
253 if ( my $dbh = DBI->connect($dsn, '', '', $self->{locator}->{dbi} ) ) {
254
255 if ($database_name) {
256 if ($dbh->do("CREATE DATABASE $database_name")) {
257 $ok = 1;
258 }
259 }
260
261 $dbh->disconnect();
262
263 }
264
265 return $ok;
266
267 }
268
269 sub getCOREHANDLE2 {
270 my $self = shift;
271 return $self->{_COREHANDLE};
272 }
273
274 sub dropDb {
275 my $self = shift;
276 my $dsn = $self->{locator}->{dbi}->{dsn};
277
278 $logger->debug( __PACKAGE__ . "->dropDb( dsn $dsn )" );
279
280 $dsn =~ s/database=(.+?);//;
281 my $database_name = $1;
282
283 my $ok;
284
285 if ( my $dbh = DBI->connect($dsn, '', '', {
286 PrintError => 0,
287 } ) ) {
288 if ($database_name) {
289 if ($dbh->do("DROP DATABASE $database_name;")) {
290 $ok = 1;
291 }
292 }
293
294 $dbh->disconnect();
295
296 }
297
298 return $ok;
299 }
300
301 sub rebuildDb {
302 my $self = shift;
303 $logger->info( __PACKAGE__ . "->rebuildDb()" );
304 my @results;
305
306 # sum up results (bool (0/1)) in array
307 #push @results, $self->retreatSchema();
308 push @results, $self->dropDb();
309 push @results, $self->createDb();
310 #push @results, $self->deploySchema();
311
312 # scan array for "bad ones"
313 my $res = 1;
314 map {
315 $res = 0 if (!$_);
316 } @results;
317
318 return $res;
319 }
320
321 sub testAvailability {
322 my $self = shift;
323 my $status = $self->testDsn();
324 $self->{locator}->{status}->{available} = $status;
325 return $status;
326 }
327
328 sub testDsn {
329 my $self = shift;
330 my $dsn = $self->{locator}->{dbi}->{dsn};
331 my $result;
332 if ( my $dbh = DBI->connect($dsn, '', '', {
333 PrintError => 0,
334 } ) ) {
335
336 # TODO: REVIEW
337 $dbh->disconnect();
338
339 return 1;
340 } else {
341 $logger->warning( __PACKAGE__ . "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );
342 }
343 }
344
345 1;
346 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed