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