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