remove cwd dep, modify pod
[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');
4b946902 19__PACKAGE__->mk_classdata('stacktrace' => $ENV{DBIC_TRACE} || 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);
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}
66d9ef6b 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 }
8b93a938 854 my @results_to_create;
855 foreach my $datum (@$data) {
856 my %result_to_create;
857 foreach my $index (0..$#names) {
858 $result_to_create{$names[$index]} = $$datum[$index];
859 }
860 push @results_to_create, \%result_to_create;
861 }
862 $rs->populate(\@results_to_create);
a37a4697 863}
864
82cc0386 865=head2 exception_action
866
867=over 4
868
869=item Arguments: $code_reference
870
871=back
872
db5dc233 873If C<exception_action> is set for this class/object, L</throw_exception>
874will prefer to call this code reference with the exception as an argument,
613397e7 875rather than its normal C<croak> or C<confess> action.
db5dc233 876
877Your subroutine should probably just wrap the error in the exception
878object/class of your choosing and rethrow. If, against all sage advice,
879you'd like your C<exception_action> to suppress a particular exception
880completely, simply have it return true.
82cc0386 881
882Example:
883
884 package My::Schema;
885 use base qw/DBIx::Class::Schema/;
886 use My::ExceptionClass;
887 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
888 __PACKAGE__->load_classes;
889
db5dc233 890 # or:
82cc0386 891 my $schema_obj = My::Schema->connect( .... );
892 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
893
db5dc233 894 # suppress all exceptions, like a moron:
895 $schema_obj->exception_action(sub { 1 });
896
613397e7 897=head2 stacktrace
898
84c5863b 899=over 4
613397e7 900
901=item Arguments: boolean
902
903=back
904
4981dc70 905Whether L</throw_exception> should include stack trace information.
4b946902 906Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
907is true.
613397e7 908
5160b401 909=head2 throw_exception
701da8c4 910
75d07914 911=over 4
82b01c38 912
ebc77b53 913=item Arguments: $message
82b01c38 914
915=back
916
917Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 918user's perspective. See L</exception_action> for details on overriding
4b946902 919this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
920default behavior will provide a detailed stack trace.
701da8c4 921
922=cut
923
924sub throw_exception {
82cc0386 925 my $self = shift;
4981dc70 926
927 DBIx::Class::Exception->throw($_[0], $self->stacktrace)
928 if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 929}
930
dfccde48 931=head2 deploy
1c339d71 932
82b01c38 933=over 4
934
6e73ac25 935=item Arguments: $sqlt_args, $dir
82b01c38 936
937=back
938
939Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 940
51bace1c 941See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
942common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
943produced include a DROP TABLE statement for each table created.
944
499adf63 945Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
946ref or an array ref, containing a list of source to deploy. If present, then
947only the sources listed will get deployed.
948
1c339d71 949=cut
950
951sub deploy {
6e73ac25 952 my ($self, $sqltargs, $dir) = @_;
1c339d71 953 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 954 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 955}
956
c0f61310 957=head2 create_ddl_dir (EXPERIMENTAL)
958
959=over 4
960
c9d2e0a2 961=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 962
963=back
964
965Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 966database types, in the given directory. Given a previous version number,
967this will also create a file containing the ALTER TABLE statements to
968transform the previous schema into the current one. Note that these
969statements may contain DROP TABLE or DROP COLUMN statements that can
970potentially destroy data.
971
972The file names are created using the C<ddl_filename> method below, please
973override this method in your schema if you would like a different file
974name format. For the ALTER file, the same format is used, replacing
975$version in the name with "$preversion-$version".
976
977If no arguments are passed, then the following default values are used:
978
979=over 4
980
981=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
982
983=item version - $schema->VERSION
984
985=item directory - './'
986
987=item preversion - <none>
988
989=back
c0f61310 990
991Note that this feature is currently EXPERIMENTAL and may not work correctly
992across all databases, or fully handle complex relationships.
993
c9d2e0a2 994WARNING: Please check all SQL files created, before applying them.
995
c0f61310 996=cut
997
6e73ac25 998sub create_ddl_dir {
e673f011 999 my $self = shift;
1000
1001 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1002 $self->storage->create_ddl_dir($self, @_);
1003}
1004
9b83fccd 1005=head2 ddl_filename (EXPERIMENTAL)
1006
c9d2e0a2 1007=over 4
1008
1009=item Arguments: $directory, $database-type, $version, $preversion
1010
1011=back
1012
1013 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1014
1015This method is called by C<create_ddl_dir> to compose a file name out of
1016the supplied directory, database type and version number. The default file
1017name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1018
c9d2e0a2 1019You may override this method in your schema if you wish to use a different
1020format.
9b83fccd 1021
1022=cut
1023
6e73ac25 1024sub ddl_filename {
c9d2e0a2 1025 my ($self, $type, $dir, $version, $pversion) = @_;
e673f011 1026
1027 my $filename = ref($self);
32be057c 1028 $filename =~ s/::/-/g;
c9d2e0a2 1029 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1030 $filename =~ s/$version/$pversion-$version/ if($pversion);
e673f011 1031
1032 return $filename;
1033}
1034
a02675cd 10351;
c2da098a 1036
c2da098a 1037=head1 AUTHORS
1038
daec44b8 1039Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1040
1041=head1 LICENSE
1042
1043You may distribute this code under the same terms as Perl itself.
1044
1045=cut