Fix the pure-perl in_global_destruction() emulation under threads
[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;
70c28808 7use DBIx::Class::Carp;
9780718f 8use Try::Tiny;
6298a324 9use Scalar::Util 'weaken';
6298a324 10use Sub::Name 'subname';
3b80fa31 11use B 'svref_2object';
a4367b26 12use DBIx::Class::GlobalDestruction;
fd323bf1 13use namespace::clean;
a02675cd 14
41a6f8c0 15use base qw/DBIx::Class/;
a02675cd 16
0dc79249 17__PACKAGE__->mk_classdata('class_mappings' => {});
18__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 19__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 20__PACKAGE__->mk_classdata('storage');
82cc0386 21__PACKAGE__->mk_classdata('exception_action');
4b946902 22__PACKAGE__->mk_classdata('stacktrace' => $ENV{DBIC_TRACE} || 0);
e6c747fd 23__PACKAGE__->mk_classdata('default_resultset_attributes' => {});
a02675cd 24
c2da098a 25=head1 NAME
26
27DBIx::Class::Schema - composable schemas
28
29=head1 SYNOPSIS
30
24d67825 31 package Library::Schema;
c2da098a 32 use base qw/DBIx::Class::Schema/;
bab77431 33
829517d4 34 # load all Result classes in Library/Schema/Result/
35 __PACKAGE__->load_namespaces();
c2da098a 36
829517d4 37 package Library::Schema::Result::CD;
d88ecca6 38 use base qw/DBIx::Class::Core/;
39
40 __PACKAGE__->load_components(qw/InflateColumn::DateTime/); # for example
24d67825 41 __PACKAGE__->table('cd');
c2da098a 42
5d9076f2 43 # Elsewhere in your code:
24d67825 44 my $schema1 = Library::Schema->connect(
a3d93194 45 $dsn,
46 $user,
47 $password,
ef131d82 48 { AutoCommit => 1 },
a3d93194 49 );
bab77431 50
24d67825 51 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 52
829517d4 53 # fetch objects using Library::Schema::Result::DVD
24d67825 54 my $resultset = $schema1->resultset('DVD')->search( ... );
55 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 56
57=head1 DESCRIPTION
58
a3d93194 59Creates database classes based on a schema. This is the recommended way to
60use L<DBIx::Class> and allows you to use more than one concurrent connection
61with your classes.
429bd4f1 62
03312470 63NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 64carefully, as DBIx::Class does things a little differently. Note in
03312470 65particular which module inherits off which.
66
829517d4 67=head1 SETUP METHODS
c2da098a 68
829517d4 69=head2 load_namespaces
87c4e602 70
27f01d1f 71=over 4
72
829517d4 73=item Arguments: %options?
27f01d1f 74
75=back
076652e8 76
829517d4 77 __PACKAGE__->load_namespaces();
66d9ef6b 78
829517d4 79 __PACKAGE__->load_namespaces(
6f731572 80 result_namespace => 'Res',
81 resultset_namespace => 'RSet',
82 default_resultset_class => '+MyDB::Othernamespace::RSet',
83 );
84
85With no arguments, this method uses L<Module::Find> to load all of the
86Result and ResultSet classes under the namespace of the schema from
87which it is called. For example, C<My::Schema> will by default find
88and load Result classes named C<My::Schema::Result::*> and ResultSet
89classes named C<My::Schema::ResultSet::*>.
90
91ResultSet classes are associated with Result class of the same name.
92For example, C<My::Schema::Result::CD> will get the ResultSet class
93C<My::Schema::ResultSet::CD> if it is present.
94
95Both Result and ResultSet namespaces are configurable via the
96C<result_namespace> and C<resultset_namespace> options.
076652e8 97
6f731572 98Another option, C<default_resultset_class> specifies a custom default
99ResultSet class for Result classes with no corresponding ResultSet.
c2da098a 100
6f731572 101All of the namespace and classname options are by default relative to
102the schema classname. To specify a fully-qualified name, prefix it
103with a literal C<+>. For example, C<+Other::NameSpace::Result>.
104
105=head3 Warnings
74b92d9a 106
672687db 107You will be warned if ResultSet classes are discovered for which there
829517d4 108are no matching Result classes like this:
87c4e602 109
829517d4 110 load_namespaces found ResultSet class $classname with no corresponding Result class
27f01d1f 111
829517d4 112If a Result class is found to already have a ResultSet class set using
113L</resultset_class> to some other class, you will be warned like this:
27f01d1f 114
fd323bf1 115 We found ResultSet class '$rs_class' for '$result', but it seems
829517d4 116 that you had already set '$result' to use '$rs_set' instead
076652e8 117
6f731572 118=head3 Examples
2a4d9487 119
829517d4 120 # load My::Schema::Result::CD, My::Schema::Result::Artist,
121 # My::Schema::ResultSet::CD, etc...
122 My::Schema->load_namespaces;
2a4d9487 123
829517d4 124 # Override everything to use ugly names.
125 # In this example, if there is a My::Schema::Res::Foo, but no matching
126 # My::Schema::RSets::Foo, then Foo will have its
127 # resultset_class set to My::Schema::RSetBase
128 My::Schema->load_namespaces(
129 result_namespace => 'Res',
130 resultset_namespace => 'RSets',
131 default_resultset_class => 'RSetBase',
132 );
2a4d9487 133
829517d4 134 # Put things in other namespaces
135 My::Schema->load_namespaces(
136 result_namespace => '+Some::Place::Results',
137 resultset_namespace => '+Another::Place::RSets',
138 );
2a4d9487 139
6f731572 140To search multiple namespaces for either Result or ResultSet classes,
141use an arrayref of namespaces for that option. In the case that the
142same result (or resultset) class exists in multiple namespaces, later
143entries in the list of namespaces will override earlier ones.
2a4d9487 144
829517d4 145 My::Schema->load_namespaces(
146 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
147 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
148 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
149 );
2a4d9487 150
151=cut
152
829517d4 153# Pre-pends our classname to the given relative classname or
154# class namespace, unless there is a '+' prefix, which will
155# be stripped.
156sub _expand_relative_name {
157 my ($class, $name) = @_;
158 return if !$name;
159 $name = $class . '::' . $name if ! ($name =~ s/^\+//);
160 return $name;
2a4d9487 161}
162
f3405058 163# Finds all modules in the supplied namespace, or if omitted in the
164# namespace of $class. Untaints all findings as they can be assumed
165# to be safe
166sub _findallmod {
167 my $proto = shift;
168 my $ns = shift || ref $proto || $proto;
169
3b80fa31 170 require Module::Find;
f3405058 171 my @mods = Module::Find::findallmod($ns);
172
173 # try to untaint module names. mods where this fails
174 # are left alone so we don't have to change the old behavior
175 no locale; # localized \w doesn't untaint expression
176 return map { $_ =~ m/^( (?:\w+::)* \w+ )$/x ? $1 : $_ } @mods;
177}
178
829517d4 179# returns a hash of $shortname => $fullname for every package
b488020e 180# found in the given namespaces ($shortname is with the $fullname's
181# namespace stripped off)
829517d4 182sub _map_namespaces {
183 my ($class, @namespaces) = @_;
6eec9003 184
829517d4 185 my @results_hash;
186 foreach my $namespace (@namespaces) {
187 push(
188 @results_hash,
189 map { (substr($_, length "${namespace}::"), $_) }
f3405058 190 $class->_findallmod($namespace)
829517d4 191 );
0dc79249 192 }
27f01d1f 193
829517d4 194 @results_hash;
ea20d0fd 195}
196
b488020e 197# returns the result_source_instance for the passed class/object,
198# or dies with an informative message (used by load_namespaces)
199sub _ns_get_rsrc_instance {
dee99c24 200 my $me = shift;
201 my $rs_class = ref ($_[0]) || $_[0];
202
203 return try {
204 $rs_class->result_source_instance
205 } catch {
206 $me->throw_exception (
207 "Attempt to load_namespaces() class $rs_class failed - are you sure this is a real Result Class?: $_"
b488020e 208 );
dee99c24 209 };
b488020e 210}
211
829517d4 212sub load_namespaces {
213 my ($class, %args) = @_;
0dc79249 214
829517d4 215 my $result_namespace = delete $args{result_namespace} || 'Result';
216 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
217 my $default_resultset_class = delete $args{default_resultset_class};
0dc79249 218
829517d4 219 $class->throw_exception('load_namespaces: unknown option(s): '
220 . join(q{,}, map { qq{'$_'} } keys %args))
221 if scalar keys %args;
0dc79249 222
829517d4 223 $default_resultset_class
224 = $class->_expand_relative_name($default_resultset_class);
9b1ba0f2 225
829517d4 226 for my $arg ($result_namespace, $resultset_namespace) {
227 $arg = [ $arg ] if !ref($arg) && $arg;
9b1ba0f2 228
829517d4 229 $class->throw_exception('load_namespaces: namespace arguments must be '
230 . 'a simple string or an arrayref')
231 if ref($arg) ne 'ARRAY';
9b1ba0f2 232
829517d4 233 $_ = $class->_expand_relative_name($_) for (@$arg);
234 }
ea20d0fd 235
829517d4 236 my %results = $class->_map_namespaces(@$result_namespace);
237 my %resultsets = $class->_map_namespaces(@$resultset_namespace);
27f01d1f 238
829517d4 239 my @to_register;
240 {
87bf71d5 241 no warnings qw/redefine/;
242 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
243 use warnings qw/redefine/;
27f01d1f 244
3988ce40 245 # ensure classes are loaded and attached in inheritance order
f5ef5fa1 246 for my $res (values %results) {
247 $class->ensure_class_loaded($res);
248 }
3988ce40 249 my %inh_idx;
250 my @subclass_last = sort {
251
252 ($inh_idx{$a} ||=
253 scalar @{mro::get_linear_isa( $results{$a} )}
254 )
255
256 <=>
257
258 ($inh_idx{$b} ||=
259 scalar @{mro::get_linear_isa( $results{$b} )}
260 )
261
262 } keys(%results);
263
3d27f771 264 foreach my $result (@subclass_last) {
829517d4 265 my $result_class = $results{$result};
82b01c38 266
829517d4 267 my $rs_class = delete $resultsets{$result};
b488020e 268 my $rs_set = $class->_ns_get_rsrc_instance ($result_class)->resultset_class;
3988ce40 269
829517d4 270 if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
3d27f771 271 if($rs_class && $rs_class ne $rs_set) {
341d5ede 272 carp "We found ResultSet class '$rs_class' for '$result', but it seems "
829517d4 273 . "that you had already set '$result' to use '$rs_set' instead";
274 }
275 }
276 elsif($rs_class ||= $default_resultset_class) {
277 $class->ensure_class_loaded($rs_class);
1d3108a4 278 if(!$rs_class->isa("DBIx::Class::ResultSet")) {
279 carp "load_namespaces found ResultSet class $rs_class that does not subclass DBIx::Class::ResultSet";
280 }
281
b488020e 282 $class->_ns_get_rsrc_instance ($result_class)->resultset_class($rs_class);
829517d4 283 }
82b01c38 284
b488020e 285 my $source_name = $class->_ns_get_rsrc_instance ($result_class)->source_name || $result;
0e6c5d58 286
287 push(@to_register, [ $source_name, $result_class ]);
829517d4 288 }
289 }
ea20d0fd 290
829517d4 291 foreach (sort keys %resultsets) {
341d5ede 292 carp "load_namespaces found ResultSet class $_ with no "
829517d4 293 . 'corresponding Result class';
294 }
ea20d0fd 295
87bf71d5 296 Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
297
829517d4 298 $class->register_class(@$_) for (@to_register);
ea20d0fd 299
829517d4 300 return;
ea20d0fd 301}
302
87c4e602 303=head2 load_classes
304
27f01d1f 305=over 4
306
307=item Arguments: @classes?, { $namespace => [ @classes ] }+
308
309=back
076652e8 310
1ab61457 311L</load_classes> is an alternative method to L</load_namespaces>, both of
312which serve similar purposes, each with different advantages and disadvantages.
313In the general case you should use L</load_namespaces>, unless you need to
314be able to specify that only specific classes are loaded at runtime.
829517d4 315
82b01c38 316With no arguments, this method uses L<Module::Find> to find all classes under
317the schema's namespace. Otherwise, this method loads the classes you specify
318(using L<use>), and registers them (using L</"register_class">).
076652e8 319
2053ab2a 320It is possible to comment out classes with a leading C<#>, but note that perl
321will think it's a mistake (trying to use a comment in a qw list), so you'll
322need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 323
829517d4 324If any classes found do not appear to be Result class files, you will
325get the following warning:
326
fd323bf1 327 Failed to load $comp_class. Can't find source_name method. Is
829517d4 328 $comp_class really a full DBIC result class? Fix it, move it elsewhere,
329 or make your load_classes call more specific.
330
2053ab2a 331Example:
82b01c38 332
333 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 334 # etc. (anything under the My::Schema namespace)
82b01c38 335
336 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
337 # not Other::Namespace::LinerNotes nor My::Schema::Track
338 My::Schema->load_classes(qw/ CD Artist #Track /, {
339 Other::Namespace => [qw/ Producer #LinerNotes /],
340 });
341
076652e8 342=cut
343
a02675cd 344sub load_classes {
5ce32fc1 345 my ($class, @params) = @_;
bab77431 346
5ce32fc1 347 my %comps_for;
bab77431 348
5ce32fc1 349 if (@params) {
350 foreach my $param (@params) {
351 if (ref $param eq 'ARRAY') {
352 # filter out commented entries
353 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 354
5ce32fc1 355 push (@{$comps_for{$class}}, @modules);
356 }
357 elsif (ref $param eq 'HASH') {
358 # more than one namespace possible
359 for my $comp ( keys %$param ) {
360 # filter out commented entries
361 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
362
363 push (@{$comps_for{$comp}}, @modules);
364 }
365 }
366 else {
367 # filter out commented entries
368 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
369 }
370 }
371 } else {
bc0c9800 372 my @comp = map { substr $_, length "${class}::" }
f3405058 373 $class->_findallmod;
5ce32fc1 374 $comps_for{$class} = \@comp;
41a6f8c0 375 }
5ce32fc1 376
e6efde04 377 my @to_register;
378 {
379 no warnings qw/redefine/;
87bf71d5 380 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
381 use warnings qw/redefine/;
382
e6efde04 383 foreach my $prefix (keys %comps_for) {
384 foreach my $comp (@{$comps_for{$prefix}||[]}) {
385 my $comp_class = "${prefix}::${comp}";
c037c03a 386 $class->ensure_class_loaded($comp_class);
bab77431 387
89271e56 388 my $snsub = $comp_class->can('source_name');
389 if(! $snsub ) {
341d5ede 390 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 391 next;
392 }
393 $comp = $snsub->($comp_class) || $comp;
394
93405cf0 395 push(@to_register, [ $comp, $comp_class ]);
bfb2bd4f 396 }
5ce32fc1 397 }
a02675cd 398 }
87bf71d5 399 Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
e6efde04 400
401 foreach my $to (@to_register) {
402 $class->register_class(@$to);
e6efde04 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(
dee99c24 833 "Unable to load storage class ${storage_class}: $_"
9780718f 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) = @_;
dee99c24 907
829517d4 908 my $schema = $self->clone;
dee99c24 909
910 $schema->source_registrations({});
911
912 # the original class-mappings must remain - otherwise
913 # reverse_relationship_info will not work
914 #$schema->class_mappings({});
915
829517d4 916 {
917 no warnings qw/redefine/;
87bf71d5 918 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
919 use warnings qw/redefine/;
920
a8c2c746 921 no strict qw/refs/;
dee99c24 922 foreach my $moniker ($self->sources) {
923 my $orig_source = $self->source($moniker);
924
829517d4 925 my $target_class = "${target}::${moniker}";
dee99c24 926 $self->inject_base($target_class, $orig_source->result_class, ($base || ()) );
927
928 # register_source examines result_class, and then returns us a clone
929 my $new_source = $schema->register_source($moniker, bless
930 { %$orig_source, result_class => $target_class },
931 ref $orig_source,
829517d4 932 );
a8c2c746 933
dee99c24 934 if ($target_class->can('result_source_instance')) {
935 # give the class a schema-less source copy
936 $target_class->result_source_instance( bless
937 { %$new_source, schema => ref $new_source->{schema} || $new_source->{schema} },
938 ref $new_source,
939 );
a8c2c746 940 }
829517d4 941 }
dee99c24 942
829517d4 943 foreach my $meth (qw/class source resultset/) {
dee99c24 944 no warnings 'redefine';
6298a324 945 *{"${target}::${meth}"} = subname "${target}::${meth}" =>
829517d4 946 sub { shift->schema->$meth(@_) };
947 }
948 }
dee99c24 949
950 Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
951
829517d4 952 return $schema;
953}
954
955sub setup_connection_class {
956 my ($class, $target, @info) = @_;
957 $class->inject_base($target => 'DBIx::Class::DB');
958 #$target->load_components('DB');
959 $target->connection(@info);
960}
961
962=head2 svp_begin
963
fd323bf1 964Creates a new savepoint (does nothing outside a transaction).
829517d4 965Equivalent to calling $schema->storage->svp_begin. See
8bfce9d5 966L<DBIx::Class::Storage/"svp_begin"> for more information.
829517d4 967
968=cut
969
970sub svp_begin {
971 my ($self, $name) = @_;
972
973 $self->storage or $self->throw_exception
974 ('svp_begin called on $schema without storage');
975
976 $self->storage->svp_begin($name);
977}
978
979=head2 svp_release
980
fd323bf1 981Releases a savepoint (does nothing outside a transaction).
829517d4 982Equivalent to calling $schema->storage->svp_release. See
8bfce9d5 983L<DBIx::Class::Storage/"svp_release"> for more information.
829517d4 984
985=cut
986
987sub svp_release {
988 my ($self, $name) = @_;
989
990 $self->storage or $self->throw_exception
991 ('svp_release called on $schema without storage');
82cc0386 992
829517d4 993 $self->storage->svp_release($name);
994}
82cc0386 995
829517d4 996=head2 svp_rollback
db5dc233 997
fd323bf1 998Rollback to a savepoint (does nothing outside a transaction).
829517d4 999Equivalent to calling $schema->storage->svp_rollback. See
8bfce9d5 1000L<DBIx::Class::Storage/"svp_rollback"> for more information.
82cc0386 1001
829517d4 1002=cut
82cc0386 1003
829517d4 1004sub svp_rollback {
1005 my ($self, $name) = @_;
82cc0386 1006
829517d4 1007 $self->storage or $self->throw_exception
1008 ('svp_rollback called on $schema without storage');
82cc0386 1009
829517d4 1010 $self->storage->svp_rollback($name);
1011}
db5dc233 1012
829517d4 1013=head2 clone
613397e7 1014
84c5863b 1015=over 4
613397e7 1016
71829446 1017=item Arguments: %attrs?
1018
829517d4 1019=item Return Value: $new_schema
613397e7 1020
1021=back
1022
829517d4 1023Clones the schema and its associated result_source objects and returns the
71829446 1024copy. The resulting copy will have the same attributes as the source schema,
1025except for those attributes explicitly overriden by the provided C<%attrs>.
829517d4 1026
1027=cut
1028
1029sub clone {
71829446 1030 my $self = shift;
1031
1032 my $clone = {
1033 (ref $self ? %$self : ()),
1034 (@_ == 1 && ref $_[0] eq 'HASH' ? %{ $_[0] } : @_),
1035 };
829517d4 1036 bless $clone, (ref $self || $self);
1037
1038 $clone->class_mappings({ %{$clone->class_mappings} });
1039 $clone->source_registrations({ %{$clone->source_registrations} });
1040 foreach my $moniker ($self->sources) {
1041 my $source = $self->source($moniker);
1042 my $new = $source->new($source);
1043 # we use extra here as we want to leave the class_mappings as they are
1044 # but overwrite the source_registrations entry with the new source
1045 $clone->register_extra_source($moniker => $new);
1046 }
1047 $clone->storage->set_schema($clone) if $clone->storage;
dee99c24 1048
829517d4 1049 return $clone;
1050}
613397e7 1051
5160b401 1052=head2 throw_exception
701da8c4 1053
75d07914 1054=over 4
82b01c38 1055
ebc77b53 1056=item Arguments: $message
82b01c38 1057
1058=back
1059
70c28808 1060Throws an exception. Obeys the exemption rules of L<DBIx::Class::Carp> to report
1061errors from outer-user's perspective. See L</exception_action> for details on overriding
4b946902 1062this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
1063default behavior will provide a detailed stack trace.
701da8c4 1064
1065=cut
1066
c3e9f718 1067my $false_exception_action_warned;
701da8c4 1068sub throw_exception {
82cc0386 1069 my $self = shift;
4981dc70 1070
c3e9f718 1071 if (my $act = $self->exception_action) {
1072 if ($act->(@_)) {
1073 DBIx::Class::Exception->throw(
1074 "Invocation of the exception_action handler installed on $self did *not*"
1075 .' result in an exception. DBIx::Class is unable to function without a reliable'
1076 .' exception mechanism, ensure that exception_action does not hide exceptions'
1077 ." (original error: $_[0])"
1078 );
1079 }
1080 elsif(! $false_exception_action_warned++) {
1081 carp (
1082 "The exception_action handler installed on $self returned false instead"
1083 .' of throwing an exception. This behavior has been deprecated, adjust your'
1084 .' handler to always rethrow the supplied error.'
1085 );
1086 }
1087 }
1088
1089 DBIx::Class::Exception->throw($_[0], $self->stacktrace);
701da8c4 1090}
1091
dfccde48 1092=head2 deploy
1c339d71 1093
82b01c38 1094=over 4
1095
10976519 1096=item Arguments: \%sqlt_args, $dir
82b01c38 1097
1098=back
1099
1100Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 1101
10976519 1102See L<SQL::Translator/METHODS> for a list of values for C<\%sqlt_args>.
1103The most common value for this would be C<< { add_drop_table => 1 } >>
1104to have the SQL produced include a C<DROP TABLE> statement for each table
1105created. For quoting purposes supply C<quote_table_names> and
3e82fc27 1106C<quote_field_names>.
51bace1c 1107
fd323bf1 1108Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1109ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 1110only the sources listed will get deployed. Furthermore, you can use the
1111C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1112FK.
499adf63 1113
1c339d71 1114=cut
1115
1116sub deploy {
6e73ac25 1117 my ($self, $sqltargs, $dir) = @_;
1c339d71 1118 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 1119 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 1120}
1121
0e0ce6c1 1122=head2 deployment_statements
1123
1124=over 4
1125
10976519 1126=item Arguments: See L<DBIx::Class::Storage::DBI/deployment_statements>
0e0ce6c1 1127
829517d4 1128=item Return value: $listofstatements
1129
0e0ce6c1 1130=back
1131
10976519 1132A convenient shortcut to
1133C<< $self->storage->deployment_statements($self, @args) >>.
1134Returns the SQL statements used by L</deploy> and
1135L<DBIx::Class::Schema::Storage/deploy>.
0e0ce6c1 1136
1137=cut
1138
1139sub deployment_statements {
7ad93f5a 1140 my $self = shift;
0e0ce6c1 1141
1142 $self->throw_exception("Can't generate deployment statements without a storage")
1143 if not $self->storage;
1144
7ad93f5a 1145 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1146}
1147
6dfbe2f8 1148=head2 create_ddl_dir
c0f61310 1149
1150=over 4
1151
10976519 1152=item Arguments: See L<DBIx::Class::Storage::DBI/create_ddl_dir>
c0f61310 1153
1154=back
1155
fd323bf1 1156A convenient shortcut to
10976519 1157C<< $self->storage->create_ddl_dir($self, @args) >>.
c9d2e0a2 1158
10976519 1159Creates an SQL file based on the Schema, for each of the specified
1160database types, in the given directory.
c9d2e0a2 1161
c0f61310 1162=cut
1163
6e73ac25 1164sub create_ddl_dir {
e673f011 1165 my $self = shift;
1166
1167 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1168 $self->storage->create_ddl_dir($self, @_);
1169}
1170
e63a82f7 1171=head2 ddl_filename
9b83fccd 1172
c9d2e0a2 1173=over 4
1174
99a74c4a 1175=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1176
829517d4 1177=item Return value: $normalised_filename
1178
c9d2e0a2 1179=back
1180
99a74c4a 1181 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1182
1183This method is called by C<create_ddl_dir> to compose a file name out of
1184the supplied directory, database type and version number. The default file
1185name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1186
c9d2e0a2 1187You may override this method in your schema if you wish to use a different
1188format.
9b83fccd 1189
1acfef8e 1190 WARNING
1191
1192 Prior to DBIx::Class version 0.08100 this method had a different signature:
1193
1194 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1195
1196 In recent versions variables $dir and $version were reversed in order to
fd323bf1 1197 bring the signature in line with other Schema/Storage methods. If you
1acfef8e 1198 really need to maintain backward compatibility, you can do the following
1199 in any overriding methods:
1200
1201 ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100);
1202
9b83fccd 1203=cut
1204
6e73ac25 1205sub ddl_filename {
99a74c4a 1206 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1207
3b80fa31 1208 require File::Spec;
1209
99a74c4a 1210 my $filename = ref($self);
1211 $filename =~ s/::/-/g;
1212 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1213 $filename =~ s/$version/$preversion-$version/ if($preversion);
d4daee7b 1214
99a74c4a 1215 return $filename;
e673f011 1216}
1217
4146e3da 1218=head2 thaw
1219
fd323bf1 1220Provided as the recommended way of thawing schema objects. You can call
4146e3da 1221C<Storable::thaw> directly if you wish, but the thawed objects will not have a
48580715 1222reference to any schema, so are rather useless.
4146e3da 1223
1224=cut
1225
1226sub thaw {
1227 my ($self, $obj) = @_;
1228 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
3b80fa31 1229 require Storable;
4146e3da 1230 return Storable::thaw($obj);
1231}
1232
1233=head2 freeze
1234
26148d36 1235This doesn't actually do anything more than call L<Storable/nfreeze>, it is just
48580715 1236provided here for symmetry.
4146e3da 1237
d2f3e87b 1238=cut
1239
4146e3da 1240sub freeze {
3b80fa31 1241 require Storable;
26148d36 1242 return Storable::nfreeze($_[1]);
4146e3da 1243}
1244
1245=head2 dclone
1246
1477a478 1247=over 4
1248
1249=item Arguments: $object
1250
1251=item Return Value: dcloned $object
1252
1253=back
1254
9e9ecfda 1255Recommended way of dcloning L<DBIx::Class::Row> and L<DBIx::Class::ResultSet>
1256objects so their references to the schema object
1257(which itself is B<not> cloned) are properly maintained.
4146e3da 1258
1259=cut
1260
1261sub dclone {
1262 my ($self, $obj) = @_;
1263 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
3b80fa31 1264 require Storable;
4146e3da 1265 return Storable::dclone($obj);
1266}
1267
93e4d41a 1268=head2 schema_version
1269
829517d4 1270Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1271
1272=cut
1273
1274sub schema_version {
1275 my ($self) = @_;
1276 my $class = ref($self)||$self;
1277
1278 # does -not- use $schema->VERSION
1279 # since that varies in results depending on if version.pm is installed, and if
1280 # so the perl or XS versions. If you want this to change, bug the version.pm
1281 # author to make vpp and vxs behave the same.
1282
1283 my $version;
1284 {
1285 no strict 'refs';
1286 $version = ${"${class}::VERSION"};
1287 }
1288 return $version;
1289}
1290
829517d4 1291
1292=head2 register_class
1293
1294=over 4
1295
1296=item Arguments: $moniker, $component_class
1297
1298=back
1299
fd323bf1 1300This 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 1301
1302You will only need this method if you have your Result classes in
1303files which are not named after the packages (or all in the same
1304file). You may also need it to register classes at runtime.
1305
1306Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1307calling:
1308
1309 $schema->register_source($moniker, $component_class->result_source_instance);
1310
1311=cut
1312
1313sub register_class {
1314 my ($self, $moniker, $to_register) = @_;
1e36ef62 1315 $self->register_source($moniker => $to_register->result_source_instance);
829517d4 1316}
1317
1318=head2 register_source
1319
1320=over 4
1321
1322=item Arguments: $moniker, $result_source
1323
1324=back
1325
1326This method is called by L</register_class>.
1327
1328Registers the L<DBIx::Class::ResultSource> in the schema with the given
1329moniker.
1330
1331=cut
1332
dee99c24 1333sub register_source { shift->_register_source(@_) }
829517d4 1334
98cabed3 1335=head2 unregister_source
1336
1337=over 4
1338
1339=item Arguments: $moniker
1340
1341=back
1342
1343Removes the L<DBIx::Class::ResultSource> from the schema for the given moniker.
1344
1345=cut
1346
dee99c24 1347sub unregister_source { shift->_unregister_source(@_) }
98cabed3 1348
829517d4 1349=head2 register_extra_source
1350
1351=over 4
1352
1353=item Arguments: $moniker, $result_source
1354
1355=back
1356
fd323bf1 1357As L</register_source> but should be used if the result class already
829517d4 1358has a source and you want to register an extra one.
1359
1360=cut
1361
dee99c24 1362sub register_extra_source { shift->_register_source(@_, { extra => 1 }) }
829517d4 1363
1364sub _register_source {
1365 my ($self, $moniker, $source, $params) = @_;
1366
0e6c5d58 1367 $source = $source->new({ %$source, source_name => $moniker });
dee99c24 1368
2461ae19 1369 $source->schema($self);
6298a324 1370 weaken $source->{schema} if ref($self);
2461ae19 1371
829517d4 1372 my %reg = %{$self->source_registrations};
1373 $reg{$moniker} = $source;
1374 $self->source_registrations(\%reg);
1375
dee99c24 1376 return $source if $params->{extra};
1377
1378 my $rs_class = $source->result_class;
1379 if ($rs_class and my $rsrc = try { $rs_class->result_source_instance } ) {
1380 my %map = %{$self->class_mappings};
1381 if (
1382 exists $map{$rs_class}
1383 and
1384 $map{$rs_class} ne $moniker
1385 and
1386 $rsrc ne $_[2] # orig_source
1387 ) {
1388 carp
1389 "$rs_class already had a registered source which was replaced by this call. "
1390 . 'Perhaps you wanted register_extra_source(), though it is more likely you did '
1391 . 'something wrong.'
1392 ;
1393 }
1394
1395 $map{$rs_class} = $moniker;
1396 $self->class_mappings(\%map);
829517d4 1397 }
dee99c24 1398
1399 return $source;
829517d4 1400}
1401
a4367b26 1402my $global_phase_destroy;
1403sub DESTROY {
1404 return if $global_phase_destroy ||= in_global_destruction;
66917da3 1405
a4367b26 1406 my $self = shift;
1407 my $srcs = $self->source_registrations;
1408
1409 for my $moniker (keys %$srcs) {
1410 # find first source that is not about to be GCed (someone other than $self
1411 # holds a reference to it) and reattach to it, weakening our own link
1412 #
1413 # during global destruction (if we have not yet bailed out) this should throw
1414 # which will serve as a signal to not try doing anything else
1415 # however beware - on older perls the exception seems randomly untrappable
1416 # due to some weird race condition during thread joining :(((
1417 if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) {
1418 local $@;
1419 eval {
1420 $srcs->{$moniker}->schema($self);
50261284 1421 weaken $srcs->{$moniker};
a4367b26 1422 1;
1423 } or do {
1424 $global_phase_destroy = 1;
1425 };
1426
1427 last;
50261284 1428 }
1429 }
1430}
1431
829517d4 1432sub _unregister_source {
1433 my ($self, $moniker) = @_;
fd323bf1 1434 my %reg = %{$self->source_registrations};
829517d4 1435
1436 my $source = delete $reg{$moniker};
1437 $self->source_registrations(\%reg);
1438 if ($source->result_class) {
1439 my %map = %{$self->class_mappings};
1440 delete $map{$source->result_class};
1441 $self->class_mappings(\%map);
1442 }
1443}
1444
1445
1446=head2 compose_connection (DEPRECATED)
1447
1448=over 4
1449
1450=item Arguments: $target_namespace, @db_info
1451
1452=item Return Value: $new_schema
1453
1454=back
1455
1456DEPRECATED. You probably wanted compose_namespace.
1457
1458Actually, you probably just wanted to call connect.
1459
1460=begin hidden
1461
1462(hidden due to deprecation)
1463
1464Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1465calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1466then injects the L<DBix::Class::ResultSetProxy> component and a
1467resultset_instance classdata entry on all the new classes, in order to support
1468$target_namespaces::$class->search(...) method calls.
1469
1470This is primarily useful when you have a specific need for class method access
1471to a connection. In normal usage it is preferred to call
1472L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1473on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1474more information.
1475
1476=end hidden
1477
1478=cut
1479
e42bbd7f 1480sub compose_connection {
1481 my ($self, $target, @info) = @_;
829517d4 1482
e42bbd7f 1483 carp_once "compose_connection deprecated as of 0.08000"
1484 unless $INC{"DBIx/Class/CDBICompat.pm"};
d4daee7b 1485
e42bbd7f 1486 my $base = 'DBIx::Class::ResultSetProxy';
1487 try {
1488 eval "require ${base};"
1489 }
1490 catch {
1491 $self->throw_exception
1492 ("No arguments to load_classes and couldn't load ${base} ($_)")
1493 };
d4daee7b 1494
e42bbd7f 1495 if ($self eq $target) {
1496 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1497 foreach my $moniker ($self->sources) {
1498 my $source = $self->source($moniker);
829517d4 1499 my $class = $source->result_class;
e42bbd7f 1500 $self->inject_base($class, $base);
829517d4 1501 $class->mk_classdata(resultset_instance => $source->resultset);
e42bbd7f 1502 $class->mk_classdata(class_resolver => $self);
829517d4 1503 }
e42bbd7f 1504 $self->connection(@info);
1505 return $self;
1506 }
1507
1508 my $schema = $self->compose_namespace($target, $base);
1509 {
1510 no strict 'refs';
1511 my $name = join '::', $target, 'schema';
1512 *$name = subname $name, sub { $schema };
829517d4 1513 }
e42bbd7f 1514
1515 $schema->connection(@info);
1516 foreach my $moniker ($schema->sources) {
1517 my $source = $schema->source($moniker);
1518 my $class = $source->result_class;
1519 #warn "$moniker $class $source ".$source->storage;
1520 $class->mk_classdata(result_source_instance => $source);
1521 $class->mk_classdata(resultset_instance => $source->resultset);
1522 $class->mk_classdata(class_resolver => $schema);
1523 }
1524 return $schema;
829517d4 1525}
1526
a02675cd 15271;
c2da098a 1528
c2da098a 1529=head1 AUTHORS
1530
daec44b8 1531Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1532
1533=head1 LICENSE
1534
1535You may distribute this code under the same terms as Perl itself.
1536
1537=cut