- $schema->deploy now accepts a list of source (name)s to deploy
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
CommitLineData
a02675cd 1package DBIx::Class::Schema;
2
3use strict;
4use warnings;
aa562407 5
701da8c4 6use Carp::Clan qw/^DBIx::Class/;
a917fb06 7use Scalar::Util qw/weaken/;
c9d2e0a2 8use File::Spec;
7cb86b38 9require Module::Find;
a02675cd 10
41a6f8c0 11use base qw/DBIx::Class/;
a02675cd 12
0dc79249 13__PACKAGE__->mk_classdata('class_mappings' => {});
14__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 15__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 16__PACKAGE__->mk_classdata('storage');
82cc0386 17__PACKAGE__->mk_classdata('exception_action');
a02675cd 18
c2da098a 19=head1 NAME
20
21DBIx::Class::Schema - composable schemas
22
23=head1 SYNOPSIS
24
24d67825 25 package Library::Schema;
c2da098a 26 use base qw/DBIx::Class::Schema/;
bab77431 27
24d67825 28 # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
29 __PACKAGE__->load_classes(qw/CD Book DVD/);
c2da098a 30
24d67825 31 package Library::Schema::CD;
03312470 32 use base qw/DBIx::Class/;
77254782 33 __PACKAGE__->load_components(qw/PK::Auto Core/); # for example
24d67825 34 __PACKAGE__->table('cd');
c2da098a 35
5d9076f2 36 # Elsewhere in your code:
24d67825 37 my $schema1 = Library::Schema->connect(
a3d93194 38 $dsn,
39 $user,
40 $password,
24d67825 41 { AutoCommit => 0 },
a3d93194 42 );
bab77431 43
24d67825 44 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 45
24d67825 46 # fetch objects using Library::Schema::DVD
47 my $resultset = $schema1->resultset('DVD')->search( ... );
48 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 49
50=head1 DESCRIPTION
51
a3d93194 52Creates database classes based on a schema. This is the recommended way to
53use L<DBIx::Class> and allows you to use more than one concurrent connection
54with your classes.
429bd4f1 55
03312470 56NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 57carefully, as DBIx::Class does things a little differently. Note in
03312470 58particular which module inherits off which.
59
c2da098a 60=head1 METHODS
61
87c4e602 62=head2 register_class
63
27f01d1f 64=over 4
65
ebc77b53 66=item Arguments: $moniker, $component_class
27f01d1f 67
68=back
076652e8 69
71f9df37 70Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
2053ab2a 71calling:
66d9ef6b 72
181a28f4 73 $schema->register_source($moniker, $component_class->result_source_instance);
076652e8 74
c2da098a 75=cut
76
a02675cd 77sub register_class {
0dc79249 78 my ($self, $moniker, $to_register) = @_;
79 $self->register_source($moniker => $to_register->result_source_instance);
74b92d9a 80}
81
87c4e602 82=head2 register_source
83
27f01d1f 84=over 4
85
ebc77b53 86=item Arguments: $moniker, $result_source
27f01d1f 87
88=back
076652e8 89
82b01c38 90Registers the L<DBIx::Class::ResultSource> in the schema with the given
91moniker.
076652e8 92
93=cut
94
0dc79249 95sub register_source {
96 my ($self, $moniker, $source) = @_;
97 my %reg = %{$self->source_registrations};
98 $reg{$moniker} = $source;
99 $self->source_registrations(\%reg);
100 $source->schema($self);
a917fb06 101 weaken($source->{schema}) if ref($self);
0dc79249 102 if ($source->result_class) {
103 my %map = %{$self->class_mappings};
104 $map{$source->result_class} = $moniker;
105 $self->class_mappings(\%map);
106 }
75d07914 107}
a02675cd 108
bfb2bd4f 109=head2 class
110
27f01d1f 111=over 4
82b01c38 112
ebc77b53 113=item Arguments: $moniker
27f01d1f 114
d601dc88 115=item Return Value: $classname
27f01d1f 116
117=back
82b01c38 118
2053ab2a 119Retrieves the result class name for the given moniker. For example:
82b01c38 120
121 my $class = $schema->class('CD');
bfb2bd4f 122
123=cut
124
125sub class {
0dc79249 126 my ($self, $moniker) = @_;
127 return $self->source($moniker)->result_class;
bfb2bd4f 128}
129
ea20d0fd 130=head2 source
131
27f01d1f 132=over 4
133
ebc77b53 134=item Arguments: $moniker
27f01d1f 135
d601dc88 136=item Return Value: $result_source
82b01c38 137
27f01d1f 138=back
82b01c38 139
24d67825 140 my $source = $schema->source('Book');
ea20d0fd 141
82b01c38 142Returns the L<DBIx::Class::ResultSource> object for the registered moniker.
ea20d0fd 143
144=cut
145
146sub source {
0dc79249 147 my ($self, $moniker) = @_;
148 my $sreg = $self->source_registrations;
149 return $sreg->{$moniker} if exists $sreg->{$moniker};
150
151 # if we got here, they probably passed a full class name
152 my $mapped = $self->class_mappings->{$moniker};
701da8c4 153 $self->throw_exception("Can't find source for ${moniker}")
0dc79249 154 unless $mapped && exists $sreg->{$mapped};
155 return $sreg->{$mapped};
ea20d0fd 156}
157
0dc79249 158=head2 sources
159
27f01d1f 160=over 4
161
d601dc88 162=item Return Value: @source_monikers
27f01d1f 163
164=back
82b01c38 165
166Returns the source monikers of all source registrations on this schema.
2053ab2a 167For example:
82b01c38 168
169 my @source_monikers = $schema->sources;
0dc79249 170
171=cut
172
173sub sources { return keys %{shift->source_registrations}; }
174
9b1ba0f2 175=head2 storage
176
177 my $storage = $schema->storage;
178
179Returns the L<DBIx::Class::Storage> object for this Schema.
180
ea20d0fd 181=head2 resultset
182
27f01d1f 183=over 4
184
ebc77b53 185=item Arguments: $moniker
27f01d1f 186
d601dc88 187=item Return Value: $result_set
82b01c38 188
27f01d1f 189=back
82b01c38 190
24d67825 191 my $rs = $schema->resultset('DVD');
ea20d0fd 192
82b01c38 193Returns the L<DBIx::Class::ResultSet> object for the registered moniker.
ea20d0fd 194
195=cut
196
197sub resultset {
0dc79249 198 my ($self, $moniker) = @_;
199 return $self->source($moniker)->resultset;
ea20d0fd 200}
201
87c4e602 202=head2 load_classes
203
27f01d1f 204=over 4
205
206=item Arguments: @classes?, { $namespace => [ @classes ] }+
207
208=back
076652e8 209
82b01c38 210With no arguments, this method uses L<Module::Find> to find all classes under
211the schema's namespace. Otherwise, this method loads the classes you specify
212(using L<use>), and registers them (using L</"register_class">).
076652e8 213
2053ab2a 214It is possible to comment out classes with a leading C<#>, but note that perl
215will think it's a mistake (trying to use a comment in a qw list), so you'll
216need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 217
2053ab2a 218Example:
82b01c38 219
220 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 221 # etc. (anything under the My::Schema namespace)
82b01c38 222
223 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
224 # not Other::Namespace::LinerNotes nor My::Schema::Track
225 My::Schema->load_classes(qw/ CD Artist #Track /, {
226 Other::Namespace => [qw/ Producer #LinerNotes /],
227 });
228
076652e8 229=cut
230
a02675cd 231sub load_classes {
5ce32fc1 232 my ($class, @params) = @_;
bab77431 233
5ce32fc1 234 my %comps_for;
bab77431 235
5ce32fc1 236 if (@params) {
237 foreach my $param (@params) {
238 if (ref $param eq 'ARRAY') {
239 # filter out commented entries
240 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 241
5ce32fc1 242 push (@{$comps_for{$class}}, @modules);
243 }
244 elsif (ref $param eq 'HASH') {
245 # more than one namespace possible
246 for my $comp ( keys %$param ) {
247 # filter out commented entries
248 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
249
250 push (@{$comps_for{$comp}}, @modules);
251 }
252 }
253 else {
254 # filter out commented entries
255 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
256 }
257 }
258 } else {
bc0c9800 259 my @comp = map { substr $_, length "${class}::" }
260 Module::Find::findallmod($class);
5ce32fc1 261 $comps_for{$class} = \@comp;
41a6f8c0 262 }
5ce32fc1 263
e6efde04 264 my @to_register;
265 {
266 no warnings qw/redefine/;
267 local *Class::C3::reinitialize = sub { };
268 foreach my $prefix (keys %comps_for) {
269 foreach my $comp (@{$comps_for{$prefix}||[]}) {
270 my $comp_class = "${prefix}::${comp}";
83542a7d 271 { # try to untaint module name. mods where this fails
272 # are left alone so we don't have to change the old behavior
273 no locale; # localized \w doesn't untaint expression
274 if ( $comp_class =~ m/^( (?:\w+::)* \w+ )$/x ) {
275 $comp_class = $1;
276 }
277 }
c037c03a 278 $class->ensure_class_loaded($comp_class);
bab77431 279 $comp_class->source_name($comp) unless $comp_class->source_name;
280
281 push(@to_register, [ $comp_class->source_name, $comp_class ]);
bfb2bd4f 282 }
5ce32fc1 283 }
a02675cd 284 }
e6efde04 285 Class::C3->reinitialize;
286
287 foreach my $to (@to_register) {
288 $class->register_class(@$to);
289 # if $class->can('result_source_instance');
290 }
a02675cd 291}
292
2374c5ff 293=head2 load_namespaces
294
295=over 4
296
85bd0538 297=item Arguments: %options?
2374c5ff 298
299=back
300
301This is an alternative to L</load_classes> above which assumes an alternative
c87014e8 302layout for automatic class loading. It assumes that all result
303classes are underneath a sub-namespace of the schema called C<Result>, any
7a58f051 304corresponding ResultSet classes are underneath a sub-namespace of the schema
46a05fd4 305called C<ResultSet>.
2374c5ff 306
46a05fd4 307Both of the sub-namespaces are configurable if you don't like the defaults,
c87014e8 308via the options C<result_namespace> and C<resultset_namespace>.
85bd0538 309
25fb14bd 310If (and only if) you specify the option C<default_resultset_class>, any found
c87014e8 311Result classes for which we do not find a corresponding
25fb14bd 312ResultSet class will have their C<resultset_class> set to
313C<default_resultset_class>.
0f4ec1d2 314
46a05fd4 315C<load_namespaces> takes care of calling C<resultset_class> for you where
316neccessary if you didn't do it for yourself.
f017c022 317
0f4ec1d2 318All of the namespace and classname options to this method are relative to
319the schema classname by default. To specify a fully-qualified name, prefix
320it with a literal C<+>.
2374c5ff 321
f017c022 322Examples:
2374c5ff 323
c87014e8 324 # load My::Schema::Result::CD, My::Schema::Result::Artist,
2374c5ff 325 # My::Schema::ResultSet::CD, etc...
0f4ec1d2 326 My::Schema->load_namespaces;
327
c87014e8 328 # Override everything to use ugly names.
329 # In this example, if there is a My::Schema::Res::Foo, but no matching
330 # My::Schema::RSets::Foo, then Foo will have its
331 # resultset_class set to My::Schema::RSetBase
0f4ec1d2 332 My::Schema->load_namespaces(
c87014e8 333 result_namespace => 'Res',
0f4ec1d2 334 resultset_namespace => 'RSets',
25fb14bd 335 default_resultset_class => 'RSetBase',
0f4ec1d2 336 );
2374c5ff 337
0f4ec1d2 338 # Put things in other namespaces
85bd0538 339 My::Schema->load_namespaces(
c87014e8 340 result_namespace => '+Some::Place::Results',
0f4ec1d2 341 resultset_namespace => '+Another::Place::RSets',
85bd0538 342 );
0f4ec1d2 343
f017c022 344If you'd like to use multiple namespaces of each type, simply use an arrayref
c87014e8 345of namespaces for that option. In the case that the same result
46a05fd4 346(or resultset) class exists in multiple namespaces, the latter entries in
347your list of namespaces will override earlier ones.
f017c022 348
349 My::Schema->load_namespaces(
c87014e8 350 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
351 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
f017c022 352 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
353 );
85bd0538 354
2374c5ff 355=cut
356
f017c022 357# Pre-pends our classname to the given relative classname or
358# class namespace, unless there is a '+' prefix, which will
7a58f051 359# be stripped.
f017c022 360sub _expand_relative_name {
7a58f051 361 my ($class, $name) = @_;
362 return if !$name;
363 $name = $class . '::' . $name if ! ($name =~ s/^\+//);
364 return $name;
f017c022 365}
366
367# returns a hash of $shortname => $fullname for every package
368# found in the given namespaces ($shortname is with the $fullname's
369# namespace stripped off)
370sub _map_namespaces {
371 my ($class, @namespaces) = @_;
372
373 my @results_hash;
374 foreach my $namespace (@namespaces) {
375 push(
376 @results_hash,
377 map { (substr($_, length "${namespace}::"), $_) }
378 Module::Find::findallmod($namespace)
379 );
380 }
381
382 @results_hash;
383}
384
2374c5ff 385sub load_namespaces {
85bd0538 386 my ($class, %args) = @_;
2374c5ff 387
c87014e8 388 my $result_namespace = delete $args{result_namespace} || 'Result';
25fb14bd 389 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
25fb14bd 390 my $default_resultset_class = delete $args{default_resultset_class};
0f4ec1d2 391
25fb14bd 392 $class->throw_exception('load_namespaces: unknown option(s): '
393 . join(q{,}, map { qq{'$_'} } keys %args))
394 if scalar keys %args;
395
7a58f051 396 $default_resultset_class
397 = $class->_expand_relative_name($default_resultset_class);
f017c022 398
c87014e8 399 for my $arg ($result_namespace, $resultset_namespace) {
f017c022 400 $arg = [ $arg ] if !ref($arg) && $arg;
2374c5ff 401
f017c022 402 $class->throw_exception('load_namespaces: namespace arguments must be '
403 . 'a simple string or an arrayref')
404 if ref($arg) ne 'ARRAY';
2374c5ff 405
7a58f051 406 $_ = $class->_expand_relative_name($_) for (@$arg);
f017c022 407 }
2374c5ff 408
c87014e8 409 my %results = $class->_map_namespaces(@$result_namespace);
f017c022 410 my %resultsets = $class->_map_namespaces(@$resultset_namespace);
0f4ec1d2 411
2374c5ff 412 my @to_register;
413 {
25fb14bd 414 no warnings 'redefine';
2374c5ff 415 local *Class::C3::reinitialize = sub { };
25fb14bd 416 use warnings 'redefine';
0f4ec1d2 417
c87014e8 418 foreach my $result (keys %results) {
419 my $result_class = $results{$result};
420 $class->ensure_class_loaded($result_class);
421 $result_class->source_name($result) unless $result_class->source_name;
0f4ec1d2 422
c87014e8 423 my $rs_class = delete $resultsets{$result};
424 my $rs_set = $result_class->resultset_class;
25fb14bd 425 if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
f017c022 426 if($rs_class && $rs_class ne $rs_set) {
c87014e8 427 warn "We found ResultSet class '$rs_class' for '$result', but it seems "
428 . "that you had already set '$result' to use '$rs_set' instead";
2374c5ff 429 }
430 }
25fb14bd 431 elsif($rs_class ||= $default_resultset_class) {
432 $class->ensure_class_loaded($rs_class);
c87014e8 433 $result_class->resultset_class($rs_class);
0f4ec1d2 434 }
2374c5ff 435
c87014e8 436 push(@to_register, [ $result_class->source_name, $result_class ]);
2374c5ff 437 }
438 }
439
0f4ec1d2 440 foreach (sort keys %resultsets) {
441 warn "load_namespaces found ResultSet class $_ with no "
c87014e8 442 . 'corresponding Result class';
2374c5ff 443 }
0f4ec1d2 444
fdcd8145 445 Class::C3->reinitialize;
446 $class->register_class(@$_) for (@to_register);
447
0f4ec1d2 448 return;
2374c5ff 449}
450
c216324a 451=head2 compose_connection (DEPRECATED)
87c4e602 452
27f01d1f 453=over 4
454
ebc77b53 455=item Arguments: $target_namespace, @db_info
429bd4f1 456
d601dc88 457=item Return Value: $new_schema
27f01d1f 458
459=back
076652e8 460
c216324a 461DEPRECATED. You probably wanted compose_namespace.
462
463Actually, you probably just wanted to call connect.
464
465=for hidden due to deprecation
466
2053ab2a 467Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
468calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
469then injects the L<DBix::Class::ResultSetProxy> component and a
470resultset_instance classdata entry on all the new classes, in order to support
82b01c38 471$target_namespaces::$class->search(...) method calls.
472
473This is primarily useful when you have a specific need for class method access
474to a connection. In normal usage it is preferred to call
475L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
476on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
477more information.
54540863 478
076652e8 479=cut
480
c216324a 481{
482 my $warn;
483
484 sub compose_connection {
485 my ($self, $target, @info) = @_;
486
487 warn "compose_connection deprecated as of 0.08000" unless $warn++;
488
489 my $base = 'DBIx::Class::ResultSetProxy';
490 eval "require ${base};";
491 $self->throw_exception
492 ("No arguments to load_classes and couldn't load ${base} ($@)")
493 if $@;
494
495 if ($self eq $target) {
496 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
497 foreach my $moniker ($self->sources) {
498 my $source = $self->source($moniker);
499 my $class = $source->result_class;
500 $self->inject_base($class, $base);
501 $class->mk_classdata(resultset_instance => $source->resultset);
502 $class->mk_classdata(class_resolver => $self);
503 }
504 $self->connection(@info);
505 return $self;
506 }
507
508 my $schema = $self->compose_namespace($target, $base);
509 {
510 no strict 'refs';
511 *{"${target}::schema"} = sub { $schema };
512 }
513
514 $schema->connection(@info);
515 foreach my $moniker ($schema->sources) {
516 my $source = $schema->source($moniker);
be381829 517 my $class = $source->result_class;
c216324a 518 #warn "$moniker $class $source ".$source->storage;
519 $class->mk_classdata(result_source_instance => $source);
be381829 520 $class->mk_classdata(resultset_instance => $source->resultset);
c216324a 521 $class->mk_classdata(class_resolver => $schema);
be381829 522 }
c216324a 523 return $schema;
bfb2bd4f 524 }
e678398e 525}
526
77254782 527=head2 compose_namespace
528
27f01d1f 529=over 4
530
531=item Arguments: $target_namespace, $additional_base_class?
82b01c38 532
d601dc88 533=item Return Value: $new_schema
27f01d1f 534
535=back
13765dad 536
82b01c38 537For each L<DBIx::Class::ResultSource> in the schema, this method creates a
538class in the target namespace (e.g. $target_namespace::CD,
539$target_namespace::Artist) that inherits from the corresponding classes
540attached to the current schema.
77254782 541
82b01c38 542It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
543new $schema object. If C<$additional_base_class> is given, the new composed
544classes will inherit from first the corresponding classe from the current
545schema then the base class.
546
2053ab2a 547For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
82b01c38 548
549 $schema->compose_namespace('My::DB', 'Base::Class');
550 print join (', ', @My::DB::CD::ISA) . "\n";
551 print join (', ', @My::DB::Artist::ISA) ."\n";
552
2053ab2a 553will produce the output
82b01c38 554
555 My::Schema::CD, Base::Class
556 My::Schema::Artist, Base::Class
77254782 557
558=cut
559
e678398e 560sub compose_namespace {
66d9ef6b 561 my ($self, $target, $base) = @_;
562 my %reg = %{ $self->source_registrations };
11b78bd6 563 my %target;
564 my %map;
66d9ef6b 565 my $schema = $self->clone;
e9100ff7 566 {
567 no warnings qw/redefine/;
568 local *Class::C3::reinitialize = sub { };
569 foreach my $moniker ($schema->sources) {
570 my $source = $schema->source($moniker);
571 my $target_class = "${target}::${moniker}";
572 $self->inject_base(
573 $target_class => $source->result_class, ($base ? $base : ())
574 );
575 $source->result_class($target_class);
9d3d5af3 576 $target_class->result_source_instance($source)
577 if $target_class->can('result_source_instance');
e9100ff7 578 }
b7951443 579 }
e9100ff7 580 Class::C3->reinitialize();
11b78bd6 581 {
582 no strict 'refs';
1edaf6fe 583 foreach my $meth (qw/class source resultset/) {
584 *{"${target}::${meth}"} =
585 sub { shift->schema->$meth(@_) };
586 }
11b78bd6 587 }
bfb2bd4f 588 return $schema;
b7951443 589}
590
87c4e602 591=head2 setup_connection_class
592
27f01d1f 593=over 4
594
ebc77b53 595=item Arguments: $target, @info
27f01d1f 596
597=back
076652e8 598
82b01c38 599Sets up a database connection class to inject between the schema and the
600subclasses that the schema creates.
429bd4f1 601
076652e8 602=cut
603
b7951443 604sub setup_connection_class {
605 my ($class, $target, @info) = @_;
63e9583a 606 $class->inject_base($target => 'DBIx::Class::DB');
607 #$target->load_components('DB');
b7951443 608 $target->connection(@info);
609}
610
6b43ba5f 611=head2 storage_type
612
613=over 4
614
615=item Arguments: $storage_type
616
617=item Return Value: $storage_type
618
619=back
620
621Set the storage class that will be instantiated when L</connect> is called.
622If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
623assumed by L</connect>. Defaults to C<::DBI>,
624which is L<DBIx::Class::Storage::DBI>.
625
626You want to use this to hardcoded subclasses of L<DBIx::Class::Storage::DBI>
627in cases where the appropriate subclass is not autodetected, such as when
628dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it to
629C<::DBI::Sybase::MSSQL>.
630
87c4e602 631=head2 connection
632
27f01d1f 633=over 4
634
ebc77b53 635=item Arguments: @args
66d9ef6b 636
d601dc88 637=item Return Value: $new_schema
27f01d1f 638
639=back
82b01c38 640
641Instantiates a new Storage object of type
642L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
85f78622 643$storage->connect_info. Sets the connection in-place on the schema.
644
645See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
646or L<DBIx::Class::Storage> in general.
66d9ef6b 647
648=cut
649
650sub connection {
651 my ($self, @info) = @_;
e59d3e5b 652 return $self if !@info && $self->storage;
1e10a11d 653 my $storage_class = $self->storage_type;
654 $storage_class = 'DBIx::Class::Storage'.$storage_class
655 if $storage_class =~ m/^::/;
8ef144ff 656 eval "require ${storage_class};";
bc0c9800 657 $self->throw_exception(
658 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
659 ) if $@;
82cc0386 660 my $storage = $storage_class->new($self);
66d9ef6b 661 $storage->connect_info(\@info);
662 $self->storage($storage);
c9d2e0a2 663 $self->on_connect() if($self->can('on_connect'));
66d9ef6b 664 return $self;
665}
666
87c4e602 667=head2 connect
668
27f01d1f 669=over 4
670
ebc77b53 671=item Arguments: @info
66d9ef6b 672
d601dc88 673=item Return Value: $new_schema
27f01d1f 674
675=back
82b01c38 676
677This is a convenience method. It is equivalent to calling
678$schema->clone->connection(@info). See L</connection> and L</clone> for more
679information.
66d9ef6b 680
681=cut
682
08b515f1 683sub connect { shift->clone->connection(@_) }
684
4012acd8 685=head2 txn_do
08b515f1 686
4012acd8 687=over 4
08b515f1 688
4012acd8 689=item Arguments: C<$coderef>, @coderef_args?
08b515f1 690
4012acd8 691=item Return Value: The return value of $coderef
08b515f1 692
4012acd8 693=back
08b515f1 694
4012acd8 695Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
696returning its result (if any). Equivalent to calling $schema->storage->txn_do.
697See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 698
4012acd8 699This interface is preferred over using the individual methods L</txn_begin>,
700L</txn_commit>, and L</txn_rollback> below.
08b515f1 701
4012acd8 702=cut
08b515f1 703
4012acd8 704sub txn_do {
705 my $self = shift;
08b515f1 706
4012acd8 707 $self->storage or $self->throw_exception
708 ('txn_do called on $schema without storage');
08b515f1 709
4012acd8 710 $self->storage->txn_do(@_);
711}
08b515f1 712
4012acd8 713=head2 txn_begin
a62cf8d4 714
4012acd8 715Begins a transaction (does nothing if AutoCommit is off). Equivalent to
716calling $schema->storage->txn_begin. See
717L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 718
4012acd8 719=cut
82b01c38 720
4012acd8 721sub txn_begin {
722 my $self = shift;
27f01d1f 723
4012acd8 724 $self->storage or $self->throw_exception
725 ('txn_begin called on $schema without storage');
a62cf8d4 726
4012acd8 727 $self->storage->txn_begin;
728}
a62cf8d4 729
4012acd8 730=head2 txn_commit
a62cf8d4 731
4012acd8 732Commits the current transaction. Equivalent to calling
733$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
734for more information.
a62cf8d4 735
4012acd8 736=cut
a62cf8d4 737
4012acd8 738sub txn_commit {
739 my $self = shift;
a62cf8d4 740
4012acd8 741 $self->storage or $self->throw_exception
742 ('txn_commit called on $schema without storage');
a62cf8d4 743
4012acd8 744 $self->storage->txn_commit;
745}
70634260 746
4012acd8 747=head2 txn_rollback
a62cf8d4 748
4012acd8 749Rolls back the current transaction. Equivalent to calling
750$schema->storage->txn_rollback. See
751L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 752
753=cut
754
4012acd8 755sub txn_rollback {
756 my $self = shift;
a62cf8d4 757
19630353 758 $self->storage or $self->throw_exception
4012acd8 759 ('txn_rollback called on $schema without storage');
a62cf8d4 760
4012acd8 761 $self->storage->txn_rollback;
a62cf8d4 762}
763
66d9ef6b 764=head2 clone
765
27f01d1f 766=over 4
767
d601dc88 768=item Return Value: $new_schema
27f01d1f 769
770=back
82b01c38 771
66d9ef6b 772Clones the schema and its associated result_source objects and returns the
773copy.
774
775=cut
776
777sub clone {
778 my ($self) = @_;
04786a4c 779 my $clone = { (ref $self ? %$self : ()) };
780 bless $clone, (ref $self || $self);
781
66d9ef6b 782 foreach my $moniker ($self->sources) {
783 my $source = $self->source($moniker);
784 my $new = $source->new($source);
785 $clone->register_source($moniker => $new);
786 }
82cc0386 787 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 788 return $clone;
789}
790
87c4e602 791=head2 populate
792
27f01d1f 793=over 4
794
16c5f7d3 795=item Arguments: $source_name, \@data;
27f01d1f 796
797=back
a37a4697 798
16c5f7d3 799Pass this method a resultsource name, and an arrayref of
800arrayrefs. The arrayrefs should contain a list of column names,
801followed by one or many sets of matching data for the given columns.
802
744076d8 803In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
804to insert the data, as this is a fast method. However, insert_bulk currently
805assumes that your datasets all contain the same type of values, using scalar
806references in a column in one row, and not in another will probably not work.
807
808Otherwise, each set of data is inserted into the database using
16c5f7d3 809L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
810objects is returned.
82b01c38 811
812i.e.,
a37a4697 813
24d67825 814 $schema->populate('Artist', [
815 [ qw/artistid name/ ],
816 [ 1, 'Popular Band' ],
817 [ 2, 'Indie Band' ],
a62cf8d4 818 ...
819 ]);
a37a4697 820
821=cut
822
823sub populate {
824 my ($self, $name, $data) = @_;
825 my $rs = $self->resultset($name);
826 my @names = @{shift(@$data)};
54e0bd06 827 if(defined wantarray) {
828 my @created;
829 foreach my $item (@$data) {
830 my %create;
831 @create{@names} = @$item;
832 push(@created, $rs->create(\%create));
833 }
834 return @created;
a37a4697 835 }
54e0bd06 836 $self->storage->insert_bulk($self->source($name)->from, \@names, $data);
a37a4697 837}
838
82cc0386 839=head2 exception_action
840
841=over 4
842
843=item Arguments: $code_reference
844
845=back
846
db5dc233 847If C<exception_action> is set for this class/object, L</throw_exception>
848will prefer to call this code reference with the exception as an argument,
849rather than its normal <croak> action.
850
851Your subroutine should probably just wrap the error in the exception
852object/class of your choosing and rethrow. If, against all sage advice,
853you'd like your C<exception_action> to suppress a particular exception
854completely, simply have it return true.
82cc0386 855
856Example:
857
858 package My::Schema;
859 use base qw/DBIx::Class::Schema/;
860 use My::ExceptionClass;
861 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
862 __PACKAGE__->load_classes;
863
db5dc233 864 # or:
82cc0386 865 my $schema_obj = My::Schema->connect( .... );
866 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
867
db5dc233 868 # suppress all exceptions, like a moron:
869 $schema_obj->exception_action(sub { 1 });
870
5160b401 871=head2 throw_exception
701da8c4 872
75d07914 873=over 4
82b01c38 874
ebc77b53 875=item Arguments: $message
82b01c38 876
877=back
878
879Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 880user's perspective. See L</exception_action> for details on overriding
881this method's behavior.
701da8c4 882
883=cut
884
885sub throw_exception {
82cc0386 886 my $self = shift;
db5dc233 887 croak @_ if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 888}
889
ec6704d4 890=head2 deploy (EXPERIMENTAL)
1c339d71 891
82b01c38 892=over 4
893
6e73ac25 894=item Arguments: $sqlt_args, $dir
82b01c38 895
896=back
897
898Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 899
900Note that this feature is currently EXPERIMENTAL and may not work correctly
499adf63 901across all databases, or fully handle complex relationships. Saying that, it
902has been used successfully by many people, including the core dev team.
1c339d71 903
51bace1c 904See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
905common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
906produced include a DROP TABLE statement for each table created.
907
499adf63 908Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
909ref or an array ref, containing a list of source to deploy. If present, then
910only the sources listed will get deployed.
911
1c339d71 912=cut
913
914sub deploy {
6e73ac25 915 my ($self, $sqltargs, $dir) = @_;
1c339d71 916 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 917 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 918}
919
c0f61310 920=head2 create_ddl_dir (EXPERIMENTAL)
921
922=over 4
923
c9d2e0a2 924=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 925
926=back
927
928Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 929database types, in the given directory. Given a previous version number,
930this will also create a file containing the ALTER TABLE statements to
931transform the previous schema into the current one. Note that these
932statements may contain DROP TABLE or DROP COLUMN statements that can
933potentially destroy data.
934
935The file names are created using the C<ddl_filename> method below, please
936override this method in your schema if you would like a different file
937name format. For the ALTER file, the same format is used, replacing
938$version in the name with "$preversion-$version".
939
940If no arguments are passed, then the following default values are used:
941
942=over 4
943
944=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
945
946=item version - $schema->VERSION
947
948=item directory - './'
949
950=item preversion - <none>
951
952=back
c0f61310 953
954Note that this feature is currently EXPERIMENTAL and may not work correctly
955across all databases, or fully handle complex relationships.
956
c9d2e0a2 957WARNING: Please check all SQL files created, before applying them.
958
c0f61310 959=cut
960
6e73ac25 961sub create_ddl_dir {
e673f011 962 my $self = shift;
963
964 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
965 $self->storage->create_ddl_dir($self, @_);
966}
967
9b83fccd 968=head2 ddl_filename (EXPERIMENTAL)
969
c9d2e0a2 970=over 4
971
972=item Arguments: $directory, $database-type, $version, $preversion
973
974=back
975
976 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
977
978This method is called by C<create_ddl_dir> to compose a file name out of
979the supplied directory, database type and version number. The default file
980name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 981
c9d2e0a2 982You may override this method in your schema if you wish to use a different
983format.
9b83fccd 984
985=cut
986
6e73ac25 987sub ddl_filename {
c9d2e0a2 988 my ($self, $type, $dir, $version, $pversion) = @_;
e673f011 989
990 my $filename = ref($self);
9e7b9292 991 $filename =~ s/::/-/;
c9d2e0a2 992 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
993 $filename =~ s/$version/$pversion-$version/ if($pversion);
e673f011 994
995 return $filename;
996}
997
a02675cd 9981;
c2da098a 999
c2da098a 1000=head1 AUTHORS
1001
daec44b8 1002Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1003
1004=head1 LICENSE
1005
1006You may distribute this code under the same terms as Perl itself.
1007
1008=cut