fixup source registration bugs where schema-specific things were being set on class...
[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;
ddc0a6c8 10use Sub::Name ();
7cb86b38 11require Module::Find;
a02675cd 12
41a6f8c0 13use base qw/DBIx::Class/;
a02675cd 14
0dc79249 15__PACKAGE__->mk_classdata('class_mappings' => {});
16__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 17__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 18__PACKAGE__->mk_classdata('storage');
82cc0386 19__PACKAGE__->mk_classdata('exception_action');
4b946902 20__PACKAGE__->mk_classdata('stacktrace' => $ENV{DBIC_TRACE} || 0);
e6c747fd 21__PACKAGE__->mk_classdata('default_resultset_attributes' => {});
a02675cd 22
c2da098a 23=head1 NAME
24
25DBIx::Class::Schema - composable schemas
26
27=head1 SYNOPSIS
28
24d67825 29 package Library::Schema;
c2da098a 30 use base qw/DBIx::Class::Schema/;
bab77431 31
829517d4 32 # load all Result classes in Library/Schema/Result/
33 __PACKAGE__->load_namespaces();
c2da098a 34
829517d4 35 package Library::Schema::Result::CD;
03312470 36 use base qw/DBIx::Class/;
829517d4 37 __PACKAGE__->load_components(qw/Core/); # for example
24d67825 38 __PACKAGE__->table('cd');
c2da098a 39
5d9076f2 40 # Elsewhere in your code:
24d67825 41 my $schema1 = Library::Schema->connect(
a3d93194 42 $dsn,
43 $user,
44 $password,
24d67825 45 { AutoCommit => 0 },
a3d93194 46 );
bab77431 47
24d67825 48 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 49
829517d4 50 # fetch objects using Library::Schema::Result::DVD
24d67825 51 my $resultset = $schema1->resultset('DVD')->search( ... );
52 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 53
54=head1 DESCRIPTION
55
a3d93194 56Creates database classes based on a schema. This is the recommended way to
57use L<DBIx::Class> and allows you to use more than one concurrent connection
58with your classes.
429bd4f1 59
03312470 60NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 61carefully, as DBIx::Class does things a little differently. Note in
03312470 62particular which module inherits off which.
63
829517d4 64=head1 SETUP METHODS
c2da098a 65
829517d4 66=head2 load_namespaces
87c4e602 67
27f01d1f 68=over 4
69
829517d4 70=item Arguments: %options?
27f01d1f 71
72=back
076652e8 73
829517d4 74 __PACKAGE__->load_namespaces();
66d9ef6b 75
829517d4 76 __PACKAGE__->load_namespaces(
77 result_namespace => 'Res',
78 resultset_namespace => 'RSet',
79 default_resultset_class => '+MyDB::Othernamespace::RSet',
80 );
076652e8 81
829517d4 82With no arguments, this method uses L<Module::Find> to load all your
83Result classes from a sub-namespace F<Result> under your Schema class'
84namespace. Eg. With a Schema of I<MyDB::Schema> all files in
85I<MyDB::Schema::Result> are assumed to be Result classes.
c2da098a 86
829517d4 87It also finds all ResultSet classes in the namespace F<ResultSet> and
88loads them into the appropriate Result classes using for you. The
89matching is done by assuming the package name of the ResultSet class
90is the same as that of the Result class.
74b92d9a 91
829517d4 92You will be warned if ResulSet classes are discovered for which there
93are no matching Result classes like this:
87c4e602 94
829517d4 95 load_namespaces found ResultSet class $classname with no corresponding Result class
27f01d1f 96
829517d4 97If a Result class is found to already have a ResultSet class set using
98L</resultset_class> to some other class, you will be warned like this:
27f01d1f 99
829517d4 100 We found ResultSet class '$rs_class' for '$result', but it seems
101 that you had already set '$result' to use '$rs_set' instead
076652e8 102
829517d4 103Both of the sub-namespaces are configurable if you don't like the defaults,
104via the options C<result_namespace> and C<resultset_namespace>.
076652e8 105
829517d4 106If (and only if) you specify the option C<default_resultset_class>, any found
107Result classes for which we do not find a corresponding
108ResultSet class will have their C<resultset_class> set to
109C<default_resultset_class>.
076652e8 110
829517d4 111All of the namespace and classname options to this method are relative to
112the schema classname by default. To specify a fully-qualified name, prefix
113it with a literal C<+>.
2a4d9487 114
829517d4 115Examples:
2a4d9487 116
829517d4 117 # load My::Schema::Result::CD, My::Schema::Result::Artist,
118 # My::Schema::ResultSet::CD, etc...
119 My::Schema->load_namespaces;
2a4d9487 120
829517d4 121 # Override everything to use ugly names.
122 # In this example, if there is a My::Schema::Res::Foo, but no matching
123 # My::Schema::RSets::Foo, then Foo will have its
124 # resultset_class set to My::Schema::RSetBase
125 My::Schema->load_namespaces(
126 result_namespace => 'Res',
127 resultset_namespace => 'RSets',
128 default_resultset_class => 'RSetBase',
129 );
2a4d9487 130
829517d4 131 # Put things in other namespaces
132 My::Schema->load_namespaces(
133 result_namespace => '+Some::Place::Results',
134 resultset_namespace => '+Another::Place::RSets',
135 );
2a4d9487 136
829517d4 137If you'd like to use multiple namespaces of each type, simply use an arrayref
138of namespaces for that option. In the case that the same result
139(or resultset) class exists in multiple namespaces, the latter entries in
140your list of namespaces will override earlier ones.
2a4d9487 141
829517d4 142 My::Schema->load_namespaces(
143 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
144 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
145 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
146 );
2a4d9487 147
148=cut
149
829517d4 150# Pre-pends our classname to the given relative classname or
151# class namespace, unless there is a '+' prefix, which will
152# be stripped.
153sub _expand_relative_name {
154 my ($class, $name) = @_;
155 return if !$name;
156 $name = $class . '::' . $name if ! ($name =~ s/^\+//);
157 return $name;
2a4d9487 158}
159
829517d4 160# returns a hash of $shortname => $fullname for every package
161# found in the given namespaces ($shortname is with the $fullname's
162# namespace stripped off)
163sub _map_namespaces {
164 my ($class, @namespaces) = @_;
6eec9003 165
829517d4 166 my @results_hash;
167 foreach my $namespace (@namespaces) {
168 push(
169 @results_hash,
170 map { (substr($_, length "${namespace}::"), $_) }
171 Module::Find::findallmod($namespace)
172 );
0dc79249 173 }
27f01d1f 174
829517d4 175 @results_hash;
ea20d0fd 176}
177
829517d4 178sub load_namespaces {
179 my ($class, %args) = @_;
0dc79249 180
829517d4 181 my $result_namespace = delete $args{result_namespace} || 'Result';
182 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
183 my $default_resultset_class = delete $args{default_resultset_class};
0dc79249 184
829517d4 185 $class->throw_exception('load_namespaces: unknown option(s): '
186 . join(q{,}, map { qq{'$_'} } keys %args))
187 if scalar keys %args;
0dc79249 188
829517d4 189 $default_resultset_class
190 = $class->_expand_relative_name($default_resultset_class);
9b1ba0f2 191
829517d4 192 for my $arg ($result_namespace, $resultset_namespace) {
193 $arg = [ $arg ] if !ref($arg) && $arg;
9b1ba0f2 194
829517d4 195 $class->throw_exception('load_namespaces: namespace arguments must be '
196 . 'a simple string or an arrayref')
197 if ref($arg) ne 'ARRAY';
9b1ba0f2 198
829517d4 199 $_ = $class->_expand_relative_name($_) for (@$arg);
200 }
ea20d0fd 201
829517d4 202 my %results = $class->_map_namespaces(@$result_namespace);
203 my %resultsets = $class->_map_namespaces(@$resultset_namespace);
27f01d1f 204
829517d4 205 my @to_register;
206 {
207 no warnings 'redefine';
208 local *Class::C3::reinitialize = sub { };
209 use warnings 'redefine';
27f01d1f 210
829517d4 211 foreach my $result (keys %results) {
212 my $result_class = $results{$result};
213 $class->ensure_class_loaded($result_class);
82b01c38 214
829517d4 215 my $rs_class = delete $resultsets{$result};
216 my $rs_set = $result_class->resultset_class;
217 if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
218 if($rs_class && $rs_class ne $rs_set) {
219 warn "We found ResultSet class '$rs_class' for '$result', but it seems "
220 . "that you had already set '$result' to use '$rs_set' instead";
221 }
222 }
223 elsif($rs_class ||= $default_resultset_class) {
224 $class->ensure_class_loaded($rs_class);
225 $result_class->resultset_class($rs_class);
226 }
82b01c38 227
0e6c5d58 228 my $source_name = $result_class->source_name || $result;
229
230 push(@to_register, [ $source_name, $result_class ]);
829517d4 231 }
232 }
ea20d0fd 233
829517d4 234 foreach (sort keys %resultsets) {
235 warn "load_namespaces found ResultSet class $_ with no "
236 . 'corresponding Result class';
237 }
ea20d0fd 238
829517d4 239 Class::C3->reinitialize;
240 $class->register_class(@$_) for (@to_register);
ea20d0fd 241
829517d4 242 return;
ea20d0fd 243}
244
87c4e602 245=head2 load_classes
246
27f01d1f 247=over 4
248
249=item Arguments: @classes?, { $namespace => [ @classes ] }+
250
251=back
076652e8 252
829517d4 253Alternative method to L</load_namespaces> which you should look at
254using if you can.
255
82b01c38 256With no arguments, this method uses L<Module::Find> to find all classes under
257the schema's namespace. Otherwise, this method loads the classes you specify
258(using L<use>), and registers them (using L</"register_class">).
076652e8 259
2053ab2a 260It is possible to comment out classes with a leading C<#>, but note that perl
261will think it's a mistake (trying to use a comment in a qw list), so you'll
262need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 263
829517d4 264If any classes found do not appear to be Result class files, you will
265get the following warning:
266
267 Failed to load $comp_class. Can't find source_name method. Is
268 $comp_class really a full DBIC result class? Fix it, move it elsewhere,
269 or make your load_classes call more specific.
270
2053ab2a 271Example:
82b01c38 272
273 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 274 # etc. (anything under the My::Schema namespace)
82b01c38 275
276 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
277 # not Other::Namespace::LinerNotes nor My::Schema::Track
278 My::Schema->load_classes(qw/ CD Artist #Track /, {
279 Other::Namespace => [qw/ Producer #LinerNotes /],
280 });
281
076652e8 282=cut
283
a02675cd 284sub load_classes {
5ce32fc1 285 my ($class, @params) = @_;
bab77431 286
5ce32fc1 287 my %comps_for;
bab77431 288
5ce32fc1 289 if (@params) {
290 foreach my $param (@params) {
291 if (ref $param eq 'ARRAY') {
292 # filter out commented entries
293 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 294
5ce32fc1 295 push (@{$comps_for{$class}}, @modules);
296 }
297 elsif (ref $param eq 'HASH') {
298 # more than one namespace possible
299 for my $comp ( keys %$param ) {
300 # filter out commented entries
301 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
302
303 push (@{$comps_for{$comp}}, @modules);
304 }
305 }
306 else {
307 # filter out commented entries
308 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
309 }
310 }
311 } else {
bc0c9800 312 my @comp = map { substr $_, length "${class}::" }
313 Module::Find::findallmod($class);
5ce32fc1 314 $comps_for{$class} = \@comp;
41a6f8c0 315 }
5ce32fc1 316
e6efde04 317 my @to_register;
318 {
319 no warnings qw/redefine/;
320 local *Class::C3::reinitialize = sub { };
321 foreach my $prefix (keys %comps_for) {
322 foreach my $comp (@{$comps_for{$prefix}||[]}) {
323 my $comp_class = "${prefix}::${comp}";
83542a7d 324 { # try to untaint module name. mods where this fails
325 # are left alone so we don't have to change the old behavior
326 no locale; # localized \w doesn't untaint expression
327 if ( $comp_class =~ m/^( (?:\w+::)* \w+ )$/x ) {
328 $comp_class = $1;
329 }
330 }
c037c03a 331 $class->ensure_class_loaded($comp_class);
bab77431 332
89271e56 333 my $snsub = $comp_class->can('source_name');
334 if(! $snsub ) {
335 warn "Failed to load $comp_class. Can't find source_name method. Is $comp_class really a full DBIC result class? Fix it, move it elsewhere, or make your load_classes call more specific.";
336 next;
337 }
338 $comp = $snsub->($comp_class) || $comp;
339
93405cf0 340 push(@to_register, [ $comp, $comp_class ]);
bfb2bd4f 341 }
5ce32fc1 342 }
a02675cd 343 }
e6efde04 344 Class::C3->reinitialize;
345
346 foreach my $to (@to_register) {
347 $class->register_class(@$to);
348 # if $class->can('result_source_instance');
349 }
a02675cd 350}
351
829517d4 352=head2 storage_type
2374c5ff 353
354=over 4
355
829517d4 356=item Arguments: $storage_type|{$storage_type, \%args}
357
358=item Return value: $storage_type|{$storage_type, \%args}
359
360=item Default value: DBIx::Class::Storage::DBI
2374c5ff 361
362=back
363
829517d4 364Set the storage class that will be instantiated when L</connect> is called.
365If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
366assumed by L</connect>.
2374c5ff 367
829517d4 368You want to use this to set subclasses of L<DBIx::Class::Storage::DBI>
369in cases where the appropriate subclass is not autodetected, such as
370when dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it
371to C<::DBI::Sybase::MSSQL>.
85bd0538 372
829517d4 373If your storage type requires instantiation arguments, those are
374defined as a second argument in the form of a hashref and the entire
375value needs to be wrapped into an arrayref or a hashref. We support
376both types of refs here in order to play nice with your
377Config::[class] or your choice. See
378L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
0f4ec1d2 379
829517d4 380=head2 exception_action
f017c022 381
829517d4 382=over 4
0f4ec1d2 383
829517d4 384=item Arguments: $code_reference
f017c022 385
829517d4 386=item Return value: $code_reference
85bd0538 387
829517d4 388=item Default value: None
2374c5ff 389
829517d4 390=back
f017c022 391
829517d4 392If C<exception_action> is set for this class/object, L</throw_exception>
393will prefer to call this code reference with the exception as an argument,
394rather than L<DBIx::Class::Exception/throw>.
f017c022 395
829517d4 396Your subroutine should probably just wrap the error in the exception
397object/class of your choosing and rethrow. If, against all sage advice,
398you'd like your C<exception_action> to suppress a particular exception
399completely, simply have it return true.
f017c022 400
829517d4 401Example:
f017c022 402
829517d4 403 package My::Schema;
404 use base qw/DBIx::Class::Schema/;
405 use My::ExceptionClass;
406 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
407 __PACKAGE__->load_classes;
2374c5ff 408
829517d4 409 # or:
410 my $schema_obj = My::Schema->connect( .... );
411 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
0f4ec1d2 412
829517d4 413 # suppress all exceptions, like a moron:
414 $schema_obj->exception_action(sub { 1 });
25fb14bd 415
829517d4 416=head2 stacktrace
f017c022 417
829517d4 418=over 4
2374c5ff 419
829517d4 420=item Arguments: boolean
2374c5ff 421
829517d4 422=back
2374c5ff 423
829517d4 424Whether L</throw_exception> should include stack trace information.
425Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
426is true.
0f4ec1d2 427
829517d4 428=head2 sqlt_deploy_hook
0f4ec1d2 429
829517d4 430=over
0f4ec1d2 431
829517d4 432=item Arguments: $sqlt_schema
2374c5ff 433
829517d4 434=back
2374c5ff 435
829517d4 436An optional sub which you can declare in your own Schema class that will get
437passed the L<SQL::Translator::Schema> object when you deploy the schema via
438L</create_ddl_dir> or L</deploy>.
0f4ec1d2 439
829517d4 440For an example of what you can do with this, see
441L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
fdcd8145 442
829517d4 443=head1 METHODS
2374c5ff 444
829517d4 445=head2 connect
87c4e602 446
27f01d1f 447=over 4
448
829517d4 449=item Arguments: @connectinfo
429bd4f1 450
d601dc88 451=item Return Value: $new_schema
27f01d1f 452
453=back
076652e8 454
829517d4 455Creates and returns a new Schema object. The connection info set on it
456is used to create a new instance of the storage backend and set it on
457the Schema object.
1c133e22 458
829517d4 459See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific
5d52945a 460syntax on the C<@connectinfo> argument, or L<DBIx::Class::Storage> in
829517d4 461general.
1c133e22 462
5d52945a 463Note that C<connect_info> expects an arrayref of arguments, but
464C<connect> does not. C<connect> wraps it's arguments in an arrayref
465before passing them to C<connect_info>.
466
076652e8 467=cut
468
829517d4 469sub connect { shift->clone->connection(@_) }
e678398e 470
829517d4 471=head2 resultset
77254782 472
27f01d1f 473=over 4
474
829517d4 475=item Arguments: $source_name
82b01c38 476
829517d4 477=item Return Value: $resultset
27f01d1f 478
479=back
13765dad 480
829517d4 481 my $rs = $schema->resultset('DVD');
82b01c38 482
829517d4 483Returns the L<DBIx::Class::ResultSet> object for the registered source
484name.
77254782 485
486=cut
487
829517d4 488sub resultset {
489 my ($self, $moniker) = @_;
490 return $self->source($moniker)->resultset;
b7951443 491}
492
829517d4 493=head2 sources
6b43ba5f 494
495=over 4
496
829517d4 497=item Return Value: @source_names
6b43ba5f 498
499=back
500
829517d4 501 my @source_names = $schema->sources;
6b43ba5f 502
829517d4 503Lists names of all the sources registered on this Schema object.
6b43ba5f 504
829517d4 505=cut
161fb223 506
829517d4 507sub sources { return keys %{shift->source_registrations}; }
106d5f3b 508
829517d4 509=head2 source
87c4e602 510
27f01d1f 511=over 4
512
829517d4 513=item Arguments: $source_name
66d9ef6b 514
829517d4 515=item Return Value: $result_source
27f01d1f 516
517=back
82b01c38 518
829517d4 519 my $source = $schema->source('Book');
85f78622 520
829517d4 521Returns the L<DBIx::Class::ResultSource> object for the registered
522source name.
66d9ef6b 523
524=cut
525
829517d4 526sub source {
527 my ($self, $moniker) = @_;
528 my $sreg = $self->source_registrations;
529 return $sreg->{$moniker} if exists $sreg->{$moniker};
530
531 # if we got here, they probably passed a full class name
532 my $mapped = $self->class_mappings->{$moniker};
533 $self->throw_exception("Can't find source for ${moniker}")
534 unless $mapped && exists $sreg->{$mapped};
535 return $sreg->{$mapped};
161fb223 536}
537
829517d4 538=head2 class
87c4e602 539
27f01d1f 540=over 4
541
829517d4 542=item Arguments: $source_name
66d9ef6b 543
829517d4 544=item Return Value: $classname
27f01d1f 545
546=back
82b01c38 547
829517d4 548 my $class = $schema->class('CD');
549
550Retrieves the Result class name for the given source name.
66d9ef6b 551
552=cut
553
829517d4 554sub class {
555 my ($self, $moniker) = @_;
556 return $self->source($moniker)->result_class;
557}
08b515f1 558
4012acd8 559=head2 txn_do
08b515f1 560
4012acd8 561=over 4
08b515f1 562
4012acd8 563=item Arguments: C<$coderef>, @coderef_args?
08b515f1 564
4012acd8 565=item Return Value: The return value of $coderef
08b515f1 566
4012acd8 567=back
08b515f1 568
4012acd8 569Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
570returning its result (if any). Equivalent to calling $schema->storage->txn_do.
571See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 572
4012acd8 573This interface is preferred over using the individual methods L</txn_begin>,
574L</txn_commit>, and L</txn_rollback> below.
08b515f1 575
4012acd8 576=cut
08b515f1 577
4012acd8 578sub txn_do {
579 my $self = shift;
08b515f1 580
4012acd8 581 $self->storage or $self->throw_exception
582 ('txn_do called on $schema without storage');
08b515f1 583
4012acd8 584 $self->storage->txn_do(@_);
585}
66d9ef6b 586
89028f42 587=head2 txn_scope_guard (EXPERIMENTAL)
75c8a7ab 588
89028f42 589Runs C<txn_scope_guard> on the schema's storage. See
590L<DBIx::Class::Storage/txn_scope_guard>.
75c8a7ab 591
b85be4c1 592=cut
593
1bc193ac 594sub txn_scope_guard {
595 my $self = shift;
596
597 $self->storage or $self->throw_exception
598 ('txn_scope_guard called on $schema without storage');
599
600 $self->storage->txn_scope_guard(@_);
601}
602
4012acd8 603=head2 txn_begin
a62cf8d4 604
4012acd8 605Begins a transaction (does nothing if AutoCommit is off). Equivalent to
606calling $schema->storage->txn_begin. See
607L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 608
4012acd8 609=cut
82b01c38 610
4012acd8 611sub txn_begin {
612 my $self = shift;
27f01d1f 613
4012acd8 614 $self->storage or $self->throw_exception
615 ('txn_begin called on $schema without storage');
a62cf8d4 616
4012acd8 617 $self->storage->txn_begin;
618}
a62cf8d4 619
4012acd8 620=head2 txn_commit
a62cf8d4 621
4012acd8 622Commits the current transaction. Equivalent to calling
623$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
624for more information.
a62cf8d4 625
4012acd8 626=cut
a62cf8d4 627
4012acd8 628sub txn_commit {
629 my $self = shift;
a62cf8d4 630
4012acd8 631 $self->storage or $self->throw_exception
632 ('txn_commit called on $schema without storage');
a62cf8d4 633
4012acd8 634 $self->storage->txn_commit;
635}
70634260 636
4012acd8 637=head2 txn_rollback
a62cf8d4 638
4012acd8 639Rolls back the current transaction. Equivalent to calling
640$schema->storage->txn_rollback. See
641L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 642
643=cut
644
4012acd8 645sub txn_rollback {
646 my $self = shift;
a62cf8d4 647
19630353 648 $self->storage or $self->throw_exception
4012acd8 649 ('txn_rollback called on $schema without storage');
a62cf8d4 650
4012acd8 651 $self->storage->txn_rollback;
a62cf8d4 652}
653
829517d4 654=head2 storage
66d9ef6b 655
829517d4 656 my $storage = $schema->storage;
04786a4c 657
829517d4 658Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
659if you want to turn on SQL statement debugging at runtime, or set the
660quote character. For the default storage, the documentation can be
661found in L<DBIx::Class::Storage::DBI>.
66d9ef6b 662
87c4e602 663=head2 populate
664
27f01d1f 665=over 4
666
16c5f7d3 667=item Arguments: $source_name, \@data;
27f01d1f 668
829517d4 669=item Return value: \@$objects | nothing
670
27f01d1f 671=back
a37a4697 672
16c5f7d3 673Pass this method a resultsource name, and an arrayref of
674arrayrefs. The arrayrefs should contain a list of column names,
675followed by one or many sets of matching data for the given columns.
676
744076d8 677In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
678to insert the data, as this is a fast method. However, insert_bulk currently
679assumes that your datasets all contain the same type of values, using scalar
680references in a column in one row, and not in another will probably not work.
681
682Otherwise, each set of data is inserted into the database using
16c5f7d3 683L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
684objects is returned.
82b01c38 685
686i.e.,
a37a4697 687
24d67825 688 $schema->populate('Artist', [
689 [ qw/artistid name/ ],
690 [ 1, 'Popular Band' ],
691 [ 2, 'Indie Band' ],
a62cf8d4 692 ...
693 ]);
5a93e138 694
695Since wantarray context is basically the same as looping over $rs->create(...)
696you won't see any performance benefits and in this case the method is more for
697convenience. Void context sends the column information directly to storage
698using <DBI>s bulk insert method. So the performance will be much better for
699storages that support this method.
700
701Because of this difference in the way void context inserts rows into your
702database you need to note how this will effect any loaded components that
703override or augment insert. For example if you are using a component such
704as L<DBIx::Class::UUIDColumns> to populate your primary keys you MUST use
705wantarray context if you want the PKs automatically created.
a37a4697 706
707=cut
708
709sub populate {
710 my ($self, $name, $data) = @_;
c4e67d31 711 if(my $rs = $self->resultset($name)) {
712 if(defined wantarray) {
713 return $rs->populate($data);
714 } else {
715 $rs->populate($data);
54e0bd06 716 }
c4e67d31 717 } else {
718 $self->throw_exception("$name is not a resultset");
8b93a938 719 }
a37a4697 720}
721
829517d4 722=head2 connection
723
724=over 4
725
726=item Arguments: @args
727
728=item Return Value: $new_schema
729
730=back
731
732Similar to L</connect> except sets the storage object and connection
733data in-place on the Schema class. You should probably be calling
734L</connect> to get a proper Schema object instead.
735
736
737=cut
738
739sub connection {
740 my ($self, @info) = @_;
741 return $self if !@info && $self->storage;
742
743 my ($storage_class, $args) = ref $self->storage_type ?
744 ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {});
745
746 $storage_class = 'DBIx::Class::Storage'.$storage_class
747 if $storage_class =~ m/^::/;
748 eval "require ${storage_class};";
749 $self->throw_exception(
750 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
751 ) if $@;
752 my $storage = $storage_class->new($self=>$args);
753 $storage->connect_info(\@info);
754 $self->storage($storage);
755 return $self;
756}
757
758sub _normalize_storage_type {
759 my ($self, $storage_type) = @_;
760 if(ref $storage_type eq 'ARRAY') {
761 return @$storage_type;
762 } elsif(ref $storage_type eq 'HASH') {
763 return %$storage_type;
764 } else {
765 $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
766 }
767}
768
769=head2 compose_namespace
82cc0386 770
771=over 4
772
829517d4 773=item Arguments: $target_namespace, $additional_base_class?
774
775=item Retur Value: $new_schema
776
777=back
778
779For each L<DBIx::Class::ResultSource> in the schema, this method creates a
780class in the target namespace (e.g. $target_namespace::CD,
781$target_namespace::Artist) that inherits from the corresponding classes
782attached to the current schema.
783
784It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
785new $schema object. If C<$additional_base_class> is given, the new composed
786classes will inherit from first the corresponding classe from the current
787schema then the base class.
788
789For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
790
791 $schema->compose_namespace('My::DB', 'Base::Class');
792 print join (', ', @My::DB::CD::ISA) . "\n";
793 print join (', ', @My::DB::Artist::ISA) ."\n";
794
795will produce the output
796
797 My::Schema::CD, Base::Class
798 My::Schema::Artist, Base::Class
799
800=cut
801
802# this might be oversimplified
803# sub compose_namespace {
804# my ($self, $target, $base) = @_;
805
806# my $schema = $self->clone;
807# foreach my $moniker ($schema->sources) {
808# my $source = $schema->source($moniker);
809# my $target_class = "${target}::${moniker}";
810# $self->inject_base(
811# $target_class => $source->result_class, ($base ? $base : ())
812# );
813# $source->result_class($target_class);
814# $target_class->result_source_instance($source)
815# if $target_class->can('result_source_instance');
816# $schema->register_source($moniker, $source);
817# }
818# return $schema;
819# }
820
821sub compose_namespace {
822 my ($self, $target, $base) = @_;
823 my $schema = $self->clone;
824 {
825 no warnings qw/redefine/;
826# local *Class::C3::reinitialize = sub { };
827 foreach my $moniker ($schema->sources) {
828 my $source = $schema->source($moniker);
829 my $target_class = "${target}::${moniker}";
830 $self->inject_base(
831 $target_class => $source->result_class, ($base ? $base : ())
832 );
833 $source->result_class($target_class);
834 $target_class->result_source_instance($source)
835 if $target_class->can('result_source_instance');
836 $schema->register_source($moniker, $source);
837 }
838 }
839# Class::C3->reinitialize();
840 {
841 no strict 'refs';
842 no warnings 'redefine';
843 foreach my $meth (qw/class source resultset/) {
844 *{"${target}::${meth}"} =
845 sub { shift->schema->$meth(@_) };
846 }
847 }
848 return $schema;
849}
850
851sub setup_connection_class {
852 my ($class, $target, @info) = @_;
853 $class->inject_base($target => 'DBIx::Class::DB');
854 #$target->load_components('DB');
855 $target->connection(@info);
856}
857
858=head2 svp_begin
859
860Creates a new savepoint (does nothing outside a transaction).
861Equivalent to calling $schema->storage->svp_begin. See
862L<DBIx::Class::Storage::DBI/"svp_begin"> for more information.
863
864=cut
865
866sub svp_begin {
867 my ($self, $name) = @_;
868
869 $self->storage or $self->throw_exception
870 ('svp_begin called on $schema without storage');
871
872 $self->storage->svp_begin($name);
873}
874
875=head2 svp_release
876
877Releases a savepoint (does nothing outside a transaction).
878Equivalent to calling $schema->storage->svp_release. See
879L<DBIx::Class::Storage::DBI/"svp_release"> for more information.
880
881=cut
882
883sub svp_release {
884 my ($self, $name) = @_;
885
886 $self->storage or $self->throw_exception
887 ('svp_release called on $schema without storage');
82cc0386 888
829517d4 889 $self->storage->svp_release($name);
890}
82cc0386 891
829517d4 892=head2 svp_rollback
db5dc233 893
829517d4 894Rollback to a savepoint (does nothing outside a transaction).
895Equivalent to calling $schema->storage->svp_rollback. See
896L<DBIx::Class::Storage::DBI/"svp_rollback"> for more information.
82cc0386 897
829517d4 898=cut
82cc0386 899
829517d4 900sub svp_rollback {
901 my ($self, $name) = @_;
82cc0386 902
829517d4 903 $self->storage or $self->throw_exception
904 ('svp_rollback called on $schema without storage');
82cc0386 905
829517d4 906 $self->storage->svp_rollback($name);
907}
db5dc233 908
829517d4 909=head2 clone
613397e7 910
84c5863b 911=over 4
613397e7 912
829517d4 913=item Return Value: $new_schema
613397e7 914
915=back
916
829517d4 917Clones the schema and its associated result_source objects and returns the
918copy.
919
920=cut
921
922sub clone {
923 my ($self) = @_;
924 my $clone = { (ref $self ? %$self : ()) };
925 bless $clone, (ref $self || $self);
926
927 $clone->class_mappings({ %{$clone->class_mappings} });
928 $clone->source_registrations({ %{$clone->source_registrations} });
929 foreach my $moniker ($self->sources) {
930 my $source = $self->source($moniker);
931 my $new = $source->new($source);
932 # we use extra here as we want to leave the class_mappings as they are
933 # but overwrite the source_registrations entry with the new source
934 $clone->register_extra_source($moniker => $new);
935 }
936 $clone->storage->set_schema($clone) if $clone->storage;
937 return $clone;
938}
613397e7 939
5160b401 940=head2 throw_exception
701da8c4 941
75d07914 942=over 4
82b01c38 943
ebc77b53 944=item Arguments: $message
82b01c38 945
946=back
947
948Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 949user's perspective. See L</exception_action> for details on overriding
4b946902 950this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
951default behavior will provide a detailed stack trace.
701da8c4 952
953=cut
954
955sub throw_exception {
82cc0386 956 my $self = shift;
4981dc70 957
958 DBIx::Class::Exception->throw($_[0], $self->stacktrace)
959 if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 960}
961
dfccde48 962=head2 deploy
1c339d71 963
82b01c38 964=over 4
965
6e73ac25 966=item Arguments: $sqlt_args, $dir
82b01c38 967
968=back
969
970Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 971
51bace1c 972See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
973common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
974produced include a DROP TABLE statement for each table created.
975
499adf63 976Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
977ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 978only the sources listed will get deployed. Furthermore, you can use the
979C<add_fk_index> parser parameter to prevent the parser from creating an index for each
980FK.
499adf63 981
1c339d71 982=cut
983
984sub deploy {
6e73ac25 985 my ($self, $sqltargs, $dir) = @_;
1c339d71 986 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 987 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 988}
989
0e0ce6c1 990=head2 deployment_statements
991
992=over 4
993
7ad93f5a 994=item Arguments: $rdbms_type, $sqlt_args, $dir
0e0ce6c1 995
829517d4 996=item Return value: $listofstatements
997
0e0ce6c1 998=back
999
829517d4 1000A convenient shortcut to storage->deployment_statements(). Returns the
1001SQL statements used by L</deploy> and
1002L<DBIx::Class::Schema::Storage/deploy>. C<$rdbms_type> provides the
1003(optional) SQLT (not DBI) database driver name for which the SQL
1004statements are produced. If not supplied, the type is determined by
1005interrogating the current connection. The other two arguments are
1006identical to those of L</deploy>.
0e0ce6c1 1007
1008=cut
1009
1010sub deployment_statements {
7ad93f5a 1011 my $self = shift;
0e0ce6c1 1012
1013 $self->throw_exception("Can't generate deployment statements without a storage")
1014 if not $self->storage;
1015
7ad93f5a 1016 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1017}
1018
c0f61310 1019=head2 create_ddl_dir (EXPERIMENTAL)
1020
1021=over 4
1022
c9d2e0a2 1023=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 1024
1025=back
1026
1027Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 1028database types, in the given directory. Given a previous version number,
1029this will also create a file containing the ALTER TABLE statements to
1030transform the previous schema into the current one. Note that these
1031statements may contain DROP TABLE or DROP COLUMN statements that can
1032potentially destroy data.
1033
1034The file names are created using the C<ddl_filename> method below, please
1035override this method in your schema if you would like a different file
1036name format. For the ALTER file, the same format is used, replacing
1037$version in the name with "$preversion-$version".
1038
0e2c6809 1039See L<DBIx::Class::Schema/deploy> for details of $sqlt_args.
1040
c9d2e0a2 1041If no arguments are passed, then the following default values are used:
1042
1043=over 4
1044
1045=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
1046
b1f9d92e 1047=item version - $schema->schema_version
c9d2e0a2 1048
1049=item directory - './'
1050
1051=item preversion - <none>
1052
1053=back
c0f61310 1054
1055Note that this feature is currently EXPERIMENTAL and may not work correctly
1056across all databases, or fully handle complex relationships.
1057
c9d2e0a2 1058WARNING: Please check all SQL files created, before applying them.
1059
c0f61310 1060=cut
1061
6e73ac25 1062sub create_ddl_dir {
e673f011 1063 my $self = shift;
1064
1065 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1066 $self->storage->create_ddl_dir($self, @_);
1067}
1068
e63a82f7 1069=head2 ddl_filename
9b83fccd 1070
c9d2e0a2 1071=over 4
1072
99a74c4a 1073=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1074
829517d4 1075=item Return value: $normalised_filename
1076
c9d2e0a2 1077=back
1078
99a74c4a 1079 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1080
1081This method is called by C<create_ddl_dir> to compose a file name out of
1082the supplied directory, database type and version number. The default file
1083name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1084
c9d2e0a2 1085You may override this method in your schema if you wish to use a different
1086format.
9b83fccd 1087
1088=cut
1089
6e73ac25 1090sub ddl_filename {
99a74c4a 1091 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1092
99a74c4a 1093 my $filename = ref($self);
1094 $filename =~ s/::/-/g;
1095 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1096 $filename =~ s/$version/$preversion-$version/ if($preversion);
1097
1098 return $filename;
e673f011 1099}
1100
4146e3da 1101=head2 thaw
1102
829517d4 1103Provided as the recommended way of thawing schema objects. You can call
4146e3da 1104C<Storable::thaw> directly if you wish, but the thawed objects will not have a
1105reference to any schema, so are rather useless
1106
1107=cut
1108
1109sub thaw {
1110 my ($self, $obj) = @_;
1111 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1112 return Storable::thaw($obj);
1113}
1114
1115=head2 freeze
1116
1117This doesn't actualy do anything more than call L<Storable/freeze>, it is just
1118provided here for symetry.
1119
d2f3e87b 1120=cut
1121
4146e3da 1122sub freeze {
1123 return Storable::freeze($_[1]);
1124}
1125
1126=head2 dclone
1127
1128Recommeneded way of dcloning objects. This is needed to properly maintain
1129references to the schema object (which itself is B<not> cloned.)
1130
1131=cut
1132
1133sub dclone {
1134 my ($self, $obj) = @_;
1135 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1136 return Storable::dclone($obj);
1137}
1138
93e4d41a 1139=head2 schema_version
1140
829517d4 1141Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1142
1143=cut
1144
1145sub schema_version {
1146 my ($self) = @_;
1147 my $class = ref($self)||$self;
1148
1149 # does -not- use $schema->VERSION
1150 # since that varies in results depending on if version.pm is installed, and if
1151 # so the perl or XS versions. If you want this to change, bug the version.pm
1152 # author to make vpp and vxs behave the same.
1153
1154 my $version;
1155 {
1156 no strict 'refs';
1157 $version = ${"${class}::VERSION"};
1158 }
1159 return $version;
1160}
1161
829517d4 1162
1163=head2 register_class
1164
1165=over 4
1166
1167=item Arguments: $moniker, $component_class
1168
1169=back
1170
1171This method is called by L</load_namespaces> and L</load_classes> to install the found classes into your Schema. You should be using those instead of this one.
1172
1173You will only need this method if you have your Result classes in
1174files which are not named after the packages (or all in the same
1175file). You may also need it to register classes at runtime.
1176
1177Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1178calling:
1179
1180 $schema->register_source($moniker, $component_class->result_source_instance);
1181
1182=cut
1183
1184sub register_class {
1185 my ($self, $moniker, $to_register) = @_;
1186 $self->register_source($moniker => $to_register->result_source_instance);
1187}
1188
1189=head2 register_source
1190
1191=over 4
1192
1193=item Arguments: $moniker, $result_source
1194
1195=back
1196
1197This method is called by L</register_class>.
1198
1199Registers the L<DBIx::Class::ResultSource> in the schema with the given
1200moniker.
1201
1202=cut
1203
1204sub register_source {
1205 my $self = shift;
1206
1207 $self->_register_source(@_);
1208}
1209
1210=head2 register_extra_source
1211
1212=over 4
1213
1214=item Arguments: $moniker, $result_source
1215
1216=back
1217
1218As L</register_source> but should be used if the result class already
1219has a source and you want to register an extra one.
1220
1221=cut
1222
1223sub register_extra_source {
1224 my $self = shift;
1225
1226 $self->_register_source(@_, { extra => 1 });
1227}
1228
1229sub _register_source {
1230 my ($self, $moniker, $source, $params) = @_;
1231
0e6c5d58 1232 $source = $source->new({ %$source, source_name => $moniker });
829517d4 1233
1234 my %reg = %{$self->source_registrations};
1235 $reg{$moniker} = $source;
1236 $self->source_registrations(\%reg);
1237
1238 $source->schema($self);
1239 weaken($source->{schema}) if ref($self);
1240 return if ($params->{extra});
1241
1242 if ($source->result_class) {
1243 my %map = %{$self->class_mappings};
1244 if (exists $map{$source->result_class}) {
1245 warn $source->result_class . ' already has a source, use register_extra_source for additional sources';
1246 }
1247 $map{$source->result_class} = $moniker;
1248 $self->class_mappings(\%map);
1249 }
1250}
1251
1252sub _unregister_source {
1253 my ($self, $moniker) = @_;
1254 my %reg = %{$self->source_registrations};
1255
1256 my $source = delete $reg{$moniker};
1257 $self->source_registrations(\%reg);
1258 if ($source->result_class) {
1259 my %map = %{$self->class_mappings};
1260 delete $map{$source->result_class};
1261 $self->class_mappings(\%map);
1262 }
1263}
1264
1265
1266=head2 compose_connection (DEPRECATED)
1267
1268=over 4
1269
1270=item Arguments: $target_namespace, @db_info
1271
1272=item Return Value: $new_schema
1273
1274=back
1275
1276DEPRECATED. You probably wanted compose_namespace.
1277
1278Actually, you probably just wanted to call connect.
1279
1280=begin hidden
1281
1282(hidden due to deprecation)
1283
1284Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1285calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1286then injects the L<DBix::Class::ResultSetProxy> component and a
1287resultset_instance classdata entry on all the new classes, in order to support
1288$target_namespaces::$class->search(...) method calls.
1289
1290This is primarily useful when you have a specific need for class method access
1291to a connection. In normal usage it is preferred to call
1292L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1293on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1294more information.
1295
1296=end hidden
1297
1298=cut
1299
1300{
1301 my $warn;
1302
1303 sub compose_connection {
1304 my ($self, $target, @info) = @_;
1305
1306 warn "compose_connection deprecated as of 0.08000"
1307 unless ($INC{"DBIx/Class/CDBICompat.pm"} || $warn++);
1308
1309 my $base = 'DBIx::Class::ResultSetProxy';
1310 eval "require ${base};";
1311 $self->throw_exception
1312 ("No arguments to load_classes and couldn't load ${base} ($@)")
1313 if $@;
1314
1315 if ($self eq $target) {
1316 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1317 foreach my $moniker ($self->sources) {
1318 my $source = $self->source($moniker);
1319 my $class = $source->result_class;
1320 $self->inject_base($class, $base);
1321 $class->mk_classdata(resultset_instance => $source->resultset);
1322 $class->mk_classdata(class_resolver => $self);
1323 }
1324 $self->connection(@info);
1325 return $self;
1326 }
1327
1328 my $schema = $self->compose_namespace($target, $base);
1329 {
1330 no strict 'refs';
1331 my $name = join '::', $target, 'schema';
1332 *$name = Sub::Name::subname $name, sub { $schema };
1333 }
1334
1335 $schema->connection(@info);
1336 foreach my $moniker ($schema->sources) {
1337 my $source = $schema->source($moniker);
1338 my $class = $source->result_class;
1339 #warn "$moniker $class $source ".$source->storage;
1340 $class->mk_classdata(result_source_instance => $source);
1341 $class->mk_classdata(resultset_instance => $source->resultset);
1342 $class->mk_classdata(class_resolver => $schema);
1343 }
1344 return $schema;
1345 }
1346}
1347
a02675cd 13481;
c2da098a 1349
c2da098a 1350=head1 AUTHORS
1351
daec44b8 1352Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1353
1354=head1 LICENSE
1355
1356You may distribute this code under the same terms as Perl itself.
1357
1358=cut