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