Move scary stuff to its own class
[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;
aea59b74 9use Scalar::Util qw/weaken blessed/;
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
93963f59 1038 $clone->$_(undef) for qw/class_mappings source_registrations storage/;
1039
1040 $clone->_copy_state_from($self);
1041
1042 return $clone;
1043}
1044
1045# Needed in Schema::Loader - if you refactor, please make a compatibility shim
1046# -- Caelum
1047sub _copy_state_from {
1048 my ($self, $from) = @_;
1049
1050 $self->class_mappings({ %{$from->class_mappings} });
1051 $self->source_registrations({ %{$from->source_registrations} });
1052
1053 foreach my $moniker ($from->sources) {
1054 my $source = $from->source($moniker);
829517d4 1055 my $new = $source->new($source);
1056 # we use extra here as we want to leave the class_mappings as they are
1057 # but overwrite the source_registrations entry with the new source
93963f59 1058 $self->register_extra_source($moniker => $new);
829517d4 1059 }
dee99c24 1060
93963f59 1061 if ($from->storage) {
1062 $self->storage($from->storage);
1063 $self->storage->set_schema($self);
1064 }
829517d4 1065}
613397e7 1066
5160b401 1067=head2 throw_exception
701da8c4 1068
75d07914 1069=over 4
82b01c38 1070
ebc77b53 1071=item Arguments: $message
82b01c38 1072
1073=back
1074
70c28808 1075Throws an exception. Obeys the exemption rules of L<DBIx::Class::Carp> to report
1076errors from outer-user's perspective. See L</exception_action> for details on overriding
4b946902 1077this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
1078default behavior will provide a detailed stack trace.
701da8c4 1079
1080=cut
1081
c3e9f718 1082my $false_exception_action_warned;
701da8c4 1083sub throw_exception {
82cc0386 1084 my $self = shift;
4981dc70 1085
c3e9f718 1086 if (my $act = $self->exception_action) {
1087 if ($act->(@_)) {
1088 DBIx::Class::Exception->throw(
1089 "Invocation of the exception_action handler installed on $self did *not*"
1090 .' result in an exception. DBIx::Class is unable to function without a reliable'
1091 .' exception mechanism, ensure that exception_action does not hide exceptions'
1092 ." (original error: $_[0])"
1093 );
1094 }
1095 elsif(! $false_exception_action_warned++) {
1096 carp (
1097 "The exception_action handler installed on $self returned false instead"
1098 .' of throwing an exception. This behavior has been deprecated, adjust your'
1099 .' handler to always rethrow the supplied error.'
1100 );
1101 }
1102 }
1103
1104 DBIx::Class::Exception->throw($_[0], $self->stacktrace);
701da8c4 1105}
1106
dfccde48 1107=head2 deploy
1c339d71 1108
82b01c38 1109=over 4
1110
10976519 1111=item Arguments: \%sqlt_args, $dir
82b01c38 1112
1113=back
1114
1115Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 1116
10976519 1117See L<SQL::Translator/METHODS> for a list of values for C<\%sqlt_args>.
1118The most common value for this would be C<< { add_drop_table => 1 } >>
1119to have the SQL produced include a C<DROP TABLE> statement for each table
1120created. For quoting purposes supply C<quote_table_names> and
3e82fc27 1121C<quote_field_names>.
51bace1c 1122
fd323bf1 1123Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1124ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 1125only the sources listed will get deployed. Furthermore, you can use the
1126C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1127FK.
499adf63 1128
1c339d71 1129=cut
1130
1131sub deploy {
6e73ac25 1132 my ($self, $sqltargs, $dir) = @_;
1c339d71 1133 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 1134 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 1135}
1136
0e0ce6c1 1137=head2 deployment_statements
1138
1139=over 4
1140
10976519 1141=item Arguments: See L<DBIx::Class::Storage::DBI/deployment_statements>
0e0ce6c1 1142
829517d4 1143=item Return value: $listofstatements
1144
0e0ce6c1 1145=back
1146
10976519 1147A convenient shortcut to
1148C<< $self->storage->deployment_statements($self, @args) >>.
1149Returns the SQL statements used by L</deploy> and
1150L<DBIx::Class::Schema::Storage/deploy>.
0e0ce6c1 1151
1152=cut
1153
1154sub deployment_statements {
7ad93f5a 1155 my $self = shift;
0e0ce6c1 1156
1157 $self->throw_exception("Can't generate deployment statements without a storage")
1158 if not $self->storage;
1159
7ad93f5a 1160 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1161}
1162
6dfbe2f8 1163=head2 create_ddl_dir
c0f61310 1164
1165=over 4
1166
10976519 1167=item Arguments: See L<DBIx::Class::Storage::DBI/create_ddl_dir>
c0f61310 1168
1169=back
1170
fd323bf1 1171A convenient shortcut to
10976519 1172C<< $self->storage->create_ddl_dir($self, @args) >>.
c9d2e0a2 1173
10976519 1174Creates an SQL file based on the Schema, for each of the specified
1175database types, in the given directory.
c9d2e0a2 1176
c0f61310 1177=cut
1178
6e73ac25 1179sub create_ddl_dir {
e673f011 1180 my $self = shift;
1181
1182 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1183 $self->storage->create_ddl_dir($self, @_);
1184}
1185
e63a82f7 1186=head2 ddl_filename
9b83fccd 1187
c9d2e0a2 1188=over 4
1189
99a74c4a 1190=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1191
829517d4 1192=item Return value: $normalised_filename
1193
c9d2e0a2 1194=back
1195
99a74c4a 1196 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1197
1198This method is called by C<create_ddl_dir> to compose a file name out of
1199the supplied directory, database type and version number. The default file
1200name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1201
c9d2e0a2 1202You may override this method in your schema if you wish to use a different
1203format.
9b83fccd 1204
1acfef8e 1205 WARNING
1206
1207 Prior to DBIx::Class version 0.08100 this method had a different signature:
1208
1209 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1210
1211 In recent versions variables $dir and $version were reversed in order to
fd323bf1 1212 bring the signature in line with other Schema/Storage methods. If you
1acfef8e 1213 really need to maintain backward compatibility, you can do the following
1214 in any overriding methods:
1215
1216 ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100);
1217
9b83fccd 1218=cut
1219
6e73ac25 1220sub ddl_filename {
99a74c4a 1221 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1222
3b80fa31 1223 require File::Spec;
1224
aea59b74 1225 $version = "$preversion-$version" if $preversion;
d4daee7b 1226
aea59b74 1227 my $class = blessed($self) || $self;
1228 $class =~ s/::/-/g;
1229
1230 return File::Spec->catfile($dir, "$class-$version-$type.sql");
e673f011 1231}
1232
4146e3da 1233=head2 thaw
1234
fd323bf1 1235Provided as the recommended way of thawing schema objects. You can call
4146e3da 1236C<Storable::thaw> directly if you wish, but the thawed objects will not have a
48580715 1237reference to any schema, so are rather useless.
4146e3da 1238
1239=cut
1240
1241sub thaw {
1242 my ($self, $obj) = @_;
1243 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
3b80fa31 1244 require Storable;
4146e3da 1245 return Storable::thaw($obj);
1246}
1247
1248=head2 freeze
1249
26148d36 1250This doesn't actually do anything more than call L<Storable/nfreeze>, it is just
48580715 1251provided here for symmetry.
4146e3da 1252
d2f3e87b 1253=cut
1254
4146e3da 1255sub freeze {
3b80fa31 1256 require Storable;
26148d36 1257 return Storable::nfreeze($_[1]);
4146e3da 1258}
1259
1260=head2 dclone
1261
1477a478 1262=over 4
1263
1264=item Arguments: $object
1265
1266=item Return Value: dcloned $object
1267
1268=back
1269
9e9ecfda 1270Recommended way of dcloning L<DBIx::Class::Row> and L<DBIx::Class::ResultSet>
1271objects so their references to the schema object
1272(which itself is B<not> cloned) are properly maintained.
4146e3da 1273
1274=cut
1275
1276sub dclone {
1277 my ($self, $obj) = @_;
1278 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
3b80fa31 1279 require Storable;
4146e3da 1280 return Storable::dclone($obj);
1281}
1282
93e4d41a 1283=head2 schema_version
1284
829517d4 1285Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1286
1287=cut
1288
1289sub schema_version {
1290 my ($self) = @_;
1291 my $class = ref($self)||$self;
1292
1293 # does -not- use $schema->VERSION
1294 # since that varies in results depending on if version.pm is installed, and if
1295 # so the perl or XS versions. If you want this to change, bug the version.pm
1296 # author to make vpp and vxs behave the same.
1297
1298 my $version;
1299 {
1300 no strict 'refs';
1301 $version = ${"${class}::VERSION"};
1302 }
1303 return $version;
1304}
1305
829517d4 1306
1307=head2 register_class
1308
1309=over 4
1310
1311=item Arguments: $moniker, $component_class
1312
1313=back
1314
fd323bf1 1315This 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 1316
1317You will only need this method if you have your Result classes in
1318files which are not named after the packages (or all in the same
1319file). You may also need it to register classes at runtime.
1320
1321Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1322calling:
1323
1324 $schema->register_source($moniker, $component_class->result_source_instance);
1325
1326=cut
1327
1328sub register_class {
1329 my ($self, $moniker, $to_register) = @_;
1e36ef62 1330 $self->register_source($moniker => $to_register->result_source_instance);
829517d4 1331}
1332
1333=head2 register_source
1334
1335=over 4
1336
1337=item Arguments: $moniker, $result_source
1338
1339=back
1340
1341This method is called by L</register_class>.
1342
1343Registers the L<DBIx::Class::ResultSource> in the schema with the given
1344moniker.
1345
1346=cut
1347
dee99c24 1348sub register_source { shift->_register_source(@_) }
829517d4 1349
98cabed3 1350=head2 unregister_source
1351
1352=over 4
1353
1354=item Arguments: $moniker
1355
1356=back
1357
1358Removes the L<DBIx::Class::ResultSource> from the schema for the given moniker.
1359
1360=cut
1361
dee99c24 1362sub unregister_source { shift->_unregister_source(@_) }
98cabed3 1363
829517d4 1364=head2 register_extra_source
1365
1366=over 4
1367
1368=item Arguments: $moniker, $result_source
1369
1370=back
1371
fd323bf1 1372As L</register_source> but should be used if the result class already
829517d4 1373has a source and you want to register an extra one.
1374
1375=cut
1376
dee99c24 1377sub register_extra_source { shift->_register_source(@_, { extra => 1 }) }
829517d4 1378
1379sub _register_source {
1380 my ($self, $moniker, $source, $params) = @_;
1381
0e6c5d58 1382 $source = $source->new({ %$source, source_name => $moniker });
dee99c24 1383
2461ae19 1384 $source->schema($self);
6298a324 1385 weaken $source->{schema} if ref($self);
2461ae19 1386
829517d4 1387 my %reg = %{$self->source_registrations};
1388 $reg{$moniker} = $source;
1389 $self->source_registrations(\%reg);
1390
dee99c24 1391 return $source if $params->{extra};
1392
1393 my $rs_class = $source->result_class;
1394 if ($rs_class and my $rsrc = try { $rs_class->result_source_instance } ) {
1395 my %map = %{$self->class_mappings};
1396 if (
1397 exists $map{$rs_class}
1398 and
1399 $map{$rs_class} ne $moniker
1400 and
1401 $rsrc ne $_[2] # orig_source
1402 ) {
1403 carp
1404 "$rs_class already had a registered source which was replaced by this call. "
1405 . 'Perhaps you wanted register_extra_source(), though it is more likely you did '
1406 . 'something wrong.'
1407 ;
1408 }
1409
1410 $map{$rs_class} = $moniker;
1411 $self->class_mappings(\%map);
829517d4 1412 }
dee99c24 1413
1414 return $source;
829517d4 1415}
1416
a4367b26 1417my $global_phase_destroy;
1418sub DESTROY {
1419 return if $global_phase_destroy ||= in_global_destruction;
66917da3 1420
a4367b26 1421 my $self = shift;
1422 my $srcs = $self->source_registrations;
1423
1424 for my $moniker (keys %$srcs) {
1425 # find first source that is not about to be GCed (someone other than $self
1426 # holds a reference to it) and reattach to it, weakening our own link
1427 #
1428 # during global destruction (if we have not yet bailed out) this should throw
1429 # which will serve as a signal to not try doing anything else
1430 # however beware - on older perls the exception seems randomly untrappable
1431 # due to some weird race condition during thread joining :(((
1432 if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) {
1433 local $@;
1434 eval {
1435 $srcs->{$moniker}->schema($self);
50261284 1436 weaken $srcs->{$moniker};
a4367b26 1437 1;
1438 } or do {
1439 $global_phase_destroy = 1;
1440 };
1441
1442 last;
50261284 1443 }
1444 }
1445}
1446
829517d4 1447sub _unregister_source {
1448 my ($self, $moniker) = @_;
fd323bf1 1449 my %reg = %{$self->source_registrations};
829517d4 1450
1451 my $source = delete $reg{$moniker};
1452 $self->source_registrations(\%reg);
1453 if ($source->result_class) {
1454 my %map = %{$self->class_mappings};
1455 delete $map{$source->result_class};
1456 $self->class_mappings(\%map);
1457 }
1458}
1459
1460
1461=head2 compose_connection (DEPRECATED)
1462
1463=over 4
1464
1465=item Arguments: $target_namespace, @db_info
1466
1467=item Return Value: $new_schema
1468
1469=back
1470
1471DEPRECATED. You probably wanted compose_namespace.
1472
1473Actually, you probably just wanted to call connect.
1474
1475=begin hidden
1476
1477(hidden due to deprecation)
1478
1479Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1480calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1481then injects the L<DBix::Class::ResultSetProxy> component and a
1482resultset_instance classdata entry on all the new classes, in order to support
1483$target_namespaces::$class->search(...) method calls.
1484
1485This is primarily useful when you have a specific need for class method access
1486to a connection. In normal usage it is preferred to call
1487L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1488on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1489more information.
1490
1491=end hidden
1492
1493=cut
1494
e42bbd7f 1495sub compose_connection {
1496 my ($self, $target, @info) = @_;
829517d4 1497
e42bbd7f 1498 carp_once "compose_connection deprecated as of 0.08000"
1499 unless $INC{"DBIx/Class/CDBICompat.pm"};
d4daee7b 1500
e42bbd7f 1501 my $base = 'DBIx::Class::ResultSetProxy';
1502 try {
1503 eval "require ${base};"
1504 }
1505 catch {
1506 $self->throw_exception
1507 ("No arguments to load_classes and couldn't load ${base} ($_)")
1508 };
d4daee7b 1509
e42bbd7f 1510 if ($self eq $target) {
1511 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1512 foreach my $moniker ($self->sources) {
1513 my $source = $self->source($moniker);
829517d4 1514 my $class = $source->result_class;
e42bbd7f 1515 $self->inject_base($class, $base);
829517d4 1516 $class->mk_classdata(resultset_instance => $source->resultset);
e42bbd7f 1517 $class->mk_classdata(class_resolver => $self);
829517d4 1518 }
e42bbd7f 1519 $self->connection(@info);
1520 return $self;
1521 }
1522
1523 my $schema = $self->compose_namespace($target, $base);
1524 {
1525 no strict 'refs';
1526 my $name = join '::', $target, 'schema';
1527 *$name = subname $name, sub { $schema };
829517d4 1528 }
e42bbd7f 1529
1530 $schema->connection(@info);
1531 foreach my $moniker ($schema->sources) {
1532 my $source = $schema->source($moniker);
1533 my $class = $source->result_class;
1534 #warn "$moniker $class $source ".$source->storage;
1535 $class->mk_classdata(result_source_instance => $source);
1536 $class->mk_classdata(resultset_instance => $source->resultset);
1537 $class->mk_classdata(class_resolver => $schema);
1538 }
1539 return $schema;
829517d4 1540}
1541
a02675cd 15421;
c2da098a 1543
c2da098a 1544=head1 AUTHORS
1545
daec44b8 1546Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1547
1548=head1 LICENSE
1549
1550You may distribute this code under the same terms as Perl itself.
1551
1552=cut