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