Fix tests, remove some random rints
[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
87c4e602 451=head2 compose_connection
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
2053ab2a 461Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
462calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
463then injects the L<DBix::Class::ResultSetProxy> component and a
464resultset_instance classdata entry on all the new classes, in order to support
82b01c38 465$target_namespaces::$class->search(...) method calls.
466
467This is primarily useful when you have a specific need for class method access
468to a connection. In normal usage it is preferred to call
469L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
470on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
471more information.
54540863 472
076652e8 473=cut
474
a02675cd 475sub compose_connection {
ea20d0fd 476 my ($self, $target, @info) = @_;
80c90f5d 477 my $base = 'DBIx::Class::ResultSetProxy';
8ef144ff 478 eval "require ${base};";
bc0c9800 479 $self->throw_exception
480 ("No arguments to load_classes and couldn't load ${base} ($@)")
481 if $@;
be381829 482
483 if ($self eq $target) {
484 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
485 foreach my $moniker ($self->sources) {
486 my $source = $self->source($moniker);
487 my $class = $source->result_class;
488 $self->inject_base($class, $base);
489 $class->mk_classdata(resultset_instance => $source->resultset);
490 $class->mk_classdata(class_resolver => $self);
491 }
50041f3c 492 $self->connection(@info);
be381829 493 return $self;
494 }
495
66d9ef6b 496 my $schema = $self->compose_namespace($target, $base);
ecceadff 497 {
498 no strict 'refs';
499 *{"${target}::schema"} = sub { $schema };
500 }
501
66d9ef6b 502 $schema->connection(@info);
0dc79249 503 foreach my $moniker ($schema->sources) {
504 my $source = $schema->source($moniker);
505 my $class = $source->result_class;
506 #warn "$moniker $class $source ".$source->storage;
8c49f629 507 $class->mk_classdata(result_source_instance => $source);
ea20d0fd 508 $class->mk_classdata(resultset_instance => $source->resultset);
66d9ef6b 509 $class->mk_classdata(class_resolver => $schema);
bfb2bd4f 510 }
511 return $schema;
e678398e 512}
513
77254782 514=head2 compose_namespace
515
27f01d1f 516=over 4
517
518=item Arguments: $target_namespace, $additional_base_class?
82b01c38 519
d601dc88 520=item Return Value: $new_schema
27f01d1f 521
522=back
13765dad 523
82b01c38 524For each L<DBIx::Class::ResultSource> in the schema, this method creates a
525class in the target namespace (e.g. $target_namespace::CD,
526$target_namespace::Artist) that inherits from the corresponding classes
527attached to the current schema.
77254782 528
82b01c38 529It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
530new $schema object. If C<$additional_base_class> is given, the new composed
531classes will inherit from first the corresponding classe from the current
532schema then the base class.
533
2053ab2a 534For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
82b01c38 535
536 $schema->compose_namespace('My::DB', 'Base::Class');
537 print join (', ', @My::DB::CD::ISA) . "\n";
538 print join (', ', @My::DB::Artist::ISA) ."\n";
539
2053ab2a 540will produce the output
82b01c38 541
542 My::Schema::CD, Base::Class
543 My::Schema::Artist, Base::Class
77254782 544
545=cut
546
e678398e 547sub compose_namespace {
66d9ef6b 548 my ($self, $target, $base) = @_;
549 my %reg = %{ $self->source_registrations };
11b78bd6 550 my %target;
551 my %map;
66d9ef6b 552 my $schema = $self->clone;
e9100ff7 553 {
554 no warnings qw/redefine/;
555 local *Class::C3::reinitialize = sub { };
556 foreach my $moniker ($schema->sources) {
557 my $source = $schema->source($moniker);
558 my $target_class = "${target}::${moniker}";
559 $self->inject_base(
560 $target_class => $source->result_class, ($base ? $base : ())
561 );
562 $source->result_class($target_class);
9d3d5af3 563 $target_class->result_source_instance($source)
564 if $target_class->can('result_source_instance');
e9100ff7 565 }
b7951443 566 }
e9100ff7 567 Class::C3->reinitialize();
11b78bd6 568 {
569 no strict 'refs';
1edaf6fe 570 foreach my $meth (qw/class source resultset/) {
571 *{"${target}::${meth}"} =
572 sub { shift->schema->$meth(@_) };
573 }
11b78bd6 574 }
bfb2bd4f 575 return $schema;
b7951443 576}
577
87c4e602 578=head2 setup_connection_class
579
27f01d1f 580=over 4
581
ebc77b53 582=item Arguments: $target, @info
27f01d1f 583
584=back
076652e8 585
82b01c38 586Sets up a database connection class to inject between the schema and the
587subclasses that the schema creates.
429bd4f1 588
076652e8 589=cut
590
b7951443 591sub setup_connection_class {
592 my ($class, $target, @info) = @_;
63e9583a 593 $class->inject_base($target => 'DBIx::Class::DB');
594 #$target->load_components('DB');
b7951443 595 $target->connection(@info);
596}
597
6b43ba5f 598=head2 storage_type
599
600=over 4
601
602=item Arguments: $storage_type
603
604=item Return Value: $storage_type
605
606=back
607
608Set the storage class that will be instantiated when L</connect> is called.
609If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
610assumed by L</connect>. Defaults to C<::DBI>,
611which is L<DBIx::Class::Storage::DBI>.
612
613You want to use this to hardcoded subclasses of L<DBIx::Class::Storage::DBI>
614in cases where the appropriate subclass is not autodetected, such as when
615dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it to
616C<::DBI::Sybase::MSSQL>.
617
87c4e602 618=head2 connection
619
27f01d1f 620=over 4
621
ebc77b53 622=item Arguments: @args
66d9ef6b 623
d601dc88 624=item Return Value: $new_schema
27f01d1f 625
626=back
82b01c38 627
628Instantiates a new Storage object of type
629L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
85f78622 630$storage->connect_info. Sets the connection in-place on the schema.
631
632See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
633or L<DBIx::Class::Storage> in general.
66d9ef6b 634
635=cut
636
637sub connection {
638 my ($self, @info) = @_;
e59d3e5b 639 return $self if !@info && $self->storage;
1e10a11d 640 my $storage_class = $self->storage_type;
641 $storage_class = 'DBIx::Class::Storage'.$storage_class
642 if $storage_class =~ m/^::/;
8ef144ff 643 eval "require ${storage_class};";
bc0c9800 644 $self->throw_exception(
645 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
646 ) if $@;
82cc0386 647 my $storage = $storage_class->new($self);
66d9ef6b 648 $storage->connect_info(\@info);
649 $self->storage($storage);
c9d2e0a2 650 $self->on_connect() if($self->can('on_connect'));
66d9ef6b 651 return $self;
652}
653
87c4e602 654=head2 connect
655
27f01d1f 656=over 4
657
ebc77b53 658=item Arguments: @info
66d9ef6b 659
d601dc88 660=item Return Value: $new_schema
27f01d1f 661
662=back
82b01c38 663
664This is a convenience method. It is equivalent to calling
665$schema->clone->connection(@info). See L</connection> and L</clone> for more
666information.
66d9ef6b 667
668=cut
669
08b515f1 670sub connect { shift->clone->connection(@_) }
671
4012acd8 672=head2 txn_do
08b515f1 673
4012acd8 674=over 4
08b515f1 675
4012acd8 676=item Arguments: C<$coderef>, @coderef_args?
08b515f1 677
4012acd8 678=item Return Value: The return value of $coderef
08b515f1 679
4012acd8 680=back
08b515f1 681
4012acd8 682Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
683returning its result (if any). Equivalent to calling $schema->storage->txn_do.
684See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 685
4012acd8 686This interface is preferred over using the individual methods L</txn_begin>,
687L</txn_commit>, and L</txn_rollback> below.
08b515f1 688
4012acd8 689=cut
08b515f1 690
4012acd8 691sub txn_do {
692 my $self = shift;
08b515f1 693
4012acd8 694 $self->storage or $self->throw_exception
695 ('txn_do called on $schema without storage');
08b515f1 696
4012acd8 697 $self->storage->txn_do(@_);
698}
08b515f1 699
4012acd8 700=head2 txn_begin
a62cf8d4 701
4012acd8 702Begins a transaction (does nothing if AutoCommit is off). Equivalent to
703calling $schema->storage->txn_begin. See
704L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 705
4012acd8 706=cut
82b01c38 707
4012acd8 708sub txn_begin {
709 my $self = shift;
27f01d1f 710
4012acd8 711 $self->storage or $self->throw_exception
712 ('txn_begin called on $schema without storage');
a62cf8d4 713
4012acd8 714 $self->storage->txn_begin;
715}
a62cf8d4 716
4012acd8 717=head2 txn_commit
a62cf8d4 718
4012acd8 719Commits the current transaction. Equivalent to calling
720$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
721for more information.
a62cf8d4 722
4012acd8 723=cut
a62cf8d4 724
4012acd8 725sub txn_commit {
726 my $self = shift;
a62cf8d4 727
4012acd8 728 $self->storage or $self->throw_exception
729 ('txn_commit called on $schema without storage');
a62cf8d4 730
4012acd8 731 $self->storage->txn_commit;
732}
70634260 733
4012acd8 734=head2 txn_rollback
a62cf8d4 735
4012acd8 736Rolls back the current transaction. Equivalent to calling
737$schema->storage->txn_rollback. See
738L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 739
740=cut
741
4012acd8 742sub txn_rollback {
743 my $self = shift;
a62cf8d4 744
19630353 745 $self->storage or $self->throw_exception
4012acd8 746 ('txn_rollback called on $schema without storage');
a62cf8d4 747
4012acd8 748 $self->storage->txn_rollback;
a62cf8d4 749}
750
66d9ef6b 751=head2 clone
752
27f01d1f 753=over 4
754
d601dc88 755=item Return Value: $new_schema
27f01d1f 756
757=back
82b01c38 758
66d9ef6b 759Clones the schema and its associated result_source objects and returns the
760copy.
761
762=cut
763
764sub clone {
765 my ($self) = @_;
04786a4c 766 my $clone = { (ref $self ? %$self : ()) };
767 bless $clone, (ref $self || $self);
768
66d9ef6b 769 foreach my $moniker ($self->sources) {
770 my $source = $self->source($moniker);
771 my $new = $source->new($source);
772 $clone->register_source($moniker => $new);
773 }
82cc0386 774 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 775 return $clone;
776}
777
87c4e602 778=head2 populate
779
27f01d1f 780=over 4
781
16c5f7d3 782=item Arguments: $source_name, \@data;
27f01d1f 783
784=back
a37a4697 785
16c5f7d3 786Pass this method a resultsource name, and an arrayref of
787arrayrefs. The arrayrefs should contain a list of column names,
788followed by one or many sets of matching data for the given columns.
789
744076d8 790In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
791to insert the data, as this is a fast method. However, insert_bulk currently
792assumes that your datasets all contain the same type of values, using scalar
793references in a column in one row, and not in another will probably not work.
794
795Otherwise, each set of data is inserted into the database using
16c5f7d3 796L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
797objects is returned.
82b01c38 798
799i.e.,
a37a4697 800
24d67825 801 $schema->populate('Artist', [
802 [ qw/artistid name/ ],
803 [ 1, 'Popular Band' ],
804 [ 2, 'Indie Band' ],
a62cf8d4 805 ...
806 ]);
a37a4697 807
808=cut
809
810sub populate {
811 my ($self, $name, $data) = @_;
812 my $rs = $self->resultset($name);
813 my @names = @{shift(@$data)};
54e0bd06 814 if(defined wantarray) {
815 my @created;
816 foreach my $item (@$data) {
817 my %create;
818 @create{@names} = @$item;
819 push(@created, $rs->create(\%create));
820 }
821 return @created;
a37a4697 822 }
54e0bd06 823 $self->storage->insert_bulk($self->source($name)->from, \@names, $data);
a37a4697 824}
825
82cc0386 826=head2 exception_action
827
828=over 4
829
830=item Arguments: $code_reference
831
832=back
833
db5dc233 834If C<exception_action> is set for this class/object, L</throw_exception>
835will prefer to call this code reference with the exception as an argument,
836rather than its normal <croak> action.
837
838Your subroutine should probably just wrap the error in the exception
839object/class of your choosing and rethrow. If, against all sage advice,
840you'd like your C<exception_action> to suppress a particular exception
841completely, simply have it return true.
82cc0386 842
843Example:
844
845 package My::Schema;
846 use base qw/DBIx::Class::Schema/;
847 use My::ExceptionClass;
848 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
849 __PACKAGE__->load_classes;
850
db5dc233 851 # or:
82cc0386 852 my $schema_obj = My::Schema->connect( .... );
853 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
854
db5dc233 855 # suppress all exceptions, like a moron:
856 $schema_obj->exception_action(sub { 1 });
857
5160b401 858=head2 throw_exception
701da8c4 859
75d07914 860=over 4
82b01c38 861
ebc77b53 862=item Arguments: $message
82b01c38 863
864=back
865
866Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 867user's perspective. See L</exception_action> for details on overriding
868this method's behavior.
701da8c4 869
870=cut
871
872sub throw_exception {
82cc0386 873 my $self = shift;
db5dc233 874 croak @_ if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 875}
876
ec6704d4 877=head2 deploy (EXPERIMENTAL)
1c339d71 878
82b01c38 879=over 4
880
6e73ac25 881=item Arguments: $sqlt_args, $dir
82b01c38 882
883=back
884
885Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 886
887Note that this feature is currently EXPERIMENTAL and may not work correctly
888across all databases, or fully handle complex relationships.
1c339d71 889
51bace1c 890See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
891common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
892produced include a DROP TABLE statement for each table created.
893
1c339d71 894=cut
895
896sub deploy {
6e73ac25 897 my ($self, $sqltargs, $dir) = @_;
1c339d71 898 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 899 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 900}
901
c0f61310 902=head2 create_ddl_dir (EXPERIMENTAL)
903
904=over 4
905
c9d2e0a2 906=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 907
908=back
909
910Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 911database types, in the given directory. Given a previous version number,
912this will also create a file containing the ALTER TABLE statements to
913transform the previous schema into the current one. Note that these
914statements may contain DROP TABLE or DROP COLUMN statements that can
915potentially destroy data.
916
917The file names are created using the C<ddl_filename> method below, please
918override this method in your schema if you would like a different file
919name format. For the ALTER file, the same format is used, replacing
920$version in the name with "$preversion-$version".
921
922If no arguments are passed, then the following default values are used:
923
924=over 4
925
926=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
927
928=item version - $schema->VERSION
929
930=item directory - './'
931
932=item preversion - <none>
933
934=back
c0f61310 935
936Note that this feature is currently EXPERIMENTAL and may not work correctly
937across all databases, or fully handle complex relationships.
938
c9d2e0a2 939WARNING: Please check all SQL files created, before applying them.
940
c0f61310 941=cut
942
6e73ac25 943sub create_ddl_dir {
e673f011 944 my $self = shift;
945
946 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
947 $self->storage->create_ddl_dir($self, @_);
948}
949
9b83fccd 950=head2 ddl_filename (EXPERIMENTAL)
951
c9d2e0a2 952=over 4
953
954=item Arguments: $directory, $database-type, $version, $preversion
955
956=back
957
958 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
959
960This method is called by C<create_ddl_dir> to compose a file name out of
961the supplied directory, database type and version number. The default file
962name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 963
c9d2e0a2 964You may override this method in your schema if you wish to use a different
965format.
9b83fccd 966
967=cut
968
6e73ac25 969sub ddl_filename {
c9d2e0a2 970 my ($self, $type, $dir, $version, $pversion) = @_;
e673f011 971
972 my $filename = ref($self);
9e7b9292 973 $filename =~ s/::/-/;
c9d2e0a2 974 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
975 $filename =~ s/$version/$pversion-$version/ if($pversion);
e673f011 976
977 return $filename;
978}
979
a02675cd 9801;
c2da098a 981
c2da098a 982=head1 AUTHORS
983
daec44b8 984Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 985
986=head1 LICENSE
987
988You may distribute this code under the same terms as Perl itself.
989
990=cut