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