File Coverage

blib/lib/DBIx/Sequence.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package DBIx::Sequence;
2              
3 5     5   12735 use strict;
  5         7  
  5         234  
4 5     5   25 use vars qw($VERSION);
  5         8  
  5         316  
5             $VERSION = '1.5';
6              
7 5     5   7967 use DBI;
  0            
  0            
8             use Carp;
9              
10             use constant COLUMN_PREFIX => '';
11             use constant DEFAULT_INIT_VALUE => 1;
12             use constant DEFAULT_ALLOW_ID_REUSE => 1;
13             use constant DEBUG_LEVEL => 0;
14             use constant DEFAULT_STATE_TABLE => 'dbix_sequence_state';
15             use constant DEFAULT_RELEASE_TABLE => 'dbix_sequence_release';
16              
17             sub new
18             {
19             my $class_name = shift;
20             my $args = shift;
21              
22             my $self = {};
23             $self = bless $self, $class_name;
24              
25             $self->{_dbh} = $args->{dbh} || $self->getDbh($args) || die 'Cannot get Database handle';
26              
27             $self->{state_table} = $args->{state_table};
28             $self->{release_table} = $args->{release_table};
29             $self->{_arg_reuse} = $args->{allow_id_reuse} if(exists $args->{allow_id_reuse});
30              
31             delete $self->{db_user};
32             delete $self->{db_pw};
33             delete $self->{db_dsn};
34              
35             $self->_InitQueries();
36              
37              
38             return $self;
39             }
40              
41             sub getDbh
42             {
43             my $self = shift;
44             my $args = shift;
45              
46             return DBI->connect($args->{db_dsn}, $args->{db_user}, $args->{db_pw}, {
47             RaiseError => 0,
48             PrintError => 0,
49             AutoCommit => 1,
50             Warn => 0, }) || croak __PACKAGE__.": $DBI::errstr";
51             }
52              
53              
54             sub Next
55             {
56             my $self = shift;
57             my $dataset = shift;
58              
59             croak "No dataset specified" if not defined $dataset;
60              
61             print STDERR "Request of Next() id\n" if $self->DEBUG_LEVEL();
62              
63             my $current_sth = $self->{_current_sth};
64             my $init_sth = $self->{_init_sth};
65              
66             if($self->_Create_Dataset($dataset))
67             {
68             return $self->DEFAULT_INIT_VALUE();
69             }
70              
71             if($self->_AllowedReuse())
72             {
73             my $released_ids_sth = $self->{_released_ids_sth};
74              
75             $released_ids_sth->execute($dataset);
76              
77             while(my $released_id = $released_ids_sth->fetchrow())
78             {
79             if($self->_release_race_for($dataset, ( $released_id =~ m/^(\d+)$/ )[0] ))
80             {
81             print STDERR "Returning released id $released_id\n" if $self->DEBUG_LEVEL();
82             $released_ids_sth->finish;
83             return $released_id;
84             }
85             }
86             }
87            
88             my $unique_id = $self->_race_for($dataset);
89             if(!$unique_id)
90             {
91             croak __PACKAGE__." was unable to generate a unique id for ".$dataset."\n";
92             }
93              
94             print STDERR "Returning new unique id $unique_id\n" if $self->DEBUG_LEVEL();
95             return $unique_id;
96             }
97              
98             sub Currval
99             {
100             my $self = shift;
101             my $dataset = shift;
102              
103             croak "No dataset specified" if !$dataset;
104              
105             my $current_sth = $self->{_current_sth};
106             $current_sth->execute($dataset) || croak __PACKAGE__.": $DBI::errstr";
107             my ($c_dataset, $current_id) = $current_sth->fetchrow(); $current_sth->finish;
108              
109             print STDERR "Returning CURRVAL $current_id for $c_dataset\n";
110             return $current_id;
111             }
112              
113              
114             sub Release
115             {
116             my $self = shift;
117             my $dataset = shift;
118             my $release_id = shift;
119              
120             croak "No dataset specified" if !$dataset;
121             croak __PACKAGE__." NO ID specified for Release()" if not defined $release_id;
122              
123             print STDERR "Asked to release id $release_id in dataset $dataset\n" if $self->DEBUG_LEVEL();
124              
125              
126             if($self->_AllowedReuse())
127             {
128             my $release_id_sth = $self->{_release_id_sth};
129            
130             if($release_id_sth->execute($dataset, $release_id) ne 'OEO')
131             {
132             print STDERR "Release successful.\n" if $self->DEBUG_LEVEL();
133             return 1;
134             }
135             return 0;
136             }
137             else
138             {
139             warn "Release() of ID not permitted by class ".__PACKAGE__;
140             }
141             }
142              
143            
144             sub Delete_Dataset
145             {
146             my $self = shift;
147             my $dataset = shift;
148              
149             croak "No dataset specified" if !$dataset;
150              
151              
152             my $delete_state_sth = $self->{_delete_state_sth};
153             my $delete_release_sth = $self->{_delete_release_sth};
154              
155             print STDERR "Deleting dataset ".$dataset."\n" if $self->DEBUG_LEVEL();
156              
157             $delete_state_sth->execute($dataset) || croak __PACKAGE__.": $DBI::errstr";
158             $delete_release_sth->execute($dataset) || croak __PACKAGE__.": $DBI::errstr";
159              
160             print STDERR "Deletion successul\n" if $self->DEBUG_LEVEL();
161              
162             return 1;
163             }
164              
165             sub Bootstrap
166             {
167             my $self = shift;
168             my $dataset = shift;
169             my $data_table = shift;
170             my $data_field = shift;
171              
172             croak "No dataset specified" if !$dataset;
173             croak "No data_table to Bootstrap()" if(!$data_table);
174             croak "No data_field to Bootstrap()" if(!$data_field);
175              
176              
177             print STDERR "Bootstrapping dataset ". $dataset." with $data_table and $data_field\n" if $self->DEBUG_LEVEL();
178              
179             my $bootstrap_query = "SELECT
180             MAX($data_field)
181             FROM
182             ".$data_table;
183            
184             print STDERR "\n\n", $bootstrap_query, "\n\n" if $self->DEBUG_LEVEL();
185              
186             my $bootstrap_sth = $self->{_dbh}->prepare($bootstrap_query) || croak __PACKAGE__.": $DBI::errstr";
187             $bootstrap_sth->execute() || croak __PACKAGE__.": $DBI::errstr";
188              
189             my $bootstrap_id = $bootstrap_sth->fetchrow(); $bootstrap_sth->finish;
190              
191             croak "Bootstrap() failed" if(!$bootstrap_id);
192              
193             $self->_Create_Dataset($dataset);
194              
195             print STDERR "Bootstrap successfull.\n" if $self->DEBUG_LEVEL();
196              
197             my $next_id = $self->_race_for($dataset, $bootstrap_id + 1);
198              
199             print STDERR "Bootstrap next id is : $next_id\n" if $self->DEBUG_LEVEL();
200              
201             return $next_id;
202             }
203              
204             sub _Create_Dataset
205             {
206             my $self = shift;
207             my $dataset = shift;
208              
209             croak "No dataset specified" if !$dataset;
210              
211             my $current_sth = $self->{_current_sth};
212             my $init_sth = $self->{_init_sth};
213              
214             $current_sth->execute($dataset) || croak __PACKAGE__.": $DBI::errstr";
215             my ($c_dataset, $current_id) = $current_sth->fetchrow(); $current_sth->finish;
216              
217             if(!$c_dataset)
218             {
219             $init_sth->execute($dataset,$self->DEFAULT_INIT_VALUE()) || croak __PACKAGE__.": $DBI::errstr";
220             return $self->DEFAULT_INIT_VALUE();
221             }
222             else { return 0; }
223             }
224              
225             sub STATE_TABLE
226             {
227             my $self = shift;
228              
229             croak "Self not defined!" if not defined $self;
230              
231             return $self->{state_table} || $self->DEFAULT_STATE_TABLE();
232             }
233              
234             sub RELEASE_TABLE
235             {
236             my $self = shift;
237            
238             croak "Self not defined!" if not defined $self;
239            
240             return $self->{release_table} || $self->DEFAULT_RELEASE_TABLE();
241             }
242            
243             sub _AllowedReuse
244             {
245             my $self = shift;
246              
247             if(exists $self->{_arg_reuse})
248             {
249             return undef if($self->{_arg_reuse} =~ /no/i);
250             return 1 if($self->{_arg_reuse});
251             return undef;
252             }
253             else
254             {
255             return $self->DEFAULT_ALLOW_ID_REUSE();
256             }
257             }
258            
259             sub _race_for
260             {
261             my $self = shift;
262             my $dataset = shift;
263             my $race_for_id = shift;
264              
265             croak "No dataset specified" if !$dataset;
266              
267             my $current_sth = $self->{_current_sth};
268             my $race_sth = $self->{_race_sth};
269              
270             my $unique_id;
271             my $got_id = 0;
272             my $current_id;
273             while($got_id == 0)
274             {
275             $current_sth->execute($dataset) || croak __PACKAGE__.": $DBI::errstr";
276             $current_id = ($current_sth->fetchrow() =~ m/^(\d+)$/ )[0]; $current_sth->finish;
277              
278             if(!$race_for_id || $race_for_id <= $current_id)
279             {
280             $race_for_id = $current_id + 1;
281             }
282            
283             if ($race_sth->execute(($race_for_id), $dataset, $current_id) ne '0E0')
284             {
285             $unique_id = $race_for_id;
286             $got_id = 1;
287             }
288             }
289              
290             return $unique_id;
291             }
292              
293             sub _release_race_for
294             {
295             my $self = shift;
296             my $dataset = shift;
297             my $release_id = shift;
298              
299             croak "No dataset specified" if !$dataset;
300             croak "No ID specified for release race" if not defined $release_id;
301              
302             if($self->{_race_release_sth}->execute($dataset, $release_id) ne 'OEO')
303             {
304             return 1;
305             }
306             return 0;
307             }
308            
309             sub _InitQueries
310             {
311             my $self = shift;
312              
313            
314             my $current_query = "SELECT
315             ".$self->COLUMN_PREFIX()."dataset,
316             ".$self->COLUMN_PREFIX()."state_id
317             FROM
318             ".$self->STATE_TABLE()."
319             WHERE
320             ".$self->COLUMN_PREFIX()."dataset = ?";
321              
322             print STDERR "\n\n", $current_query, "\n\n" if $self->DEBUG_LEVEL();
323              
324             $self->{_current_sth} = $self->{_dbh}->prepare_cached($current_query) || croak __PACKAGE__.": $DBI::errstr";
325              
326             my $init_query = "INSERT INTO
327             ".$self->STATE_TABLE()." (
328             ".$self->COLUMN_PREFIX()."dataset,
329             ".$self->COLUMN_PREFIX()."state_id
330             ) values (?,?)";
331              
332             print STDERR "\n\n", $init_query, "\n\n" if $self->DEBUG_LEVEL();
333              
334             $self->{_init_sth} = $self->{_dbh}->prepare_cached($init_query) || croak __PACKAGE__.": $DBI::errstr";
335              
336            
337             my $race_query = "UPDATE
338             ".$self->STATE_TABLE()."
339             SET
340             ".$self->COLUMN_PREFIX()."state_id = ?
341             WHERE
342             ".$self->COLUMN_PREFIX()."dataset = ?
343             AND
344             ".$self->COLUMN_PREFIX()."state_id = ?";
345              
346              
347             print STDERR "\n\n", $race_query, "\n\n" if $self->DEBUG_LEVEL();
348              
349             $self->{_race_sth} = $self->{_dbh}->prepare_cached($race_query) || croak __PACKAGE__.": $DBI::errstr";
350              
351            
352             my $release_query = "DELETE FROM
353             ".$self->RELEASE_TABLE()."
354             WHERE
355             ".$self->COLUMN_PREFIX()."dataset = ?
356             AND
357             ".$self->COLUMN_PREFIX()."released_id = ?";
358              
359              
360             print STDERR "\n\n", $release_query, "\n\n" if $self->DEBUG_LEVEL();
361              
362             $self->{_race_release_sth} = $self->{_dbh}->prepare_cached($release_query) || croak __PACKAGE__.": $DBI::errstr";
363              
364              
365             my $released_ids_query = "SELECT
366             ".$self->COLUMN_PREFIX()."released_id
367             FROM
368             ".$self->RELEASE_TABLE()."
369             WHERE
370             ".$self->COLUMN_PREFIX()."dataset = ?";
371              
372             print STDERR "\n\n", $released_ids_query, "\n\n" if $self->DEBUG_LEVEL();
373              
374             $self->{_released_ids_sth} = $self->{_dbh}->prepare_cached($released_ids_query) || croak __PACKAGE__.": $DBI::errstr";
375            
376              
377              
378             my $release_id_query = "INSERT INTO
379             ".$self->RELEASE_TABLE()."
380             (
381             ".$self->COLUMN_PREFIX()."dataset,
382             ".$self->COLUMN_PREFIX()."released_id
383             ) values (?,?)";
384              
385             print STDERR "\n\n", $release_id_query, "\n\n" if $self->DEBUG_LEVEL();
386              
387             $self->{_release_id_sth} = $self->{_dbh}->prepare_cached($release_id_query) || croak __PACKAGE__.": $DBI::errstr";
388              
389              
390             my $delete_state_query = "DELETE FROM
391             ".$self->STATE_TABLE()."
392             WHERE
393             dataset = ?";
394              
395             print STDERR "\n\n", $delete_state_query, "\n\n" if $self->DEBUG_LEVEL();
396              
397             $self->{_delete_state_sth} = $self->{_dbh}->prepare_cached($delete_state_query) || croak __PACKAGE__.": $DBI::errstr";
398              
399              
400             my $delete_release_query = "DELETE FROM
401             ".$self->RELEASE_TABLE()."
402             WHERE
403             dataset = ?";
404            
405             print STDERR "\n\n", $delete_release_query, "\n\n" if $self->DEBUG_LEVEL();
406              
407             $self->{_delete_release_sth} = $self->{_dbh}->prepare_cached($delete_release_query) || croak __PACKAGE__.": $DBI::errstr";
408              
409            
410             return 1;
411             }
412              
413             42;
414              
415              
416             __END__