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