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