/[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.12 - (show annotations)
Thu Jan 30 22:28:21 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.11: +30 -1 lines
+ implemented new concrete methods

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

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