File Coverage

blib/lib/Class/Persistent/Plugin/MySQL.pm
Criterion Covered Total %
statement 9 221 4.0
branch 1 102 0.9
condition 0 6 0.0
subroutine 3 14 21.4
pod 0 11 0.0
total 13 354 3.6


line stmt bran cond sub pod time code
1             #
2             # Class::Persistent::Plugin::MySQL - Plugin to enable persistence through the MySQL-database.
3             # $Id$
4             #
5             # Copyright (C) 2000 by Heiko Wundram.
6             # All rights reserved.
7             #
8             # This program is free software; you can redistribute and/or modify it under the same terms as Perl itself.
9             #
10             # $Log$
11             #
12              
13             package Class::Persistent::Plugin::MySQL;
14             $Class::Persistent::Plugin::MySQL::VERSION = '0.01';
15              
16 1     1   2403 use DBI qw(:sql_types);
  1         22954  
  1         587  
17              
18 1     1   12 use Carp;
  1         1  
  1         2861  
19              
20             sub new
21             {
22 1     1 0 3 my ($class,$dsn,$user,$passwd) = @_;
23 1 50       4 $class = ref $class ? ref $class : $class;
24 1 0       9 my $dbh = DBI->connect( $dsn, $user, $passwd,
25             { PrintError => 0, RaiseError => 0 } )
26             or confess("Cannot connect to database: $DBI::errstr!");
27 0           my $self = {};
28              
29 0           $self->{"_dbh"} = $dbh;
30              
31 0           bless( $self, $class );
32              
33 0           return $self;
34             }
35              
36             sub normalize_pkg
37             {
38 0     0 0   my ($pkg) = @_;
39              
40 0           $pkg =~ s/:/_/g;
41 0           return $pkg;
42             }
43              
44             sub get_max_id
45             {
46 0 0   0 0   if( @_ != 2 )
47             {
48 0           confess "get_max_id can only be called with one arguments!";
49             }
50              
51 0           my ($class,$pkg) = @_;
52 0 0         ref $class or confess "get_max_id can only be called on an instance of the storage class!";
53 0           my $dbh = $class->{"_dbh"};
54 0           my $db_pkg = normalize_pkg($pkg);
55 0           my $sth;
56             my $ret_val;
57              
58 0 0         ( $sth = $dbh->prepare("SELECT max(_id) FROM $db_pkg") )
59             or confess("Something is really wrong with the database!");
60              
61 0 0         if( !$sth->execute() )
62             {
63 0           $ret_val = 0;
64             }
65             else
66             {
67 0           ($ret_val) = $sth->fetchrow_array;
68             }
69 0           $sth->finish();
70              
71 0           return $ret_val+1;
72             }
73              
74             sub load
75             {
76 0 0 0 0 0   if( @_ < 3 || @_ > 4 )
77             {
78 0           confess "load can only be called with two or three arguments!";
79             }
80              
81 0           my ($class,$out,$pkg,$type) = @_;
82 0 0         ref $class or confess "load can only be called on an instance of the storage class!";
83 0 0         ref $out or confess "load can only be called on an instance of the container class!";
84 0           my $dbh = $class->{"_dbh"};
85 0           my $db_pkg = normalize_pkg($pkg);
86 0           my $sth = $class->{"_sth"};
87 0           my $ret_val;
88             my $set_val;
89 0           my ($attribs,$types);
90              
91 0 0         if( $sth )
92             {
93 0           $set_val = $sth->fetchrow_hashref();
94 0 0         if( !$set_val )
95             {
96 0           $ret_val = 1;
97 0           $sth->finish();
98 0           delete $class->{"_sth"};
99             }
100             else
101             {
102 0           $ret_val = 0;
103             }
104             }
105             else
106             {
107 0 0         ( $sth = $dbh->prepare("SELECT * FROM $db_pkg".($type?" WHERE $type":"")) )
    0          
108             or confess("Something is really wrong with the database!");
109              
110 0 0         if( !$sth->execute() )
111             {
112 0           $set_val = undef;
113 0           $ret_val = -1;
114             }
115             else
116             {
117 0           $set_val = $sth->fetchrow_hashref();
118 0           $ret_val = 0;
119 0           $class->{"_sth"} = $sth;
120             }
121             }
122              
123 0 0         if( $ret_val == 0 )
124             {
125 0           ($attribs,$types) = split_hash($set_val);
126 0           $out->set_attributes_type($attribs,$types);
127             }
128              
129 0           return $ret_val;
130             }
131              
132             sub split_hash
133             {
134 0 0   0 0   if( @_ != 1 )
135             {
136 0           confess "split_hash can only be called with one argument!";
137             }
138              
139 0           my ($set_val) = @_;
140 0           my $key;
141 0           my ($attribs,$types) = ({},{});
142              
143 0           foreach $key (keys %$set_val)
144             {
145 0 0         if( $key =~ /^(.*)_type$/ )
146             {
147 0           $types->{$1} = $set_val->{$key};
148             }
149             else
150             {
151 0           $attribs->{$key} = $set_val->{$key};
152             }
153             }
154              
155 0           return ($attribs,$types);
156             }
157              
158             sub store
159             {
160 0 0   0 0   if( @_ != 3 )
161             {
162 0           confess "store can only be called with two arguments!";
163             }
164              
165 0           my ($class,$out,$pkg) = @_;
166 0 0         ref $class or confess "store can only be called on an instance of the storage class!";
167 0 0         ref $out or confess "store can only be called on an instance of the container class!";
168 0           my $dbh = $class->{"_dbh"};
169 0           my $db_pkg = normalize_pkg($pkg);
170 0           my $sth;
171 0           my ($attribs,$types);
172 0           my ($statement_pre,$statement_post,$statement);
173 0           my %binds;
174 0           my @binds;
175 0           my ($attrib,$i);
176              
177 0           ($attribs,$types) = $out->get_attributes_type();
178              
179 0           construct_table($dbh,$db_pkg,$types);
180              
181 0           $statement_pre = "INSERT INTO $db_pkg (";
182 0           $statement_post = "VALUES (";
183 0           $i = 1;
184              
185 0           foreach $attrib (keys %$attribs)
186             {
187 0           $binds{$i++} = $attribs->{$attrib};
188 0           $binds{$i++} = $types->{$attrib};
189              
190 0           $statement_pre .= $attrib.",".$attrib."_type,";
191 0           $statement_post .= "?,?,";
192             }
193              
194 0           $statement_pre =~ s/,$//;
195 0           $statement_post =~ s/,$//;
196              
197 0           $statement = $statement_pre.") ".$statement_post.")";
198              
199 0 0         ( $sth = $dbh->prepare($statement) )
200             or confess("Something amiss with the database!");
201              
202 0           foreach $attrib (keys %binds)
203             {
204 0           $sth->bind_param($attrib,$binds{$attrib},SQL_VARCHAR);
205             }
206              
207 0           return $sth->execute(@binds);
208             }
209              
210             sub save
211             {
212 0 0   0 0   if( @_ != 3 )
213             {
214 0           confess "save can only be called with two arguments!";
215             }
216              
217 0           my ($class,$out,$pkg) = @_;
218 0 0         ref $class or confess "save can only be called on an instance of the storage class!";
219 0 0         ref $out or confess "save can only be called on an instance of the container class!";
220 0           my $dbh = $class->{"_dbh"};
221 0           my $db_pkg = normalize_pkg($pkg);
222 0           my $sth;
223 0           my ($attribs,$types);
224 0           my $statement;
225 0           my %binds;
226 0           my ($attrib,$i);
227              
228 0           ($attribs,$types) = $out->get_attributes_type();
229              
230 0           construct_table($dbh,$db_pkg,$types);
231              
232 0           $statement = "UPDATE $db_pkg SET ";
233 0           $i = 1;
234              
235 0           foreach $attrib (keys %$attribs)
236             {
237 0           $binds{$i++} = $attribs->{$attrib};
238 0           $binds{$i++} = $types->{$attrib};
239              
240 0           $statement .= $attrib."=?,".$attrib."_type=?,";
241             }
242              
243 0           $statement =~ s/,$//;
244              
245 0           $statement .= " WHERE _id = ".$attribs->{"_id"};
246              
247 0 0         ( $sth = $dbh->prepare($statement) )
248             or confess("Something amiss with the database!");
249              
250 0           foreach $attrib (keys %binds)
251             {
252 0           $sth->bind_param($attrib,$binds{$attrib},SQL_VARCHAR);
253             }
254              
255 0           return $sth->execute();
256             }
257              
258             sub delete
259             {
260 0 0   0 0   if( @_ != 3 )
261             {
262 0           confess "delete requires two arguments!";
263             }
264              
265 0           my ($class,$out,$pkg) = @_;
266 0 0         ref $class or confess "delete can only be called on an instance of the storage class!";
267 0 0         ref $out or confess "delete can only be called on an instance of the container class!";
268 0           my $dbh = $class->{"_dbh"};
269 0           my $db_pkg = normalize_pkg($pkg);
270 0           my $sth;
271 0           my ($attribs,$types);
272 0           my $statement;
273              
274 0           ($attribs,$types) = $out->get_attributes_type();
275              
276 0           $statement = "DELETE FROM $db_pkg WHERE _id = ".$attribs->{"_id"};
277              
278 0 0         ( $sth = $dbh->prepare($statement) )
279             or confess("Something is amiss with the database!");
280              
281 0           return $sth->execute();
282             }
283              
284             sub calc_refs
285             {
286 0 0   0 0   if( @_ != 3 )
287             {
288 0           confess "calc_refs requires two arguments!";
289             }
290              
291 0           my ($class,$out,$pkg) = @_;
292 0 0         ref $class or confess "calc_refs can only be called on an instance of the storage class!";
293 0 0         ref $out or confess "calc_refs can only be called on an instance of the container class!";
294 0           my $dbh = $class->{"_dbh"};
295 0           my $sth;
296 0           my ($attribs,$types);
297 0           my $id;
298 0           my (@tables,$table);
299 0           my $refs;
300 0           my $vals;
301 0           my $key;
302              
303 0           ($attribs,$types) = $out->get_attributes_type();
304              
305 0           $id = $attribs->{"_id"}."|$pkg";
306              
307 0           $statement = "SELECT * FROM pkg_list";
308              
309 0 0         ( $sth = $dbh->prepare($statement) )
310             or confess("Something is amiss with the database!");
311              
312 0           $sth->execute();
313              
314 0           while( ($table) = $sth->fetchrow_array() )
315             {
316 0           push @tables, $table;
317             }
318              
319 0           foreach $table (@tables)
320             {
321 0           $statement = "SELECT * FROM $table";
322              
323 0 0         ( $sth = $dbh->prepare($statement) )
324             or confess("Something is amiss with the database!");
325              
326 0           $sth->execute();
327              
328 0           while( $vals = $sth->fetchrow_hashref() )
329             {
330 0           foreach $key (keys %$vals)
331             {
332 0 0         if( $key =~ /_type$/ )
333             {
334 0           next;
335             }
336              
337 0 0         if( $vals->{$key."_type"} eq 'c' )
338             {
339 0 0         if( $vals->{$key} eq $id )
340             {
341 0           $refs++;
342             }
343             }
344             }
345             }
346             }
347              
348 0           return $refs;
349             }
350              
351             sub check_tables
352             {
353 0 0   0 0   if( @_ != 1 )
354             {
355 0           confess "check_tables takes no arguments!";
356             }
357              
358 0           my ($class) = @_;
359 0 0         ref $class or confess "delete can only be called on an instance of the storage class!";
360 0           my $dbh = $class->{"_dbh"};
361 0           my $sth;
362             my $statement;
363 0           my (@tables,$table);
364 0           my $count;
365 0           my @delete;
366              
367 0           $statement = "SELECT * FROM pkg_list";
368              
369 0 0         ( $sth = $dbh->prepare($statement) )
370             or confess("Something is amiss with the database!");
371              
372 0           $sth->execute();
373              
374 0           while( ($table) = $sth->fetchrow_array() )
375             {
376 0           push @tables, $table;
377             }
378              
379 0           foreach $table (@tables)
380             {
381 0           $statement = "SELECT COUNT(*) FROM $table";
382              
383 0 0         ( $sth = $dbh->prepare($statement) )
384             or confess("Something is amiss with the database!");
385              
386 0           $sth->execute();
387              
388 0           ($count) = $sth->fetchrow_array();
389              
390 0 0         if( $count == 0 )
391             {
392 0           push @delete, $table;
393             }
394             }
395              
396 0           foreach $table (@delete)
397             {
398 0           $statement = "DROP TABLE $table";
399              
400 0 0         ( $sth = $dbh->prepare($statement) )
401             or confess("Something is amiss with the database!");
402              
403 0           $sth->execute();
404              
405 0           $statement = "DELETE FROM pkg_list WHERE pkg = '$table'";
406              
407 0 0         ( $sth = $dbh->prepare($statement) )
408             or confess("Something is amiss with the database!");
409              
410 0           $sth->execute();
411             }
412             }
413              
414             sub construct_table
415             {
416 0 0   0 0   if( @_ != 3 )
417             {
418 0           confess "construct_table can only be called with two arguments!";
419             }
420              
421 0           my ($dbh,$db_pkg,$types) = @_;
422 0           my $statement;
423             my $field;
424              
425 0           $statement = "CREATE TABLE pkg_list (pkg VARCHAR(255) NOT NULL,UNIQUE (pkg))";
426              
427 0 0         ( $sth = $dbh->prepare($statement) )
428             or confess("Something is amiss with the database!");
429              
430 0           $sth->execute();
431              
432 0           $statement = "INSERT INTO pkg_list VALUES (?)";
433              
434 0 0         ( $sth = $dbh->prepare($statement) )
435             or confess("Something is amiss with the database!");
436              
437 0           $sth->bind_param(1,$db_pkg,SQL_VARCHAR);
438              
439 0           $sth->execute();
440              
441 0           $statement = "CREATE TABLE $db_pkg (";
442              
443 0           foreach $field (keys %$types)
444             {
445 0           $statement .= $field." ";
446              
447 0 0 0       if( $types->{$field} eq 'n' )
    0          
448             {
449 0           $statement .= "BIGINT,";
450             }
451             elsif( $types->{$field} eq 's' || $types->{$field} eq 'c' )
452             {
453 0           $statement .= "LONGTEXT,";
454             }
455             else
456             {
457 0           $statement .= "LONGBLOB,";
458             }
459              
460 0           $statement .= $field."_type CHAR(1),";
461             }
462              
463 0           $statement =~ s/,$/\)/;
464              
465 0 0         ( $sth = $dbh->prepare($statement) )
466             or confess("Something is amiss with the database!");
467              
468 0           return $sth->execute();
469             }
470              
471             sub DESTROY
472             {
473 0     0     my ($class) = @_;
474              
475 0 0         $class->{"_dbh"}->disconnect() or croak("Could not disconnect from Datasource!");
476             }
477              
478             1;