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