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