Fix for SpeedyCGI and an extensive test of persistent environments (RT#65131)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
CommitLineData
a02675cd 1package DBIx::Class::Schema;
2
3use strict;
4use warnings;
aa562407 5
4981dc70 6use DBIx::Class::Exception;
c3e9f718 7use Carp::Clan qw/^DBIx::Class|^Try::Tiny/;
9780718f 8use Try::Tiny;
6298a324 9use Scalar::Util 'weaken';
c9d2e0a2 10use File::Spec;
6298a324 11use Sub::Name 'subname';
329d7385 12use Module::Find();
6298a324 13use Storable();
50261284 14use B qw/svref_2object/;
fd323bf1 15use namespace::clean;
a02675cd 16
41a6f8c0 17use base qw/DBIx::Class/;
a02675cd 18
0dc79249 19__PACKAGE__->mk_classdata('class_mappings' => {});
20__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 21__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 22__PACKAGE__->mk_classdata('storage');
82cc0386 23__PACKAGE__->mk_classdata('exception_action');
4b946902 24__PACKAGE__->mk_classdata('stacktrace' => $ENV{DBIC_TRACE} || 0);
e6c747fd 25__PACKAGE__->mk_classdata('default_resultset_attributes' => {});
a02675cd 26
c2da098a 27=head1 NAME
28
29DBIx::Class::Schema - composable schemas
30
31=head1 SYNOPSIS
32
24d67825 33 package Library::Schema;
c2da098a 34 use base qw/DBIx::Class::Schema/;
bab77431 35
829517d4 36 # load all Result classes in Library/Schema/Result/
37 __PACKAGE__->load_namespaces();
c2da098a 38
829517d4 39 package Library::Schema::Result::CD;
d88ecca6 40 use base qw/DBIx::Class::Core/;
41
42 __PACKAGE__->load_components(qw/InflateColumn::DateTime/); # for example
24d67825 43 __PACKAGE__->table('cd');
c2da098a 44
5d9076f2 45 # Elsewhere in your code:
24d67825 46 my $schema1 = Library::Schema->connect(
a3d93194 47 $dsn,
48 $user,
49 $password,
ef131d82 50 { AutoCommit => 1 },
a3d93194 51 );
bab77431 52
24d67825 53 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 54
829517d4 55 # fetch objects using Library::Schema::Result::DVD
24d67825 56 my $resultset = $schema1->resultset('DVD')->search( ... );
57 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 58
59=head1 DESCRIPTION
60
a3d93194 61Creates database classes based on a schema. This is the recommended way to
62use L<DBIx::Class> and allows you to use more than one concurrent connection
63with your classes.
429bd4f1 64
03312470 65NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 66carefully, as DBIx::Class does things a little differently. Note in
03312470 67particular which module inherits off which.
68
829517d4 69=head1 SETUP METHODS
c2da098a 70
829517d4 71=head2 load_namespaces
87c4e602 72
27f01d1f 73=over 4
74
829517d4 75=item Arguments: %options?
27f01d1f 76
77=back
076652e8 78
829517d4 79 __PACKAGE__->load_namespaces();
66d9ef6b 80
829517d4 81 __PACKAGE__->load_namespaces(
82 result_namespace => 'Res',
83 resultset_namespace => 'RSet',
84 default_resultset_class => '+MyDB::Othernamespace::RSet',
85 );
076652e8 86
829517d4 87With no arguments, this method uses L<Module::Find> to load all your
88Result classes from a sub-namespace F<Result> under your Schema class'
48580715 89namespace, i.e. with a Schema of I<MyDB::Schema> all files in
829517d4 90I<MyDB::Schema::Result> are assumed to be Result classes.
c2da098a 91
829517d4 92It also finds all ResultSet classes in the namespace F<ResultSet> and
93loads them into the appropriate Result classes using for you. The
94matching is done by assuming the package name of the ResultSet class
95is the same as that of the Result class.
74b92d9a 96
672687db 97You will be warned if ResultSet classes are discovered for which there
829517d4 98are no matching Result classes like this:
87c4e602 99
829517d4 100 load_namespaces found ResultSet class $classname with no corresponding Result class
27f01d1f 101
829517d4 102If a Result class is found to already have a ResultSet class set using
103L</resultset_class> to some other class, you will be warned like this:
27f01d1f 104
fd323bf1 105 We found ResultSet class '$rs_class' for '$result', but it seems
829517d4 106 that you had already set '$result' to use '$rs_set' instead
076652e8 107
829517d4 108Both of the sub-namespaces are configurable if you don't like the defaults,
109via the options C<result_namespace> and C<resultset_namespace>.
076652e8 110
829517d4 111If (and only if) you specify the option C<default_resultset_class>, any found
112Result classes for which we do not find a corresponding
113ResultSet class will have their C<resultset_class> set to
114C<default_resultset_class>.
076652e8 115
829517d4 116All of the namespace and classname options to this method are relative to
117the schema classname by default. To specify a fully-qualified name, prefix
118it with a literal C<+>.
2a4d9487 119
829517d4 120Examples:
2a4d9487 121
829517d4 122 # load My::Schema::Result::CD, My::Schema::Result::Artist,
123 # My::Schema::ResultSet::CD, etc...
124 My::Schema->load_namespaces;
2a4d9487 125
829517d4 126 # Override everything to use ugly names.
127 # In this example, if there is a My::Schema::Res::Foo, but no matching
128 # My::Schema::RSets::Foo, then Foo will have its
129 # resultset_class set to My::Schema::RSetBase
130 My::Schema->load_namespaces(
131 result_namespace => 'Res',
132 resultset_namespace => 'RSets',
133 default_resultset_class => 'RSetBase',
134 );
2a4d9487 135
829517d4 136 # Put things in other namespaces
137 My::Schema->load_namespaces(
138 result_namespace => '+Some::Place::Results',
139 resultset_namespace => '+Another::Place::RSets',
140 );
2a4d9487 141
829517d4 142If you'd like to use multiple namespaces of each type, simply use an arrayref
143of namespaces for that option. In the case that the same result
144(or resultset) class exists in multiple namespaces, the latter entries in
145your list of namespaces will override earlier ones.
2a4d9487 146
829517d4 147 My::Schema->load_namespaces(
148 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
149 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
150 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
151 );
2a4d9487 152
153=cut
154
829517d4 155# Pre-pends our classname to the given relative classname or
156# class namespace, unless there is a '+' prefix, which will
157# be stripped.
158sub _expand_relative_name {
159 my ($class, $name) = @_;
160 return if !$name;
161 $name = $class . '::' . $name if ! ($name =~ s/^\+//);
162 return $name;
2a4d9487 163}
164
f3405058 165# Finds all modules in the supplied namespace, or if omitted in the
166# namespace of $class. Untaints all findings as they can be assumed
167# to be safe
168sub _findallmod {
169 my $proto = shift;
170 my $ns = shift || ref $proto || $proto;
171
172 my @mods = Module::Find::findallmod($ns);
173
174 # try to untaint module names. mods where this fails
175 # are left alone so we don't have to change the old behavior
176 no locale; # localized \w doesn't untaint expression
177 return map { $_ =~ m/^( (?:\w+::)* \w+ )$/x ? $1 : $_ } @mods;
178}
179
829517d4 180# returns a hash of $shortname => $fullname for every package
b488020e 181# found in the given namespaces ($shortname is with the $fullname's
182# namespace stripped off)
829517d4 183sub _map_namespaces {
184 my ($class, @namespaces) = @_;
6eec9003 185
829517d4 186 my @results_hash;
187 foreach my $namespace (@namespaces) {
188 push(
189 @results_hash,
190 map { (substr($_, length "${namespace}::"), $_) }
f3405058 191 $class->_findallmod($namespace)
829517d4 192 );
0dc79249 193 }
27f01d1f 194
829517d4 195 @results_hash;
ea20d0fd 196}
197
b488020e 198# returns the result_source_instance for the passed class/object,
199# or dies with an informative message (used by load_namespaces)
200sub _ns_get_rsrc_instance {
201 my $class = shift;
202 my $rs = ref ($_[0]) || $_[0];
203
204 if ($rs->can ('result_source_instance') ) {
0647e0cc 205 return $rs->result_source_instance;
b488020e 206 }
207 else {
208 $class->throw_exception (
209 "Attempt to load_namespaces() class $rs failed - are you sure this is a real Result Class?"
210 );
211 }
212}
213
829517d4 214sub load_namespaces {
215 my ($class, %args) = @_;
0dc79249 216
829517d4 217 my $result_namespace = delete $args{result_namespace} || 'Result';
218 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
219 my $default_resultset_class = delete $args{default_resultset_class};
0dc79249 220
829517d4 221 $class->throw_exception('load_namespaces: unknown option(s): '
222 . join(q{,}, map { qq{'$_'} } keys %args))
223 if scalar keys %args;
0dc79249 224
829517d4 225 $default_resultset_class
226 = $class->_expand_relative_name($default_resultset_class);
9b1ba0f2 227
829517d4 228 for my $arg ($result_namespace, $resultset_namespace) {
229 $arg = [ $arg ] if !ref($arg) && $arg;
9b1ba0f2 230
829517d4 231 $class->throw_exception('load_namespaces: namespace arguments must be '
232 . 'a simple string or an arrayref')
233 if ref($arg) ne 'ARRAY';
9b1ba0f2 234
829517d4 235 $_ = $class->_expand_relative_name($_) for (@$arg);
236 }
ea20d0fd 237
829517d4 238 my %results = $class->_map_namespaces(@$result_namespace);
239 my %resultsets = $class->_map_namespaces(@$resultset_namespace);
27f01d1f 240
829517d4 241 my @to_register;
242 {
243 no warnings 'redefine';
244 local *Class::C3::reinitialize = sub { };
245 use warnings 'redefine';
27f01d1f 246
3988ce40 247 # ensure classes are loaded and attached in inheritance order
f5ef5fa1 248 for my $res (values %results) {
249 $class->ensure_class_loaded($res);
250 }
3988ce40 251 my %inh_idx;
252 my @subclass_last = sort {
253
254 ($inh_idx{$a} ||=
255 scalar @{mro::get_linear_isa( $results{$a} )}
256 )
257
258 <=>
259
260 ($inh_idx{$b} ||=
261 scalar @{mro::get_linear_isa( $results{$b} )}
262 )
263
264 } keys(%results);
265
3d27f771 266 foreach my $result (@subclass_last) {
829517d4 267 my $result_class = $results{$result};
82b01c38 268
829517d4 269 my $rs_class = delete $resultsets{$result};
b488020e 270 my $rs_set = $class->_ns_get_rsrc_instance ($result_class)->resultset_class;
3988ce40 271
829517d4 272 if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
3d27f771 273 if($rs_class && $rs_class ne $rs_set) {
341d5ede 274 carp "We found ResultSet class '$rs_class' for '$result', but it seems "
829517d4 275 . "that you had already set '$result' to use '$rs_set' instead";
276 }
277 }
278 elsif($rs_class ||= $default_resultset_class) {
279 $class->ensure_class_loaded($rs_class);
1d3108a4 280 if(!$rs_class->isa("DBIx::Class::ResultSet")) {
281 carp "load_namespaces found ResultSet class $rs_class that does not subclass DBIx::Class::ResultSet";
282 }
283
b488020e 284 $class->_ns_get_rsrc_instance ($result_class)->resultset_class($rs_class);
829517d4 285 }
82b01c38 286
b488020e 287 my $source_name = $class->_ns_get_rsrc_instance ($result_class)->source_name || $result;
0e6c5d58 288
289 push(@to_register, [ $source_name, $result_class ]);
829517d4 290 }
291 }
ea20d0fd 292
829517d4 293 foreach (sort keys %resultsets) {
341d5ede 294 carp "load_namespaces found ResultSet class $_ with no "
829517d4 295 . 'corresponding Result class';
296 }
ea20d0fd 297
829517d4 298 Class::C3->reinitialize;
299 $class->register_class(@$_) for (@to_register);
ea20d0fd 300
829517d4 301 return;
ea20d0fd 302}
303
87c4e602 304=head2 load_classes
305
27f01d1f 306=over 4
307
308=item Arguments: @classes?, { $namespace => [ @classes ] }+
309
310=back
076652e8 311
1ab61457 312L</load_classes> is an alternative method to L</load_namespaces>, both of
313which serve similar purposes, each with different advantages and disadvantages.
314In the general case you should use L</load_namespaces>, unless you need to
315be able to specify that only specific classes are loaded at runtime.
829517d4 316
82b01c38 317With no arguments, this method uses L<Module::Find> to find all classes under
318the schema's namespace. Otherwise, this method loads the classes you specify
319(using L<use>), and registers them (using L</"register_class">).
076652e8 320
2053ab2a 321It is possible to comment out classes with a leading C<#>, but note that perl
322will think it's a mistake (trying to use a comment in a qw list), so you'll
323need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 324
829517d4 325If any classes found do not appear to be Result class files, you will
326get the following warning:
327
fd323bf1 328 Failed to load $comp_class. Can't find source_name method. Is
829517d4 329 $comp_class really a full DBIC result class? Fix it, move it elsewhere,
330 or make your load_classes call more specific.
331
2053ab2a 332Example:
82b01c38 333
334 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 335 # etc. (anything under the My::Schema namespace)
82b01c38 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
076652e8 343=cut
344
a02675cd 345sub load_classes {
5ce32fc1 346 my ($class, @params) = @_;
bab77431 347
5ce32fc1 348 my %comps_for;
bab77431 349
5ce32fc1 350 if (@params) {
351 foreach my $param (@params) {
352 if (ref $param eq 'ARRAY') {
353 # filter out commented entries
354 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 355
5ce32fc1 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 {
bc0c9800 373 my @comp = map { substr $_, length "${class}::" }
f3405058 374 $class->_findallmod;
5ce32fc1 375 $comps_for{$class} = \@comp;
41a6f8c0 376 }
5ce32fc1 377
e6efde04 378 my @to_register;
379 {
380 no warnings qw/redefine/;
381 local *Class::C3::reinitialize = sub { };
382 foreach my $prefix (keys %comps_for) {
383 foreach my $comp (@{$comps_for{$prefix}||[]}) {
384 my $comp_class = "${prefix}::${comp}";
c037c03a 385 $class->ensure_class_loaded($comp_class);
bab77431 386
89271e56 387 my $snsub = $comp_class->can('source_name');
388 if(! $snsub ) {
341d5ede 389 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.";
89271e56 390 next;
391 }
392 $comp = $snsub->($comp_class) || $comp;
393
93405cf0 394 push(@to_register, [ $comp, $comp_class ]);
bfb2bd4f 395 }
5ce32fc1 396 }
a02675cd 397 }
e6efde04 398 Class::C3->reinitialize;
399
400 foreach my $to (@to_register) {
401 $class->register_class(@$to);
402 # if $class->can('result_source_instance');
403 }
a02675cd 404}
405
829517d4 406=head2 storage_type
2374c5ff 407
408=over 4
409
829517d4 410=item Arguments: $storage_type|{$storage_type, \%args}
411
412=item Return value: $storage_type|{$storage_type, \%args}
413
414=item Default value: DBIx::Class::Storage::DBI
2374c5ff 415
416=back
417
829517d4 418Set the storage class that will be instantiated when L</connect> is called.
419If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
95787afe 420assumed by L</connect>.
2374c5ff 421
829517d4 422You want to use this to set subclasses of L<DBIx::Class::Storage::DBI>
95787afe 423in cases where the appropriate subclass is not autodetected.
85bd0538 424
829517d4 425If your storage type requires instantiation arguments, those are
426defined as a second argument in the form of a hashref and the entire
427value needs to be wrapped into an arrayref or a hashref. We support
428both types of refs here in order to play nice with your
429Config::[class] or your choice. See
430L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
0f4ec1d2 431
829517d4 432=head2 exception_action
f017c022 433
829517d4 434=over 4
0f4ec1d2 435
829517d4 436=item Arguments: $code_reference
f017c022 437
829517d4 438=item Return value: $code_reference
85bd0538 439
829517d4 440=item Default value: None
2374c5ff 441
829517d4 442=back
f017c022 443
c3e9f718 444When L</throw_exception> is invoked and L</exception_action> is set to a code
445reference, this reference will be called instead of
446L<DBIx::Class::Exception/throw>, with the exception message passed as the only
447argument.
f017c022 448
c3e9f718 449Your custom throw code B<must> rethrow the exception, as L</throw_exception> is
450an integral part of DBIC's internal execution control flow.
f017c022 451
829517d4 452Example:
f017c022 453
829517d4 454 package My::Schema;
455 use base qw/DBIx::Class::Schema/;
456 use My::ExceptionClass;
457 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
458 __PACKAGE__->load_classes;
2374c5ff 459
829517d4 460 # or:
461 my $schema_obj = My::Schema->connect( .... );
462 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
0f4ec1d2 463
829517d4 464=head2 stacktrace
f017c022 465
829517d4 466=over 4
2374c5ff 467
829517d4 468=item Arguments: boolean
2374c5ff 469
829517d4 470=back
2374c5ff 471
829517d4 472Whether L</throw_exception> should include stack trace information.
473Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
474is true.
0f4ec1d2 475
829517d4 476=head2 sqlt_deploy_hook
0f4ec1d2 477
829517d4 478=over
0f4ec1d2 479
829517d4 480=item Arguments: $sqlt_schema
2374c5ff 481
829517d4 482=back
2374c5ff 483
fd323bf1 484An optional sub which you can declare in your own Schema class that will get
829517d4 485passed the L<SQL::Translator::Schema> object when you deploy the schema via
486L</create_ddl_dir> or L</deploy>.
0f4ec1d2 487
fd323bf1 488For an example of what you can do with this, see
829517d4 489L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
fdcd8145 490
2d7d8459 491Note that sqlt_deploy_hook is called by L</deployment_statements>, which in turn
492is called before L</deploy>. Therefore the hook can be used only to manipulate
493the L<SQL::Translator::Schema> object before it is turned into SQL fed to the
494database. If you want to execute post-deploy statements which can not be generated
495by L<SQL::Translator>, the currently suggested method is to overload L</deploy>
496and use L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
497
829517d4 498=head1 METHODS
2374c5ff 499
829517d4 500=head2 connect
87c4e602 501
27f01d1f 502=over 4
503
829517d4 504=item Arguments: @connectinfo
429bd4f1 505
d601dc88 506=item Return Value: $new_schema
27f01d1f 507
508=back
076652e8 509
829517d4 510Creates and returns a new Schema object. The connection info set on it
511is used to create a new instance of the storage backend and set it on
512the Schema object.
1c133e22 513
829517d4 514See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific
5d52945a 515syntax on the C<@connectinfo> argument, or L<DBIx::Class::Storage> in
829517d4 516general.
1c133e22 517
5d52945a 518Note that C<connect_info> expects an arrayref of arguments, but
faaba25f 519C<connect> does not. C<connect> wraps its arguments in an arrayref
5d52945a 520before passing them to C<connect_info>.
521
4c7d99ca 522=head3 Overloading
523
524C<connect> is a convenience method. It is equivalent to calling
525$schema->clone->connection(@connectinfo). To write your own overloaded
526version, overload L</connection> instead.
527
076652e8 528=cut
529
829517d4 530sub connect { shift->clone->connection(@_) }
e678398e 531
829517d4 532=head2 resultset
77254782 533
27f01d1f 534=over 4
535
829517d4 536=item Arguments: $source_name
82b01c38 537
829517d4 538=item Return Value: $resultset
27f01d1f 539
540=back
13765dad 541
829517d4 542 my $rs = $schema->resultset('DVD');
82b01c38 543
829517d4 544Returns the L<DBIx::Class::ResultSet> object for the registered source
545name.
77254782 546
547=cut
548
829517d4 549sub resultset {
550 my ($self, $moniker) = @_;
73d47f9f 551 $self->throw_exception('resultset() expects a source name')
552 unless defined $moniker;
829517d4 553 return $self->source($moniker)->resultset;
b7951443 554}
555
829517d4 556=head2 sources
6b43ba5f 557
558=over 4
559
829517d4 560=item Return Value: @source_names
6b43ba5f 561
562=back
563
829517d4 564 my @source_names = $schema->sources;
6b43ba5f 565
829517d4 566Lists names of all the sources registered on this Schema object.
6b43ba5f 567
829517d4 568=cut
161fb223 569
829517d4 570sub sources { return keys %{shift->source_registrations}; }
106d5f3b 571
829517d4 572=head2 source
87c4e602 573
27f01d1f 574=over 4
575
829517d4 576=item Arguments: $source_name
66d9ef6b 577
829517d4 578=item Return Value: $result_source
27f01d1f 579
580=back
82b01c38 581
829517d4 582 my $source = $schema->source('Book');
85f78622 583
829517d4 584Returns the L<DBIx::Class::ResultSource> object for the registered
585source name.
66d9ef6b 586
587=cut
588
829517d4 589sub source {
f5f2af8f 590 my $self = shift;
591
592 $self->throw_exception("source() expects a source name")
593 unless @_;
594
595 my $moniker = shift;
596
829517d4 597 my $sreg = $self->source_registrations;
598 return $sreg->{$moniker} if exists $sreg->{$moniker};
599
600 # if we got here, they probably passed a full class name
601 my $mapped = $self->class_mappings->{$moniker};
602 $self->throw_exception("Can't find source for ${moniker}")
603 unless $mapped && exists $sreg->{$mapped};
604 return $sreg->{$mapped};
161fb223 605}
606
829517d4 607=head2 class
87c4e602 608
27f01d1f 609=over 4
610
829517d4 611=item Arguments: $source_name
66d9ef6b 612
829517d4 613=item Return Value: $classname
27f01d1f 614
615=back
82b01c38 616
829517d4 617 my $class = $schema->class('CD');
618
619Retrieves the Result class name for the given source name.
66d9ef6b 620
621=cut
622
829517d4 623sub class {
624 my ($self, $moniker) = @_;
625 return $self->source($moniker)->result_class;
626}
08b515f1 627
4012acd8 628=head2 txn_do
08b515f1 629
4012acd8 630=over 4
08b515f1 631
4012acd8 632=item Arguments: C<$coderef>, @coderef_args?
08b515f1 633
4012acd8 634=item Return Value: The return value of $coderef
08b515f1 635
4012acd8 636=back
08b515f1 637
4012acd8 638Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
639returning its result (if any). Equivalent to calling $schema->storage->txn_do.
640See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 641
4012acd8 642This interface is preferred over using the individual methods L</txn_begin>,
643L</txn_commit>, and L</txn_rollback> below.
08b515f1 644
f9f06ae0 645WARNING: If you are connected with C<< AutoCommit => 0 >> the transaction is
281719d2 646considered nested, and you will still need to call L</txn_commit> to write your
f9f06ae0 647changes when appropriate. You will also want to connect with C<< auto_savepoint =>
6481 >> to get partial rollback to work, if the storage driver for your database
281719d2 649supports it.
650
f9f06ae0 651Connecting with C<< AutoCommit => 1 >> is recommended.
281719d2 652
4012acd8 653=cut
08b515f1 654
4012acd8 655sub txn_do {
656 my $self = shift;
08b515f1 657
4012acd8 658 $self->storage or $self->throw_exception
659 ('txn_do called on $schema without storage');
08b515f1 660
4012acd8 661 $self->storage->txn_do(@_);
662}
66d9ef6b 663
6936e902 664=head2 txn_scope_guard
75c8a7ab 665
fd323bf1 666Runs C<txn_scope_guard> on the schema's storage. See
89028f42 667L<DBIx::Class::Storage/txn_scope_guard>.
75c8a7ab 668
b85be4c1 669=cut
670
1bc193ac 671sub txn_scope_guard {
672 my $self = shift;
673
674 $self->storage or $self->throw_exception
675 ('txn_scope_guard called on $schema without storage');
676
677 $self->storage->txn_scope_guard(@_);
678}
679
4012acd8 680=head2 txn_begin
a62cf8d4 681
4012acd8 682Begins a transaction (does nothing if AutoCommit is off). Equivalent to
683calling $schema->storage->txn_begin. See
8bfce9d5 684L<DBIx::Class::Storage/"txn_begin"> for more information.
27f01d1f 685
4012acd8 686=cut
82b01c38 687
4012acd8 688sub txn_begin {
689 my $self = shift;
27f01d1f 690
4012acd8 691 $self->storage or $self->throw_exception
692 ('txn_begin called on $schema without storage');
a62cf8d4 693
4012acd8 694 $self->storage->txn_begin;
695}
a62cf8d4 696
4012acd8 697=head2 txn_commit
a62cf8d4 698
4012acd8 699Commits the current transaction. Equivalent to calling
8bfce9d5 700$schema->storage->txn_commit. See L<DBIx::Class::Storage/"txn_commit">
4012acd8 701for more information.
a62cf8d4 702
4012acd8 703=cut
a62cf8d4 704
4012acd8 705sub txn_commit {
706 my $self = shift;
a62cf8d4 707
4012acd8 708 $self->storage or $self->throw_exception
709 ('txn_commit called on $schema without storage');
a62cf8d4 710
4012acd8 711 $self->storage->txn_commit;
712}
70634260 713
4012acd8 714=head2 txn_rollback
a62cf8d4 715
4012acd8 716Rolls back the current transaction. Equivalent to calling
717$schema->storage->txn_rollback. See
8bfce9d5 718L<DBIx::Class::Storage/"txn_rollback"> for more information.
a62cf8d4 719
720=cut
721
4012acd8 722sub txn_rollback {
723 my $self = shift;
a62cf8d4 724
19630353 725 $self->storage or $self->throw_exception
4012acd8 726 ('txn_rollback called on $schema without storage');
a62cf8d4 727
4012acd8 728 $self->storage->txn_rollback;
a62cf8d4 729}
730
829517d4 731=head2 storage
66d9ef6b 732
829517d4 733 my $storage = $schema->storage;
04786a4c 734
829517d4 735Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
736if you want to turn on SQL statement debugging at runtime, or set the
737quote character. For the default storage, the documentation can be
738found in L<DBIx::Class::Storage::DBI>.
66d9ef6b 739
87c4e602 740=head2 populate
741
27f01d1f 742=over 4
743
16c5f7d3 744=item Arguments: $source_name, \@data;
27f01d1f 745
829517d4 746=item Return value: \@$objects | nothing
747
27f01d1f 748=back
a37a4697 749
16c5f7d3 750Pass this method a resultsource name, and an arrayref of
751arrayrefs. The arrayrefs should contain a list of column names,
fd323bf1 752followed by one or many sets of matching data for the given columns.
16c5f7d3 753
744076d8 754In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
755to insert the data, as this is a fast method. However, insert_bulk currently
756assumes that your datasets all contain the same type of values, using scalar
757references in a column in one row, and not in another will probably not work.
758
759Otherwise, each set of data is inserted into the database using
16c5f7d3 760L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
761objects is returned.
82b01c38 762
48580715 763e.g.
a37a4697 764
24d67825 765 $schema->populate('Artist', [
766 [ qw/artistid name/ ],
767 [ 1, 'Popular Band' ],
768 [ 2, 'Indie Band' ],
a62cf8d4 769 ...
770 ]);
d4daee7b 771
fd323bf1 772Since wantarray context is basically the same as looping over $rs->create(...)
5a93e138 773you won't see any performance benefits and in this case the method is more for
774convenience. Void context sends the column information directly to storage
fd323bf1 775using <DBI>s bulk insert method. So the performance will be much better for
5a93e138 776storages that support this method.
777
fd323bf1 778Because of this difference in the way void context inserts rows into your
5a93e138 779database you need to note how this will effect any loaded components that
fd323bf1 780override or augment insert. For example if you are using a component such
781as L<DBIx::Class::UUIDColumns> to populate your primary keys you MUST use
5a93e138 782wantarray context if you want the PKs automatically created.
a37a4697 783
784=cut
785
786sub populate {
787 my ($self, $name, $data) = @_;
c4e67d31 788 if(my $rs = $self->resultset($name)) {
789 if(defined wantarray) {
790 return $rs->populate($data);
791 } else {
792 $rs->populate($data);
54e0bd06 793 }
c4e67d31 794 } else {
fd323bf1 795 $self->throw_exception("$name is not a resultset");
8b93a938 796 }
a37a4697 797}
798
829517d4 799=head2 connection
800
801=over 4
802
803=item Arguments: @args
804
805=item Return Value: $new_schema
806
807=back
808
809Similar to L</connect> except sets the storage object and connection
810data in-place on the Schema class. You should probably be calling
811L</connect> to get a proper Schema object instead.
812
4c7d99ca 813=head3 Overloading
814
815Overload C<connection> to change the behaviour of C<connect>.
829517d4 816
817=cut
818
819sub connection {
820 my ($self, @info) = @_;
821 return $self if !@info && $self->storage;
d4daee7b 822
fd323bf1 823 my ($storage_class, $args) = ref $self->storage_type ?
829517d4 824 ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {});
d4daee7b 825
829517d4 826 $storage_class = 'DBIx::Class::Storage'.$storage_class
827 if $storage_class =~ m/^::/;
9780718f 828 try {
829 $self->ensure_class_loaded ($storage_class);
830 }
831 catch {
832 $self->throw_exception(
833 "No arguments to load_classes and couldn't load ${storage_class} ($_)"
834 );
835 };
829517d4 836 my $storage = $storage_class->new($self=>$args);
837 $storage->connect_info(\@info);
838 $self->storage($storage);
839 return $self;
840}
841
842sub _normalize_storage_type {
843 my ($self, $storage_type) = @_;
844 if(ref $storage_type eq 'ARRAY') {
845 return @$storage_type;
846 } elsif(ref $storage_type eq 'HASH') {
847 return %$storage_type;
848 } else {
849 $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
850 }
851}
852
853=head2 compose_namespace
82cc0386 854
855=over 4
856
829517d4 857=item Arguments: $target_namespace, $additional_base_class?
858
859=item Retur Value: $new_schema
860
861=back
862
863For each L<DBIx::Class::ResultSource> in the schema, this method creates a
864class in the target namespace (e.g. $target_namespace::CD,
865$target_namespace::Artist) that inherits from the corresponding classes
866attached to the current schema.
867
868It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
869new $schema object. If C<$additional_base_class> is given, the new composed
48580715 870classes will inherit from first the corresponding class from the current
829517d4 871schema then the base class.
872
873For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
874
875 $schema->compose_namespace('My::DB', 'Base::Class');
876 print join (', ', @My::DB::CD::ISA) . "\n";
877 print join (', ', @My::DB::Artist::ISA) ."\n";
878
879will produce the output
880
881 My::Schema::CD, Base::Class
882 My::Schema::Artist, Base::Class
883
884=cut
885
886# this might be oversimplified
887# sub compose_namespace {
888# my ($self, $target, $base) = @_;
889
890# my $schema = $self->clone;
891# foreach my $moniker ($schema->sources) {
892# my $source = $schema->source($moniker);
893# my $target_class = "${target}::${moniker}";
894# $self->inject_base(
895# $target_class => $source->result_class, ($base ? $base : ())
896# );
897# $source->result_class($target_class);
898# $target_class->result_source_instance($source)
899# if $target_class->can('result_source_instance');
900# $schema->register_source($moniker, $source);
901# }
902# return $schema;
903# }
904
905sub compose_namespace {
906 my ($self, $target, $base) = @_;
907 my $schema = $self->clone;
908 {
909 no warnings qw/redefine/;
a8c2c746 910 no strict qw/refs/;
829517d4 911# local *Class::C3::reinitialize = sub { };
912 foreach my $moniker ($schema->sources) {
913 my $source = $schema->source($moniker);
914 my $target_class = "${target}::${moniker}";
915 $self->inject_base(
916 $target_class => $source->result_class, ($base ? $base : ())
917 );
918 $source->result_class($target_class);
a8c2c746 919 if ($target_class->can('result_source_instance')) {
920
921 # since the newly created classes are registered only with
922 # the instance of $schema, it should be safe to weaken
923 # the ref (it will GC when $schema is destroyed)
924 $target_class->result_source_instance($source);
925 weaken ${"${target_class}::__cag_result_source_instance"};
926 }
829517d4 927 $schema->register_source($moniker, $source);
928 }
929 }
930# Class::C3->reinitialize();
931 {
932 no strict 'refs';
933 no warnings 'redefine';
934 foreach my $meth (qw/class source resultset/) {
6298a324 935 *{"${target}::${meth}"} = subname "${target}::${meth}" =>
829517d4 936 sub { shift->schema->$meth(@_) };
937 }
938 }
939 return $schema;
940}
941
942sub setup_connection_class {
943 my ($class, $target, @info) = @_;
944 $class->inject_base($target => 'DBIx::Class::DB');
945 #$target->load_components('DB');
946 $target->connection(@info);
947}
948
949=head2 svp_begin
950
fd323bf1 951Creates a new savepoint (does nothing outside a transaction).
829517d4 952Equivalent to calling $schema->storage->svp_begin. See
8bfce9d5 953L<DBIx::Class::Storage/"svp_begin"> for more information.
829517d4 954
955=cut
956
957sub svp_begin {
958 my ($self, $name) = @_;
959
960 $self->storage or $self->throw_exception
961 ('svp_begin called on $schema without storage');
962
963 $self->storage->svp_begin($name);
964}
965
966=head2 svp_release
967
fd323bf1 968Releases a savepoint (does nothing outside a transaction).
829517d4 969Equivalent to calling $schema->storage->svp_release. See
8bfce9d5 970L<DBIx::Class::Storage/"svp_release"> for more information.
829517d4 971
972=cut
973
974sub svp_release {
975 my ($self, $name) = @_;
976
977 $self->storage or $self->throw_exception
978 ('svp_release called on $schema without storage');
82cc0386 979
829517d4 980 $self->storage->svp_release($name);
981}
82cc0386 982
829517d4 983=head2 svp_rollback
db5dc233 984
fd323bf1 985Rollback to a savepoint (does nothing outside a transaction).
829517d4 986Equivalent to calling $schema->storage->svp_rollback. See
8bfce9d5 987L<DBIx::Class::Storage/"svp_rollback"> for more information.
82cc0386 988
829517d4 989=cut
82cc0386 990
829517d4 991sub svp_rollback {
992 my ($self, $name) = @_;
82cc0386 993
829517d4 994 $self->storage or $self->throw_exception
995 ('svp_rollback called on $schema without storage');
82cc0386 996
829517d4 997 $self->storage->svp_rollback($name);
998}
db5dc233 999
829517d4 1000=head2 clone
613397e7 1001
84c5863b 1002=over 4
613397e7 1003
829517d4 1004=item Return Value: $new_schema
613397e7 1005
1006=back
1007
829517d4 1008Clones the schema and its associated result_source objects and returns the
1009copy.
1010
1011=cut
1012
1013sub clone {
1014 my ($self) = @_;
1015 my $clone = { (ref $self ? %$self : ()) };
1016 bless $clone, (ref $self || $self);
1017
1018 $clone->class_mappings({ %{$clone->class_mappings} });
1019 $clone->source_registrations({ %{$clone->source_registrations} });
1020 foreach my $moniker ($self->sources) {
1021 my $source = $self->source($moniker);
1022 my $new = $source->new($source);
1023 # we use extra here as we want to leave the class_mappings as they are
1024 # but overwrite the source_registrations entry with the new source
1025 $clone->register_extra_source($moniker => $new);
1026 }
1027 $clone->storage->set_schema($clone) if $clone->storage;
1028 return $clone;
1029}
613397e7 1030
5160b401 1031=head2 throw_exception
701da8c4 1032
75d07914 1033=over 4
82b01c38 1034
ebc77b53 1035=item Arguments: $message
82b01c38 1036
1037=back
1038
1039Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 1040user's perspective. See L</exception_action> for details on overriding
4b946902 1041this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
1042default behavior will provide a detailed stack trace.
701da8c4 1043
1044=cut
1045
c3e9f718 1046my $false_exception_action_warned;
701da8c4 1047sub throw_exception {
82cc0386 1048 my $self = shift;
4981dc70 1049
c3e9f718 1050 if (my $act = $self->exception_action) {
1051 if ($act->(@_)) {
1052 DBIx::Class::Exception->throw(
1053 "Invocation of the exception_action handler installed on $self did *not*"
1054 .' result in an exception. DBIx::Class is unable to function without a reliable'
1055 .' exception mechanism, ensure that exception_action does not hide exceptions'
1056 ." (original error: $_[0])"
1057 );
1058 }
1059 elsif(! $false_exception_action_warned++) {
1060 carp (
1061 "The exception_action handler installed on $self returned false instead"
1062 .' of throwing an exception. This behavior has been deprecated, adjust your'
1063 .' handler to always rethrow the supplied error.'
1064 );
1065 }
1066 }
1067
1068 DBIx::Class::Exception->throw($_[0], $self->stacktrace);
701da8c4 1069}
1070
dfccde48 1071=head2 deploy
1c339d71 1072
82b01c38 1073=over 4
1074
10976519 1075=item Arguments: \%sqlt_args, $dir
82b01c38 1076
1077=back
1078
1079Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 1080
10976519 1081See L<SQL::Translator/METHODS> for a list of values for C<\%sqlt_args>.
1082The most common value for this would be C<< { add_drop_table => 1 } >>
1083to have the SQL produced include a C<DROP TABLE> statement for each table
1084created. For quoting purposes supply C<quote_table_names> and
3e82fc27 1085C<quote_field_names>.
51bace1c 1086
fd323bf1 1087Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1088ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 1089only the sources listed will get deployed. Furthermore, you can use the
1090C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1091FK.
499adf63 1092
1c339d71 1093=cut
1094
1095sub deploy {
6e73ac25 1096 my ($self, $sqltargs, $dir) = @_;
1c339d71 1097 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 1098 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 1099}
1100
0e0ce6c1 1101=head2 deployment_statements
1102
1103=over 4
1104
10976519 1105=item Arguments: See L<DBIx::Class::Storage::DBI/deployment_statements>
0e0ce6c1 1106
829517d4 1107=item Return value: $listofstatements
1108
0e0ce6c1 1109=back
1110
10976519 1111A convenient shortcut to
1112C<< $self->storage->deployment_statements($self, @args) >>.
1113Returns the SQL statements used by L</deploy> and
1114L<DBIx::Class::Schema::Storage/deploy>.
0e0ce6c1 1115
1116=cut
1117
1118sub deployment_statements {
7ad93f5a 1119 my $self = shift;
0e0ce6c1 1120
1121 $self->throw_exception("Can't generate deployment statements without a storage")
1122 if not $self->storage;
1123
7ad93f5a 1124 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1125}
1126
6dfbe2f8 1127=head2 create_ddl_dir
c0f61310 1128
1129=over 4
1130
10976519 1131=item Arguments: See L<DBIx::Class::Storage::DBI/create_ddl_dir>
c0f61310 1132
1133=back
1134
fd323bf1 1135A convenient shortcut to
10976519 1136C<< $self->storage->create_ddl_dir($self, @args) >>.
c9d2e0a2 1137
10976519 1138Creates an SQL file based on the Schema, for each of the specified
1139database types, in the given directory.
c9d2e0a2 1140
c0f61310 1141=cut
1142
6e73ac25 1143sub create_ddl_dir {
e673f011 1144 my $self = shift;
1145
1146 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1147 $self->storage->create_ddl_dir($self, @_);
1148}
1149
e63a82f7 1150=head2 ddl_filename
9b83fccd 1151
c9d2e0a2 1152=over 4
1153
99a74c4a 1154=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1155
829517d4 1156=item Return value: $normalised_filename
1157
c9d2e0a2 1158=back
1159
99a74c4a 1160 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1161
1162This method is called by C<create_ddl_dir> to compose a file name out of
1163the supplied directory, database type and version number. The default file
1164name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1165
c9d2e0a2 1166You may override this method in your schema if you wish to use a different
1167format.
9b83fccd 1168
1acfef8e 1169 WARNING
1170
1171 Prior to DBIx::Class version 0.08100 this method had a different signature:
1172
1173 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1174
1175 In recent versions variables $dir and $version were reversed in order to
fd323bf1 1176 bring the signature in line with other Schema/Storage methods. If you
1acfef8e 1177 really need to maintain backward compatibility, you can do the following
1178 in any overriding methods:
1179
1180 ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100);
1181
9b83fccd 1182=cut
1183
6e73ac25 1184sub ddl_filename {
99a74c4a 1185 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1186
99a74c4a 1187 my $filename = ref($self);
1188 $filename =~ s/::/-/g;
1189 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1190 $filename =~ s/$version/$preversion-$version/ if($preversion);
d4daee7b 1191
99a74c4a 1192 return $filename;
e673f011 1193}
1194
4146e3da 1195=head2 thaw
1196
fd323bf1 1197Provided as the recommended way of thawing schema objects. You can call
4146e3da 1198C<Storable::thaw> directly if you wish, but the thawed objects will not have a
48580715 1199reference to any schema, so are rather useless.
4146e3da 1200
1201=cut
1202
1203sub thaw {
1204 my ($self, $obj) = @_;
1205 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1206 return Storable::thaw($obj);
1207}
1208
1209=head2 freeze
1210
26148d36 1211This doesn't actually do anything more than call L<Storable/nfreeze>, it is just
48580715 1212provided here for symmetry.
4146e3da 1213
d2f3e87b 1214=cut
1215
4146e3da 1216sub freeze {
26148d36 1217 return Storable::nfreeze($_[1]);
4146e3da 1218}
1219
1220=head2 dclone
1221
1477a478 1222=over 4
1223
1224=item Arguments: $object
1225
1226=item Return Value: dcloned $object
1227
1228=back
1229
9e9ecfda 1230Recommended way of dcloning L<DBIx::Class::Row> and L<DBIx::Class::ResultSet>
1231objects so their references to the schema object
1232(which itself is B<not> cloned) are properly maintained.
4146e3da 1233
1234=cut
1235
1236sub dclone {
1237 my ($self, $obj) = @_;
1238 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1239 return Storable::dclone($obj);
1240}
1241
93e4d41a 1242=head2 schema_version
1243
829517d4 1244Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1245
1246=cut
1247
1248sub schema_version {
1249 my ($self) = @_;
1250 my $class = ref($self)||$self;
1251
1252 # does -not- use $schema->VERSION
1253 # since that varies in results depending on if version.pm is installed, and if
1254 # so the perl or XS versions. If you want this to change, bug the version.pm
1255 # author to make vpp and vxs behave the same.
1256
1257 my $version;
1258 {
1259 no strict 'refs';
1260 $version = ${"${class}::VERSION"};
1261 }
1262 return $version;
1263}
1264
829517d4 1265
1266=head2 register_class
1267
1268=over 4
1269
1270=item Arguments: $moniker, $component_class
1271
1272=back
1273
fd323bf1 1274This 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.
829517d4 1275
1276You will only need this method if you have your Result classes in
1277files which are not named after the packages (or all in the same
1278file). You may also need it to register classes at runtime.
1279
1280Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1281calling:
1282
1283 $schema->register_source($moniker, $component_class->result_source_instance);
1284
1285=cut
1286
1287sub register_class {
1288 my ($self, $moniker, $to_register) = @_;
1e36ef62 1289 $self->register_source($moniker => $to_register->result_source_instance);
829517d4 1290}
1291
1292=head2 register_source
1293
1294=over 4
1295
1296=item Arguments: $moniker, $result_source
1297
1298=back
1299
1300This method is called by L</register_class>.
1301
1302Registers the L<DBIx::Class::ResultSource> in the schema with the given
1303moniker.
1304
1305=cut
1306
1307sub register_source {
1308 my $self = shift;
1309
1310 $self->_register_source(@_);
1311}
1312
98cabed3 1313=head2 unregister_source
1314
1315=over 4
1316
1317=item Arguments: $moniker
1318
1319=back
1320
1321Removes the L<DBIx::Class::ResultSource> from the schema for the given moniker.
1322
1323=cut
1324
1325sub unregister_source {
1326 my $self = shift;
1327
1328 $self->_unregister_source(@_);
1329}
1330
829517d4 1331=head2 register_extra_source
1332
1333=over 4
1334
1335=item Arguments: $moniker, $result_source
1336
1337=back
1338
fd323bf1 1339As L</register_source> but should be used if the result class already
829517d4 1340has a source and you want to register an extra one.
1341
1342=cut
1343
1344sub register_extra_source {
1345 my $self = shift;
1346
1347 $self->_register_source(@_, { extra => 1 });
1348}
1349
1350sub _register_source {
1351 my ($self, $moniker, $source, $params) = @_;
1352
6d4f9d94 1353 my $orig_source = $source;
2461ae19 1354
0e6c5d58 1355 $source = $source->new({ %$source, source_name => $moniker });
2461ae19 1356 $source->schema($self);
6298a324 1357 weaken $source->{schema} if ref($self);
2461ae19 1358
1359 my $rs_class = $source->result_class;
829517d4 1360
1361 my %reg = %{$self->source_registrations};
1362 $reg{$moniker} = $source;
1363 $self->source_registrations(\%reg);
1364
829517d4 1365 return if ($params->{extra});
5dfe40b8 1366 return unless defined($rs_class) && $rs_class->can('result_source_instance');
829517d4 1367
2461ae19 1368 my %map = %{$self->class_mappings};
f18d2d04 1369 if (
1370 exists $map{$rs_class}
1371 and
1372 $map{$rs_class} ne $moniker
1373 and
1374 $rs_class->result_source_instance ne $orig_source
1375 ) {
2461ae19 1376 carp "$rs_class already has a source, use register_extra_source for additional sources";
829517d4 1377 }
2461ae19 1378 $map{$rs_class} = $moniker;
1379 $self->class_mappings(\%map);
829517d4 1380}
1381
50261284 1382{
1383 my $global_phase_destroy;
1384
66917da3 1385 # SpeedyCGI runs END blocks every cycle but keeps object instances
1386 # hence we have to disable the globaldestroy hatch, and rely on the
1387 # eval trap below (which appears to work, but is risky done so late)
1388 END { $global_phase_destroy = 1 unless $CGI::SpeedyCGI::i_am_speedy }
50261284 1389
1390 sub DESTROY {
1391 return if $global_phase_destroy;
1392
1393 my $self = shift;
1394 my $srcs = $self->source_registrations;
1395
1396 for my $moniker (keys %$srcs) {
1397 # find first source that is not about to be GCed (someone other than $self
1398 # holds a reference to it) and reattach to it, weakening our own link
66917da3 1399 #
1400 # during global destruction (if we have not yet bailed out) this will throw
1401 # which will serve as a signal to not try doing anything else
50261284 1402 if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) {
66917da3 1403 local $@;
1404 eval {
1405 $srcs->{$moniker}->schema($self);
1406 1;
1407 } or do {
1408 $global_phase_destroy = 1;
1409 last;
1410 };
1411
50261284 1412 weaken $srcs->{$moniker};
1413 last;
1414 }
1415 }
1416 }
1417}
1418
829517d4 1419sub _unregister_source {
1420 my ($self, $moniker) = @_;
fd323bf1 1421 my %reg = %{$self->source_registrations};
829517d4 1422
1423 my $source = delete $reg{$moniker};
1424 $self->source_registrations(\%reg);
1425 if ($source->result_class) {
1426 my %map = %{$self->class_mappings};
1427 delete $map{$source->result_class};
1428 $self->class_mappings(\%map);
1429 }
1430}
1431
1432
1433=head2 compose_connection (DEPRECATED)
1434
1435=over 4
1436
1437=item Arguments: $target_namespace, @db_info
1438
1439=item Return Value: $new_schema
1440
1441=back
1442
1443DEPRECATED. You probably wanted compose_namespace.
1444
1445Actually, you probably just wanted to call connect.
1446
1447=begin hidden
1448
1449(hidden due to deprecation)
1450
1451Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1452calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1453then injects the L<DBix::Class::ResultSetProxy> component and a
1454resultset_instance classdata entry on all the new classes, in order to support
1455$target_namespaces::$class->search(...) method calls.
1456
1457This is primarily useful when you have a specific need for class method access
1458to a connection. In normal usage it is preferred to call
1459L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1460on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1461more information.
1462
1463=end hidden
1464
1465=cut
1466
1467{
1468 my $warn;
1469
1470 sub compose_connection {
1471 my ($self, $target, @info) = @_;
1472
341d5ede 1473 carp "compose_connection deprecated as of 0.08000"
829517d4 1474 unless ($INC{"DBIx/Class/CDBICompat.pm"} || $warn++);
1475
1476 my $base = 'DBIx::Class::ResultSetProxy';
9780718f 1477 try {
1478 eval "require ${base};"
1479 }
1480 catch {
1481 $self->throw_exception
1482 ("No arguments to load_classes and couldn't load ${base} ($_)")
1483 };
d4daee7b 1484
829517d4 1485 if ($self eq $target) {
1486 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1487 foreach my $moniker ($self->sources) {
1488 my $source = $self->source($moniker);
1489 my $class = $source->result_class;
1490 $self->inject_base($class, $base);
1491 $class->mk_classdata(resultset_instance => $source->resultset);
1492 $class->mk_classdata(class_resolver => $self);
1493 }
1494 $self->connection(@info);
1495 return $self;
1496 }
d4daee7b 1497
829517d4 1498 my $schema = $self->compose_namespace($target, $base);
1499 {
1500 no strict 'refs';
1501 my $name = join '::', $target, 'schema';
6298a324 1502 *$name = subname $name, sub { $schema };
829517d4 1503 }
d4daee7b 1504
829517d4 1505 $schema->connection(@info);
1506 foreach my $moniker ($schema->sources) {
1507 my $source = $schema->source($moniker);
1508 my $class = $source->result_class;
1509 #warn "$moniker $class $source ".$source->storage;
1510 $class->mk_classdata(result_source_instance => $source);
1511 $class->mk_classdata(resultset_instance => $source->resultset);
1512 $class->mk_classdata(class_resolver => $schema);
1513 }
1514 return $schema;
1515 }
1516}
1517
a02675cd 15181;
c2da098a 1519
c2da098a 1520=head1 AUTHORS
1521
daec44b8 1522Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1523
1524=head1 LICENSE
1525
1526You may distribute this code under the same terms as Perl itself.
1527
1528=cut