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