File Coverage

blib/lib/DBIx/DataModel/Source/Join.pm
Criterion Covered Total %
statement 25 33 75.7
branch 2 6 33.3
condition 0 3 0.0
subroutine 8 9 88.8
pod 0 3 0.0
total 35 54 64.8


line stmt bran cond sub pod time code
1             package DBIx::DataModel::Source::Join;
2 17     17   136 use warnings;
  17         39  
  17         564  
3 17     17   94 use strict;
  17         36  
  17         374  
4 17     17   83 use parent 'DBIx::DataModel::Source';
  17         33  
  17         94  
5 17     17   691 use mro 'c3';
  17         41  
  17         87  
6             require 5.008; # for filehandle in memory
7 17     17   494 use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)];
  17         32  
  17         57  
8              
9             sub db_from {
10 43     43 0 126 my $self = shift;
11              
12             # list of join components from the Meta::Join
13 43         85 my $db_from = $self->metadm->db_from;
14              
15             # if there is no db_schema, just return that list
16 43 50       88 my $db_schema = $self->schema->db_schema
17             or return $db_from;
18              
19             # otherwise, prefix each table in list with $db_schema. The list is of
20             # shape: [-join => $table1, $join_spec1, $table2, $join_spec2 .... $table_n];
21             # therefore tables are at odd positions in the list. Tables already containing
22             # a '.' are left untouched.
23 0         0 my @copy = @$db_from;
24 0         0 for (my $i=1; $i < @copy; $i += 2) {
25 0   0     0 /\./ or $_ = "$db_schema.$_" for $copy[$i];
26             }
27              
28 0         0 return \@copy;
29             }
30              
31              
32              
33              
34             # Support for Storable::{freeze,thaw} : just a stupid blank operation,
35             # but that will force Storable::thaw to try to reload the join class ...
36             # and then we can catch it and generate it on the fly (see @INC below)
37              
38             sub STORABLE_freeze {
39 0     0 0 0 my ($self, $is_cloning) = @_;
40              
41 0 0       0 return if $is_cloning;
42 0         0 my $copy = {%$self};
43 0         0 return Storable::freeze($copy);
44             }
45              
46             sub STORABLE_thaw {
47 3     3 0 43 my ($self, $is_cloning, $serialized) = @_;
48              
49 3 50       6 return if $is_cloning;
50 3         8 my $copy = Storable::thaw($serialized);
51 3         91 %$self = %$copy;
52             }
53              
54             # Add a coderef handler into @INC, so that when Storable::thaw tries to load
55             # a join, we take control, generate the Join on the fly, and return
56             # a fake file to load.
57              
58             push @INC, sub { # coderef into @INC: see L
59             my ($self_coderef, $filename) = @_;
60              
61             # did we try to load an AutoJoin ?
62             my ($schema, $join) = ($filename =~ m[^(.+?)/AutoJoin/(.+)$])
63             or return;
64              
65             # is it really an AutoJoin in DBIx::DataModel ?
66             $schema =~ s[/][::]g;
67             $schema->isa('DBIx::DataModel::Schema')
68             or return;
69              
70             # OK, this is really our business. Parse the join name into path items, i.e.
71             # qw/My::Table <=> path1 => path2 => .../
72             $join =~ s/\.pm$//;
73             my ($initial_table, @paths) = split /()/, $join;
74             $initial_table =~ s[/][::]g;
75              
76             # ask schema to create the Join
77             $schema->metadm->define_join($initial_table, @paths);
78              
79             # return a fake filehandle in memory so that "require" is happy
80 1     1   27 open my $fh, "<", \"1"; # pseudo-file just containing "1"
  1         3  
  1         26  
81              
82             return $fh;
83             };
84              
85              
86              
87              
88             1; # End of DBIx::DataModel::Source::Join
89              
90             __END__