auto_nextval support for Firebird
[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
988bf309 468The primary key columns are used by L<DBIx::Class::PK::Auto> to
16ccb4fe 469retrieve automatically created values from the database. They are also
470used as default joining columns when specifying relationships, see
471L<DBIx::Class::Relationship>.
988bf309 472
87f0da6a 473=cut
9c992ba1 474
475sub set_primary_key {
476 my ($self, @cols) = @_;
477 # check if primary key columns are valid columns
8e04bf91 478 foreach my $col (@cols) {
479 $self->throw_exception("No such column $col on table " . $self->name)
480 unless $self->has_column($col);
9c992ba1 481 }
482 $self->_primaries(\@cols);
87f0da6a 483
484 $self->add_unique_constraint(primary => \@cols);
9c992ba1 485}
486
87f0da6a 487=head2 primary_columns
488
391ccf38 489=over 4
490
491=item Arguments: None
492
493=item Return value: Ordered list of primary column names
494
495=back
496
497Read-only accessor which returns the list of primary keys, supplied by
498L</set_primary_key>.
30126ac7 499
87f0da6a 500=cut
9c992ba1 501
502sub primary_columns {
503 return @{shift->_primaries||[]};
504}
505
e8fb771b 506sub _pri_cols {
507 my $self = shift;
508 my @pcols = $self->primary_columns
509 or $self->throw_exception (sprintf(
510 'Operation requires a primary key to be declared on %s via set_primary_key',
511 ref $self,
512 ));
513 return @pcols;
514}
515
87f0da6a 516=head2 add_unique_constraint
517
391ccf38 518=over 4
519
16ccb4fe 520=item Arguments: $name?, \@colnames
391ccf38 521
522=item Return value: undefined
523
524=back
525
87f0da6a 526Declare a unique constraint on this source. Call once for each unique
58b5bb8c 527constraint.
27f01d1f 528
529 # For UNIQUE (column1, column2)
530 __PACKAGE__->add_unique_constraint(
531 constraint_name => [ qw/column1 column2/ ],
532 );
87f0da6a 533
368a5228 534Alternatively, you can specify only the columns:
535
536 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
537
16ccb4fe 538This will result in a unique constraint named
539C<table_column1_column2>, where C<table> is replaced with the table
540name.
368a5228 541
16ccb4fe 542Unique constraints are used, for example, when you pass the constraint
543name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then
544only columns in the constraint are searched.
58b5bb8c 545
391ccf38 546Throws an error if any of the given column names do not yet exist on
547the result source.
548
87f0da6a 549=cut
550
551sub add_unique_constraint {
368a5228 552 my $self = shift;
553 my $cols = pop @_;
554 my $name = shift;
555
556 $name ||= $self->name_unique_constraint($cols);
87f0da6a 557
8e04bf91 558 foreach my $col (@$cols) {
559 $self->throw_exception("No such column $col on table " . $self->name)
560 unless $self->has_column($col);
87f0da6a 561 }
562
563 my %unique_constraints = $self->unique_constraints;
564 $unique_constraints{$name} = $cols;
565 $self->_unique_constraints(\%unique_constraints);
566}
567
d9c74322 568=head2 name_unique_constraint
368a5228 569
391ccf38 570=over 4
571
572=item Arguments: @colnames
573
574=item Return value: Constraint name
575
576=back
577
578 $source->table('mytable');
579 $source->name_unique_constraint('col1', 'col2');
580 # returns
581 'mytable_col1_col2'
582
583Return a name for a unique constraint containing the specified
584columns. The name is created by joining the table name and each column
585name, using an underscore character.
368a5228 586
587For example, a constraint on a table named C<cd> containing the columns
588C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
589
391ccf38 590This is used by L</add_unique_constraint> if you do not specify the
591optional constraint name.
592
368a5228 593=cut
594
595sub name_unique_constraint {
596 my ($self, $cols) = @_;
597
3e6c1131 598 my $name = $self->name;
4678e9da 599 $name = $$name if (ref $name eq 'SCALAR');
3e6c1131 600
601 return join '_', $name, @$cols;
368a5228 602}
603
87f0da6a 604=head2 unique_constraints
605
391ccf38 606=over 4
607
608=item Arguments: None
609
610=item Return value: Hash of unique constraint data
611
612=back
613
614 $source->unique_constraints();
615
16ccb4fe 616Read-only accessor which returns a hash of unique constraints on this
617source.
391ccf38 618
619The hash is keyed by constraint name, and contains an arrayref of
620column names as values.
87f0da6a 621
622=cut
623
624sub unique_constraints {
625 return %{shift->_unique_constraints||{}};
626}
627
e6a0e17c 628=head2 unique_constraint_names
629
391ccf38 630=over 4
631
632=item Arguments: None
633
634=item Return value: Unique constraint names
635
636=back
637
638 $source->unique_constraint_names();
639
e6a0e17c 640Returns the list of unique constraint names defined on this source.
641
642=cut
643
644sub unique_constraint_names {
645 my ($self) = @_;
646
647 my %unique_constraints = $self->unique_constraints;
648
649 return keys %unique_constraints;
650}
651
652=head2 unique_constraint_columns
653
391ccf38 654=over 4
655
656=item Arguments: $constraintname
657
658=item Return value: List of constraint columns
659
660=back
661
662 $source->unique_constraint_columns('myconstraint');
663
e6a0e17c 664Returns the list of columns that make up the specified unique constraint.
665
666=cut
667
668sub unique_constraint_columns {
669 my ($self, $constraint_name) = @_;
670
671 my %unique_constraints = $self->unique_constraints;
672
673 $self->throw_exception(
674 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
675 ) unless exists $unique_constraints{$constraint_name};
676
677 return @{ $unique_constraints{$constraint_name} };
678}
679
880c075b 680=head2 sqlt_deploy_callback
681
682=over
683
684=item Arguments: $callback
685
686=back
687
688 __PACKAGE__->sqlt_deploy_callback('mycallbackmethod');
689
690An accessor to set a callback to be called during deployment of
691the schema via L<DBIx::Class::Schema/create_ddl_dir> or
692L<DBIx::Class::Schema/deploy>.
693
694The callback can be set as either a code reference or the name of a
695method in the current result class.
696
697If not set, the L</default_sqlt_deploy_hook> is called.
698
699Your callback will be passed the $source object representing the
700ResultSource instance being deployed, and the
701L<SQL::Translator::Schema::Table> object being created from it. The
702callback can be used to manipulate the table object or add your own
703customised indexes. If you need to manipulate a non-table object, use
704the L<DBIx::Class::Schema/sqlt_deploy_hook>.
705
706See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To
707Your SQL> for examples.
708
709This sqlt deployment callback can only be used to manipulate
710SQL::Translator objects as they get turned into SQL. To execute
711post-deploy statements which SQL::Translator does not currently
712handle, override L<DBIx::Class::Schema/deploy> in your Schema class
713and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
714
715=head2 default_sqlt_deploy_hook
716
717=over
718
719=item Arguments: $source, $sqlt_table
720
721=item Return value: undefined
722
723=back
724
725This is the sensible default for L</sqlt_deploy_callback>.
726
727If a method named C<sqlt_deploy_hook> exists in your Result class, it
728will be called and passed the current C<$source> and the
729C<$sqlt_table> being deployed.
730
731=cut
732
733sub default_sqlt_deploy_hook {
734 my $self = shift;
735
736 my $class = $self->result_class;
737
738 if ($class and $class->can('sqlt_deploy_hook')) {
739 $class->sqlt_deploy_hook(@_);
740 }
741}
742
743sub _invoke_sqlt_deploy_hook {
744 my $self = shift;
745 if ( my $hook = $self->sqlt_deploy_callback) {
746 $self->$hook(@_);
747 }
748}
749
843f6bc1 750=head2 resultset
751
752=over 4
753
754=item Arguments: None
755
756=item Return value: $resultset
757
758=back
759
760Returns a resultset for the given source. This will initially be created
761on demand by calling
762
763 $self->resultset_class->new($self, $self->resultset_attributes)
764
765but is cached from then on unless resultset_class changes.
766
767=head2 resultset_class
768
769=over 4
770
771=item Arguments: $classname
772
773=item Return value: $classname
774
775=back
776
16ccb4fe 777 package My::Schema::ResultSet::Artist;
843f6bc1 778 use base 'DBIx::Class::ResultSet';
779 ...
780
16ccb4fe 781 # In the result class
782 __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist');
783
784 # Or in code
785 $source->resultset_class('My::Schema::ResultSet::Artist');
843f6bc1 786
7e51afbf 787Set the class of the resultset. This is useful if you want to create your
843f6bc1 788own resultset methods. Create your own class derived from
789L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
790this method returns the name of the existing resultset class, if one
791exists.
792
793=head2 resultset_attributes
794
795=over 4
796
797=item Arguments: \%attrs
798
799=item Return value: \%attrs
800
801=back
802
16ccb4fe 803 # In the result class
804 __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] });
805
806 # Or in code
843f6bc1 807 $source->resultset_attributes({ order_by => [ 'id' ] });
808
809Store a collection of resultset attributes, that will be set on every
810L<DBIx::Class::ResultSet> produced from this result source. For a full
811list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
812
813=cut
814
815sub resultset {
816 my $self = shift;
817 $self->throw_exception(
818 'resultset does not take any arguments. If you want another resultset, '.
819 'call it on the schema instead.'
820 ) if scalar @_;
821
822 return $self->resultset_class->new(
823 $self,
824 {
825 %{$self->{resultset_attributes}},
826 %{$self->schema->default_resultset_attributes}
827 },
828 );
829}
830
831=head2 source_name
832
833=over 4
834
835=item Arguments: $source_name
836
837=item Result value: $source_name
838
839=back
840
841Set an alternate name for the result source when it is loaded into a schema.
842This is useful if you want to refer to a result source by a name other than
843its class name.
844
845 package ArchivedBooks;
846 use base qw/DBIx::Class/;
847 __PACKAGE__->table('books_archive');
848 __PACKAGE__->source_name('Books');
849
850 # from your schema...
851 $schema->resultset('Books')->find(1);
852
9c992ba1 853=head2 from
854
391ccf38 855=over 4
856
857=item Arguments: None
858
859=item Return value: FROM clause
860
861=back
862
863 my $from_clause = $source->from();
864
9c992ba1 865Returns an expression of the source to be supplied to storage to specify
2053ab2a 866retrieval from this source. In the case of a database, the required FROM
867clause contents.
9c992ba1 868
f9b7bd6e 869=head2 schema
870
391ccf38 871=over 4
872
873=item Arguments: None
874
875=item Return value: A schema object
876
877=back
878
879 my $schema = $source->schema();
880
f9b7bd6e 881Returns the L<DBIx::Class::Schema> object that this result source
391ccf38 882belongs to.
9c992ba1 883
884=head2 storage
885
391ccf38 886=over 4
887
888=item Arguments: None
889
890=item Return value: A Storage object
891
892=back
893
894 $source->storage->debug(1);
895
75d07914 896Returns the storage handle for the current schema.
988bf309 897
898See also: L<DBIx::Class::Storage>
9c992ba1 899
900=cut
901
902sub storage { shift->schema->storage; }
903
8452e496 904=head2 add_relationship
905
391ccf38 906=over 4
907
908=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
909
910=item Return value: 1/true if it succeeded
911
912=back
913
8452e496 914 $source->add_relationship('relname', 'related_source', $cond, $attrs);
915
391ccf38 916L<DBIx::Class::Relationship> describes a series of methods which
917create pre-defined useful types of relationships. Look there first
918before using this method directly.
919
24d67825 920The relationship name can be arbitrary, but must be unique for each
921relationship attached to this result source. 'related_source' should
922be the name with which the related result source was registered with
923the current schema. For example:
8452e496 924
24d67825 925 $schema->source('Book')->add_relationship('reviews', 'Review', {
926 'foreign.book_id' => 'self.id',
927 });
928
2053ab2a 929The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 930representation of the join between the tables. For example, if you're
391ccf38 931creating a relation from Author to Book,
988bf309 932
933 { 'foreign.author_id' => 'self.id' }
934
935will result in the JOIN clause
936
937 author me JOIN book foreign ON foreign.author_id = me.id
938
8452e496 939You can specify as many foreign => self mappings as necessary.
940
988bf309 941Valid attributes are as follows:
942
943=over 4
944
945=item join_type
946
947Explicitly specifies the type of join to use in the relationship. Any
948SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
949the SQL command immediately before C<JOIN>.
950
951=item proxy
952
24d67825 953An arrayref containing a list of accessors in the foreign class to proxy in
954the main class. If, for example, you do the following:
002a359a 955
24d67825 956 CD->might_have(liner_notes => 'LinerNotes', undef, {
957 proxy => [ qw/notes/ ],
958 });
002a359a 959
24d67825 960Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 961
24d67825 962 my $cd = CD->find(1);
2053ab2a 963 # set notes -- LinerNotes object is created if it doesn't exist
964 $cd->notes('Notes go here');
988bf309 965
966=item accessor
967
968Specifies the type of accessor that should be created for the
75d07914 969relationship. Valid values are C<single> (for when there is only a single
970related object), C<multi> (when there can be many), and C<filter> (for
971when there is a single related object, but you also want the relationship
972accessor to double as a column accessor). For C<multi> accessors, an
973add_to_* method is also created, which calls C<create_related> for the
988bf309 974relationship.
975
8452e496 976=back
977
391ccf38 978Throws an exception if the condition is improperly supplied, or cannot
6d0ee587 979be resolved.
391ccf38 980
8452e496 981=cut
982
983sub add_relationship {
984 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 985 $self->throw_exception("Can't create relationship without join condition")
986 unless $cond;
8452e496 987 $attrs ||= {};
87772e46 988
eba322a7 989 # Check foreign and self are right in cond
990 if ( (ref $cond ||'') eq 'HASH') {
991 for (keys %$cond) {
992 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
993 if /\./ && !/^foreign\./;
994 }
995 }
996
8452e496 997 my %rels = %{ $self->_relationships };
998 $rels{$rel} = { class => $f_source_name,
87772e46 999 source => $f_source_name,
8452e496 1000 cond => $cond,
1001 attrs => $attrs };
1002 $self->_relationships(\%rels);
1003
30126ac7 1004 return $self;
87772e46 1005
953a18ef 1006 # XXX disabled. doesn't work properly currently. skip in tests.
1007
8452e496 1008 my $f_source = $self->schema->source($f_source_name);
1009 unless ($f_source) {
c037c03a 1010 $self->ensure_class_loaded($f_source_name);
8452e496 1011 $f_source = $f_source_name->result_source;
87772e46 1012 #my $s_class = ref($self->schema);
1013 #$f_source_name =~ m/^${s_class}::(.*)$/;
1014 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
1015 #$f_source = $self->schema->source($f_source_name);
8452e496 1016 }
1017 return unless $f_source; # Can't test rel without f_source
1018
88a66388 1019 eval { $self->_resolve_join($rel, 'me', {}, []) };
8452e496 1020
1021 if ($@) { # If the resolve failed, back out and re-throw the error
75d07914 1022 delete $rels{$rel}; #
8452e496 1023 $self->_relationships(\%rels);
701da8c4 1024 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 1025 }
1026 1;
1027}
1028
87c4e602 1029=head2 relationships
8452e496 1030
391ccf38 1031=over 4
1032
1033=item Arguments: None
1034
1035=item Return value: List of relationship names
1036
1037=back
1038
1039 my @relnames = $source->relationships();
1040
2053ab2a 1041Returns all relationship names for this source.
8452e496 1042
1043=cut
1044
1045sub relationships {
1046 return keys %{shift->_relationships};
1047}
1048
87c4e602 1049=head2 relationship_info
1050
27f01d1f 1051=over 4
1052
ebc77b53 1053=item Arguments: $relname
27f01d1f 1054
391ccf38 1055=item Return value: Hashref of relation data,
1056
27f01d1f 1057=back
8452e496 1058
2053ab2a 1059Returns a hash of relationship information for the specified relationship
391ccf38 1060name. The keys/values are as specified for L</add_relationship>.
8452e496 1061
1062=cut
1063
1064sub relationship_info {
1065 my ($self, $rel) = @_;
1066 return $self->_relationships->{$rel};
75d07914 1067}
8452e496 1068
87c4e602 1069=head2 has_relationship
1070
27f01d1f 1071=over 4
1072
ebc77b53 1073=item Arguments: $rel
27f01d1f 1074
391ccf38 1075=item Return value: 1/0 (true/false)
1076
27f01d1f 1077=back
953a18ef 1078
2053ab2a 1079Returns true if the source has a relationship of this name, false otherwise.
988bf309 1080
1081=cut
953a18ef 1082
1083sub has_relationship {
1084 my ($self, $rel) = @_;
1085 return exists $self->_relationships->{$rel};
1086}
1087
de60a93d 1088=head2 reverse_relationship_info
1089
1090=over 4
1091
1092=item Arguments: $relname
1093
391ccf38 1094=item Return value: Hashref of relationship data
1095
de60a93d 1096=back
1097
391ccf38 1098Looks through all the relationships on the source this relationship
1099points to, looking for one whose condition is the reverse of the
1100condition on this relationship.
1101
1102A common use of this is to find the name of the C<belongs_to> relation
1103opposing a C<has_many> relation. For definition of these look in
1104L<DBIx::Class::Relationship>.
1105
1106The returned hashref is keyed by the name of the opposing
faaba25f 1107relationship, and contains its data in the same manner as
391ccf38 1108L</relationship_info>.
de60a93d 1109
1110=cut
1111
1112sub reverse_relationship_info {
1113 my ($self, $rel) = @_;
1114 my $rel_info = $self->relationship_info($rel);
1115 my $ret = {};
1116
1117 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1118
1119 my @cond = keys(%{$rel_info->{cond}});
1120 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
1121 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 1122
de60a93d 1123 # Get the related result source for this relationship
1124 my $othertable = $self->related_source($rel);
1125
1126 # Get all the relationships for that source that related to this source
1127 # whose foreign column set are our self columns on $rel and whose self
bab77431 1128 # columns are our foreign columns on $rel.
de60a93d 1129 my @otherrels = $othertable->relationships();
1130 my $otherrelationship;
1131 foreach my $otherrel (@otherrels) {
1132 my $otherrel_info = $othertable->relationship_info($otherrel);
1133
1134 my $back = $othertable->related_source($otherrel);
f3fb2641 1135 next unless $back->source_name eq $self->source_name;
de60a93d 1136
1137 my @othertestconds;
1138
1139 if (ref $otherrel_info->{cond} eq 'HASH') {
1140 @othertestconds = ($otherrel_info->{cond});
1141 }
1142 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
1143 @othertestconds = @{$otherrel_info->{cond}};
1144 }
1145 else {
1146 next;
1147 }
1148
1149 foreach my $othercond (@othertestconds) {
1150 my @other_cond = keys(%$othercond);
1151 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
1152 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
6d0ee587 1153 next if (!$self->_compare_relationship_keys(\@refkeys, \@other_keys) ||
1154 !$self->_compare_relationship_keys(\@other_refkeys, \@keys));
de60a93d 1155 $ret->{$otherrel} = $otherrel_info;
1156 }
1157 }
1158 return $ret;
1159}
1160
de60a93d 1161sub compare_relationship_keys {
6d0ee587 1162 carp 'compare_relationship_keys is a private method, stop calling it';
1163 my $self = shift;
1164 $self->_compare_relationship_keys (@_);
1165}
1166
1167# Returns true if both sets of keynames are the same, false otherwise.
1168sub _compare_relationship_keys {
de60a93d 1169 my ($self, $keys1, $keys2) = @_;
1170
1171 # Make sure every keys1 is in keys2
1172 my $found;
1173 foreach my $key (@$keys1) {
1174 $found = 0;
1175 foreach my $prim (@$keys2) {
1176 if ($prim eq $key) {
1177 $found = 1;
1178 last;
1179 }
1180 }
1181 last unless $found;
1182 }
1183
1184 # Make sure every key2 is in key1
1185 if ($found) {
1186 foreach my $prim (@$keys2) {
1187 $found = 0;
1188 foreach my $key (@$keys1) {
1189 if ($prim eq $key) {
1190 $found = 1;
1191 last;
1192 }
1193 }
1194 last unless $found;
1195 }
1196 }
1197
1198 return $found;
1199}
1200
6d0ee587 1201# Returns the {from} structure used to express JOIN conditions
1202sub _resolve_join {
8a3fa4ae 1203 my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
1979278e 1204
1205 # we need a supplied one, because we do in-place modifications, no returns
6d0ee587 1206 $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
88a66388 1207 unless ref $seen eq 'HASH';
1979278e 1208
88a66388 1209 $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1210 unless ref $jpath eq 'ARRAY';
1211
38f42d85 1212 $jpath = [@$jpath]; # copy
1979278e 1213
8a3fa4ae 1214 if (not defined $join) {
1215 return ();
1216 }
1217 elsif (ref $join eq 'ARRAY') {
caac1708 1218 return
1219 map {
8a3fa4ae 1220 $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left);
caac1708 1221 } @$join;
8a3fa4ae 1222 }
1223 elsif (ref $join eq 'HASH') {
1224
1225 my @ret;
1226 for my $rel (keys %$join) {
1227
1228 my $rel_info = $self->relationship_info($rel)
1229 or $self->throw_exception("No such relationship ${rel}");
1230
1231 my $force_left = $parent_force_left;
1232 $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left';
1233
1234 # the actual seen value will be incremented by the recursion
6c0230de 1235 my $as = $self->storage->relname_to_table_alias(
1236 $rel, ($seen->{$rel} && $seen->{$rel} + 1)
1237 );
1979278e 1238
8a3fa4ae 1239 push @ret, (
1240 $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left),
1241 $self->related_source($rel)->_resolve_join(
38f42d85 1242 $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left
8a3fa4ae 1243 )
1244 );
1245 }
1246 return @ret;
096395af 1247
8a3fa4ae 1248 }
1249 elsif (ref $join) {
1250 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1251 }
1252 else {
489709af 1253 my $count = ++$seen->{$join};
6c0230de 1254 my $as = $self->storage->relname_to_table_alias(
1255 $join, ($count > 1 && $count)
1256 );
1979278e 1257
8a3fa4ae 1258 my $rel_info = $self->relationship_info($join)
1259 or $self->throw_exception("No such relationship ${join}");
ba61fa2a 1260
1261 my $rel_src = $self->related_source($join);
1262 return [ { $as => $rel_src->from,
35ec0366 1263 -source_handle => $rel_src->handle,
8a3fa4ae 1264 -join_type => $parent_force_left
1265 ? 'left'
1266 : $rel_info->{attrs}{join_type}
1267 ,
38f42d85 1268 -join_path => [@$jpath, { $join => $as } ],
b82c8a28 1269 -is_single => (
1270 $rel_info->{attrs}{accessor}
1271 &&
1272 List::Util::first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/)
1273 ),
ba61fa2a 1274 -alias => $as,
1979278e 1275 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
1276 },
6d0ee587 1277 $self->_resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 1278 }
1279}
1280
370f2ba2 1281sub pk_depends_on {
6d0ee587 1282 carp 'pk_depends_on is a private method, stop calling it';
1283 my $self = shift;
1284 $self->_pk_depends_on (@_);
1285}
1286
1287# Determines whether a relation is dependent on an object from this source
1288# having already been inserted. Takes the name of the relationship and a
1289# hashref of columns of the related object.
1290sub _pk_depends_on {
370f2ba2 1291 my ($self, $relname, $rel_data) = @_;
370f2ba2 1292
c39b48e5 1293 my $relinfo = $self->relationship_info($relname);
1294
1295 # don't assume things if the relationship direction is specified
1296 return $relinfo->{attrs}{is_foreign_key_constraint}
1297 if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1298
1299 my $cond = $relinfo->{cond};
370f2ba2 1300 return 0 unless ref($cond) eq 'HASH';
1301
1302 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
370f2ba2 1303 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1304
1305 # assume anything that references our PK probably is dependent on us
1306 # rather than vice versa, unless the far side is (a) defined or (b)
1307 # auto-increment
370f2ba2 1308 my $rel_source = $self->related_source($relname);
1309
1310 foreach my $p ($self->primary_columns) {
1311 if (exists $keyhash->{$p}) {
1312 unless (defined($rel_data->{$keyhash->{$p}})
1313 || $rel_source->column_info($keyhash->{$p})
1314 ->{is_auto_increment}) {
1315 return 0;
1316 }
1317 }
1318 }
1319
1320 return 1;
1321}
1322
6d0ee587 1323sub resolve_condition {
1324 carp 'resolve_condition is a private method, stop calling it';
1325 my $self = shift;
1326 $self->_resolve_condition (@_);
1327}
953a18ef 1328
6d0ee587 1329# Resolves the passed condition to a concrete query fragment. If given an alias,
1330# returns a join condition; if given an object, inverts that object to produce
1331# a related conditional from that object.
8c368cf3 1332our $UNRESOLVABLE_CONDITION = \'1 = 0';
1333
6d0ee587 1334sub _resolve_condition {
489709af 1335 my ($self, $cond, $as, $for) = @_;
953a18ef 1336 if (ref $cond eq 'HASH') {
1337 my %ret;
bd054cb4 1338 foreach my $k (keys %{$cond}) {
1339 my $v = $cond->{$k};
953a18ef 1340 # XXX should probably check these are valid columns
27f01d1f 1341 $k =~ s/^foreign\.// ||
75d07914 1342 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1343 $v =~ s/^self\.// ||
75d07914 1344 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1345 if (ref $for) { # Object
3842b955 1346 #warn "$self $k $for $v";
370f2ba2 1347 unless ($for->has_column_loaded($v)) {
1348 if ($for->in_storage) {
8bbfe6b2 1349 $self->throw_exception(sprintf
5c89c897 1350 "Unable to resolve relationship '%s' from object %s: column '%s' not "
1351 . 'loaded from storage (or not passed to new() prior to insert()). You '
1352 . 'probably need to call ->discard_changes to get the server-side defaults '
1353 . 'from the database.',
8bbfe6b2 1354 $as,
971beb94 1355 $for,
5c89c897 1356 $v,
a4fcda00 1357 );
370f2ba2 1358 }
68f3b0dd 1359 return $UNRESOLVABLE_CONDITION;
370f2ba2 1360 }
1361 $ret{$k} = $for->get_column($v);
1362 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1363 #warn %ret;
2c037e6b 1364 } elsif (!defined $for) { # undef, i.e. "no object"
1365 $ret{$k} = undef;
2ec8e594 1366 } elsif (ref $as eq 'HASH') { # reverse hashref
1367 $ret{$v} = $as->{$k};
fde6e28e 1368 } elsif (ref $as) { # reverse object
1369 $ret{$v} = $as->get_column($k);
2c037e6b 1370 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1371 $ret{$v} = undef;
953a18ef 1372 } else {
489709af 1373 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1374 }
953a18ef 1375 }
1376 return \%ret;
5efe4c79 1377 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1378 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1379 } else {
35c77aa3 1380 die("Can't handle condition $cond yet :(");
87772e46 1381 }
1382}
1383
988bf309 1384
6d0ee587 1385# Accepts one or more relationships for the current source and returns an
1386# array of column names for each of those relationships. Column names are
1387# prefixed relative to the current source, in accordance with where they appear
38f42d85 1388# in the supplied relationships.
b3e8ac9b 1389
6d0ee587 1390sub _resolve_prefetch {
1979278e 1391 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1392 $pref_path ||= [];
1393
8a3fa4ae 1394 if (not defined $pre) {
1395 return ();
1396 }
1397 elsif( ref $pre eq 'ARRAY' ) {
0f66a01b 1398 return
6d0ee587 1399 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1400 @$pre;
b3e8ac9b 1401 }
1402 elsif( ref $pre eq 'HASH' ) {
1403 my @ret =
1404 map {
6d0ee587 1405 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1406 $self->related_source($_)->_resolve_prefetch(
1979278e 1407 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1408 } keys %$pre;
b3e8ac9b 1409 return @ret;
1410 }
1411 elsif( ref $pre ) {
a86b1efe 1412 $self->throw_exception(
1413 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1414 }
1415 else {
1979278e 1416 my $p = $alias_map;
1417 $p = $p->{$_} for (@$pref_path, $pre);
1418
1419 $self->throw_exception (
5e8cb53c 1420 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1979278e 1421 . join (' -> ', @$pref_path, $pre)
1422 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1423
1979278e 1424 my $as = shift @{$p->{-join_aliases}};
1425
b3e8ac9b 1426 my $rel_info = $self->relationship_info( $pre );
a86b1efe 1427 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1428 unless $rel_info;
37f23589 1429 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1430 my $rel_source = $self->related_source($pre);
0f66a01b 1431
b82c8a28 1432 if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') {
0f66a01b 1433 $self->throw_exception(
1434 "Can't prefetch has_many ${pre} (join cond too complex)")
1435 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1436 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1437 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1438 keys %{$collapse}) {
1439 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1440 carp (
1441 "Prefetching multiple has_many rels ${last} and ${pre} "
1442 .(length($as_prefix)
1443 ? "at the same level (${as_prefix}) "
1444 : "at top level "
1445 )
2e251255 1446 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1447 . 'Use at your own risk.'
1448 );
cb136e67 1449 }
b25e9fa0 1450 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1451 # values %{$rel_info->{cond}};
1452 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1453 # action at a distance. prepending the '.' allows simpler code
1454 # in ResultSet->_collapse_result
37f23589 1455 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1456 keys %{$rel_info->{cond}};
5a5bec6c 1457 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1458 ? @{$rel_info->{attrs}{order_by}}
b82c8a28 1459
1460 : (defined $rel_info->{attrs}{order_by}
5a5bec6c 1461 ? ($rel_info->{attrs}{order_by})
1462 : ()));
1463 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1464 }
1465
489709af 1466 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1467 $rel_source->columns;
b3e8ac9b 1468 }
1469}
953a18ef 1470
87c4e602 1471=head2 related_source
1472
27f01d1f 1473=over 4
1474
ebc77b53 1475=item Arguments: $relname
27f01d1f 1476
391ccf38 1477=item Return value: $source
1478
27f01d1f 1479=back
87772e46 1480
2053ab2a 1481Returns the result source object for the given relationship.
87772e46 1482
1483=cut
1484
1485sub related_source {
1486 my ($self, $rel) = @_;
aea52c85 1487 if( !$self->has_relationship( $rel ) ) {
701da8c4 1488 $self->throw_exception("No such relationship '$rel'");
aea52c85 1489 }
87772e46 1490 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1491}
1492
77254782 1493=head2 related_class
1494
27f01d1f 1495=over 4
1496
ebc77b53 1497=item Arguments: $relname
27f01d1f 1498
391ccf38 1499=item Return value: $classname
1500
27f01d1f 1501=back
77254782 1502
2053ab2a 1503Returns the class name for objects in the given relationship.
77254782 1504
1505=cut
1506
1507sub related_class {
1508 my ($self, $rel) = @_;
1509 if( !$self->has_relationship( $rel ) ) {
1510 $self->throw_exception("No such relationship '$rel'");
1511 }
1512 return $self->schema->class($self->relationship_info($rel)->{source});
1513}
1514
aec3eff1 1515=head2 handle
1516
1517Obtain a new handle to this source. Returns an instance of a
1518L<DBIx::Class::ResultSourceHandle>.
1519
1520=cut
1521
1522sub handle {
24c349e8 1523 return DBIx::Class::ResultSourceHandle->new({
aec3eff1 1524 schema => $_[0]->schema,
3441fd57 1525 source_moniker => $_[0]->source_name
aec3eff1 1526 });
1527}
1528
701da8c4 1529=head2 throw_exception
1530
2053ab2a 1531See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1532
1533=cut
1534
1535sub throw_exception {
1536 my $self = shift;
1a58752c 1537
0b4926ce 1538 if (defined $self->schema) {
701da8c4 1539 $self->schema->throw_exception(@_);
1a58752c 1540 }
1541 else {
1542 DBIx::Class::Exception->throw(@_);
701da8c4 1543 }
1544}
1545
843f6bc1 1546=head2 source_info
d2f3e87b 1547
843f6bc1 1548Stores a hashref of per-source metadata. No specific key names
1549have yet been standardized, the examples below are purely hypothetical
1550and don't actually accomplish anything on their own:
391ccf38 1551
843f6bc1 1552 __PACKAGE__->source_info({
1553 "_tablespace" => 'fast_disk_array_3',
1554 "_engine" => 'InnoDB',
1555 });
391ccf38 1556
843f6bc1 1557=head2 new
391ccf38 1558
843f6bc1 1559 $class->new();
391ccf38 1560
843f6bc1 1561 $class->new({attribute_name => value});
d2f3e87b 1562
843f6bc1 1563Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1564
843f6bc1 1565=head2 column_info_from_storage
1566
1567=over
1568
1569=item Arguments: 1/0 (default: 0)
1570
1571=item Return value: 1/0
1572
1573=back
1574
880c075b 1575 __PACKAGE__->column_info_from_storage(1);
1576
843f6bc1 1577Enables the on-demand automatic loading of the above column
c1300297 1578metadata from storage as necessary. This is *deprecated*, and
843f6bc1 1579should not be used. It will be removed before 1.0.
1580
f89bb832 1581
9c992ba1 1582=head1 AUTHORS
1583
1584Matt S. Trout <mst@shadowcatsystems.co.uk>
1585
1586=head1 LICENSE
1587
1588You may distribute this code under the same terms as Perl itself.
1589
1590=cut
1591
b25e9fa0 15921;