File Coverage

blib/lib/DBIx/Class/ResultSourceHandle.pm
Criterion Covered Total %
statement 43 46 93.4
branch 10 16 62.5
condition 3 9 33.3
subroutine 12 12 100.0
pod 4 4 100.0
total 72 87 82.7


line stmt bran cond sub pod time code
1             package DBIx::Class::ResultSourceHandle;
2              
3 8     8   71741 use strict;
  8         18  
  8         225  
4 8     8   36 use warnings;
  8         16  
  8         218  
5              
6 8     8   37 use base qw/DBIx::Class/;
  8         16  
  8         925  
7              
8 8     8   50 use DBIx::Class::_Util 'dbic_internal_try';
  8         16  
  8         388  
9 8     8   44 use namespace::clean;
  8         19  
  8         50  
10              
11             use overload
12 2     2   10 q/""/ => sub { __PACKAGE__ . ":" . shift->source_moniker; },
13 8     8   1912 fallback => 1;
  8         18  
  8         73  
14              
15             __PACKAGE__->mk_group_accessors('simple' => qw/schema source_moniker _detached_source/);
16              
17             # Schema to use when thawing.
18             our $thaw_schema;
19              
20             =head1 NAME
21              
22             DBIx::Class::ResultSourceHandle - Serializable pointers to ResultSource instances
23              
24             =head1 DESCRIPTION
25              
26             Currently instances of this class are used to allow proper serialization of
27             L (which may contain unserializable
28             elements like C references).
29              
30             Originally this module was used to remove the fixed link between
31             L/L and the actual
32             L in order to obviate the need
33             of keeping a L constantly in scope, while
34             at the same time avoiding leaks due to circular dependencies. This is however
35             no longer needed after introduction of a proper mutual-assured-destruction
36             contract between a C instance and its C registrants.
37              
38             =head1 METHODS
39              
40             =head2 new
41              
42             =cut
43              
44             sub new {
45 206     206 1 447 my ($class, $args) = @_;
46 206   33     851 my $self = bless $args, ref $class || $class;
47              
48 206 50 33     2416 unless( ($self->{schema} || $self->{_detached_source}) && $self->{source_moniker} ) {
      33        
49 0         0 my $err = 'Expecting a schema instance and a source moniker';
50             $self->{schema}
51 0 0       0 ? $self->{schema}->throw_exception($err)
52             : DBIx::Class::Exception->throw($err)
53             }
54              
55 206         778 $self;
56             }
57              
58             =head2 resolve
59              
60             Resolve the moniker into the actual ResultSource object
61              
62             =cut
63              
64             sub resolve {
65 198 100   198 1 3293 return $_[0]->{schema}->source($_[0]->source_moniker) if $_[0]->{schema};
66              
67 57 50       1379 $_[0]->_detached_source || DBIx::Class::Exception->throw( sprintf (
68             # vague error message as this is never supposed to happen
69             "Unable to resolve moniker '%s' - please contact the dev team at %s",
70             $_[0]->source_moniker,
71             DBIx::Class::_ENV_::HELP_URL,
72             ), 'full_stacktrace');
73             }
74              
75             =head2 STORABLE_freeze
76              
77             Freezes a handle.
78              
79             =cut
80              
81             sub STORABLE_freeze {
82 207     207 1 4522 my ($self, $cloning) = @_;
83              
84 207         675 my $to_serialize = { %$self };
85              
86 207         445 delete $to_serialize->{schema};
87 207         358 delete $to_serialize->{_detached_source};
88             $to_serialize->{_frozen_from_class} = $self->{schema}
89             ? $self->{schema}->class($self->source_moniker)
90             : $self->{_detached_source}->result_class
91 207 50       1039 ;
92              
93 207         681 Storable::nfreeze($to_serialize);
94             }
95              
96             =head2 STORABLE_thaw
97              
98             Thaws frozen handle. Resets the internal schema reference to the package
99             variable C<$thaw_schema>. The recommended way of setting this is to use
100             C<< $schema->thaw($ice) >> which handles this for you.
101              
102             =cut
103              
104             sub STORABLE_thaw {
105 199     199 1 2370 my ($self, $cloning, $ice) = @_;
106 199         305 %$self = %{ Storable::thaw($ice) };
  199         385  
107              
108 199         3770 my $from_class = delete $self->{_frozen_from_class};
109              
110 199 100       3932 if( $thaw_schema ) {
    50          
111 22         177 $self->schema( $thaw_schema );
112             }
113             elsif( my $rs = $from_class->result_source_instance ) {
114             # in the off-chance we are using CDBI-compat and have leaked $schema already
115 177 100   177   3435 if( my $s = dbic_internal_try { $rs->schema } ) {
  177         473  
116 119         898 $self->schema( $s );
117             }
118             else {
119             # FIXME do not use accessor here - will trigger the divergent meta logic
120             # Ideally this should be investigated and fixed properly, but the
121             # codepath is so obscure, and the trigger point (t/52leaks.t) so bizarre
122             # that... meh.
123 58         198 $rs->{source_name} = $self->source_moniker;
124              
125 58         92 $rs->{_detached_thaw} = 1;
126 58         483 $self->_detached_source( $rs );
127             }
128             }
129             else {
130 0           DBIx::Class::Exception->throw(
131             "Thaw failed - original result class '$from_class' does not exist on this system"
132             );
133             }
134             }
135              
136             =head1 FURTHER QUESTIONS?
137              
138             Check the list of L.
139              
140             =head1 COPYRIGHT AND LICENSE
141              
142             This module is free software L
143             by the L. You can
144             redistribute it and/or modify it under the same terms as the
145             L.
146              
147             =cut
148              
149             1;