implemented _collapse_result and _merge_result
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
CommitLineData
9c992ba1 1package DBIx::Class::ResultSource;
2
3use strict;
4use warnings;
5
3904d3c3 6use base qw/DBIx::Class/;
7
9c992ba1 8use DBIx::Class::ResultSet;
aec3eff1 9use DBIx::Class::ResultSourceHandle;
1a58752c 10
11use DBIx::Class::Exception;
701da8c4 12use Carp::Clan qw/^DBIx::Class/;
6da5894c 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'
253L<DBIx::Class::ResultSource/data_type> whose values you want to automatically
254generate using C<NEWID()>, unless they are a primary key in which case this will
255be 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',
d4d8e97b 511 $self->source_name,
e8fb771b 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') {
1979278e 1224
8a3fa4ae 1225 my @ret;
1226 for my $rel (keys %$join) {
096395af 1227
8a3fa4ae 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.
3904d3c3 1332our $UNRESOLVABLE_CONDITION = \ '1 = 0';
8c368cf3 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 {
22e40557 1391 my ($self, $pre, $alias, $alias_map, $order, $pref_path) = @_;
1979278e 1392 $pref_path ||= [];
1393
8a3fa4ae 1394 if (not defined $pre) {
1395 return ();
1396 }
1397 elsif( ref $pre eq 'ARRAY' ) {
0f66a01b 1398 return
22e40557 1399 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, [ @$pref_path ] ) }
0f66a01b 1400 @$pre;
b3e8ac9b 1401 }
1402 elsif( ref $pre eq 'HASH' ) {
1403 my @ret =
1404 map {
22e40557 1405 $self->_resolve_prefetch($_, $alias, $alias_map, $order, [ @$pref_path ] ),
6d0ee587 1406 $self->related_source($_)->_resolve_prefetch(
22e40557 1407 $pre->{$_}, "${alias}.$_", $alias_map, $order, [ @$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}"
27ffa6c0 1437
b25e9fa0 1438 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1439 # values %{$rel_info->{cond}};
37f23589 1440 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1441 keys %{$rel_info->{cond}};
5a5bec6c 1442 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1443 ? @{$rel_info->{attrs}{order_by}}
22e40557 1444
b82c8a28 1445 : (defined $rel_info->{attrs}{order_by}
5a5bec6c 1446 ? ($rel_info->{attrs}{order_by})
3904d3c3 1447 : ()
1448 ));
5a5bec6c 1449 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1450 }
1451
489709af 1452 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1453 $rel_source->columns;
b3e8ac9b 1454 }
1455}
953a18ef 1456
d4d8e97b 1457# Takes a selection list and generates a collapse-map representing
1458# row-object fold-points. Every relationship is assigned a set of unique,
1459# non-nullable columns (which may *not even be* from the same resultset)
1460# and the collapser will use this information to correctly distinguish
3904d3c3 1461# data of individual to-be-row-objects.
d4d8e97b 1462sub _resolve_collapse {
3904d3c3 1463 my ($self, $as, $as_fq_idx, $rel_chain, $parent_info) = @_;
1464
1465 # for comprehensible error messages put ourselves at the head of the relationship chain
1466 $rel_chain ||= [ $self->source_name ];
d4d8e97b 1467
3904d3c3 1468 # record top-level fully-qualified column index
1469 $as_fq_idx ||= { %$as };
1470
1471 my ($my_cols, $rel_cols);
1472 for (keys %$as) {
d4d8e97b 1473 if ($_ =~ /^ ([^\.]+) \. (.+) /x) {
3904d3c3 1474 $rel_cols->{$1}{$2} = 1;
d4d8e97b 1475 }
1476 else {
1477 $my_cols->{$_} = {}; # important for ||= below
1478 }
1479 }
1480
1481 my $relinfo;
3904d3c3 1482 # run through relationships, collect metadata, inject non-left fk-bridges from
1483 # *INNER-JOINED* children (if any)
d4d8e97b 1484 for my $rel (keys %$rel_cols) {
1485 my $rel_src = $self->related_source ($rel);
1486 my $inf = $self->relationship_info ($rel);
1487
1488 $relinfo->{$rel}{is_single} = $inf->{attrs}{accessor} && $inf->{attrs}{accessor} ne 'multi';
1489 $relinfo->{$rel}{is_inner} = ( $inf->{attrs}{join_type} || '' ) !~ /^left/i;
1490 $relinfo->{$rel}{rsrc} = $rel_src;
1491
1492 my $cond = $inf->{cond};
3904d3c3 1493
d4d8e97b 1494 if (
1495 ref $cond eq 'HASH'
1496 and
1497 keys %$cond
1498 and
1499 ! List::Util::first { $_ !~ /^foreign\./ } (keys %$cond)
1500 and
1501 ! List::Util::first { $_ !~ /^self\./ } (values %$cond)
1502 ) {
1503 for my $f (keys %$cond) {
1504 my $s = $cond->{$f};
1505 $_ =~ s/^ (?: foreign | self ) \.//x for ($f, $s);
1506 $relinfo->{$rel}{fk_map}{$s} = $f;
1507
1508 $my_cols->{$s} ||= { via_fk => "$rel.$f" } # need to know source from *our* pov
3904d3c3 1509 if ($relinfo->{$rel}{is_inner} && defined $rel_cols->{$rel}{$f}); # only if it is inner and in fact selected of course
d4d8e97b 1510 }
1511 }
1512 }
1513
3904d3c3 1514 # if the parent is already defined, assume all of its related FKs are selected
1515 # (even if they in fact are NOT in the select list). Keep a record of what we
1516 # assumed, and if any such phantom-column becomes part of our own collapser,
1517 # throw everything assumed-from-parent away and replace with the collapser of
1518 # the parent (whatever it may be)
1519 my $assumed_from_parent;
1520 unless ($parent_info->{underdefined}) {
1521 $assumed_from_parent->{columns} = { map
1522 # only add to the list if we do not already select said columns
1523 { ! exists $my_cols->{$_} ? ( $_ => 1 ) : () }
1524 values %{$parent_info->{rel_condition} || {}}
1525 };
1526
1527 $my_cols->{$_} = { via_collapse => $parent_info->{collapse_on} }
1528 for keys %{$assumed_from_parent->{columns}};
1529 }
1530
d4d8e97b 1531 # get colinfo for everything
1532 if ($my_cols) {
1533 $my_cols->{$_}{colinfo} = (
1534 $self->has_column ($_) ? $self->column_info ($_) : undef
1535 ) for keys %$my_cols;
1536 }
1537
3904d3c3 1538 my $collapse_map;
1539
1540 # try to resolve based on our columns (plus already inserted FK bridges)
d4d8e97b 1541 if (
1542 $my_cols
1543 and
d4d8e97b 1544 my $uset = $self->_unique_column_set ($my_cols)
1545 ) {
3904d3c3 1546 # see if the resulting collapser relies on any implied columns,
1547 # and fix stuff up if this is the case
1548
1549 my $parent_collapser_used;
1550
1551 if (List::Util::first
1552 { exists $assumed_from_parent->{columns}{$_} }
1553 keys %$uset
1554 ) {
1555 # remove implied stuff from the uset, we will inject the equivalent collapser a bit below
1556 delete @{$uset}{keys %{$assumed_from_parent->{columns}}};
1557 $parent_collapser_used = 1;
1558 }
1559
1560 $collapse_map->{-collapse_on} = {
1561 %{ $parent_collapser_used ? $parent_info->{collapse_on} : {} },
1562 (map
1563 {
1564 my $fqc = join ('.',
1565 @{$rel_chain}[1 .. $#$rel_chain],
1566 ( $my_cols->{$_}{via_fk} || $_ ),
1567 );
1568
1569 $fqc => $as_fq_idx->{$fqc};
1570 }
1571 keys %$uset
1572 ),
d4d8e97b 1573 };
1574 }
1575
3904d3c3 1576 # don't know how to collapse - keep descending down 1:1 chains - if
1577 # a related non-LEFT 1:1 is resolvable - its condition will collapse us
1578 # too
d4d8e97b 1579 unless ($collapse_map->{-collapse_on}) {
3904d3c3 1580 my @candidates;
1581
d4d8e97b 1582 for my $rel (keys %$relinfo) {
3904d3c3 1583 next unless ($relinfo->{$rel}{is_single} && $relinfo->{$rel}{is_inner});
d4d8e97b 1584
3904d3c3 1585 if ( my $rel_collapse = $relinfo->{$rel}{rsrc}->_resolve_collapse (
d4d8e97b 1586 $rel_cols->{$rel},
3904d3c3 1587 $as_fq_idx,
1588 [ @$rel_chain, $rel ],
1589 { underdefined => 1 }
d4d8e97b 1590 )) {
3904d3c3 1591 push @candidates, $rel_collapse->{-collapse_on};
d4d8e97b 1592 }
1593 }
3904d3c3 1594
1595 # get the set with least amount of columns
1596 # FIXME - maybe need to implement a data type order as well (i.e. prefer several ints
1597 # to a single varchar)
1598 if (@candidates) {
1599 ($collapse_map->{-collapse_on}) = sort { keys %$a <=> keys %$b } (@candidates);
1600 }
d4d8e97b 1601 }
1602
3904d3c3 1603 # Still dont know how to collapse - see if the parent passed us anything
1604 # (i.e. reuse collapser over 1:1)
d4d8e97b 1605 unless ($collapse_map->{-collapse_on}) {
3904d3c3 1606 $collapse_map->{-collapse_on} = $parent_info->{collapse_on}
1607 if $parent_info->{collapser_reusable};
1608 }
1609
1610
1611 # stop descending into children if we were called by a parent for first-pass
1612 # and don't despair if nothing was found (there may be other parallel branches
1613 # to dive into)
1614 if ($parent_info->{underdefined}) {
1615 return $collapse_map->{-collapse_on} ? $collapse_map : undef
1616 }
1617 # nothing down the chain resolved - can't calculate a collapse-map
1618 elsif (! $collapse_map->{-collapse_on}) {
d4d8e97b 1619 $self->throw_exception ( sprintf
3904d3c3 1620 "Unable to calculate a definitive collapse column set for %s%s: fetch more unique non-nullable columns",
d4d8e97b 1621 $self->source_name,
3904d3c3 1622 @$rel_chain > 1
1623 ? sprintf (' (last member of the %s chain)', join ' -> ', @$rel_chain )
1624 : ''
1625 ,
d4d8e97b 1626 );
1627 }
1628
d4d8e97b 1629
3904d3c3 1630 # If we got that far - we are collapsable - GREAT! Now go down all children
1631 # a second time, and fill in the rest
d4d8e97b 1632
3904d3c3 1633 for my $rel (keys %$relinfo) {
d4d8e97b 1634
3904d3c3 1635 $collapse_map->{$rel} = $relinfo->{$rel}{rsrc}->_resolve_collapse (
1636 { map { $_ => 1 } ( keys %{$rel_cols->{$rel}} ) },
d4d8e97b 1637
3904d3c3 1638 $as_fq_idx,
d4d8e97b 1639
3904d3c3 1640 [ @$rel_chain, $rel],
d4d8e97b 1641
3904d3c3 1642 {
1643 collapse_on => { %{$collapse_map->{-collapse_on}} },
d4d8e97b 1644
3904d3c3 1645 rel_condition => $relinfo->{$rel}{fk_map},
d4d8e97b 1646
3904d3c3 1647 # if this is a 1:1 our own collapser can be used as a collapse-map
1648 # (regardless of left or not)
1649 collapser_reusable => $relinfo->{$rel}{is_single},
1650 },
1651 );
d4d8e97b 1652 }
1653
3904d3c3 1654 return $collapse_map;
d4d8e97b 1655}
1656
1657sub _unique_column_set {
1658 my ($self, $cols) = @_;
1659
1660 my %unique = $self->unique_constraints;
1661
1662 # always prefer the PK first, and then shortest constraints first
1663 USET:
1664 for my $set (delete $unique{primary}, sort { @$a <=> @$b } (values %unique) ) {
1665 next unless $set && @$set;
1666
1667 for (@$set) {
1668 next USET unless ($cols->{$_} && $cols->{$_}{colinfo} && !$cols->{$_}{colinfo}{is_nullable} );
1669 }
1670
1671 return { map { $_ => 1 } @$set };
1672 }
1673
1674 return undef;
1675}
1676
3904d3c3 1677# Takes an arrayref of {as} dbic column aliases and the collapse and select
1678# attributes from the same $rs (the slector requirement is a temporary
1679# workaround), and returns a coderef capable of:
1680# my $me_pref_clps = $coderef->([$rs->cursor->next])
1681# Where the $me_pref_clps arrayref is the future argument to
1682# ::ResultSet::_collapse_result.
1683#
1684# $me_pref_clps->[0] is always returned (even if as an empty hash with no
1685# rowdata), however branches of related data in $me_pref_clps->[1] may be
1686# pruned short of what was originally requested based on {as}, depending
1687# on:
9f6555d3 1688#
3904d3c3 1689# * If collapse is requested, a definitive collapse map is calculated for
1690# every relationship "fold-point", consisting of a set of values (which
1691# may not even be contained in the future 'me' of said relationship
1692# (for example a cd.artist_id defines the related inner-joined artist)).
1693# Thus a definedness check is carried on all collapse-condition values
1694# and if at least one is undef it is assumed that we are dealing with a
1695# NULLed right-side of a left-join, so we don't return a related data
1696# container at all, which implies no related objects
9f6555d3 1697#
3904d3c3 1698# * If we are not collapsing, there is no constraint on having a selector
1699# uniquely identifying all possible objects, and the user might have very
1700# well requested a column that just *happens* to be all NULLs. What we do
1701# in this case is fallback to the old behavior (which is a potential FIXME)
1702# by always returning a data container, but only filling it with columns
1703# IFF at least one of them is defined. This way we do not get an object
1704# with a bunch of has_column_loaded to undef, but at the same time do not
1705# further relationships based off this "null" object (e.g. in case the user
1706# deliberately skipped link-table values). I am pretty sure there are some
1707# tests that codify this behavior, need to find the exact testname.
1708#
1709# For an example of this coderef in action (and to see its guts) look at
1710# t/prefetch/_internals.t
1711#
1712# This is a huge performance win, as we call the same code for
1713# every row returned from the db, thus avoiding repeated method
1714# lookups when traversing relationships
1715#
1716# Also since the coderef is completely stateless (the returned structure is
1717# always fresh on every new invocation) this is a very good opportunity for
1718# memoization if further speed improvements are needed
1719#
1720# The way we construct this coderef is somewhat fugly, although I am not
1721# sure if the string eval is *that* bad of an idea. The alternative is to
1722# have a *very* large number of anon coderefs calling each other in a twisty
1723# maze, whereas the current result is a nice, smooth, single-pass function.
1724# In any case - the output of this thing is meticulously micro-tested, so
1725# any sort of rewrite should be relatively easy
1726#
1727sub _mk_row_parser {
1728 my ($self, $as, $with_collapse, $select) = @_;
1729
1730 my $as_indexed = { map
1731 { $as->[$_] => $_ }
1732 ( 0 .. $#$as )
1733 };
1734
1735 # calculate collapse fold-points if needed
1736 my $collapse_on = do {
1737 # FIXME
1738 # only consider real columns (not functions) during collapse resolution
1739 # this check shouldn't really be here, as fucktards are not supposed to
1740 # alias random crap to existing column names anyway, but still - just in
1741 # case (also saves us from select/as mismatches which need fixing as well...)
1742
1743 my $plain_as = { %$as_indexed };
1744 for (keys %$plain_as) {
1745 delete $plain_as->{$_} if ref $select->[$plain_as->{$_}];
1746 }
1747 $self->_resolve_collapse ($plain_as);
9f6555d3 1748
3904d3c3 1749 } if $with_collapse;
9f6555d3 1750
3904d3c3 1751 my $perl = $self->__visit_as ($as_indexed, $collapse_on);
1752 my $cref = eval "sub { $perl }"
1753 or die "Oops! _mk_row_parser generated invalid perl:\n$@\n\n$perl\n";
1754 return $cref;
1755}
1756
1757{
1758 my $visit_as_dumper; # keep our own DD object around so we don't have to fitz with quoting
1759
1760 sub __visit_as {
1761 my ($self, $as, $collapse_on, $known_defined) = @_;
1762 $known_defined ||= {};
1763
1764 # prepopulate the known defined map with our own collapse value positions
1765 # the rationale is that if an Artist needs column 0 to be uniquely
1766 # identified, and related CDs need columns 0 and 1, by the time we get to
1767 # CDs we already know that column 0 is defined (otherwise there would be
1768 # no related CDs as there is no Artist in the 1st place). So we use this
1769 # index to cut on repetitive defined() checks.
1770 $known_defined->{$_}++ for ( values %{$collapse_on->{-collapse_on} || {}} );
1771
1772 my $my_cols = {};
1773 my $rel_cols;
1774 for (keys %$as) {
1775 if ($_ =~ /^ ([^\.]+) \. (.+) /x) {
1776 $rel_cols->{$1}{$2} = $as->{$_};
1777 }
1778 else {
1779 $my_cols->{$_} = $as->{$_};
1780 }
9f6555d3 1781 }
1782
3904d3c3 1783 my @relperl;
1784 for my $rel (sort keys %$rel_cols) {
1785 my $rel_node = $self->__visit_as($rel_cols->{$rel}, $collapse_on->{$rel}, {%$known_defined} );
1786
1787 my @null_checks;
1788 if ($collapse_on->{$rel}{-collapse_on}) {
1789 @null_checks = map
1790 { "(! defined '__VALPOS__${_}__')" }
1791 ( grep
1792 { ! $known_defined->{$_} }
1793 ( sort
1794 { $a <=> $b }
1795 values %{$collapse_on->{$rel}{-collapse_on}}
1796 )
1797 )
1798 ;
1799 }
9f6555d3 1800
3904d3c3 1801 if (@null_checks) {
1802 push @relperl, sprintf ( '(%s) ? () : ( %s => %s )',
1803 join (' || ', @null_checks ),
1804 $rel,
1805 $rel_node,
1806 );
1807 }
1808 else {
1809 push @relperl, "$rel => $rel_node";
1810 }
1811 }
1812 my $rels = @relperl
1813 ? sprintf ('{ %s }', join (',', @relperl))
1814 : 'undef'
1815 ;
9f6555d3 1816
3904d3c3 1817 my $me = {
1818 map { $_ => "__VALPOS__$my_cols->{$_}__" } (keys %$my_cols)
1819 };
1820
01272eb8 1821 my $clps = undef; # funny thing, but this prevents a memory leak, I guess it's Data::Dumper#s fault (mo)
1822 $clps = [
3904d3c3 1823 map { "__VALPOS__${_}__" } ( sort { $a <=> $b } (values %{$collapse_on->{-collapse_on}}) )
1824 ] if $collapse_on->{-collapse_on};
1825
1826 # we actually will be producing functional perl code here,
1827 # thus no second-guessing of what these globals might have
1828 # been set to. DO NOT CHANGE!
1829 $visit_as_dumper ||= do {
1830 require Data::Dumper;
1831 Data::Dumper->new([])
1832 ->Purity (1)
1833 ->Pad ('')
1834 ->Useqq (0)
1835 ->Terse (1)
1836 ->Quotekeys (1)
1837 ->Deepcopy (1)
1838 ->Deparse (0)
1839 ->Maxdepth (0)
1840 ->Indent (0)
1841 };
1842 for ($me, $clps) {
1843 $_ = $visit_as_dumper->Values ([$_])->Dump;
1844 }
1845
1846 unless ($collapse_on->{-collapse_on}) { # we are not collapsing, insert a definedness check on 'me'
1847 $me = sprintf ( '(%s) ? %s : {}',
1848 join (' || ', map { "( defined '__VALPOS__${_}__')" } (sort { $a <=> $b } values %$my_cols) ),
1849 $me,
1850 );
9f6555d3 1851 }
1852
3904d3c3 1853 my @rv_list = ($me, $rels, $clps);
1854 pop @rv_list while ($rv_list[-1] eq 'undef'); # strip trailing undefs
1855
1856 # change the quoted placeholders to unquoted alias-references
1857 $_ =~ s/ \' __VALPOS__(\d+)__ \' /sprintf ('$_[0][%d]', $1)/gex
1858 for grep { defined $_ } @rv_list;
3904d3c3 1859 return sprintf '[%s]', join (',', @rv_list);
1860 }
9f6555d3 1861}
1862
87c4e602 1863=head2 related_source
1864
27f01d1f 1865=over 4
1866
ebc77b53 1867=item Arguments: $relname
27f01d1f 1868
391ccf38 1869=item Return value: $source
1870
27f01d1f 1871=back
87772e46 1872
2053ab2a 1873Returns the result source object for the given relationship.
87772e46 1874
1875=cut
1876
1877sub related_source {
1878 my ($self, $rel) = @_;
aea52c85 1879 if( !$self->has_relationship( $rel ) ) {
d4d8e97b 1880 $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
aea52c85 1881 }
87772e46 1882 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1883}
1884
77254782 1885=head2 related_class
1886
27f01d1f 1887=over 4
1888
ebc77b53 1889=item Arguments: $relname
27f01d1f 1890
391ccf38 1891=item Return value: $classname
1892
27f01d1f 1893=back
77254782 1894
2053ab2a 1895Returns the class name for objects in the given relationship.
77254782 1896
1897=cut
1898
1899sub related_class {
1900 my ($self, $rel) = @_;
1901 if( !$self->has_relationship( $rel ) ) {
1902 $self->throw_exception("No such relationship '$rel'");
1903 }
1904 return $self->schema->class($self->relationship_info($rel)->{source});
1905}
1906
aec3eff1 1907=head2 handle
1908
1909Obtain a new handle to this source. Returns an instance of a
1910L<DBIx::Class::ResultSourceHandle>.
1911
1912=cut
1913
1914sub handle {
24c349e8 1915 return DBIx::Class::ResultSourceHandle->new({
aec3eff1 1916 schema => $_[0]->schema,
3441fd57 1917 source_moniker => $_[0]->source_name
aec3eff1 1918 });
1919}
1920
701da8c4 1921=head2 throw_exception
1922
2053ab2a 1923See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1924
1925=cut
1926
1927sub throw_exception {
1928 my $self = shift;
1a58752c 1929
75d07914 1930 if (defined $self->schema) {
701da8c4 1931 $self->schema->throw_exception(@_);
1a58752c 1932 }
1933 else {
1934 DBIx::Class::Exception->throw(@_);
701da8c4 1935 }
1936}
1937
843f6bc1 1938=head2 source_info
d2f3e87b 1939
843f6bc1 1940Stores a hashref of per-source metadata. No specific key names
1941have yet been standardized, the examples below are purely hypothetical
1942and don't actually accomplish anything on their own:
391ccf38 1943
843f6bc1 1944 __PACKAGE__->source_info({
1945 "_tablespace" => 'fast_disk_array_3',
1946 "_engine" => 'InnoDB',
1947 });
391ccf38 1948
843f6bc1 1949=head2 new
391ccf38 1950
843f6bc1 1951 $class->new();
391ccf38 1952
843f6bc1 1953 $class->new({attribute_name => value});
d2f3e87b 1954
843f6bc1 1955Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1956
843f6bc1 1957=head2 column_info_from_storage
1958
1959=over
1960
1961=item Arguments: 1/0 (default: 0)
1962
1963=item Return value: 1/0
1964
1965=back
1966
880c075b 1967 __PACKAGE__->column_info_from_storage(1);
1968
843f6bc1 1969Enables the on-demand automatic loading of the above column
c1300297 1970metadata from storage as necessary. This is *deprecated*, and
843f6bc1 1971should not be used. It will be removed before 1.0.
1972
f89bb832 1973
9c992ba1 1974=head1 AUTHORS
1975
1976Matt S. Trout <mst@shadowcatsystems.co.uk>
1977
1978=head1 LICENSE
1979
1980You may distribute this code under the same terms as Perl itself.
1981
1982=cut
1983
b25e9fa0 19841;