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