153d7292f4d969435450240f72f49dd7c60b3880
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
1 package DBIx::Class::Schema;
2
3 use strict;
4 use warnings;
5
6 use base 'DBIx::Class';
7
8 use DBIx::Class::Carp;
9 use Try::Tiny;
10 use Scalar::Util qw/weaken blessed/;
11 use DBIx::Class::_Util qw(
12   refcount quote_sub scope_guard
13   is_exception dbic_internal_try
14   fail_on_internal_call emit_loud_diag
15 );
16 use Devel::GlobalDestruction;
17 use namespace::clean;
18
19 __PACKAGE__->mk_group_accessors( inherited => qw( storage exception_action ) );
20 __PACKAGE__->mk_classaccessor('storage_type' => '::DBI');
21 __PACKAGE__->mk_classaccessor('stacktrace' => $ENV{DBIC_TRACE} || 0);
22 __PACKAGE__->mk_classaccessor('default_resultset_attributes' => {});
23
24 # These two should have been private from the start but too late now
25 # Undocumented on purpose, hopefully it won't ever be necessary to
26 # screw with them
27 __PACKAGE__->mk_classaccessor('class_mappings' => {});
28 __PACKAGE__->mk_classaccessor('source_registrations' => {});
29
30 =head1 NAME
31
32 DBIx::Class::Schema - composable schemas
33
34 =head1 SYNOPSIS
35
36   package Library::Schema;
37   use base qw/DBIx::Class::Schema/;
38
39   # load all Result classes in Library/Schema/Result/
40   __PACKAGE__->load_namespaces();
41
42   package Library::Schema::Result::CD;
43   use base qw/DBIx::Class::Core/;
44
45   __PACKAGE__->load_components(qw/InflateColumn::DateTime/); # for example
46   __PACKAGE__->table('cd');
47
48   # Elsewhere in your code:
49   my $schema1 = Library::Schema->connect(
50     $dsn,
51     $user,
52     $password,
53     { AutoCommit => 1 },
54   );
55
56   my $schema2 = Library::Schema->connect($coderef_returning_dbh);
57
58   # fetch objects using Library::Schema::Result::DVD
59   my $resultset = $schema1->resultset('DVD')->search( ... );
60   my @dvd_objects = $schema2->resultset('DVD')->search( ... );
61
62 =head1 DESCRIPTION
63
64 Creates database classes based on a schema. This is the recommended way to
65 use L<DBIx::Class> and allows you to use more than one concurrent connection
66 with your classes.
67
68 NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
69 carefully, as DBIx::Class does things a little differently. Note in
70 particular which module inherits off which.
71
72 =head1 SETUP METHODS
73
74 =head2 load_namespaces
75
76 =over 4
77
78 =item Arguments: %options?
79
80 =back
81
82   package MyApp::Schema;
83   __PACKAGE__->load_namespaces();
84
85   __PACKAGE__->load_namespaces(
86      result_namespace => 'Res',
87      resultset_namespace => 'RSet',
88      default_resultset_class => '+MyApp::Othernamespace::RSet',
89   );
90
91 With no arguments, this method uses L<Module::Find> to load all of the
92 Result and ResultSet classes under the namespace of the schema from
93 which it is called.  For example, C<My::Schema> will by default find
94 and load Result classes named C<My::Schema::Result::*> and ResultSet
95 classes named C<My::Schema::ResultSet::*>.
96
97 ResultSet classes are associated with Result class of the same name.
98 For example, C<My::Schema::Result::CD> will get the ResultSet class
99 C<My::Schema::ResultSet::CD> if it is present.
100
101 Both Result and ResultSet namespaces are configurable via the
102 C<result_namespace> and C<resultset_namespace> options.
103
104 Another option, C<default_resultset_class> specifies a custom default
105 ResultSet class for Result classes with no corresponding ResultSet.
106
107 All of the namespace and classname options are by default relative to
108 the schema classname.  To specify a fully-qualified name, prefix it
109 with a literal C<+>.  For example, C<+Other::NameSpace::Result>.
110
111 =head3 Warnings
112
113 You will be warned if ResultSet classes are discovered for which there
114 are no matching Result classes like this:
115
116   load_namespaces found ResultSet class $classname with no corresponding Result class
117
118 If a ResultSource instance is found to already have a ResultSet class set
119 using L<resultset_class|DBIx::Class::ResultSource/resultset_class> to some
120 other class, you will be warned like this:
121
122   We found ResultSet class '$rs_class' for '$result_class', but it seems
123   that you had already set '$result_class' to use '$rs_set' instead
124
125 =head3 Examples
126
127   # load My::Schema::Result::CD, My::Schema::Result::Artist,
128   #    My::Schema::ResultSet::CD, etc...
129   My::Schema->load_namespaces;
130
131   # Override everything to use ugly names.
132   # In this example, if there is a My::Schema::Res::Foo, but no matching
133   #   My::Schema::RSets::Foo, then Foo will have its
134   #   resultset_class set to My::Schema::RSetBase
135   My::Schema->load_namespaces(
136     result_namespace => 'Res',
137     resultset_namespace => 'RSets',
138     default_resultset_class => 'RSetBase',
139   );
140
141   # Put things in other namespaces
142   My::Schema->load_namespaces(
143     result_namespace => '+Some::Place::Results',
144     resultset_namespace => '+Another::Place::RSets',
145   );
146
147 To search multiple namespaces for either Result or ResultSet classes,
148 use an arrayref of namespaces for that option.  In the case that the
149 same result (or resultset) class exists in multiple namespaces, later
150 entries in the list of namespaces will override earlier ones.
151
152   My::Schema->load_namespaces(
153     # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
154     result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
155     resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
156   );
157
158 =cut
159
160 # Pre-pends our classname to the given relative classname or
161 #   class namespace, unless there is a '+' prefix, which will
162 #   be stripped.
163 sub _expand_relative_name {
164   my ($class, $name) = @_;
165   $name =~ s/^\+// or $name = "${class}::${name}";
166   return $name;
167 }
168
169 # Finds all modules in the supplied namespace, or if omitted in the
170 # namespace of $class. Untaints all findings as they can be assumed
171 # to be safe
172 sub _findallmod {
173   require Module::Find;
174   return map
175     { $_ =~ /(.+)/ }   # untaint result
176     Module::Find::findallmod( $_[1] || ref $_[0] || $_[0] )
177   ;
178 }
179
180 # returns a hash of $shortname => $fullname for every package
181 # found in the given namespaces ($shortname is with the $fullname's
182 # namespace stripped off)
183 sub _map_namespaces {
184   my ($me, $namespaces) = @_;
185
186   my %res;
187   for my $ns (@$namespaces) {
188     $res{ substr($_, length "${ns}::") } = $_
189       for $me->_findallmod($ns);
190   }
191
192   \%res;
193 }
194
195 # returns the result_source_instance for the passed class/object,
196 # or dies with an informative message (used by load_namespaces)
197 sub _ns_get_rsrc_instance {
198   my $me = shift;
199   my $rs_class = ref ($_[0]) || $_[0];
200
201   return dbic_internal_try {
202     $rs_class->result_source_instance
203   } catch {
204     $me->throw_exception (
205       "Attempt to load_namespaces() class $rs_class failed - are you sure this is a real Result Class?: $_"
206     );
207   };
208 }
209
210 sub load_namespaces {
211   my ($class, %args) = @_;
212
213   my $result_namespace = delete $args{result_namespace} || 'Result';
214   my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
215
216   my $default_resultset_class = delete $args{default_resultset_class};
217
218   $default_resultset_class = $class->_expand_relative_name($default_resultset_class)
219     if $default_resultset_class;
220
221   $class->throw_exception('load_namespaces: unknown option(s): '
222     . join(q{,}, map { qq{'$_'} } keys %args))
223       if scalar keys %args;
224
225   for my $arg ($result_namespace, $resultset_namespace) {
226     $arg = [ $arg ] if ( $arg and ! ref $arg );
227
228     $class->throw_exception('load_namespaces: namespace arguments must be '
229       . 'a simple string or an arrayref')
230         if ref($arg) ne 'ARRAY';
231
232     $_ = $class->_expand_relative_name($_) for (@$arg);
233   }
234
235   my $results_by_source_name = $class->_map_namespaces($result_namespace);
236   my $resultsets_by_source_name = $class->_map_namespaces($resultset_namespace);
237
238   my @to_register;
239   {
240     no warnings qw/redefine/;
241     local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
242     use warnings qw/redefine/;
243
244     # ensure classes are loaded and attached in inheritance order
245     for my $result_class (values %$results_by_source_name) {
246       $class->ensure_class_loaded($result_class);
247     }
248     my %inh_idx;
249     my @source_names_by_subclass_last = sort {
250
251       ($inh_idx{$a} ||=
252         scalar @{mro::get_linear_isa( $results_by_source_name->{$a} )}
253       )
254
255           <=>
256
257       ($inh_idx{$b} ||=
258         scalar @{mro::get_linear_isa( $results_by_source_name->{$b} )}
259       )
260
261     } keys(%$results_by_source_name);
262
263     foreach my $source_name (@source_names_by_subclass_last) {
264       my $result_class = $results_by_source_name->{$source_name};
265
266       my $preset_resultset_class = $class->_ns_get_rsrc_instance ($result_class)->resultset_class;
267       my $found_resultset_class = delete $resultsets_by_source_name->{$source_name};
268
269       if($preset_resultset_class && $preset_resultset_class ne 'DBIx::Class::ResultSet') {
270         if($found_resultset_class && $found_resultset_class ne $preset_resultset_class) {
271           carp "We found ResultSet class '$found_resultset_class' matching '$results_by_source_name->{$source_name}', but it seems "
272              . "that you had already set the '$results_by_source_name->{$source_name}' resultet to '$preset_resultset_class' instead";
273         }
274       }
275       # elsif - there may be *no* default_resultset_class, in which case we fallback to
276       # DBIx::Class::Resultset and there is nothing to check
277       elsif($found_resultset_class ||= $default_resultset_class) {
278         $class->ensure_class_loaded($found_resultset_class);
279         if(!$found_resultset_class->isa("DBIx::Class::ResultSet")) {
280             carp "load_namespaces found ResultSet class '$found_resultset_class' that does not subclass DBIx::Class::ResultSet";
281         }
282
283         $class->_ns_get_rsrc_instance ($result_class)->resultset_class($found_resultset_class);
284       }
285
286       my $source_name = $class->_ns_get_rsrc_instance ($result_class)->source_name || $source_name;
287
288       push(@to_register, [ $source_name, $result_class ]);
289     }
290   }
291
292   foreach (sort keys %$resultsets_by_source_name) {
293     carp "load_namespaces found ResultSet class '$resultsets_by_source_name->{$_}' "
294         .'with no corresponding Result class';
295   }
296
297   Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
298
299   $class->register_class(@$_) for (@to_register);
300
301   return;
302 }
303
304 =head2 load_classes
305
306 =over 4
307
308 =item Arguments: @classes?, { $namespace => [ @classes ] }+
309
310 =back
311
312 L</load_classes> is an alternative method to L</load_namespaces>, both of
313 which serve similar purposes, each with different advantages and disadvantages.
314 In the general case you should use L</load_namespaces>, unless you need to
315 be able to specify that only specific classes are loaded at runtime.
316
317 With no arguments, this method uses L<Module::Find> to find all classes under
318 the schema's namespace. Otherwise, this method loads the classes you specify
319 (using L<use>), and registers them (using L</"register_class">).
320
321 It is possible to comment out classes with a leading C<#>, but note that perl
322 will think it's a mistake (trying to use a comment in a qw list), so you'll
323 need to add C<no warnings 'qw';> before your load_classes call.
324
325 If any classes found do not appear to be Result class files, you will
326 get the following warning:
327
328    Failed to load $comp_class. Can't find source_name method. Is
329    $comp_class really a full DBIC result class? Fix it, move it elsewhere,
330    or make your load_classes call more specific.
331
332 Example:
333
334   My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
335                               # etc. (anything under the My::Schema namespace)
336
337   # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
338   # not Other::Namespace::LinerNotes nor My::Schema::Track
339   My::Schema->load_classes(qw/ CD Artist #Track /, {
340     Other::Namespace => [qw/ Producer #LinerNotes /],
341   });
342
343 =cut
344
345 sub load_classes {
346   my ($class, @params) = @_;
347
348   my %comps_for;
349
350   if (@params) {
351     foreach my $param (@params) {
352       if (ref $param eq 'ARRAY') {
353         # filter out commented entries
354         my @modules = grep { $_ !~ /^#/ } @$param;
355
356         push (@{$comps_for{$class}}, @modules);
357       }
358       elsif (ref $param eq 'HASH') {
359         # more than one namespace possible
360         for my $comp ( keys %$param ) {
361           # filter out commented entries
362           my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
363
364           push (@{$comps_for{$comp}}, @modules);
365         }
366       }
367       else {
368         # filter out commented entries
369         push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
370       }
371     }
372   } else {
373     my @comp = map { substr $_, length "${class}::"  }
374                  $class->_findallmod($class);
375     $comps_for{$class} = \@comp;
376   }
377
378   my @to_register;
379   {
380     no warnings qw/redefine/;
381     local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
382     use warnings qw/redefine/;
383
384     foreach my $prefix (keys %comps_for) {
385       foreach my $comp (@{$comps_for{$prefix}||[]}) {
386         my $comp_class = "${prefix}::${comp}";
387         $class->ensure_class_loaded($comp_class);
388
389         my $snsub = $comp_class->can('source_name');
390         if(! $snsub ) {
391           carp "Failed to load $comp_class. Can't find source_name method. Is $comp_class really a full DBIC result class? Fix it, move it elsewhere, or make your load_classes call more specific.";
392           next;
393         }
394         $comp = $snsub->($comp_class) || $comp;
395
396         push(@to_register, [ $comp, $comp_class ]);
397       }
398     }
399   }
400   Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
401
402   foreach my $to (@to_register) {
403     $class->register_class(@$to);
404   }
405 }
406
407 =head2 storage_type
408
409 =over 4
410
411 =item Arguments: $storage_type|{$storage_type, \%args}
412
413 =item Return Value: $storage_type|{$storage_type, \%args}
414
415 =item Default value: DBIx::Class::Storage::DBI
416
417 =back
418
419 Set the storage class that will be instantiated when L</connect> is called.
420 If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
421 assumed by L</connect>.
422
423 You want to use this to set subclasses of L<DBIx::Class::Storage::DBI>
424 in cases where the appropriate subclass is not autodetected.
425
426 If your storage type requires instantiation arguments, those are
427 defined as a second argument in the form of a hashref and the entire
428 value needs to be wrapped into an arrayref or a hashref.  We support
429 both types of refs here in order to play nice with your
430 Config::[class] or your choice. See
431 L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
432
433 =head2 default_resultset_attributes
434
435 =over 4
436
437 =item Arguments: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
438
439 =item Return Value: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
440
441 =item Default value: None
442
443 =back
444
445 Like L<DBIx::Class::ResultSource/resultset_attributes> stores a collection
446 of resultset attributes, to be used as defaults for B<every> ResultSet
447 instance schema-wide. The same list of CAVEATS and WARNINGS applies, with
448 the extra downside of these defaults being practically inescapable: you will
449 B<not> be able to derive a ResultSet instance with these attributes unset.
450
451 Example:
452
453    package My::Schema;
454    use base qw/DBIx::Class::Schema/;
455    __PACKAGE__->default_resultset_attributes( { software_limit => 1 } );
456
457 =head2 exception_action
458
459 =over 4
460
461 =item Arguments: $code_reference
462
463 =item Return Value: $code_reference
464
465 =item Default value: None
466
467 =back
468
469 When L</throw_exception> is invoked and L</exception_action> is set to a code
470 reference, this reference will be called instead of
471 L<DBIx::Class::Exception/throw>, with the exception message passed as the only
472 argument.
473
474 Your custom throw code B<must> rethrow the exception, as L</throw_exception> is
475 an integral part of DBIC's internal execution control flow.
476
477 Example:
478
479    package My::Schema;
480    use base qw/DBIx::Class::Schema/;
481    use My::ExceptionClass;
482    __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
483    __PACKAGE__->load_classes;
484
485    # or:
486    my $schema_obj = My::Schema->connect( .... );
487    $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
488
489 =head2 stacktrace
490
491 =over 4
492
493 =item Arguments: boolean
494
495 =back
496
497 Whether L</throw_exception> should include stack trace information.
498 Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
499 is true.
500
501 =head2 sqlt_deploy_hook
502
503 =over
504
505 =item Arguments: $sqlt_schema
506
507 =back
508
509 An optional sub which you can declare in your own Schema class that will get
510 passed the L<SQL::Translator::Schema> object when you deploy the schema via
511 L</create_ddl_dir> or L</deploy>.
512
513 For an example of what you can do with this, see
514 L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
515
516 Note that sqlt_deploy_hook is called by L</deployment_statements>, which in turn
517 is called before L</deploy>. Therefore the hook can be used only to manipulate
518 the L<SQL::Translator::Schema> object before it is turned into SQL fed to the
519 database. If you want to execute post-deploy statements which can not be generated
520 by L<SQL::Translator>, the currently suggested method is to overload L</deploy>
521 and use L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
522
523 =head1 METHODS
524
525 =head2 connect
526
527 =over 4
528
529 =item Arguments: @connectinfo
530
531 =item Return Value: $new_schema
532
533 =back
534
535 Creates and returns a new Schema object. The connection info set on it
536 is used to create a new instance of the storage backend and set it on
537 the Schema object.
538
539 See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific
540 syntax on the C<@connectinfo> argument, or L<DBIx::Class::Storage> in
541 general.
542
543 Note that C<connect_info> expects an arrayref of arguments, but
544 C<connect> does not. C<connect> wraps its arguments in an arrayref
545 before passing them to C<connect_info>.
546
547 =head3 Overloading
548
549 C<connect> is a convenience method. It is equivalent to calling
550 $schema->clone->connection(@connectinfo). To write your own overloaded
551 version, overload L</connection> instead.
552
553 =cut
554
555 sub connect {
556   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
557   shift->clone->connection(@_);
558 }
559
560 =head2 resultset
561
562 =over 4
563
564 =item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
565
566 =item Return Value: L<$resultset|DBIx::Class::ResultSet>
567
568 =back
569
570   my $rs = $schema->resultset('DVD');
571
572 Returns the L<DBIx::Class::ResultSet> object for the registered source
573 name.
574
575 =cut
576
577 sub resultset {
578   my ($self, $source_name) = @_;
579   $self->throw_exception('resultset() expects a source name')
580     unless defined $source_name;
581   return $self->source($source_name)->resultset;
582 }
583
584 =head2 sources
585
586 =over 4
587
588 =item Return Value: L<@source_names|DBIx::Class::ResultSource/source_name>
589
590 =back
591
592   my @source_names = $schema->sources;
593
594 Lists names of all the sources registered on this Schema object.
595
596 =cut
597
598 sub sources { keys %{shift->source_registrations} }
599
600 =head2 source
601
602 =over 4
603
604 =item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
605
606 =item Return Value: L<$result_source|DBIx::Class::ResultSource>
607
608 =back
609
610   my $source = $schema->source('Book');
611
612 Returns the L<DBIx::Class::ResultSource> object for the registered
613 source name.
614
615 =cut
616
617 sub source {
618   my ($self, $source_name) = @_;
619
620   $self->throw_exception("source() expects a source name")
621     unless $source_name;
622
623   my $source_registrations;
624
625   my $rsrc =
626     ( $source_registrations = $self->source_registrations )->{$source_name}
627       ||
628     # if we got here, they probably passed a full class name
629     $source_registrations->{ $self->class_mappings->{$source_name} || '' }
630       ||
631     $self->throw_exception( "Can't find source for ${source_name}" )
632   ;
633
634   # DO NOT REMOVE:
635   # We need to prevent alterations of pre-existing $@ due to where this call
636   # sits in the overall stack ( *unless* of course there is an actual error
637   # to report ). set_mro does alter $@ (and yes - it *can* throw an exception)
638   # We do not use local because set_mro *can* throw an actual exception
639   # We do not use a try/catch either, as on one hand it would slow things
640   # down for no reason (we would always rethrow), but also because adding *any*
641   # try/catch block below will segfault various threading tests on older perls
642   # ( which in itself is a FIXME but ENOTIMETODIG )
643   my $old_dollarat = $@;
644
645   no strict 'refs';
646   mro::set_mro($_, 'c3') for
647     grep
648       {
649         # some pseudo-sources do not have a result/resultset yet
650         defined $_
651           and
652         (
653           (
654             ${"${_}::__INITIAL_MRO_UPON_DBIC_LOAD__"}
655               ||= mro::get_mro($_)
656           )
657             ne
658           'c3'
659         )
660       }
661       map
662         { length ref $_ ? ref $_ : $_ }
663         ( $rsrc, $rsrc->result_class, $rsrc->resultset_class )
664   ;
665
666   # DO NOT REMOVE - see comment above
667   $@ = $old_dollarat;
668
669   $rsrc;
670 }
671
672 =head2 class
673
674 =over 4
675
676 =item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
677
678 =item Return Value: $classname
679
680 =back
681
682   my $class = $schema->class('CD');
683
684 Retrieves the Result class name for the given source name.
685
686 =cut
687
688 sub class {
689   return shift->source(shift)->result_class;
690 }
691
692 =head2 txn_do
693
694 =over 4
695
696 =item Arguments: C<$coderef>, @coderef_args?
697
698 =item Return Value: The return value of $coderef
699
700 =back
701
702 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
703 returning its result (if any). Equivalent to calling $schema->storage->txn_do.
704 See L<DBIx::Class::Storage/"txn_do"> for more information.
705
706 This interface is preferred over using the individual methods L</txn_begin>,
707 L</txn_commit>, and L</txn_rollback> below.
708
709 WARNING: If you are connected with C<< AutoCommit => 0 >> the transaction is
710 considered nested, and you will still need to call L</txn_commit> to write your
711 changes when appropriate. You will also want to connect with C<< auto_savepoint =>
712 1 >> to get partial rollback to work, if the storage driver for your database
713 supports it.
714
715 Connecting with C<< AutoCommit => 1 >> is recommended.
716
717 =cut
718
719 sub txn_do {
720   my $self = shift;
721
722   $self->storage or $self->throw_exception
723     ('txn_do called on $schema without storage');
724
725   $self->storage->txn_do(@_);
726 }
727
728 =head2 txn_scope_guard
729
730 Runs C<txn_scope_guard> on the schema's storage. See
731 L<DBIx::Class::Storage/txn_scope_guard>.
732
733 =cut
734
735 sub txn_scope_guard {
736   my $self = shift;
737
738   $self->storage or $self->throw_exception
739     ('txn_scope_guard called on $schema without storage');
740
741   $self->storage->txn_scope_guard(@_);
742 }
743
744 =head2 txn_begin
745
746 Begins a transaction (does nothing if AutoCommit is off). Equivalent to
747 calling $schema->storage->txn_begin. See
748 L<DBIx::Class::Storage/"txn_begin"> for more information.
749
750 =cut
751
752 sub txn_begin {
753   my $self = shift;
754
755   $self->storage or $self->throw_exception
756     ('txn_begin called on $schema without storage');
757
758   $self->storage->txn_begin;
759 }
760
761 =head2 txn_commit
762
763 Commits the current transaction. Equivalent to calling
764 $schema->storage->txn_commit. See L<DBIx::Class::Storage/"txn_commit">
765 for more information.
766
767 =cut
768
769 sub txn_commit {
770   my $self = shift;
771
772   $self->storage or $self->throw_exception
773     ('txn_commit called on $schema without storage');
774
775   $self->storage->txn_commit;
776 }
777
778 =head2 txn_rollback
779
780 Rolls back the current transaction. Equivalent to calling
781 $schema->storage->txn_rollback. See
782 L<DBIx::Class::Storage/"txn_rollback"> for more information.
783
784 =cut
785
786 sub txn_rollback {
787   my $self = shift;
788
789   $self->storage or $self->throw_exception
790     ('txn_rollback called on $schema without storage');
791
792   $self->storage->txn_rollback;
793 }
794
795 =head2 storage
796
797   my $storage = $schema->storage;
798
799 Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
800 if you want to turn on SQL statement debugging at runtime, or set the
801 quote character. For the default storage, the documentation can be
802 found in L<DBIx::Class::Storage::DBI>.
803
804 =head2 populate
805
806 =over 4
807
808 =item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>, [ \@column_list, \@row_values+ ] | [ \%col_data+ ]
809
810 =item Return Value: L<\@result_objects|DBIx::Class::Manual::ResultClass> (scalar context) | L<@result_objects|DBIx::Class::Manual::ResultClass> (list context)
811
812 =back
813
814 A convenience shortcut to L<DBIx::Class::ResultSet/populate>. Equivalent to:
815
816  $schema->resultset($source_name)->populate([...]);
817
818 =over 4
819
820 =item NOTE
821
822 The context of this method call has an important effect on what is
823 submitted to storage. In void context data is fed directly to fastpath
824 insertion routines provided by the underlying storage (most often
825 L<DBI/execute_for_fetch>), bypassing the L<new|DBIx::Class::Row/new> and
826 L<insert|DBIx::Class::Row/insert> calls on the
827 L<Result|DBIx::Class::Manual::ResultClass> class, including any
828 augmentation of these methods provided by components. For example if you
829 are using something like L<DBIx::Class::UUIDColumns> to create primary
830 keys for you, you will find that your PKs are empty.  In this case you
831 will have to explicitly force scalar or list context in order to create
832 those values.
833
834 =back
835
836 =cut
837
838 sub populate {
839   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
840
841   my ($self, $name, $data) = @_;
842   my $rs = $self->resultset($name)
843     or $self->throw_exception("'$name' is not a resultset");
844
845   return $rs->populate($data);
846 }
847
848 =head2 connection
849
850 =over 4
851
852 =item Arguments: @args
853
854 =item Return Value: $self
855
856 =back
857
858 Similar to L</connect> except sets the storage object and connection
859 data B<in-place> on C<$self>. You should probably be calling
860 L</connect> to get a properly L<cloned|/clone> Schema object instead.
861
862 =head3 Overloading
863
864 Overload C<connection> to change the behaviour of C<connect>.
865
866 =cut
867
868 sub connection {
869   my ($self, @info) = @_;
870   return $self if !@info && $self->storage;
871
872   my ($storage_class, $args) = ref $self->storage_type
873     ? $self->_normalize_storage_type($self->storage_type)
874     : $self->storage_type
875   ;
876
877   $storage_class =~ s/^::/DBIx::Class::Storage::/;
878
879   dbic_internal_try {
880     $self->ensure_class_loaded ($storage_class);
881   }
882   catch {
883     $self->throw_exception(
884       "Unable to load storage class ${storage_class}: $_"
885     );
886   };
887
888   my $storage = $storage_class->new( $self => $args||{} );
889   $storage->connect_info(\@info);
890   $self->storage($storage);
891   return $self;
892 }
893
894 sub _normalize_storage_type {
895   my ($self, $storage_type) = @_;
896   if(ref $storage_type eq 'ARRAY') {
897     return @$storage_type;
898   } elsif(ref $storage_type eq 'HASH') {
899     return %$storage_type;
900   } else {
901     $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
902   }
903 }
904
905 =head2 compose_namespace
906
907 =over 4
908
909 =item Arguments: $target_namespace, $additional_base_class?
910
911 =item Return Value: $new_schema
912
913 =back
914
915 For each L<DBIx::Class::ResultSource> in the schema, this method creates a
916 class in the target namespace (e.g. $target_namespace::CD,
917 $target_namespace::Artist) that inherits from the corresponding classes
918 attached to the current schema.
919
920 It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
921 new $schema object. If C<$additional_base_class> is given, the new composed
922 classes will inherit from first the corresponding class from the current
923 schema then the base class.
924
925 For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
926
927   $schema->compose_namespace('My::DB', 'Base::Class');
928   print join (', ', @My::DB::CD::ISA) . "\n";
929   print join (', ', @My::DB::Artist::ISA) ."\n";
930
931 will produce the output
932
933   My::Schema::CD, Base::Class
934   My::Schema::Artist, Base::Class
935
936 =cut
937
938 sub compose_namespace {
939   my ($self, $target, $base) = @_;
940
941   my $schema = $self->clone;
942
943   $schema->source_registrations({});
944
945   # the original class-mappings must remain - otherwise
946   # reverse_relationship_info will not work
947   #$schema->class_mappings({});
948
949   {
950     no warnings qw/redefine/;
951     local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
952     use warnings qw/redefine/;
953
954     foreach my $source_name ($self->sources) {
955       my $orig_source = $self->source($source_name);
956
957       my $target_class = "${target}::${source_name}";
958       $self->inject_base($target_class, $orig_source->result_class, ($base || ()) );
959
960       $schema->register_source(
961         $source_name,
962         $orig_source->clone(
963           result_class => $target_class
964         ),
965       );
966     }
967
968     # Legacy stuff, not inserting INDIRECT assertions
969     quote_sub "${target}::${_}" => "shift->schema->$_(\@_)"
970       for qw(class source resultset);
971   }
972
973   Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
974
975   # Give each composed class yet another *schema-less* source copy
976   # this is used for the freeze/thaw cycle
977   #
978   # This is not covered by any tests directly, but is indirectly exercised
979   # in t/cdbi/sweet/08pager by re-setting the schema on an existing object
980   # FIXME - there is likely a much cheaper way to take care of this
981   for my $source_name ($self->sources) {
982
983     my $target_class = "${target}::${source_name}";
984
985     $target_class->result_source_instance(
986       $self->source($source_name)->clone(
987         result_class => $target_class,
988         schema => ( ref $schema || $schema ),
989       )
990     );
991   }
992
993   return $schema;
994 }
995
996 # LEGACY: The intra-call to this was removed in 66d9ef6b and then
997 # the sub was de-documented way later in 249963d4. No way to be sure
998 # nothing on darkpan is calling it directly, so keeping as-is
999 sub setup_connection_class {
1000   my ($class, $target, @info) = @_;
1001   $class->inject_base($target => 'DBIx::Class::DB');
1002   #$target->load_components('DB');
1003   $target->connection(@info);
1004 }
1005
1006 =head2 svp_begin
1007
1008 Creates a new savepoint (does nothing outside a transaction).
1009 Equivalent to calling $schema->storage->svp_begin.  See
1010 L<DBIx::Class::Storage/"svp_begin"> for more information.
1011
1012 =cut
1013
1014 sub svp_begin {
1015   my ($self, $name) = @_;
1016
1017   $self->storage or $self->throw_exception
1018     ('svp_begin called on $schema without storage');
1019
1020   $self->storage->svp_begin($name);
1021 }
1022
1023 =head2 svp_release
1024
1025 Releases a savepoint (does nothing outside a transaction).
1026 Equivalent to calling $schema->storage->svp_release.  See
1027 L<DBIx::Class::Storage/"svp_release"> for more information.
1028
1029 =cut
1030
1031 sub svp_release {
1032   my ($self, $name) = @_;
1033
1034   $self->storage or $self->throw_exception
1035     ('svp_release called on $schema without storage');
1036
1037   $self->storage->svp_release($name);
1038 }
1039
1040 =head2 svp_rollback
1041
1042 Rollback to a savepoint (does nothing outside a transaction).
1043 Equivalent to calling $schema->storage->svp_rollback.  See
1044 L<DBIx::Class::Storage/"svp_rollback"> for more information.
1045
1046 =cut
1047
1048 sub svp_rollback {
1049   my ($self, $name) = @_;
1050
1051   $self->storage or $self->throw_exception
1052     ('svp_rollback called on $schema without storage');
1053
1054   $self->storage->svp_rollback($name);
1055 }
1056
1057 =head2 clone
1058
1059 =over 4
1060
1061 =item Arguments: %attrs?
1062
1063 =item Return Value: $new_schema
1064
1065 =back
1066
1067 Clones the schema and its associated result_source objects and returns the
1068 copy. The resulting copy will have the same attributes as the source schema,
1069 except for those attributes explicitly overridden by the provided C<%attrs>.
1070
1071 =cut
1072
1073 sub clone {
1074   my $self = shift;
1075
1076   my $clone = {
1077       (ref $self ? %$self : ()),
1078       (@_ == 1 && ref $_[0] eq 'HASH' ? %{ $_[0] } : @_),
1079   };
1080   bless $clone, (ref $self || $self);
1081
1082   $clone->$_(undef) for qw/class_mappings source_registrations storage/;
1083
1084   $clone->_copy_state_from($self);
1085
1086   return $clone;
1087 }
1088
1089 # Needed in Schema::Loader - if you refactor, please make a compatibility shim
1090 # -- Caelum
1091 sub _copy_state_from {
1092   my ($self, $from) = @_;
1093
1094   $self->class_mappings({ %{$from->class_mappings} });
1095   $self->source_registrations({ %{$from->source_registrations} });
1096
1097   # we use extra here as we want to leave the class_mappings as they are
1098   # but overwrite the source_registrations entry with the new source
1099   $self->register_extra_source( $_ => $from->source($_) )
1100     for $from->sources;
1101
1102   if ($from->storage) {
1103     $self->storage($from->storage);
1104     $self->storage->set_schema($self);
1105   }
1106 }
1107
1108 =head2 throw_exception
1109
1110 =over 4
1111
1112 =item Arguments: $message
1113
1114 =back
1115
1116 Throws an exception. Obeys the exemption rules of L<DBIx::Class::Carp> to report
1117 errors from outer-user's perspective. See L</exception_action> for details on overriding
1118 this method's behavior.  If L</stacktrace> is turned on, C<throw_exception>'s
1119 default behavior will provide a detailed stack trace.
1120
1121 =cut
1122
1123 sub throw_exception {
1124   my ($self, @args) = @_;
1125
1126   if (
1127     ! DBIx::Class::_Util::in_internal_try()
1128       and
1129     my $act = $self->exception_action
1130   ) {
1131
1132     my $guard_disarmed;
1133
1134     my $guard = scope_guard {
1135       return if $guard_disarmed;
1136       emit_loud_diag( emit_dups => 1, msg => "
1137
1138                     !!! DBIx::Class INTERNAL PANIC !!!
1139
1140 The exception_action() handler installed on '$self'
1141 aborted the stacktrace below via a longjmp (either via Return::Multilevel or
1142 plain goto, or Scope::Upper or something equally nefarious). There currently
1143 is nothing safe DBIx::Class can do, aside from displaying this error. A future
1144 version ( 0.082900, when available ) will reduce the cases in which the
1145 handler is invoked, but this is neither a complete solution, nor can it do
1146 anything for other software that might be affected by a similar problem.
1147
1148                       !!! FIX YOUR ERROR HANDLING !!!
1149
1150 This guard was activated starting",
1151       );
1152     };
1153
1154     dbic_internal_try {
1155       # if it throws - good, we'll assign to @args in the end
1156       # if it doesn't - do different things depending on RV truthiness
1157       if( $act->(@args) ) {
1158         $args[0] = (
1159           "Invocation of the exception_action handler installed on $self did *not*"
1160         .' result in an exception. DBIx::Class is unable to function without a reliable'
1161         .' exception mechanism, ensure your exception_action does not hide exceptions'
1162         ." (original error: $args[0])"
1163         );
1164       }
1165       else {
1166         carp_unique (
1167           "The exception_action handler installed on $self returned false instead"
1168         .' of throwing an exception. This behavior has been deprecated, adjust your'
1169         .' handler to always rethrow the supplied error'
1170         );
1171       }
1172
1173       1;
1174     }
1175     catch {
1176       # We call this to get the necessary warnings emitted and disregard the RV
1177       # as it's definitely an exception if we got as far as this catch{} block
1178       is_exception(
1179         $args[0] = $_
1180       );
1181     };
1182
1183     # Done guarding against https://github.com/PerlDancer/Dancer2/issues/1125
1184     $guard_disarmed = 1;
1185   }
1186
1187   DBIx::Class::Exception->throw( $args[0], $self->stacktrace );
1188 }
1189
1190 =head2 deploy
1191
1192 =over 4
1193
1194 =item Arguments: \%sqlt_args, $dir
1195
1196 =back
1197
1198 Attempts to deploy the schema to the current storage using L<SQL::Translator>.
1199
1200 See L<SQL::Translator/METHODS> for a list of values for C<\%sqlt_args>.
1201 The most common value for this would be C<< { add_drop_table => 1 } >>
1202 to have the SQL produced include a C<DROP TABLE> statement for each table
1203 created. For quoting purposes supply C<quote_identifiers>.
1204
1205 Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1206 ref or an array ref, containing a list of source to deploy. If present, then
1207 only the sources listed will get deployed. Furthermore, you can use the
1208 C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1209 FK.
1210
1211 =cut
1212
1213 sub deploy {
1214   my ($self, $sqltargs, $dir) = @_;
1215   $self->throw_exception("Can't deploy without storage") unless $self->storage;
1216   $self->storage->deploy($self, undef, $sqltargs, $dir);
1217 }
1218
1219 =head2 deployment_statements
1220
1221 =over 4
1222
1223 =item Arguments: See L<DBIx::Class::Storage::DBI/deployment_statements>
1224
1225 =item Return Value: $listofstatements
1226
1227 =back
1228
1229 A convenient shortcut to
1230 C<< $self->storage->deployment_statements($self, @args) >>.
1231 Returns the statements used by L</deploy> and
1232 L<DBIx::Class::Storage/deploy>.
1233
1234 =cut
1235
1236 sub deployment_statements {
1237   my $self = shift;
1238
1239   $self->throw_exception("Can't generate deployment statements without a storage")
1240     if not $self->storage;
1241
1242   $self->storage->deployment_statements($self, @_);
1243 }
1244
1245 =head2 create_ddl_dir
1246
1247 =over 4
1248
1249 =item Arguments: See L<DBIx::Class::Storage::DBI/create_ddl_dir>
1250
1251 =back
1252
1253 A convenient shortcut to
1254 C<< $self->storage->create_ddl_dir($self, @args) >>.
1255
1256 Creates an SQL file based on the Schema, for each of the specified
1257 database types, in the given directory.
1258
1259 =cut
1260
1261 sub create_ddl_dir {
1262   my $self = shift;
1263
1264   $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1265   $self->storage->create_ddl_dir($self, @_);
1266 }
1267
1268 =head2 ddl_filename
1269
1270 =over 4
1271
1272 =item Arguments: $database-type, $version, $directory, $preversion
1273
1274 =item Return Value: $normalised_filename
1275
1276 =back
1277
1278   my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
1279
1280 This method is called by C<create_ddl_dir> to compose a file name out of
1281 the supplied directory, database type and version number. The default file
1282 name format is: C<$dir$schema-$version-$type.sql>.
1283
1284 You may override this method in your schema if you wish to use a different
1285 format.
1286
1287  WARNING
1288
1289  Prior to DBIx::Class version 0.08100 this method had a different signature:
1290
1291     my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1292
1293  In recent versions variables $dir and $version were reversed in order to
1294  bring the signature in line with other Schema/Storage methods. If you
1295  really need to maintain backward compatibility, you can do the following
1296  in any overriding methods:
1297
1298     ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100);
1299
1300 =cut
1301
1302 sub ddl_filename {
1303   my ($self, $type, $version, $dir, $preversion) = @_;
1304
1305   $version = "$preversion-$version" if $preversion;
1306
1307   my $class = blessed($self) || $self;
1308   $class =~ s/::/-/g;
1309
1310   return "$dir/$class-$version-$type.sql";
1311 }
1312
1313 =head2 thaw
1314
1315 Provided as the recommended way of thawing schema objects. You can call
1316 C<Storable::thaw> directly if you wish, but the thawed objects will not have a
1317 reference to any schema, so are rather useless.
1318
1319 =cut
1320
1321 sub thaw {
1322   my ($self, $obj) = @_;
1323   local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1324   return Storable::thaw($obj);
1325 }
1326
1327 =head2 freeze
1328
1329 This doesn't actually do anything beyond calling L<nfreeze|Storable/SYNOPSIS>,
1330 it is just provided here for symmetry.
1331
1332 =cut
1333
1334 sub freeze {
1335   return Storable::nfreeze($_[1]);
1336 }
1337
1338 =head2 dclone
1339
1340 =over 4
1341
1342 =item Arguments: $object
1343
1344 =item Return Value: dcloned $object
1345
1346 =back
1347
1348 Recommended way of dcloning L<DBIx::Class::Row> and L<DBIx::Class::ResultSet>
1349 objects so their references to the schema object
1350 (which itself is B<not> cloned) are properly maintained.
1351
1352 =cut
1353
1354 sub dclone {
1355   my ($self, $obj) = @_;
1356   local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1357   return Storable::dclone($obj);
1358 }
1359
1360 =head2 schema_version
1361
1362 Returns the current schema class' $VERSION in a normalised way.
1363
1364 =cut
1365
1366 sub schema_version {
1367   my ($self) = @_;
1368   my $class = ref($self)||$self;
1369
1370   # does -not- use $schema->VERSION
1371   # since that varies in results depending on if version.pm is installed, and if
1372   # so the perl or XS versions. If you want this to change, bug the version.pm
1373   # author to make vpp and vxs behave the same.
1374
1375   my $version;
1376   {
1377     no strict 'refs';
1378     $version = ${"${class}::VERSION"};
1379   }
1380   return $version;
1381 }
1382
1383
1384 =head2 register_class
1385
1386 =over 4
1387
1388 =item Arguments: $source_name, $component_class
1389
1390 =back
1391
1392 This method is called by L</load_namespaces> and L</load_classes> to install the found classes into your Schema. You should be using those instead of this one.
1393
1394 You will only need this method if you have your Result classes in
1395 files which are not named after the packages (or all in the same
1396 file). You may also need it to register classes at runtime.
1397
1398 Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1399 calling:
1400
1401   $schema->register_source($source_name, $component_class->result_source_instance);
1402
1403 =cut
1404
1405 sub register_class {
1406   my ($self, $source_name, $to_register) = @_;
1407   $self->register_source($source_name => $to_register->result_source_instance);
1408 }
1409
1410 =head2 register_source
1411
1412 =over 4
1413
1414 =item Arguments: $source_name, L<$result_source|DBIx::Class::ResultSource>
1415
1416 =back
1417
1418 This method is called by L</register_class>.
1419
1420 Registers the L<DBIx::Class::ResultSource> in the schema with the given
1421 source name.
1422
1423 =cut
1424
1425 sub register_source { shift->_register_source(@_) }
1426
1427 =head2 unregister_source
1428
1429 =over 4
1430
1431 =item Arguments: $source_name
1432
1433 =back
1434
1435 Removes the L<DBIx::Class::ResultSource> from the schema for the given source name.
1436
1437 =cut
1438
1439 sub unregister_source { shift->_unregister_source(@_) }
1440
1441 =head2 register_extra_source
1442
1443 =over 4
1444
1445 =item Arguments: $source_name, L<$result_source|DBIx::Class::ResultSource>
1446
1447 =back
1448
1449 As L</register_source> but should be used if the result class already
1450 has a source and you want to register an extra one.
1451
1452 =cut
1453
1454 sub register_extra_source { shift->_register_source(@_, { extra => 1 }) }
1455
1456 sub _register_source {
1457   my ($self, $source_name, $supplied_rsrc, $params) = @_;
1458
1459   my $derived_rsrc = $supplied_rsrc->clone({
1460     source_name => $source_name,
1461   });
1462
1463   # Do not move into the clone-hashref above: there are things
1464   # on CPAN that do hook 'sub schema' </facepalm>
1465   # https://metacpan.org/source/LSAUNDERS/DBIx-Class-Preview-1.000003/lib/DBIx/Class/ResultSource/Table/Previewed.pm#L9-38
1466   $derived_rsrc->schema($self);
1467
1468   weaken $derived_rsrc->{schema}
1469     if length ref($self);
1470
1471   my %reg = %{$self->source_registrations};
1472   $reg{$source_name} = $derived_rsrc;
1473   $self->source_registrations(\%reg);
1474
1475   return $derived_rsrc if $params->{extra};
1476
1477   my( $result_class, $result_class_level_rsrc );
1478   if (
1479     $result_class = $derived_rsrc->result_class
1480       and
1481     # There are known cases where $rs_class is *ONLY* an inflator, without
1482     # any hint of a rsrc (e.g. DBIx::Class::KiokuDB::EntryProxy)
1483     $result_class_level_rsrc = dbic_internal_try { $result_class->result_source_instance }
1484   ) {
1485     my %map = %{$self->class_mappings};
1486
1487     carp (
1488       "$result_class already had a registered source which was replaced by "
1489     . 'this call. Perhaps you wanted register_extra_source(), though it is '
1490     . 'more likely you did something wrong.'
1491     ) if (
1492       exists $map{$result_class}
1493         and
1494       $map{$result_class} ne $source_name
1495         and
1496       $result_class_level_rsrc != $supplied_rsrc
1497     );
1498
1499     $map{$result_class} = $source_name;
1500     $self->class_mappings(\%map);
1501   }
1502
1503   $derived_rsrc;
1504 }
1505
1506 my $global_phase_destroy;
1507 sub DESTROY {
1508   ### NO detected_reinvoked_destructor check
1509   ### This code very much relies on being called multuple times
1510
1511   return if $global_phase_destroy ||= in_global_destruction;
1512
1513   my $self = shift;
1514   my $srcs = $self->source_registrations;
1515
1516   for my $source_name (keys %$srcs) {
1517     # find first source that is not about to be GCed (someone other than $self
1518     # holds a reference to it) and reattach to it, weakening our own link
1519     #
1520     # during global destruction (if we have not yet bailed out) this should throw
1521     # which will serve as a signal to not try doing anything else
1522     # however beware - on older perls the exception seems randomly untrappable
1523     # due to some weird race condition during thread joining :(((
1524     if (length ref $srcs->{$source_name} and refcount($srcs->{$source_name}) > 1) {
1525       local $SIG{__DIE__} if $SIG{__DIE__};
1526       local $@ if DBIx::Class::_ENV_::UNSTABLE_DOLLARAT;
1527       eval {
1528         $srcs->{$source_name}->schema($self);
1529         weaken $srcs->{$source_name};
1530         1;
1531       } or do {
1532         $global_phase_destroy = 1;
1533       };
1534
1535       last;
1536     }
1537   }
1538
1539   # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage
1540   # collected before leaving this scope. Depending on the code above, this
1541   # may very well be just a preventive measure guarding future modifications
1542   undef;
1543 }
1544
1545 sub _unregister_source {
1546     my ($self, $source_name) = @_;
1547     my %reg = %{$self->source_registrations};
1548
1549     my $source = delete $reg{$source_name};
1550     $self->source_registrations(\%reg);
1551     if ($source->result_class) {
1552         my %map = %{$self->class_mappings};
1553         delete $map{$source->result_class};
1554         $self->class_mappings(\%map);
1555     }
1556 }
1557
1558
1559 =head2 compose_connection (DEPRECATED)
1560
1561 =over 4
1562
1563 =item Arguments: $target_namespace, @db_info
1564
1565 =item Return Value: $new_schema
1566
1567 =back
1568
1569 DEPRECATED. You probably wanted compose_namespace.
1570
1571 Actually, you probably just wanted to call connect.
1572
1573 =begin hidden
1574
1575 (hidden due to deprecation)
1576
1577 Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1578 calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1579 then injects the L<DBix::Class::ResultSetProxy> component and a
1580 resultset_instance classdata entry on all the new classes, in order to support
1581 $target_namespaces::$class->search(...) method calls.
1582
1583 This is primarily useful when you have a specific need for class method access
1584 to a connection. In normal usage it is preferred to call
1585 L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1586 on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1587 more information.
1588
1589 =end hidden
1590
1591 =cut
1592
1593 sub compose_connection {
1594   my ($self, $target, @info) = @_;
1595
1596   carp_once "compose_connection deprecated as of 0.08000"
1597     unless $INC{"DBIx/Class/CDBICompat.pm"};
1598
1599   dbic_internal_try {
1600     require DBIx::Class::ResultSetProxy;
1601   }
1602   catch {
1603     $self->throw_exception
1604       ("No arguments to load_classes and couldn't load DBIx::Class::ResultSetProxy ($_)")
1605   };
1606
1607   if ($self eq $target) {
1608     # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1609     foreach my $source_name ($self->sources) {
1610       my $source = $self->source($source_name);
1611       my $class = $source->result_class;
1612       $self->inject_base($class, 'DBIx::Class::ResultSetProxy');
1613       $class->mk_classaccessor(resultset_instance => $source->resultset);
1614       $class->mk_classaccessor(class_resolver => $self);
1615     }
1616     $self->connection(@info);
1617     return $self;
1618   }
1619
1620   my $schema = $self->compose_namespace($target, 'DBIx::Class::ResultSetProxy');
1621   quote_sub "${target}::schema", '$s', { '$s' => \$schema };
1622
1623   $schema->connection(@info);
1624   foreach my $source_name ($schema->sources) {
1625     my $source = $schema->source($source_name);
1626     my $class = $source->result_class;
1627     #warn "$source_name $class $source ".$source->storage;
1628     $class->mk_classaccessor(result_source_instance => $source);
1629     $class->mk_classaccessor(resultset_instance => $source->resultset);
1630     $class->mk_classaccessor(class_resolver => $schema);
1631   }
1632   return $schema;
1633 }
1634
1635 =head1 FURTHER QUESTIONS?
1636
1637 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1638
1639 =head1 COPYRIGHT AND LICENSE
1640
1641 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1642 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1643 redistribute it and/or modify it under the same terms as the
1644 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
1645
1646 =cut
1647
1648 1;