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