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