Fix POD link
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
CommitLineData
9c992ba1 1package DBIx::Class::ResultSource;
2
3use strict;
4use warnings;
5
6use DBIx::Class::ResultSet;
aec3eff1 7use DBIx::Class::ResultSourceHandle;
1a58752c 8
9use DBIx::Class::Exception;
701da8c4 10use Carp::Clan qw/^DBIx::Class/;
6da5894c 11
9c992ba1 12use base qw/DBIx::Class/;
9c992ba1 13
aa1088bf 14__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
15 _columns _primaries _unique_constraints name resultset_attributes
acbe81cf 16 schema from _relationships column_info_from_storage source_info
f89bb832 17 source_name sqlt_deploy_callback/);
aa1088bf 18
fac560c2 19__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
b0dd0e03 20 result_class/);
9c992ba1 21
75d07914 22=head1 NAME
9c992ba1 23
24DBIx::Class::ResultSource - Result source object
25
26=head1 SYNOPSIS
27
16ccb4fe 28 # Create a table based result source, in a result class.
29
30 package MyDB::Schema::Result::Artist;
d88ecca6 31 use base qw/DBIx::Class::Core/;
16ccb4fe 32
16ccb4fe 33 __PACKAGE__->table('artist');
34 __PACKAGE__->add_columns(qw/ artistid name /);
35 __PACKAGE__->set_primary_key('artistid');
36 __PACKAGE__->has_many(cds => 'MyDB::Schema::Result::CD');
37
38 1;
39
40 # Create a query (view) based result source, in a result class
41 package MyDB::Schema::Result::Year2000CDs;
d88ecca6 42 use base qw/DBIx::Class::Core/;
16ccb4fe 43
d88ecca6 44 __PACKAGE__->load_components('InflateColumn::DateTime');
16ccb4fe 45 __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
46
47 __PACKAGE__->table('year2000cds');
48 __PACKAGE__->result_source_instance->is_virtual(1);
49 __PACKAGE__->result_source_instance->view_definition(
50 "SELECT cdid, artist, title FROM cd WHERE year ='2000'"
51 );
52
53
9c992ba1 54=head1 DESCRIPTION
55
16ccb4fe 56A ResultSource is an object that represents a source of data for querying.
57
58This class is a base class for various specialised types of result
59sources, for example L<DBIx::Class::ResultSource::Table>. Table is the
60default result source type, so one is created for you when defining a
61result class as described in the synopsis above.
62
d88ecca6 63More specifically, the L<DBIx::Class::Core> base class pulls in the
64L<DBIx::Class::ResultSourceProxy::Table> component, which defines
65the L<table|DBIx::Class::ResultSourceProxy::Table/table> method.
66When called, C<table> creates and stores an instance of
16ccb4fe 67L<DBIx::Class::ResultSoure::Table>. Luckily, to use tables as result
68sources, you don't need to remember any of this.
69
70Result sources representing select queries, or views, can also be
71created, see L<DBIx::Class::ResultSource::View> for full details.
72
73=head2 Finding result source objects
74
75As mentioned above, a result source instance is created and stored for
76you when you define a L<Result Class|DBIx::Class::Manual::Glossary/Result Class>.
77
78You can retrieve the result source at runtime in the following ways:
79
80=over
81
82=item From a Schema object:
83
84 $schema->source($source_name);
85
86=item From a Row object:
9c992ba1 87
16ccb4fe 88 $row->result_source;
89
90=item From a ResultSet object:
91
92 $rs->result_source;
93
94=back
00be2e0b 95
9c992ba1 96=head1 METHODS
97
7eb4ecc8 98=pod
99
9c992ba1 100=cut
101
102sub new {
103 my ($class, $attrs) = @_;
104 $class = ref $class if ref $class;
04786a4c 105
6b051e14 106 my $new = bless { %{$attrs || {}} }, $class;
9c992ba1 107 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 108 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 109 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
110 $new->{_columns} = { %{$new->{_columns}||{}} };
111 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 112 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 113 $new->{_columns_info_loaded} ||= 0;
f89bb832 114 $new->{sqlt_deploy_callback} ||= "default_sqlt_deploy_hook";
9c992ba1 115 return $new;
116}
117
988bf309 118=pod
119
5ac6a044 120=head2 add_columns
121
391ccf38 122=over
123
124=item Arguments: @columns
125
126=item Return value: The ResultSource object
127
128=back
129
843f6bc1 130 $source->add_columns(qw/col1 col2 col3/);
5ac6a044 131
843f6bc1 132 $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
5ac6a044 133
16ccb4fe 134Adds columns to the result source. If supplied colname => hashref
135pairs, uses the hashref as the L</column_info> for that column. Repeated
136calls of this method will add more columns, not replace them.
5ac6a044 137
5d9d9e87 138The column names given will be created as accessor methods on your
7e51afbf 139L<DBIx::Class::Row> objects. You can change the name of the accessor
5d9d9e87 140by supplying an L</accessor> in the column_info hash.
141
2053ab2a 142The contents of the column_info are not set in stone. The following
143keys are currently recognised/used by DBIx::Class:
988bf309 144
145=over 4
146
75d07914 147=item accessor
988bf309 148
16ccb4fe 149 { accessor => '_name' }
150
151 # example use, replace standard accessor with one of your own:
152 sub name {
153 my ($self, $value) = @_;
154
155 die "Name cannot contain digits!" if($value =~ /\d/);
156 $self->_name($value);
157
158 return $self->_name();
159 }
160
5d9d9e87 161Use this to set the name of the accessor method for this column. If unset,
988bf309 162the name of the column will be used.
163
164=item data_type
165
16ccb4fe 166 { data_type => 'integer' }
167
168This contains the column type. It is automatically filled if you use the
169L<SQL::Translator::Producer::DBIx::Class::File> producer, or the
170L<DBIx::Class::Schema::Loader> module.
988bf309 171
2053ab2a 172Currently there is no standard set of values for the data_type. Use
173whatever your database supports.
988bf309 174
175=item size
176
16ccb4fe 177 { size => 20 }
178
988bf309 179The length of your column, if it is a column type that can have a size
16ccb4fe 180restriction. This is currently only used to create tables from your
181schema, see L<DBIx::Class::Schema/deploy>.
988bf309 182
183=item is_nullable
184
16ccb4fe 185 { is_nullable => 1 }
186
187Set this to a true value for a columns that is allowed to contain NULL
188values, default is false. This is currently only used to create tables
189from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 190
191=item is_auto_increment
192
16ccb4fe 193 { is_auto_increment => 1 }
194
2053ab2a 195Set this to a true value for a column whose value is somehow
16ccb4fe 196automatically set, defaults to false. This is used to determine which
197columns to empty when cloning objects using
198L<DBIx::Class::Row/copy>. It is also used by
d7be2784 199L<DBIx::Class::Schema/deploy>.
988bf309 200
26a29815 201=item is_numeric
202
16ccb4fe 203 { is_numeric => 1 }
204
26a29815 205Set this to a true or false value (not C<undef>) to explicitly specify
206if this column contains numeric data. This controls how set_column
207decides whether to consider a column dirty after an update: if
0bad1823 208C<is_numeric> is true a numeric comparison C<< != >> will take place
26a29815 209instead of the usual C<eq>
210
211If not specified the storage class will attempt to figure this out on
212first access to the column, based on the column C<data_type>. The
213result will be cached in this attribute.
214
988bf309 215=item is_foreign_key
216
16ccb4fe 217 { is_foreign_key => 1 }
218
2053ab2a 219Set this to a true value for a column that contains a key from a
16ccb4fe 220foreign table, defaults to false. This is currently only used to
221create tables from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 222
223=item default_value
224
16ccb4fe 225 { default_value => \'now()' }
226
227Set this to the default value which will be inserted into a column by
228the database. Can contain either a value or a function (use a
4858fea7 229reference to a scalar e.g. C<\'now()'> if you want a function). This
16ccb4fe 230is currently only used to create tables from your schema, see
231L<DBIx::Class::Schema/deploy>.
988bf309 232
a4fcda00 233See the note on L<DBIx::Class::Row/new> for more information about possible
234issues related to db-side default values.
235
988bf309 236=item sequence
237
16ccb4fe 238 { sequence => 'my_table_seq' }
239
2053ab2a 240Set this on a primary key column to the name of the sequence used to
241generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
242will attempt to retrieve the name of the sequence from the database
243automatically.
988bf309 244
838ef78d 245=item auto_nextval
246
ca791b95 247Set this to a true value for a column whose value is retrieved automatically
248from a sequence or function (if supported by your Storage driver.) For a
249sequence, if you do not use a trigger to get the nextval, you have to set the
250L</sequence> value as well.
251
252Also set this for MSSQL columns with the 'uniqueidentifier'
e1958268 253L<data_type|DBIx::Class::ResultSource/data_type> whose values you want to
254automatically generate using C<NEWID()>, unless they are a primary key in which
255case this will be done anyway.
838ef78d 256
190615a7 257=item extra
d7be2784 258
259This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
190615a7 260to add extra non-generic data to the column. For example: C<< extra
d7be2784 261=> { unsigned => 1} >> is used by the MySQL producer to set an integer
262column to unsigned. For more details, see
263L<SQL::Translator::Producer::MySQL>.
264
988bf309 265=back
266
5ac6a044 267=head2 add_column
268
391ccf38 269=over
270
16ccb4fe 271=item Arguments: $colname, \%columninfo?
391ccf38 272
273=item Return value: 1/0 (true/false)
274
275=back
276
16ccb4fe 277 $source->add_column('col' => \%info);
5ac6a044 278
391ccf38 279Add a single column and optional column info. Uses the same column
280info keys as L</add_columns>.
5ac6a044 281
282=cut
283
9c992ba1 284sub add_columns {
285 my ($self, @cols) = @_;
8e04bf91 286 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
002a359a 287
20518cb4 288 my @added;
289 my $columns = $self->_columns;
9c992ba1 290 while (my $col = shift @cols) {
8e04bf91 291 # If next entry is { ... } use that for the column info, if not
292 # use an empty hashref
30126ac7 293 my $column_info = ref $cols[0] ? shift(@cols) : {};
20518cb4 294 push(@added, $col) unless exists $columns->{$col};
20518cb4 295 $columns->{$col} = $column_info;
9c992ba1 296 }
20518cb4 297 push @{ $self->_ordered_columns }, @added;
30126ac7 298 return $self;
9c992ba1 299}
300
b25e9fa0 301sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
9c992ba1 302
3842b955 303=head2 has_column
304
391ccf38 305=over
306
307=item Arguments: $colname
308
309=item Return value: 1/0 (true/false)
310
311=back
312
843f6bc1 313 if ($source->has_column($colname)) { ... }
988bf309 314
2053ab2a 315Returns true if the source has a column of this name, false otherwise.
988bf309 316
317=cut
9c992ba1 318
319sub has_column {
320 my ($self, $column) = @_;
321 return exists $self->_columns->{$column};
322}
323
87c4e602 324=head2 column_info
9c992ba1 325
391ccf38 326=over
327
328=item Arguments: $colname
329
330=item Return value: Hashref of info
331
332=back
333
843f6bc1 334 my $info = $source->column_info($col);
9c992ba1 335
391ccf38 336Returns the column metadata hashref for a column, as originally passed
16ccb4fe 337to L</add_columns>. See L</add_columns> above for information on the
338contents of the hashref.
9c992ba1 339
988bf309 340=cut
9c992ba1 341
342sub column_info {
343 my ($self, $column) = @_;
75d07914 344 $self->throw_exception("No such column $column")
701da8c4 345 unless exists $self->_columns->{$column};
5afa2a15 346 #warn $self->{_columns_info_loaded}, "\n";
75d07914 347 if ( ! $self->_columns->{$column}{data_type}
6eda9bcf 348 and $self->column_info_from_storage
75d07914 349 and ! $self->{_columns_info_loaded}
8e04bf91 350 and $self->schema and $self->storage )
351 {
352 $self->{_columns_info_loaded}++;
d51f93c8 353 my $info = {};
354 my $lc_info = {};
75d07914 355 # eval for the case of storage without table
955f1590 356 eval { $info = $self->storage->columns_info_for( $self->from ) };
8e04bf91 357 unless ($@) {
0b88a5bb 358 for my $realcol ( keys %{$info} ) {
359 $lc_info->{lc $realcol} = $info->{$realcol};
360 }
8e04bf91 361 foreach my $col ( keys %{$self->_columns} ) {
d51f93c8 362 $self->_columns->{$col} = {
363 %{ $self->_columns->{$col} },
364 %{ $info->{$col} || $lc_info->{lc $col} || {} }
365 };
a953d8d9 366 }
8e04bf91 367 }
a953d8d9 368 }
9c992ba1 369 return $self->_columns->{$column};
370}
371
372=head2 columns
373
391ccf38 374=over
375
376=item Arguments: None
377
378=item Return value: Ordered list of column names
379
380=back
381
382 my @column_names = $source->columns;
20518cb4 383
391ccf38 384Returns all column names in the order they were declared to L</add_columns>.
87f0da6a 385
386=cut
9c992ba1 387
388sub columns {
8e04bf91 389 my $self = shift;
aa1088bf 390 $self->throw_exception(
391 "columns() is a read-only accessor, did you mean add_columns()?"
9851dada 392 ) if @_;
701da8c4 393 return @{$self->{_ordered_columns}||[]};
571dced3 394}
395
002a359a 396=head2 remove_columns
397
391ccf38 398=over
002a359a 399
391ccf38 400=item Arguments: @colnames
401
402=item Return value: undefined
403
404=back
405
406 $source->remove_columns(qw/col1 col2 col3/);
407
408Removes the given list of columns by name, from the result source.
409
410B<Warning>: Removing a column that is also used in the sources primary
411key, or in one of the sources unique constraints, B<will> result in a
412broken result source.
002a359a 413
414=head2 remove_column
415
391ccf38 416=over
417
418=item Arguments: $colname
419
420=item Return value: undefined
421
422=back
002a359a 423
391ccf38 424 $source->remove_column('col');
425
426Remove a single column by name from the result source, similar to
427L</remove_columns>.
428
429B<Warning>: Removing a column that is also used in the sources primary
430key, or in one of the sources unique constraints, B<will> result in a
431broken result source.
002a359a 432
433=cut
434
435sub remove_columns {
4738027b 436 my ($self, @to_remove) = @_;
002a359a 437
4738027b 438 my $columns = $self->_columns
439 or return;
002a359a 440
4738027b 441 my %to_remove;
442 for (@to_remove) {
a918d901 443 delete $columns->{$_};
4738027b 444 ++$to_remove{$_};
445 }
002a359a 446
4738027b 447 $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]);
002a359a 448}
449
b25e9fa0 450sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
002a359a 451
87c4e602 452=head2 set_primary_key
453
27f01d1f 454=over 4
455
ebc77b53 456=item Arguments: @cols
27f01d1f 457
391ccf38 458=item Return value: undefined
459
27f01d1f 460=back
87f0da6a 461
16ccb4fe 462Defines one or more columns as primary key for this source. Must be
391ccf38 463called after L</add_columns>.
87f0da6a 464
391ccf38 465Additionally, defines a L<unique constraint|add_unique_constraint>
466named C<primary>.
87f0da6a 467
90f250bc 468Note: you normally do want to define a primary key on your sources
469B<even if the underlying database table does not have a primary key>.
470See
471L<DBIx::Class::Intro/The Significance and Importance of Primary Keys>
472for more info.
988bf309 473
87f0da6a 474=cut
9c992ba1 475
476sub set_primary_key {
477 my ($self, @cols) = @_;
478 # check if primary key columns are valid columns
8e04bf91 479 foreach my $col (@cols) {
480 $self->throw_exception("No such column $col on table " . $self->name)
481 unless $self->has_column($col);
9c992ba1 482 }
483 $self->_primaries(\@cols);
87f0da6a 484
485 $self->add_unique_constraint(primary => \@cols);
9c992ba1 486}
487
87f0da6a 488=head2 primary_columns
489
391ccf38 490=over 4
491
492=item Arguments: None
493
494=item Return value: Ordered list of primary column names
495
496=back
497
498Read-only accessor which returns the list of primary keys, supplied by
499L</set_primary_key>.
30126ac7 500
87f0da6a 501=cut
9c992ba1 502
503sub primary_columns {
504 return @{shift->_primaries||[]};
505}
506
e8fb771b 507sub _pri_cols {
508 my $self = shift;
509 my @pcols = $self->primary_columns
510 or $self->throw_exception (sprintf(
511 'Operation requires a primary key to be declared on %s via set_primary_key',
512 ref $self,
513 ));
514 return @pcols;
515}
516
87f0da6a 517=head2 add_unique_constraint
518
391ccf38 519=over 4
520
16ccb4fe 521=item Arguments: $name?, \@colnames
391ccf38 522
523=item Return value: undefined
524
525=back
526
87f0da6a 527Declare a unique constraint on this source. Call once for each unique
58b5bb8c 528constraint.
27f01d1f 529
530 # For UNIQUE (column1, column2)
531 __PACKAGE__->add_unique_constraint(
532 constraint_name => [ qw/column1 column2/ ],
533 );
87f0da6a 534
368a5228 535Alternatively, you can specify only the columns:
536
537 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
538
16ccb4fe 539This will result in a unique constraint named
540C<table_column1_column2>, where C<table> is replaced with the table
541name.
368a5228 542
16ccb4fe 543Unique constraints are used, for example, when you pass the constraint
544name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then
545only columns in the constraint are searched.
58b5bb8c 546
391ccf38 547Throws an error if any of the given column names do not yet exist on
548the result source.
549
87f0da6a 550=cut
551
552sub add_unique_constraint {
368a5228 553 my $self = shift;
554 my $cols = pop @_;
555 my $name = shift;
556
557 $name ||= $self->name_unique_constraint($cols);
87f0da6a 558
8e04bf91 559 foreach my $col (@$cols) {
560 $self->throw_exception("No such column $col on table " . $self->name)
561 unless $self->has_column($col);
87f0da6a 562 }
563
564 my %unique_constraints = $self->unique_constraints;
565 $unique_constraints{$name} = $cols;
566 $self->_unique_constraints(\%unique_constraints);
567}
568
d9c74322 569=head2 name_unique_constraint
368a5228 570
391ccf38 571=over 4
572
573=item Arguments: @colnames
574
575=item Return value: Constraint name
576
577=back
578
579 $source->table('mytable');
580 $source->name_unique_constraint('col1', 'col2');
581 # returns
582 'mytable_col1_col2'
583
584Return a name for a unique constraint containing the specified
585columns. The name is created by joining the table name and each column
586name, using an underscore character.
368a5228 587
588For example, a constraint on a table named C<cd> containing the columns
589C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
590
391ccf38 591This is used by L</add_unique_constraint> if you do not specify the
592optional constraint name.
593
368a5228 594=cut
595
596sub name_unique_constraint {
597 my ($self, $cols) = @_;
598
3e6c1131 599 my $name = $self->name;
4678e9da 600 $name = $$name if (ref $name eq 'SCALAR');
3e6c1131 601
602 return join '_', $name, @$cols;
368a5228 603}
604
87f0da6a 605=head2 unique_constraints
606
391ccf38 607=over 4
608
609=item Arguments: None
610
611=item Return value: Hash of unique constraint data
612
613=back
614
615 $source->unique_constraints();
616
16ccb4fe 617Read-only accessor which returns a hash of unique constraints on this
618source.
391ccf38 619
620The hash is keyed by constraint name, and contains an arrayref of
621column names as values.
87f0da6a 622
623=cut
624
625sub unique_constraints {
626 return %{shift->_unique_constraints||{}};
627}
628
e6a0e17c 629=head2 unique_constraint_names
630
391ccf38 631=over 4
632
633=item Arguments: None
634
635=item Return value: Unique constraint names
636
637=back
638
639 $source->unique_constraint_names();
640
e6a0e17c 641Returns the list of unique constraint names defined on this source.
642
643=cut
644
645sub unique_constraint_names {
646 my ($self) = @_;
647
648 my %unique_constraints = $self->unique_constraints;
649
650 return keys %unique_constraints;
651}
652
653=head2 unique_constraint_columns
654
391ccf38 655=over 4
656
657=item Arguments: $constraintname
658
659=item Return value: List of constraint columns
660
661=back
662
663 $source->unique_constraint_columns('myconstraint');
664
e6a0e17c 665Returns the list of columns that make up the specified unique constraint.
666
667=cut
668
669sub unique_constraint_columns {
670 my ($self, $constraint_name) = @_;
671
672 my %unique_constraints = $self->unique_constraints;
673
674 $self->throw_exception(
675 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
676 ) unless exists $unique_constraints{$constraint_name};
677
678 return @{ $unique_constraints{$constraint_name} };
679}
680
880c075b 681=head2 sqlt_deploy_callback
682
683=over
684
685=item Arguments: $callback
686
687=back
688
689 __PACKAGE__->sqlt_deploy_callback('mycallbackmethod');
690
691An accessor to set a callback to be called during deployment of
692the schema via L<DBIx::Class::Schema/create_ddl_dir> or
693L<DBIx::Class::Schema/deploy>.
694
695The callback can be set as either a code reference or the name of a
696method in the current result class.
697
698If not set, the L</default_sqlt_deploy_hook> is called.
699
700Your callback will be passed the $source object representing the
701ResultSource instance being deployed, and the
702L<SQL::Translator::Schema::Table> object being created from it. The
703callback can be used to manipulate the table object or add your own
704customised indexes. If you need to manipulate a non-table object, use
705the L<DBIx::Class::Schema/sqlt_deploy_hook>.
706
707See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To
708Your SQL> for examples.
709
710This sqlt deployment callback can only be used to manipulate
711SQL::Translator objects as they get turned into SQL. To execute
712post-deploy statements which SQL::Translator does not currently
713handle, override L<DBIx::Class::Schema/deploy> in your Schema class
714and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
715
716=head2 default_sqlt_deploy_hook
717
718=over
719
720=item Arguments: $source, $sqlt_table
721
722=item Return value: undefined
723
724=back
725
726This is the sensible default for L</sqlt_deploy_callback>.
727
728If a method named C<sqlt_deploy_hook> exists in your Result class, it
729will be called and passed the current C<$source> and the
730C<$sqlt_table> being deployed.
731
732=cut
733
734sub default_sqlt_deploy_hook {
735 my $self = shift;
736
737 my $class = $self->result_class;
738
739 if ($class and $class->can('sqlt_deploy_hook')) {
740 $class->sqlt_deploy_hook(@_);
741 }
742}
743
744sub _invoke_sqlt_deploy_hook {
745 my $self = shift;
746 if ( my $hook = $self->sqlt_deploy_callback) {
747 $self->$hook(@_);
748 }
749}
750
843f6bc1 751=head2 resultset
752
753=over 4
754
755=item Arguments: None
756
757=item Return value: $resultset
758
759=back
760
761Returns a resultset for the given source. This will initially be created
762on demand by calling
763
764 $self->resultset_class->new($self, $self->resultset_attributes)
765
766but is cached from then on unless resultset_class changes.
767
768=head2 resultset_class
769
770=over 4
771
772=item Arguments: $classname
773
774=item Return value: $classname
775
776=back
777
16ccb4fe 778 package My::Schema::ResultSet::Artist;
843f6bc1 779 use base 'DBIx::Class::ResultSet';
780 ...
781
16ccb4fe 782 # In the result class
783 __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist');
784
785 # Or in code
786 $source->resultset_class('My::Schema::ResultSet::Artist');
843f6bc1 787
7e51afbf 788Set the class of the resultset. This is useful if you want to create your
843f6bc1 789own resultset methods. Create your own class derived from
790L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
791this method returns the name of the existing resultset class, if one
792exists.
793
794=head2 resultset_attributes
795
796=over 4
797
798=item Arguments: \%attrs
799
800=item Return value: \%attrs
801
802=back
803
16ccb4fe 804 # In the result class
805 __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] });
806
807 # Or in code
843f6bc1 808 $source->resultset_attributes({ order_by => [ 'id' ] });
809
810Store a collection of resultset attributes, that will be set on every
811L<DBIx::Class::ResultSet> produced from this result source. For a full
812list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
813
814=cut
815
816sub resultset {
817 my $self = shift;
818 $self->throw_exception(
819 'resultset does not take any arguments. If you want another resultset, '.
820 'call it on the schema instead.'
821 ) if scalar @_;
822
823 return $self->resultset_class->new(
824 $self,
825 {
826 %{$self->{resultset_attributes}},
827 %{$self->schema->default_resultset_attributes}
828 },
829 );
830}
831
832=head2 source_name
833
834=over 4
835
836=item Arguments: $source_name
837
838=item Result value: $source_name
839
840=back
841
842Set an alternate name for the result source when it is loaded into a schema.
843This is useful if you want to refer to a result source by a name other than
844its class name.
845
846 package ArchivedBooks;
847 use base qw/DBIx::Class/;
848 __PACKAGE__->table('books_archive');
849 __PACKAGE__->source_name('Books');
850
851 # from your schema...
852 $schema->resultset('Books')->find(1);
853
9c992ba1 854=head2 from
855
391ccf38 856=over 4
857
858=item Arguments: None
859
860=item Return value: FROM clause
861
862=back
863
864 my $from_clause = $source->from();
865
9c992ba1 866Returns an expression of the source to be supplied to storage to specify
2053ab2a 867retrieval from this source. In the case of a database, the required FROM
868clause contents.
9c992ba1 869
f9b7bd6e 870=head2 schema
871
391ccf38 872=over 4
873
874=item Arguments: None
875
876=item Return value: A schema object
877
878=back
879
880 my $schema = $source->schema();
881
f9b7bd6e 882Returns the L<DBIx::Class::Schema> object that this result source
391ccf38 883belongs to.
9c992ba1 884
885=head2 storage
886
391ccf38 887=over 4
888
889=item Arguments: None
890
891=item Return value: A Storage object
892
893=back
894
895 $source->storage->debug(1);
896
75d07914 897Returns the storage handle for the current schema.
988bf309 898
899See also: L<DBIx::Class::Storage>
9c992ba1 900
901=cut
902
903sub storage { shift->schema->storage; }
904
8452e496 905=head2 add_relationship
906
391ccf38 907=over 4
908
909=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
910
911=item Return value: 1/true if it succeeded
912
913=back
914
8452e496 915 $source->add_relationship('relname', 'related_source', $cond, $attrs);
916
391ccf38 917L<DBIx::Class::Relationship> describes a series of methods which
918create pre-defined useful types of relationships. Look there first
919before using this method directly.
920
24d67825 921The relationship name can be arbitrary, but must be unique for each
922relationship attached to this result source. 'related_source' should
923be the name with which the related result source was registered with
924the current schema. For example:
8452e496 925
24d67825 926 $schema->source('Book')->add_relationship('reviews', 'Review', {
927 'foreign.book_id' => 'self.id',
928 });
929
2053ab2a 930The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 931representation of the join between the tables. For example, if you're
391ccf38 932creating a relation from Author to Book,
988bf309 933
934 { 'foreign.author_id' => 'self.id' }
935
936will result in the JOIN clause
937
938 author me JOIN book foreign ON foreign.author_id = me.id
939
8452e496 940You can specify as many foreign => self mappings as necessary.
941
988bf309 942Valid attributes are as follows:
943
944=over 4
945
946=item join_type
947
948Explicitly specifies the type of join to use in the relationship. Any
949SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
950the SQL command immediately before C<JOIN>.
951
952=item proxy
953
24d67825 954An arrayref containing a list of accessors in the foreign class to proxy in
955the main class. If, for example, you do the following:
002a359a 956
24d67825 957 CD->might_have(liner_notes => 'LinerNotes', undef, {
958 proxy => [ qw/notes/ ],
959 });
002a359a 960
24d67825 961Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 962
24d67825 963 my $cd = CD->find(1);
2053ab2a 964 # set notes -- LinerNotes object is created if it doesn't exist
965 $cd->notes('Notes go here');
988bf309 966
967=item accessor
968
969Specifies the type of accessor that should be created for the
75d07914 970relationship. Valid values are C<single> (for when there is only a single
971related object), C<multi> (when there can be many), and C<filter> (for
972when there is a single related object, but you also want the relationship
973accessor to double as a column accessor). For C<multi> accessors, an
974add_to_* method is also created, which calls C<create_related> for the
988bf309 975relationship.
976
8452e496 977=back
978
391ccf38 979Throws an exception if the condition is improperly supplied, or cannot
6d0ee587 980be resolved.
391ccf38 981
8452e496 982=cut
983
984sub add_relationship {
985 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 986 $self->throw_exception("Can't create relationship without join condition")
987 unless $cond;
8452e496 988 $attrs ||= {};
87772e46 989
eba322a7 990 # Check foreign and self are right in cond
991 if ( (ref $cond ||'') eq 'HASH') {
992 for (keys %$cond) {
993 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
994 if /\./ && !/^foreign\./;
995 }
996 }
997
8452e496 998 my %rels = %{ $self->_relationships };
999 $rels{$rel} = { class => $f_source_name,
87772e46 1000 source => $f_source_name,
8452e496 1001 cond => $cond,
1002 attrs => $attrs };
1003 $self->_relationships(\%rels);
1004
30126ac7 1005 return $self;
87772e46 1006
953a18ef 1007 # XXX disabled. doesn't work properly currently. skip in tests.
1008
8452e496 1009 my $f_source = $self->schema->source($f_source_name);
1010 unless ($f_source) {
c037c03a 1011 $self->ensure_class_loaded($f_source_name);
8452e496 1012 $f_source = $f_source_name->result_source;
87772e46 1013 #my $s_class = ref($self->schema);
1014 #$f_source_name =~ m/^${s_class}::(.*)$/;
1015 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
1016 #$f_source = $self->schema->source($f_source_name);
8452e496 1017 }
1018 return unless $f_source; # Can't test rel without f_source
1019
88a66388 1020 eval { $self->_resolve_join($rel, 'me', {}, []) };
8452e496 1021
1022 if ($@) { # If the resolve failed, back out and re-throw the error
75d07914 1023 delete $rels{$rel}; #
8452e496 1024 $self->_relationships(\%rels);
701da8c4 1025 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 1026 }
1027 1;
1028}
1029
87c4e602 1030=head2 relationships
8452e496 1031
391ccf38 1032=over 4
1033
1034=item Arguments: None
1035
1036=item Return value: List of relationship names
1037
1038=back
1039
1040 my @relnames = $source->relationships();
1041
2053ab2a 1042Returns all relationship names for this source.
8452e496 1043
1044=cut
1045
1046sub relationships {
1047 return keys %{shift->_relationships};
1048}
1049
87c4e602 1050=head2 relationship_info
1051
27f01d1f 1052=over 4
1053
ebc77b53 1054=item Arguments: $relname
27f01d1f 1055
391ccf38 1056=item Return value: Hashref of relation data,
1057
27f01d1f 1058=back
8452e496 1059
2053ab2a 1060Returns a hash of relationship information for the specified relationship
391ccf38 1061name. The keys/values are as specified for L</add_relationship>.
8452e496 1062
1063=cut
1064
1065sub relationship_info {
1066 my ($self, $rel) = @_;
1067 return $self->_relationships->{$rel};
75d07914 1068}
8452e496 1069
87c4e602 1070=head2 has_relationship
1071
27f01d1f 1072=over 4
1073
ebc77b53 1074=item Arguments: $rel
27f01d1f 1075
391ccf38 1076=item Return value: 1/0 (true/false)
1077
27f01d1f 1078=back
953a18ef 1079
2053ab2a 1080Returns true if the source has a relationship of this name, false otherwise.
988bf309 1081
1082=cut
953a18ef 1083
1084sub has_relationship {
1085 my ($self, $rel) = @_;
1086 return exists $self->_relationships->{$rel};
1087}
1088
de60a93d 1089=head2 reverse_relationship_info
1090
1091=over 4
1092
1093=item Arguments: $relname
1094
391ccf38 1095=item Return value: Hashref of relationship data
1096
de60a93d 1097=back
1098
391ccf38 1099Looks through all the relationships on the source this relationship
1100points to, looking for one whose condition is the reverse of the
1101condition on this relationship.
1102
1103A common use of this is to find the name of the C<belongs_to> relation
1104opposing a C<has_many> relation. For definition of these look in
1105L<DBIx::Class::Relationship>.
1106
1107The returned hashref is keyed by the name of the opposing
faaba25f 1108relationship, and contains its data in the same manner as
391ccf38 1109L</relationship_info>.
de60a93d 1110
1111=cut
1112
1113sub reverse_relationship_info {
1114 my ($self, $rel) = @_;
1115 my $rel_info = $self->relationship_info($rel);
1116 my $ret = {};
1117
1118 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1119
1120 my @cond = keys(%{$rel_info->{cond}});
1121 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
1122 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 1123
de60a93d 1124 # Get the related result source for this relationship
1125 my $othertable = $self->related_source($rel);
1126
1127 # Get all the relationships for that source that related to this source
1128 # whose foreign column set are our self columns on $rel and whose self
bab77431 1129 # columns are our foreign columns on $rel.
de60a93d 1130 my @otherrels = $othertable->relationships();
1131 my $otherrelationship;
1132 foreach my $otherrel (@otherrels) {
1133 my $otherrel_info = $othertable->relationship_info($otherrel);
1134
1135 my $back = $othertable->related_source($otherrel);
f3fb2641 1136 next unless $back->source_name eq $self->source_name;
de60a93d 1137
1138 my @othertestconds;
1139
1140 if (ref $otherrel_info->{cond} eq 'HASH') {
1141 @othertestconds = ($otherrel_info->{cond});
1142 }
1143 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
1144 @othertestconds = @{$otherrel_info->{cond}};
1145 }
1146 else {
1147 next;
1148 }
1149
1150 foreach my $othercond (@othertestconds) {
1151 my @other_cond = keys(%$othercond);
1152 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
1153 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
6d0ee587 1154 next if (!$self->_compare_relationship_keys(\@refkeys, \@other_keys) ||
1155 !$self->_compare_relationship_keys(\@other_refkeys, \@keys));
de60a93d 1156 $ret->{$otherrel} = $otherrel_info;
1157 }
1158 }
1159 return $ret;
1160}
1161
de60a93d 1162sub compare_relationship_keys {
6d0ee587 1163 carp 'compare_relationship_keys is a private method, stop calling it';
1164 my $self = shift;
1165 $self->_compare_relationship_keys (@_);
1166}
1167
1168# Returns true if both sets of keynames are the same, false otherwise.
1169sub _compare_relationship_keys {
de60a93d 1170 my ($self, $keys1, $keys2) = @_;
1171
1172 # Make sure every keys1 is in keys2
1173 my $found;
1174 foreach my $key (@$keys1) {
1175 $found = 0;
1176 foreach my $prim (@$keys2) {
1177 if ($prim eq $key) {
1178 $found = 1;
1179 last;
1180 }
1181 }
1182 last unless $found;
1183 }
1184
1185 # Make sure every key2 is in key1
1186 if ($found) {
1187 foreach my $prim (@$keys2) {
1188 $found = 0;
1189 foreach my $key (@$keys1) {
1190 if ($prim eq $key) {
1191 $found = 1;
1192 last;
1193 }
1194 }
1195 last unless $found;
1196 }
1197 }
1198
1199 return $found;
1200}
1201
6d0ee587 1202# Returns the {from} structure used to express JOIN conditions
1203sub _resolve_join {
8a3fa4ae 1204 my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
1979278e 1205
1206 # we need a supplied one, because we do in-place modifications, no returns
6d0ee587 1207 $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
88a66388 1208 unless ref $seen eq 'HASH';
1979278e 1209
88a66388 1210 $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1211 unless ref $jpath eq 'ARRAY';
1212
38f42d85 1213 $jpath = [@$jpath]; # copy
1979278e 1214
8a3fa4ae 1215 if (not defined $join) {
1216 return ();
1217 }
1218 elsif (ref $join eq 'ARRAY') {
caac1708 1219 return
1220 map {
8a3fa4ae 1221 $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left);
caac1708 1222 } @$join;
8a3fa4ae 1223 }
1224 elsif (ref $join eq 'HASH') {
1225
1226 my @ret;
1227 for my $rel (keys %$join) {
1228
1229 my $rel_info = $self->relationship_info($rel)
1230 or $self->throw_exception("No such relationship ${rel}");
1231
1232 my $force_left = $parent_force_left;
1233 $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left';
1234
1235 # the actual seen value will be incremented by the recursion
6c0230de 1236 my $as = $self->storage->relname_to_table_alias(
1237 $rel, ($seen->{$rel} && $seen->{$rel} + 1)
1238 );
1979278e 1239
8a3fa4ae 1240 push @ret, (
1241 $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left),
1242 $self->related_source($rel)->_resolve_join(
38f42d85 1243 $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left
8a3fa4ae 1244 )
1245 );
1246 }
1247 return @ret;
096395af 1248
8a3fa4ae 1249 }
1250 elsif (ref $join) {
1251 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1252 }
1253 else {
489709af 1254 my $count = ++$seen->{$join};
6c0230de 1255 my $as = $self->storage->relname_to_table_alias(
1256 $join, ($count > 1 && $count)
1257 );
1979278e 1258
8a3fa4ae 1259 my $rel_info = $self->relationship_info($join)
1260 or $self->throw_exception("No such relationship ${join}");
ba61fa2a 1261
1262 my $rel_src = $self->related_source($join);
1263 return [ { $as => $rel_src->from,
35ec0366 1264 -source_handle => $rel_src->handle,
8a3fa4ae 1265 -join_type => $parent_force_left
1266 ? 'left'
1267 : $rel_info->{attrs}{join_type}
1268 ,
38f42d85 1269 -join_path => [@$jpath, { $join => $as } ],
b82c8a28 1270 -is_single => (
1271 $rel_info->{attrs}{accessor}
1272 &&
1273 List::Util::first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/)
1274 ),
ba61fa2a 1275 -alias => $as,
1979278e 1276 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
1277 },
6d0ee587 1278 $self->_resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 1279 }
1280}
1281
370f2ba2 1282sub pk_depends_on {
6d0ee587 1283 carp 'pk_depends_on is a private method, stop calling it';
1284 my $self = shift;
1285 $self->_pk_depends_on (@_);
1286}
1287
1288# Determines whether a relation is dependent on an object from this source
1289# having already been inserted. Takes the name of the relationship and a
1290# hashref of columns of the related object.
1291sub _pk_depends_on {
370f2ba2 1292 my ($self, $relname, $rel_data) = @_;
370f2ba2 1293
c39b48e5 1294 my $relinfo = $self->relationship_info($relname);
1295
1296 # don't assume things if the relationship direction is specified
1297 return $relinfo->{attrs}{is_foreign_key_constraint}
1298 if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1299
1300 my $cond = $relinfo->{cond};
370f2ba2 1301 return 0 unless ref($cond) eq 'HASH';
1302
1303 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
370f2ba2 1304 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1305
1306 # assume anything that references our PK probably is dependent on us
1307 # rather than vice versa, unless the far side is (a) defined or (b)
1308 # auto-increment
370f2ba2 1309 my $rel_source = $self->related_source($relname);
1310
1311 foreach my $p ($self->primary_columns) {
1312 if (exists $keyhash->{$p}) {
1313 unless (defined($rel_data->{$keyhash->{$p}})
1314 || $rel_source->column_info($keyhash->{$p})
1315 ->{is_auto_increment}) {
1316 return 0;
1317 }
1318 }
1319 }
1320
1321 return 1;
1322}
1323
6d0ee587 1324sub resolve_condition {
1325 carp 'resolve_condition is a private method, stop calling it';
1326 my $self = shift;
1327 $self->_resolve_condition (@_);
1328}
953a18ef 1329
6d0ee587 1330# Resolves the passed condition to a concrete query fragment. If given an alias,
1331# returns a join condition; if given an object, inverts that object to produce
1332# a related conditional from that object.
8c368cf3 1333our $UNRESOLVABLE_CONDITION = \'1 = 0';
1334
6d0ee587 1335sub _resolve_condition {
489709af 1336 my ($self, $cond, $as, $for) = @_;
953a18ef 1337 if (ref $cond eq 'HASH') {
1338 my %ret;
bd054cb4 1339 foreach my $k (keys %{$cond}) {
1340 my $v = $cond->{$k};
953a18ef 1341 # XXX should probably check these are valid columns
27f01d1f 1342 $k =~ s/^foreign\.// ||
75d07914 1343 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1344 $v =~ s/^self\.// ||
75d07914 1345 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1346 if (ref $for) { # Object
3842b955 1347 #warn "$self $k $for $v";
370f2ba2 1348 unless ($for->has_column_loaded($v)) {
1349 if ($for->in_storage) {
8bbfe6b2 1350 $self->throw_exception(sprintf
5c89c897 1351 "Unable to resolve relationship '%s' from object %s: column '%s' not "
1352 . 'loaded from storage (or not passed to new() prior to insert()). You '
1353 . 'probably need to call ->discard_changes to get the server-side defaults '
1354 . 'from the database.',
8bbfe6b2 1355 $as,
971beb94 1356 $for,
5c89c897 1357 $v,
a4fcda00 1358 );
370f2ba2 1359 }
68f3b0dd 1360 return $UNRESOLVABLE_CONDITION;
370f2ba2 1361 }
1362 $ret{$k} = $for->get_column($v);
1363 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1364 #warn %ret;
2c037e6b 1365 } elsif (!defined $for) { # undef, i.e. "no object"
1366 $ret{$k} = undef;
2ec8e594 1367 } elsif (ref $as eq 'HASH') { # reverse hashref
1368 $ret{$v} = $as->{$k};
fde6e28e 1369 } elsif (ref $as) { # reverse object
1370 $ret{$v} = $as->get_column($k);
2c037e6b 1371 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1372 $ret{$v} = undef;
953a18ef 1373 } else {
489709af 1374 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1375 }
953a18ef 1376 }
1377 return \%ret;
5efe4c79 1378 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1379 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1380 } else {
35c77aa3 1381 die("Can't handle condition $cond yet :(");
87772e46 1382 }
1383}
1384
988bf309 1385
6d0ee587 1386# Accepts one or more relationships for the current source and returns an
1387# array of column names for each of those relationships. Column names are
1388# prefixed relative to the current source, in accordance with where they appear
38f42d85 1389# in the supplied relationships.
b3e8ac9b 1390
6d0ee587 1391sub _resolve_prefetch {
1979278e 1392 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1393 $pref_path ||= [];
1394
8a3fa4ae 1395 if (not defined $pre) {
1396 return ();
1397 }
1398 elsif( ref $pre eq 'ARRAY' ) {
0f66a01b 1399 return
6d0ee587 1400 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1401 @$pre;
b3e8ac9b 1402 }
1403 elsif( ref $pre eq 'HASH' ) {
1404 my @ret =
1405 map {
6d0ee587 1406 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1407 $self->related_source($_)->_resolve_prefetch(
1979278e 1408 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1409 } keys %$pre;
b3e8ac9b 1410 return @ret;
1411 }
1412 elsif( ref $pre ) {
a86b1efe 1413 $self->throw_exception(
1414 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1415 }
1416 else {
1979278e 1417 my $p = $alias_map;
1418 $p = $p->{$_} for (@$pref_path, $pre);
1419
1420 $self->throw_exception (
5e8cb53c 1421 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1979278e 1422 . join (' -> ', @$pref_path, $pre)
1423 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1424
1979278e 1425 my $as = shift @{$p->{-join_aliases}};
1426
b3e8ac9b 1427 my $rel_info = $self->relationship_info( $pre );
a86b1efe 1428 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1429 unless $rel_info;
37f23589 1430 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1431 my $rel_source = $self->related_source($pre);
0f66a01b 1432
b82c8a28 1433 if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') {
0f66a01b 1434 $self->throw_exception(
1435 "Can't prefetch has_many ${pre} (join cond too complex)")
1436 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1437 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1438 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1439 keys %{$collapse}) {
1440 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1441 carp (
1442 "Prefetching multiple has_many rels ${last} and ${pre} "
1443 .(length($as_prefix)
1444 ? "at the same level (${as_prefix}) "
1445 : "at top level "
1446 )
2e251255 1447 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1448 . 'Use at your own risk.'
1449 );
cb136e67 1450 }
b25e9fa0 1451 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1452 # values %{$rel_info->{cond}};
1453 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1454 # action at a distance. prepending the '.' allows simpler code
1455 # in ResultSet->_collapse_result
37f23589 1456 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1457 keys %{$rel_info->{cond}};
5a5bec6c 1458 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1459 ? @{$rel_info->{attrs}{order_by}}
b82c8a28 1460
1461 : (defined $rel_info->{attrs}{order_by}
5a5bec6c 1462 ? ($rel_info->{attrs}{order_by})
1463 : ()));
1464 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1465 }
1466
489709af 1467 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1468 $rel_source->columns;
b3e8ac9b 1469 }
1470}
953a18ef 1471
87c4e602 1472=head2 related_source
1473
27f01d1f 1474=over 4
1475
ebc77b53 1476=item Arguments: $relname
27f01d1f 1477
391ccf38 1478=item Return value: $source
1479
27f01d1f 1480=back
87772e46 1481
2053ab2a 1482Returns the result source object for the given relationship.
87772e46 1483
1484=cut
1485
1486sub related_source {
1487 my ($self, $rel) = @_;
aea52c85 1488 if( !$self->has_relationship( $rel ) ) {
701da8c4 1489 $self->throw_exception("No such relationship '$rel'");
aea52c85 1490 }
87772e46 1491 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1492}
1493
77254782 1494=head2 related_class
1495
27f01d1f 1496=over 4
1497
ebc77b53 1498=item Arguments: $relname
27f01d1f 1499
391ccf38 1500=item Return value: $classname
1501
27f01d1f 1502=back
77254782 1503
2053ab2a 1504Returns the class name for objects in the given relationship.
77254782 1505
1506=cut
1507
1508sub related_class {
1509 my ($self, $rel) = @_;
1510 if( !$self->has_relationship( $rel ) ) {
1511 $self->throw_exception("No such relationship '$rel'");
1512 }
1513 return $self->schema->class($self->relationship_info($rel)->{source});
1514}
1515
aec3eff1 1516=head2 handle
1517
1518Obtain a new handle to this source. Returns an instance of a
1519L<DBIx::Class::ResultSourceHandle>.
1520
1521=cut
1522
1523sub handle {
24c349e8 1524 return DBIx::Class::ResultSourceHandle->new({
aec3eff1 1525 schema => $_[0]->schema,
3441fd57 1526 source_moniker => $_[0]->source_name
aec3eff1 1527 });
1528}
1529
701da8c4 1530=head2 throw_exception
1531
2053ab2a 1532See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1533
1534=cut
1535
1536sub throw_exception {
1537 my $self = shift;
1a58752c 1538
0b4926ce 1539 if (defined $self->schema) {
701da8c4 1540 $self->schema->throw_exception(@_);
1a58752c 1541 }
1542 else {
1543 DBIx::Class::Exception->throw(@_);
701da8c4 1544 }
1545}
1546
843f6bc1 1547=head2 source_info
d2f3e87b 1548
843f6bc1 1549Stores a hashref of per-source metadata. No specific key names
1550have yet been standardized, the examples below are purely hypothetical
1551and don't actually accomplish anything on their own:
391ccf38 1552
843f6bc1 1553 __PACKAGE__->source_info({
1554 "_tablespace" => 'fast_disk_array_3',
1555 "_engine" => 'InnoDB',
1556 });
391ccf38 1557
843f6bc1 1558=head2 new
391ccf38 1559
843f6bc1 1560 $class->new();
391ccf38 1561
843f6bc1 1562 $class->new({attribute_name => value});
d2f3e87b 1563
843f6bc1 1564Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1565
843f6bc1 1566=head2 column_info_from_storage
1567
1568=over
1569
1570=item Arguments: 1/0 (default: 0)
1571
1572=item Return value: 1/0
1573
1574=back
1575
880c075b 1576 __PACKAGE__->column_info_from_storage(1);
1577
843f6bc1 1578Enables the on-demand automatic loading of the above column
c1300297 1579metadata from storage as necessary. This is *deprecated*, and
843f6bc1 1580should not be used. It will be removed before 1.0.
1581
f89bb832 1582
9c992ba1 1583=head1 AUTHORS
1584
1585Matt S. Trout <mst@shadowcatsystems.co.uk>
1586
1587=head1 LICENSE
1588
1589You may distribute this code under the same terms as Perl itself.
1590
1591=cut
1592
b25e9fa0 15931;