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