remove_columns() sanitization by Oleg Pronin
[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
281719d2 576WARNING: If you are connected with C<AutoCommit => 0> the transaction is
577considered nested, and you will still need to call L</txn_commit> to write your
578changes when appropriate. You will also want to connect with C<auto_savepoint =>
5791> to get partial rollback to work, if the storage driver for your database
580supports it.
581
582Connecting with C<AutoCommit => 1> is recommended.
583
4012acd8 584=cut
08b515f1 585
4012acd8 586sub txn_do {
587 my $self = shift;
08b515f1 588
4012acd8 589 $self->storage or $self->throw_exception
590 ('txn_do called on $schema without storage');
08b515f1 591
4012acd8 592 $self->storage->txn_do(@_);
593}
66d9ef6b 594
89028f42 595=head2 txn_scope_guard (EXPERIMENTAL)
75c8a7ab 596
89028f42 597Runs C<txn_scope_guard> on the schema's storage. See
598L<DBIx::Class::Storage/txn_scope_guard>.
75c8a7ab 599
b85be4c1 600=cut
601
1bc193ac 602sub txn_scope_guard {
603 my $self = shift;
604
605 $self->storage or $self->throw_exception
606 ('txn_scope_guard called on $schema without storage');
607
608 $self->storage->txn_scope_guard(@_);
609}
610
4012acd8 611=head2 txn_begin
a62cf8d4 612
4012acd8 613Begins a transaction (does nothing if AutoCommit is off). Equivalent to
614calling $schema->storage->txn_begin. See
615L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 616
4012acd8 617=cut
82b01c38 618
4012acd8 619sub txn_begin {
620 my $self = shift;
27f01d1f 621
4012acd8 622 $self->storage or $self->throw_exception
623 ('txn_begin called on $schema without storage');
a62cf8d4 624
4012acd8 625 $self->storage->txn_begin;
626}
a62cf8d4 627
4012acd8 628=head2 txn_commit
a62cf8d4 629
4012acd8 630Commits the current transaction. Equivalent to calling
631$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
632for more information.
a62cf8d4 633
4012acd8 634=cut
a62cf8d4 635
4012acd8 636sub txn_commit {
637 my $self = shift;
a62cf8d4 638
4012acd8 639 $self->storage or $self->throw_exception
640 ('txn_commit called on $schema without storage');
a62cf8d4 641
4012acd8 642 $self->storage->txn_commit;
643}
70634260 644
4012acd8 645=head2 txn_rollback
a62cf8d4 646
4012acd8 647Rolls back the current transaction. Equivalent to calling
648$schema->storage->txn_rollback. See
649L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 650
651=cut
652
4012acd8 653sub txn_rollback {
654 my $self = shift;
a62cf8d4 655
19630353 656 $self->storage or $self->throw_exception
4012acd8 657 ('txn_rollback called on $schema without storage');
a62cf8d4 658
4012acd8 659 $self->storage->txn_rollback;
a62cf8d4 660}
661
829517d4 662=head2 storage
66d9ef6b 663
829517d4 664 my $storage = $schema->storage;
04786a4c 665
829517d4 666Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
667if you want to turn on SQL statement debugging at runtime, or set the
668quote character. For the default storage, the documentation can be
669found in L<DBIx::Class::Storage::DBI>.
66d9ef6b 670
87c4e602 671=head2 populate
672
27f01d1f 673=over 4
674
16c5f7d3 675=item Arguments: $source_name, \@data;
27f01d1f 676
829517d4 677=item Return value: \@$objects | nothing
678
27f01d1f 679=back
a37a4697 680
16c5f7d3 681Pass this method a resultsource name, and an arrayref of
682arrayrefs. The arrayrefs should contain a list of column names,
683followed by one or many sets of matching data for the given columns.
684
744076d8 685In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
686to insert the data, as this is a fast method. However, insert_bulk currently
687assumes that your datasets all contain the same type of values, using scalar
688references in a column in one row, and not in another will probably not work.
689
690Otherwise, each set of data is inserted into the database using
16c5f7d3 691L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
692objects is returned.
82b01c38 693
694i.e.,
a37a4697 695
24d67825 696 $schema->populate('Artist', [
697 [ qw/artistid name/ ],
698 [ 1, 'Popular Band' ],
699 [ 2, 'Indie Band' ],
a62cf8d4 700 ...
701 ]);
5a93e138 702
703Since wantarray context is basically the same as looping over $rs->create(...)
704you won't see any performance benefits and in this case the method is more for
705convenience. Void context sends the column information directly to storage
706using <DBI>s bulk insert method. So the performance will be much better for
707storages that support this method.
708
709Because of this difference in the way void context inserts rows into your
710database you need to note how this will effect any loaded components that
711override or augment insert. For example if you are using a component such
712as L<DBIx::Class::UUIDColumns> to populate your primary keys you MUST use
713wantarray context if you want the PKs automatically created.
a37a4697 714
715=cut
716
717sub populate {
718 my ($self, $name, $data) = @_;
c4e67d31 719 if(my $rs = $self->resultset($name)) {
720 if(defined wantarray) {
721 return $rs->populate($data);
722 } else {
723 $rs->populate($data);
54e0bd06 724 }
c4e67d31 725 } else {
726 $self->throw_exception("$name is not a resultset");
8b93a938 727 }
a37a4697 728}
729
829517d4 730=head2 connection
731
732=over 4
733
734=item Arguments: @args
735
736=item Return Value: $new_schema
737
738=back
739
740Similar to L</connect> except sets the storage object and connection
741data in-place on the Schema class. You should probably be calling
742L</connect> to get a proper Schema object instead.
743
744
745=cut
746
747sub connection {
748 my ($self, @info) = @_;
749 return $self if !@info && $self->storage;
750
751 my ($storage_class, $args) = ref $self->storage_type ?
752 ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {});
753
754 $storage_class = 'DBIx::Class::Storage'.$storage_class
755 if $storage_class =~ m/^::/;
756 eval "require ${storage_class};";
757 $self->throw_exception(
758 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
759 ) if $@;
760 my $storage = $storage_class->new($self=>$args);
761 $storage->connect_info(\@info);
762 $self->storage($storage);
763 return $self;
764}
765
766sub _normalize_storage_type {
767 my ($self, $storage_type) = @_;
768 if(ref $storage_type eq 'ARRAY') {
769 return @$storage_type;
770 } elsif(ref $storage_type eq 'HASH') {
771 return %$storage_type;
772 } else {
773 $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
774 }
775}
776
777=head2 compose_namespace
82cc0386 778
779=over 4
780
829517d4 781=item Arguments: $target_namespace, $additional_base_class?
782
783=item Retur Value: $new_schema
784
785=back
786
787For each L<DBIx::Class::ResultSource> in the schema, this method creates a
788class in the target namespace (e.g. $target_namespace::CD,
789$target_namespace::Artist) that inherits from the corresponding classes
790attached to the current schema.
791
792It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
793new $schema object. If C<$additional_base_class> is given, the new composed
794classes will inherit from first the corresponding classe from the current
795schema then the base class.
796
797For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
798
799 $schema->compose_namespace('My::DB', 'Base::Class');
800 print join (', ', @My::DB::CD::ISA) . "\n";
801 print join (', ', @My::DB::Artist::ISA) ."\n";
802
803will produce the output
804
805 My::Schema::CD, Base::Class
806 My::Schema::Artist, Base::Class
807
808=cut
809
810# this might be oversimplified
811# sub compose_namespace {
812# my ($self, $target, $base) = @_;
813
814# my $schema = $self->clone;
815# foreach my $moniker ($schema->sources) {
816# my $source = $schema->source($moniker);
817# my $target_class = "${target}::${moniker}";
818# $self->inject_base(
819# $target_class => $source->result_class, ($base ? $base : ())
820# );
821# $source->result_class($target_class);
822# $target_class->result_source_instance($source)
823# if $target_class->can('result_source_instance');
824# $schema->register_source($moniker, $source);
825# }
826# return $schema;
827# }
828
829sub compose_namespace {
830 my ($self, $target, $base) = @_;
831 my $schema = $self->clone;
832 {
833 no warnings qw/redefine/;
834# local *Class::C3::reinitialize = sub { };
835 foreach my $moniker ($schema->sources) {
836 my $source = $schema->source($moniker);
837 my $target_class = "${target}::${moniker}";
838 $self->inject_base(
839 $target_class => $source->result_class, ($base ? $base : ())
840 );
841 $source->result_class($target_class);
842 $target_class->result_source_instance($source)
843 if $target_class->can('result_source_instance');
844 $schema->register_source($moniker, $source);
845 }
846 }
847# Class::C3->reinitialize();
848 {
849 no strict 'refs';
850 no warnings 'redefine';
851 foreach my $meth (qw/class source resultset/) {
852 *{"${target}::${meth}"} =
853 sub { shift->schema->$meth(@_) };
854 }
855 }
856 return $schema;
857}
858
859sub setup_connection_class {
860 my ($class, $target, @info) = @_;
861 $class->inject_base($target => 'DBIx::Class::DB');
862 #$target->load_components('DB');
863 $target->connection(@info);
864}
865
866=head2 svp_begin
867
868Creates a new savepoint (does nothing outside a transaction).
869Equivalent to calling $schema->storage->svp_begin. See
870L<DBIx::Class::Storage::DBI/"svp_begin"> for more information.
871
872=cut
873
874sub svp_begin {
875 my ($self, $name) = @_;
876
877 $self->storage or $self->throw_exception
878 ('svp_begin called on $schema without storage');
879
880 $self->storage->svp_begin($name);
881}
882
883=head2 svp_release
884
885Releases a savepoint (does nothing outside a transaction).
886Equivalent to calling $schema->storage->svp_release. See
887L<DBIx::Class::Storage::DBI/"svp_release"> for more information.
888
889=cut
890
891sub svp_release {
892 my ($self, $name) = @_;
893
894 $self->storage or $self->throw_exception
895 ('svp_release called on $schema without storage');
82cc0386 896
829517d4 897 $self->storage->svp_release($name);
898}
82cc0386 899
829517d4 900=head2 svp_rollback
db5dc233 901
829517d4 902Rollback to a savepoint (does nothing outside a transaction).
903Equivalent to calling $schema->storage->svp_rollback. See
904L<DBIx::Class::Storage::DBI/"svp_rollback"> for more information.
82cc0386 905
829517d4 906=cut
82cc0386 907
829517d4 908sub svp_rollback {
909 my ($self, $name) = @_;
82cc0386 910
829517d4 911 $self->storage or $self->throw_exception
912 ('svp_rollback called on $schema without storage');
82cc0386 913
829517d4 914 $self->storage->svp_rollback($name);
915}
db5dc233 916
829517d4 917=head2 clone
613397e7 918
84c5863b 919=over 4
613397e7 920
829517d4 921=item Return Value: $new_schema
613397e7 922
923=back
924
829517d4 925Clones the schema and its associated result_source objects and returns the
926copy.
927
928=cut
929
930sub clone {
931 my ($self) = @_;
932 my $clone = { (ref $self ? %$self : ()) };
933 bless $clone, (ref $self || $self);
934
935 $clone->class_mappings({ %{$clone->class_mappings} });
936 $clone->source_registrations({ %{$clone->source_registrations} });
937 foreach my $moniker ($self->sources) {
938 my $source = $self->source($moniker);
939 my $new = $source->new($source);
940 # we use extra here as we want to leave the class_mappings as they are
941 # but overwrite the source_registrations entry with the new source
942 $clone->register_extra_source($moniker => $new);
943 }
944 $clone->storage->set_schema($clone) if $clone->storage;
945 return $clone;
946}
613397e7 947
5160b401 948=head2 throw_exception
701da8c4 949
75d07914 950=over 4
82b01c38 951
ebc77b53 952=item Arguments: $message
82b01c38 953
954=back
955
956Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 957user's perspective. See L</exception_action> for details on overriding
4b946902 958this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
959default behavior will provide a detailed stack trace.
701da8c4 960
961=cut
962
963sub throw_exception {
82cc0386 964 my $self = shift;
4981dc70 965
966 DBIx::Class::Exception->throw($_[0], $self->stacktrace)
967 if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 968}
969
dfccde48 970=head2 deploy
1c339d71 971
82b01c38 972=over 4
973
6e73ac25 974=item Arguments: $sqlt_args, $dir
82b01c38 975
976=back
977
978Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 979
51bace1c 980See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
981common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
982produced include a DROP TABLE statement for each table created.
983
499adf63 984Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
985ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 986only the sources listed will get deployed. Furthermore, you can use the
987C<add_fk_index> parser parameter to prevent the parser from creating an index for each
988FK.
499adf63 989
1c339d71 990=cut
991
992sub deploy {
6e73ac25 993 my ($self, $sqltargs, $dir) = @_;
1c339d71 994 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 995 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 996}
997
0e0ce6c1 998=head2 deployment_statements
999
1000=over 4
1001
7ad93f5a 1002=item Arguments: $rdbms_type, $sqlt_args, $dir
0e0ce6c1 1003
829517d4 1004=item Return value: $listofstatements
1005
0e0ce6c1 1006=back
1007
829517d4 1008A convenient shortcut to storage->deployment_statements(). Returns the
1009SQL statements used by L</deploy> and
1010L<DBIx::Class::Schema::Storage/deploy>. C<$rdbms_type> provides the
1011(optional) SQLT (not DBI) database driver name for which the SQL
1012statements are produced. If not supplied, the type is determined by
1013interrogating the current connection. The other two arguments are
1014identical to those of L</deploy>.
0e0ce6c1 1015
1016=cut
1017
1018sub deployment_statements {
7ad93f5a 1019 my $self = shift;
0e0ce6c1 1020
1021 $self->throw_exception("Can't generate deployment statements without a storage")
1022 if not $self->storage;
1023
7ad93f5a 1024 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1025}
1026
c0f61310 1027=head2 create_ddl_dir (EXPERIMENTAL)
1028
1029=over 4
1030
c9d2e0a2 1031=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 1032
1033=back
1034
1035Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 1036database types, in the given directory. Given a previous version number,
1037this will also create a file containing the ALTER TABLE statements to
1038transform the previous schema into the current one. Note that these
1039statements may contain DROP TABLE or DROP COLUMN statements that can
1040potentially destroy data.
1041
1042The file names are created using the C<ddl_filename> method below, please
1043override this method in your schema if you would like a different file
1044name format. For the ALTER file, the same format is used, replacing
1045$version in the name with "$preversion-$version".
1046
0e2c6809 1047See L<DBIx::Class::Schema/deploy> for details of $sqlt_args.
1048
c9d2e0a2 1049If no arguments are passed, then the following default values are used:
1050
1051=over 4
1052
1053=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
1054
b1f9d92e 1055=item version - $schema->schema_version
c9d2e0a2 1056
1057=item directory - './'
1058
1059=item preversion - <none>
1060
1061=back
c0f61310 1062
1063Note that this feature is currently EXPERIMENTAL and may not work correctly
1064across all databases, or fully handle complex relationships.
1065
c9d2e0a2 1066WARNING: Please check all SQL files created, before applying them.
1067
c0f61310 1068=cut
1069
6e73ac25 1070sub create_ddl_dir {
e673f011 1071 my $self = shift;
1072
1073 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1074 $self->storage->create_ddl_dir($self, @_);
1075}
1076
e63a82f7 1077=head2 ddl_filename
9b83fccd 1078
c9d2e0a2 1079=over 4
1080
99a74c4a 1081=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1082
829517d4 1083=item Return value: $normalised_filename
1084
c9d2e0a2 1085=back
1086
99a74c4a 1087 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1088
1089This method is called by C<create_ddl_dir> to compose a file name out of
1090the supplied directory, database type and version number. The default file
1091name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1092
c9d2e0a2 1093You may override this method in your schema if you wish to use a different
1094format.
9b83fccd 1095
1096=cut
1097
6e73ac25 1098sub ddl_filename {
99a74c4a 1099 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1100
99a74c4a 1101 my $filename = ref($self);
1102 $filename =~ s/::/-/g;
1103 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1104 $filename =~ s/$version/$preversion-$version/ if($preversion);
1105
1106 return $filename;
e673f011 1107}
1108
4146e3da 1109=head2 thaw
1110
829517d4 1111Provided as the recommended way of thawing schema objects. You can call
4146e3da 1112C<Storable::thaw> directly if you wish, but the thawed objects will not have a
1113reference to any schema, so are rather useless
1114
1115=cut
1116
1117sub thaw {
1118 my ($self, $obj) = @_;
1119 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1120 return Storable::thaw($obj);
1121}
1122
1123=head2 freeze
1124
1125This doesn't actualy do anything more than call L<Storable/freeze>, it is just
1126provided here for symetry.
1127
d2f3e87b 1128=cut
1129
4146e3da 1130sub freeze {
1131 return Storable::freeze($_[1]);
1132}
1133
1134=head2 dclone
1135
1136Recommeneded way of dcloning objects. This is needed to properly maintain
1137references to the schema object (which itself is B<not> cloned.)
1138
1139=cut
1140
1141sub dclone {
1142 my ($self, $obj) = @_;
1143 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1144 return Storable::dclone($obj);
1145}
1146
93e4d41a 1147=head2 schema_version
1148
829517d4 1149Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1150
1151=cut
1152
1153sub schema_version {
1154 my ($self) = @_;
1155 my $class = ref($self)||$self;
1156
1157 # does -not- use $schema->VERSION
1158 # since that varies in results depending on if version.pm is installed, and if
1159 # so the perl or XS versions. If you want this to change, bug the version.pm
1160 # author to make vpp and vxs behave the same.
1161
1162 my $version;
1163 {
1164 no strict 'refs';
1165 $version = ${"${class}::VERSION"};
1166 }
1167 return $version;
1168}
1169
829517d4 1170
1171=head2 register_class
1172
1173=over 4
1174
1175=item Arguments: $moniker, $component_class
1176
1177=back
1178
1179This 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.
1180
1181You will only need this method if you have your Result classes in
1182files which are not named after the packages (or all in the same
1183file). You may also need it to register classes at runtime.
1184
1185Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1186calling:
1187
1188 $schema->register_source($moniker, $component_class->result_source_instance);
1189
1190=cut
1191
1192sub register_class {
1193 my ($self, $moniker, $to_register) = @_;
1194 $self->register_source($moniker => $to_register->result_source_instance);
1195}
1196
1197=head2 register_source
1198
1199=over 4
1200
1201=item Arguments: $moniker, $result_source
1202
1203=back
1204
1205This method is called by L</register_class>.
1206
1207Registers the L<DBIx::Class::ResultSource> in the schema with the given
1208moniker.
1209
1210=cut
1211
1212sub register_source {
1213 my $self = shift;
1214
1215 $self->_register_source(@_);
1216}
1217
1218=head2 register_extra_source
1219
1220=over 4
1221
1222=item Arguments: $moniker, $result_source
1223
1224=back
1225
1226As L</register_source> but should be used if the result class already
1227has a source and you want to register an extra one.
1228
1229=cut
1230
1231sub register_extra_source {
1232 my $self = shift;
1233
1234 $self->_register_source(@_, { extra => 1 });
1235}
1236
1237sub _register_source {
1238 my ($self, $moniker, $source, $params) = @_;
1239
0e6c5d58 1240 $source = $source->new({ %$source, source_name => $moniker });
829517d4 1241
1242 my %reg = %{$self->source_registrations};
1243 $reg{$moniker} = $source;
1244 $self->source_registrations(\%reg);
1245
1246 $source->schema($self);
1247 weaken($source->{schema}) if ref($self);
1248 return if ($params->{extra});
1249
1250 if ($source->result_class) {
1251 my %map = %{$self->class_mappings};
1252 if (exists $map{$source->result_class}) {
1253 warn $source->result_class . ' already has a source, use register_extra_source for additional sources';
1254 }
1255 $map{$source->result_class} = $moniker;
1256 $self->class_mappings(\%map);
1257 }
1258}
1259
1260sub _unregister_source {
1261 my ($self, $moniker) = @_;
1262 my %reg = %{$self->source_registrations};
1263
1264 my $source = delete $reg{$moniker};
1265 $self->source_registrations(\%reg);
1266 if ($source->result_class) {
1267 my %map = %{$self->class_mappings};
1268 delete $map{$source->result_class};
1269 $self->class_mappings(\%map);
1270 }
1271}
1272
1273
1274=head2 compose_connection (DEPRECATED)
1275
1276=over 4
1277
1278=item Arguments: $target_namespace, @db_info
1279
1280=item Return Value: $new_schema
1281
1282=back
1283
1284DEPRECATED. You probably wanted compose_namespace.
1285
1286Actually, you probably just wanted to call connect.
1287
1288=begin hidden
1289
1290(hidden due to deprecation)
1291
1292Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1293calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1294then injects the L<DBix::Class::ResultSetProxy> component and a
1295resultset_instance classdata entry on all the new classes, in order to support
1296$target_namespaces::$class->search(...) method calls.
1297
1298This is primarily useful when you have a specific need for class method access
1299to a connection. In normal usage it is preferred to call
1300L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1301on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1302more information.
1303
1304=end hidden
1305
1306=cut
1307
1308{
1309 my $warn;
1310
1311 sub compose_connection {
1312 my ($self, $target, @info) = @_;
1313
1314 warn "compose_connection deprecated as of 0.08000"
1315 unless ($INC{"DBIx/Class/CDBICompat.pm"} || $warn++);
1316
1317 my $base = 'DBIx::Class::ResultSetProxy';
1318 eval "require ${base};";
1319 $self->throw_exception
1320 ("No arguments to load_classes and couldn't load ${base} ($@)")
1321 if $@;
1322
1323 if ($self eq $target) {
1324 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
1325 foreach my $moniker ($self->sources) {
1326 my $source = $self->source($moniker);
1327 my $class = $source->result_class;
1328 $self->inject_base($class, $base);
1329 $class->mk_classdata(resultset_instance => $source->resultset);
1330 $class->mk_classdata(class_resolver => $self);
1331 }
1332 $self->connection(@info);
1333 return $self;
1334 }
1335
1336 my $schema = $self->compose_namespace($target, $base);
1337 {
1338 no strict 'refs';
1339 my $name = join '::', $target, 'schema';
1340 *$name = Sub::Name::subname $name, sub { $schema };
1341 }
1342
1343 $schema->connection(@info);
1344 foreach my $moniker ($schema->sources) {
1345 my $source = $schema->source($moniker);
1346 my $class = $source->result_class;
1347 #warn "$moniker $class $source ".$source->storage;
1348 $class->mk_classdata(result_source_instance => $source);
1349 $class->mk_classdata(resultset_instance => $source->resultset);
1350 $class->mk_classdata(class_resolver => $schema);
1351 }
1352 return $schema;
1353 }
1354}
1355
a02675cd 13561;
c2da098a 1357
c2da098a 1358=head1 AUTHORS
1359
daec44b8 1360Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1361
1362=head1 LICENSE
1363
1364You may distribute this code under the same terms as Perl itself.
1365
1366=cut