File Coverage

blib/lib/DBomb.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package DBomb;
2              
3             =head1 NAME
4              
5             DBomb - Database Object Mapping
6              
7             =cut
8              
9 11     11   1050546 use strict;
  11         28  
  11         669  
10 11     11   64 use warnings;
  11         24  
  11         588  
11 11     11   6345 use DBomb::Util qw(is_same_value);
  11         28  
  11         879  
12 11     11   7260 use DBomb::Query;
  11         43  
  11         370  
13 11     11   115 use Carp::Assert;
  11         29  
  11         81  
14 11     11   1849 use Carp qw(cluck);
  11         27  
  11         739  
15 11     11   70 use base qw(DBomb::DBH::Owner);
  11         31  
  11         8449  
16             use base qw(Exporter);
17              
18             our $VERSION = '$Revision: 1.26 $';
19              
20             our %EXPORT_TAGS = ( 'all' => [qw( PlaceHolder ) ]);
21             Exporter::export_ok_tags('all');
22             sub PlaceHolder { DBomb::Query::PlaceHolder() }
23              
24              
25              
26             __PACKAGE__->mk_classdata('tables');
27             __PACKAGE__->mk_classdata('databases');
28             __PACKAGE__->mk_classdata('one_to_manys');
29             __PACKAGE__->mk_classdata('todo_after_resolve');
30             __PACKAGE__->mk_classdata('did_resolve');
31              
32             __PACKAGE__->tables(+{}); ## table_name -> table_info
33             __PACKAGE__->databases(+{}); ## TODO
34             __PACKAGE__->one_to_manys([]); ## List of OneToMany objects
35             __PACKAGE__->todo_after_resolve([]); ## [ [ CODEREF, $args_list, caller] , ... ]
36              
37              
38             ## eval { DBomb->resolve };
39             sub resolve
40             {
41             my $class = shift;
42              
43             if (defined $class->did_resolve){
44             my ($package, $filename, $line, $subroutine) = @{$class->did_resolve};
45             cluck("DBomb::resolve was already called. The first time was from $package\:\:$subroutine at $filename line $line ");
46             }
47             $class->did_resolve([caller(1)]);
48              
49             for(values %{$class->tables}){
50             $_->resolve;
51             }
52              
53             for (@{$class->todo_after_resolve}){
54             my ($coderef, $args, $caller_info) = @$_;
55             eval {
56             $coderef->(@$args);
57             };
58             if ($@) {
59             ## The coderef failed.
60             my ($package, $filename, $line, $subroutine) = map{defined($_)?$_:''} @$caller_info;
61             die("$filename\:$line in $package\:\:$subroutine\: $@\n");
62             }
63             }
64             }
65              
66             ## returns a table_info object or undef
67             ## $class->resolve_table_name($database,$tname)
68             sub resolve_table_name
69             {
70             ##TODO: database not used
71             my ($class,$database,$table_name) = @_;
72             assert(@_ == 3, 'parameter count');
73             assert(UNIVERSAL::isa($class,__PACKAGE__));
74             assert(defined($table_name), "resolve_table_info requires a table name");
75             return $table_name if UNIVERSAL::isa($table_name,'DBomb::Meta::TableInfo');
76             return $class->tables->{$table_name} if exists $class->tables->{$table_name};
77              
78             ## Ok, it's not a table name. maybe it is a package name.
79              
80             for (values %{$class->tables}){
81             next unless UNIVERSAL::isa($_,'DBomb::TableInfo');
82              
83             ## TODO: compare database name too.
84             return $_ if is_same_value($_->class, $table_name);
85             }
86              
87             undef; ## not found
88             }
89              
90             ## push code to be run after resolve. caller information is for error handling
91             ## do_after_resolve(sub{...}, $args, [caller])
92             sub do_after_resolve
93             {
94             my ($class,$coderef,$args, $caller) = @_;
95             assert(UNIVERSAL::isa($coderef,'CODE'), 'do_after_resolve requires a coderef');
96             assert(UNIVERSAL::isa($args,'ARRAY'), 'do_after_resolve requires an args listref');
97             assert(UNIVERSAL::isa($caller,'ARRAY'), 'do_after_resolve requires a caller listref');
98             assert(@$caller >= 4, 'do_after_resolve requires a valid caller list.');
99              
100             push @{$class->todo_after_resolve}, [ $coderef, $args, $caller];
101             }
102              
103             1;
104             __END__