File Coverage

blib/lib/SQL/Translator/Schema/Table.pm
Criterion Covered Total %
statement 281 344 81.6
branch 112 162 69.1
condition 24 31 77.4
subroutine 37 38 97.3
pod 22 22 100.0
total 476 597 79.7


line stmt bran cond sub pod time code
1             package SQL::Translator::Schema::Table;
2              
3             =pod
4              
5             =head1 NAME
6              
7             SQL::Translator::Schema::Table - SQL::Translator table object
8              
9             =head1 SYNOPSIS
10              
11             use SQL::Translator::Schema::Table;
12             my $table = SQL::Translator::Schema::Table->new( name => 'foo' );
13              
14             =head1 DESCRIPTION
15              
16             C is the table object.
17              
18             =head1 METHODS
19              
20             =cut
21              
22 76     76   2766 use Moo;
  76         17858  
  76         703  
23 76     76   43655 use SQL::Translator::Utils qw(parse_list_arg ex2err throw carp_ro);
  76         213  
  76         9075  
24 76     76   1450 use SQL::Translator::Types qw(schema_obj);
  76         233  
  76         4479  
25 76     76   1875 use SQL::Translator::Role::ListAttr;
  76         345  
  76         997  
26 76     76   5431 use SQL::Translator::Schema::Constants;
  76         324  
  76         7374  
27 76     76   48840 use SQL::Translator::Schema::Constraint;
  76         372  
  76         3482  
28 76     76   53052 use SQL::Translator::Schema::Field;
  76         437  
  76         7232  
29 76     76   53054 use SQL::Translator::Schema::Index;
  76         424  
  76         3919  
30              
31 76     76   48526 use Carp::Clan '^SQL::Translator';
  76         263779  
  76         623  
32 76     76   9908 use List::Util 'max';
  76         219  
  76         7393  
33 76     76   537 use Sub::Quote qw(quote_sub);
  76         189  
  76         10070  
34              
35             extends 'SQL::Translator::Schema::Object';
36              
37             our $VERSION = '1.66';
38              
39             # Stringify to our name, being careful not to pass any args through so we don't
40             # accidentally set it to undef. We also have to tweak bool so the object is
41             # still true when it doesn't have a name (which shouldn't happen!).
42             use overload
43 477     477   62421 '""' => sub { shift->name },
44 7089 50   7089   356796 'bool' => sub { $_[0]->name || $_[0] },
45 76         1115 fallback => 1,
46 76     76   550 ;
  76         161  
47              
48             =pod
49              
50             =head2 new
51              
52             Object constructor.
53              
54             my $table = SQL::Translator::Schema::Table->new(
55             schema => $schema,
56             name => 'foo',
57             );
58              
59             =head2 add_constraint
60              
61             Add a constraint to the table. Returns the newly created
62             C object.
63              
64             my $c1 = $table->add_constraint(
65             name => 'pk',
66             type => PRIMARY_KEY,
67             fields => [ 'foo_id' ],
68             );
69              
70             my $c2 = SQL::Translator::Schema::Constraint->new( name => 'uniq' );
71             $c2 = $table->add_constraint( $constraint );
72              
73             =cut
74              
75             has _constraints => (
76             is => 'ro',
77             init_arg => undef,
78             default => quote_sub(q{ +[] }),
79             predicate => 1,
80             lazy => 1,
81             );
82              
83             sub add_constraint {
84 614     614 1 8091 my $self = shift;
85 614         1392 my $constraint_class = 'SQL::Translator::Schema::Constraint';
86 614         1198 my $constraint;
87              
88 614 100       4491 if (UNIVERSAL::isa($_[0], $constraint_class)) {
89 3         5 $constraint = shift;
90 3         75 $constraint->table($self);
91             } else {
92 611         5117 my %args = @_;
93 611         1606 $args{'table'} = $self;
94 611 50       17873 $constraint = $constraint_class->new(\%args)
95             or return $self->error($constraint_class->error);
96             }
97              
98             #
99             # If we're trying to add a PK when one is already defined,
100             # then just add the fields to the existing definition.
101             #
102 614         20763 my $ok = 1;
103 614         2551 my $pk = $self->primary_key;
104 614 100 100     22719 if ($pk && $constraint->type eq PRIMARY_KEY) {
    100          
105 79         2029 $self->primary_key($constraint->fields);
106 79 50       2110 $pk->name($constraint->name) if $constraint->name;
107 79         2346 my %extra = $constraint->extra;
108 79 100       757 $pk->extra(%extra) if keys %extra;
109 79         753 $constraint = $pk;
110 79         249 $ok = 0;
111             } elsif ($constraint->type eq PRIMARY_KEY) {
112 237         6817 for my $fname ($constraint->fields) {
113 270 50       2148 if (my $f = $self->get_field($fname)) {
114 270         12125 $f->is_primary_key(1);
115             }
116             }
117             }
118             #
119             # See if another constraint of the same type
120             # covers the same fields. -- This doesn't work! ky
121             #
122             # elsif ( $constraint->type ne CHECK_C ) {
123             # my @field_names = $constraint->fields;
124             # for my $c (
125             # grep { $_->type eq $constraint->type }
126             # $self->get_constraints
127             # ) {
128             # my %fields = map { $_, 1 } $c->fields;
129             # for my $field_name ( @field_names ) {
130             # if ( $fields{ $field_name } ) {
131             # $constraint = $c;
132             # $ok = 0;
133             # last;
134             # }
135             # }
136             # last unless $ok;
137             # }
138             # }
139              
140 614 100       17556 if ($ok) {
141 535         993 push @{ $self->_constraints }, $constraint;
  535         12051  
142             }
143              
144 614         8962 return $constraint;
145             }
146              
147             =head2 drop_constraint
148              
149             Remove a constraint from the table. Returns the constraint object if the index
150             was found and removed, an error otherwise. The single parameter can be either
151             an index name or an C object.
152              
153             $table->drop_constraint('myconstraint');
154              
155             =cut
156              
157             sub drop_constraint {
158 3     3 1 7 my $self = shift;
159 3         6 my $constraint_class = 'SQL::Translator::Schema::Constraint';
160 3         6 my $constraint_name;
161              
162 3 100       16 if (UNIVERSAL::isa($_[0], $constraint_class)) {
163 1         16 $constraint_name = shift->name;
164             } else {
165 2         5 $constraint_name = shift;
166             }
167              
168 3 100 66     12 if (!($self->_has_constraints && grep { $_->name eq $constraint_name } @{ $self->_constraints })) {
  8         107  
  3         51  
169 1         17 return $self->error(qq[Can't drop constraint: "$constraint_name" doesn't exist]);
170             }
171              
172 2         3 my @cs = @{ $self->_constraints };
  2         21  
173             my ($constraint_id)
174 2         14 = grep { $cs[$_]->name eq $constraint_name } (0 .. $#cs);
  6         68  
175 2         5 my $constraint = splice(@{ $self->_constraints }, $constraint_id, 1);
  2         41  
176              
177 2         21 return $constraint;
178             }
179              
180             =head2 add_index
181              
182             Add an index to the table. Returns the newly created
183             C object.
184              
185             my $i1 = $table->add_index(
186             name => 'name',
187             fields => [ 'name' ],
188             type => 'normal',
189             );
190              
191             my $i2 = SQL::Translator::Schema::Index->new( name => 'id' );
192             $i2 = $table->add_index( $index );
193              
194             =cut
195              
196             has _indices => (
197             is => 'ro',
198             init_arg => undef,
199             default => quote_sub(q{ [] }),
200             predicate => 1,
201             lazy => 1,
202             );
203              
204             sub add_index {
205 157     157 1 16805 my $self = shift;
206 157         428 my $index_class = 'SQL::Translator::Schema::Index';
207 157         311 my $index;
208              
209 157 100       1762 if (UNIVERSAL::isa($_[0], $index_class)) {
210 3         8 $index = shift;
211 3         119 $index->table($self);
212             } else {
213 154         933 my %args = @_;
214 154         467 $args{'table'} = $self;
215 154 50       5008 $index = $index_class->new(\%args)
216             or return $self->error($index_class->error);
217             }
218 157         5758 foreach my $ex_index ($self->get_indices) {
219 89 50       2666 return if ($ex_index->equals($index));
220             }
221 157         1002 push @{ $self->_indices }, $index;
  157         5468  
222 157         2575 return $index;
223             }
224              
225             =head2 drop_index
226              
227             Remove an index from the table. Returns the index object if the index was
228             found and removed, an error otherwise. The single parameter can be either
229             an index name of an C object.
230              
231             $table->drop_index('myindex');
232              
233             =cut
234              
235             sub drop_index {
236 3     3 1 3529 my $self = shift;
237 3         6 my $index_class = 'SQL::Translator::Schema::Index';
238 3         5 my $index_name;
239              
240 3 100       14 if (UNIVERSAL::isa($_[0], $index_class)) {
241 1         12 $index_name = shift->name;
242             } else {
243 2         4 $index_name = shift;
244             }
245              
246 3 100 66     13 if (!($self->_has_indices && grep { $_->name eq $index_name } @{ $self->_indices })) {
  8         104  
  3         41  
247 1         25 return $self->error(qq[Can't drop index: "$index_name" doesn't exist]);
248             }
249              
250 2         11 my @is = @{ $self->_indices };
  2         22  
251 2         13 my ($index_id) = grep { $is[$_]->name eq $index_name } (0 .. $#is);
  6         65  
252 2         9 my $index = splice(@{ $self->_indices }, $index_id, 1);
  2         20  
253              
254 2         13 return $index;
255             }
256              
257             =head2 add_field
258              
259             Add an field to the table. Returns the newly created
260             C object. The "name" parameter is
261             required. If you try to create a field with the same name as an
262             existing field, you will get an error and the field will not be created.
263              
264             my $f1 = $table->add_field(
265             name => 'foo_id',
266             data_type => 'integer',
267             size => 11,
268             );
269              
270             my $f2 = SQL::Translator::Schema::Field->new(
271             name => 'name',
272             table => $table,
273             );
274             $f2 = $table->add_field( $field2 ) or die $table->error;
275              
276             =cut
277              
278             has _fields => (
279             is => 'ro',
280             init_arg => undef,
281             default => quote_sub(q{ +{} }),
282             predicate => 1,
283             lazy => 1
284             );
285              
286             sub add_field {
287 1557     1557 1 9942 my $self = shift;
288 1557         2903 my $field_class = 'SQL::Translator::Schema::Field';
289 1557         2604 my $field;
290              
291 1557 100       10938 if (UNIVERSAL::isa($_[0], $field_class)) {
292 7         19 $field = shift;
293 7         234 $field->table($self);
294             } else {
295 1550         21446 my %args = @_;
296 1550         7118 $args{'table'} = $self;
297 1550 100       47215 $field = $field_class->new(\%args)
298             or return $self->error($field_class->error);
299             }
300              
301 1556         53095 my $existing_order = { map { $_->order => $_->name } $self->get_fields };
  5662         224445  
302              
303             # supplied order, possible unordered assembly
304 1556 100       69802 if ($field->order) {
305 203 100       4097 if ($existing_order->{ $field->order }) {
306             croak sprintf
307             "Requested order '%d' for column '%s' conflicts with already existing column '%s'",
308             $field->order,
309             $field->name,
310 1         29 $existing_order->{ $field->order },
311             ;
312             }
313             } else {
314 1353   100     14062 my $last_field_no = max(keys %$existing_order) || 0;
315 1353 100       5411 if ($last_field_no != scalar keys %$existing_order) {
316 1         31 croak sprintf
317             "Table '%s' field order incomplete - unable to auto-determine order for newly added field",
318             $self->name,
319             ;
320             }
321              
322 1352         31304 $field->order($last_field_no + 1);
323             }
324              
325             # We know we have a name as the Field->new above errors if none given.
326 1554         36532 my $field_name = $field->name;
327              
328 1554 100       38528 if ($self->get_field($field_name)) {
329 2         86 return $self->error(qq[Can't use field name "$field_name": field exists]);
330             } else {
331 1552         30933 $self->_fields->{$field_name} = $field;
332             }
333              
334 1552         25364 return $field;
335             }
336              
337             =head2 drop_field
338              
339             Remove a field from the table. Returns the field object if the field was
340             found and removed, an error otherwise. The single parameter can be either
341             a field name or an C object.
342              
343             $table->drop_field('myfield');
344              
345             =cut
346              
347             sub drop_field {
348 3     3 1 47 my $self = shift;
349 3         6 my $field_class = 'SQL::Translator::Schema::Field';
350 3         4 my $field_name;
351              
352 3 100       16 if (UNIVERSAL::isa($_[0], $field_class)) {
353 1         14 $field_name = shift->name;
354             } else {
355 2         3 $field_name = shift;
356             }
357 3         22 my %args = @_;
358 3         6 my $cascade = $args{'cascade'};
359              
360 3 100 66     85 if (!($self->_has_fields && exists $self->_fields->{$field_name})) {
361 1         23 return $self->error(qq[Can't drop field: "$field_name" doesn't exists]);
362             }
363              
364 2         53 my $field = delete $self->_fields->{$field_name};
365              
366 2 50       17 if ($cascade) {
367              
368             # Remove this field from all indices using it
369 2         8 foreach my $i ($self->get_indices()) {
370 0         0 my @fs = $i->fields();
371 0         0 @fs = grep { $_ ne $field->name } @fs;
  0         0  
372 0         0 $i->fields(@fs);
373             }
374              
375             # Remove this field from all constraints using it
376 2         6 foreach my $c ($self->get_constraints()) {
377 0         0 my @cs = $c->fields();
378 0         0 @cs = grep { $_ ne $field->name } @cs;
  0         0  
379 0         0 $c->fields(@cs);
380             }
381             }
382              
383 2         7 return $field;
384             }
385              
386             =head2 comments
387              
388             Get or set the comments on a table. May be called several times to
389             set and it will accumulate the comments. Called in an array context,
390             returns each comment individually; called in a scalar context, returns
391             all the comments joined on newlines.
392              
393             $table->comments('foo');
394             $table->comments('bar');
395             print join( ', ', $table->comments ); # prints "foo, bar"
396              
397             =cut
398              
399             has comments => (
400             is => 'rw',
401             coerce => quote_sub(q{ ref($_[0]) eq 'ARRAY' ? $_[0] : [$_[0]] }),
402             default => quote_sub(q{ [] }),
403             );
404              
405             around comments => sub {
406             my $orig = shift;
407             my $self = shift;
408             my @comments = ref $_[0] ? @{ $_[0] } : @_;
409              
410             for my $arg (@comments) {
411             $arg = $arg->[0] if ref $arg;
412             push @{ $self->$orig }, $arg if defined $arg && $arg;
413             }
414              
415             @comments = @{ $self->$orig };
416             return
417             wantarray ? @comments
418             : @comments ? join("\n", @comments)
419             : undef;
420             };
421              
422             =head2 get_constraints
423              
424             Returns all the constraint objects as an array or array reference.
425              
426             my @constraints = $table->get_constraints;
427              
428             =cut
429              
430             sub get_constraints {
431 2778     2778 1 25163 my $self = shift;
432              
433 2778 100       10794 if ($self->_has_constraints) {
434 2105 100       5336 return wantarray ? @{ $self->_constraints } : $self->_constraints;
  2103         51618  
435             } else {
436 673         32838 $self->error('No constraints');
437 673         2161 return;
438             }
439             }
440              
441             =head2 get_indices
442              
443             Returns all the index objects as an array or array reference.
444              
445             my @indices = $table->get_indices;
446              
447             =cut
448              
449             sub get_indices {
450 628     628 1 12431 my $self = shift;
451              
452 628 100       2841 if ($self->_has_indices) {
453             return wantarray
454 228 100       779 ? @{ $self->_indices }
  227         6135  
455             : $self->_indices;
456             } else {
457 400         11113 $self->error('No indices');
458 400         1572 return;
459             }
460             }
461              
462             =head2 get_field
463              
464             Returns a field by the name provided.
465              
466             my $field = $table->get_field('foo');
467              
468             =cut
469              
470             sub get_field {
471 5520     5520 1 10774 my $self = shift;
472 5520 50       20020 my $field_name = shift or return $self->error('No field name');
473 5520         33930 my $case_insensitive = shift;
474 5520 100       30100 return $self->error(qq[Field "$field_name" does not exist])
475             unless $self->_has_fields;
476 5152 100       13138 if ($case_insensitive) {
477 1         3 $field_name = uc($field_name);
478 1         3 foreach my $field (keys %{ $self->_fields }) {
  1         26  
479 2 100       28 return $self->_fields->{$field} if $field_name eq uc($field);
480             }
481 0         0 return $self->error(qq[Field "$field_name" does not exist]);
482             }
483             return $self->error(qq[Field "$field_name" does not exist])
484 5151 100       111412 unless exists $self->_fields->{$field_name};
485 3871         117870 return $self->_fields->{$field_name};
486             }
487              
488             =head2 get_fields
489              
490             Returns all the field objects as an array or array reference.
491              
492             my @fields = $table->get_fields;
493              
494             =cut
495              
496             sub get_fields {
497 2466     2466 1 35477 my $self = shift;
498 9299         17417 my @fields = map { $_->[1] }
499 16268         29048 sort { $a->[0] <=> $b->[0] }
500 2466 100       5308 map { [ $_->order, $_ ] } values %{ $self->_has_fields ? $self->_fields : {} };
  9299         229366  
  2466         59614  
501              
502 2466 100       9785 if (@fields) {
503 2115 100       10246 return wantarray ? @fields : \@fields;
504             } else {
505 351         13361 $self->error('No fields');
506 351         1244 return;
507             }
508             }
509              
510             =head2 is_valid
511              
512             Determine whether the view is valid or not.
513              
514             my $ok = $view->is_valid;
515              
516             =cut
517              
518             sub is_valid {
519 59     59 1 1424 my $self = shift;
520 59 50       1293 return $self->error('No name') unless $self->name;
521 59 100       1371 return $self->error('No fields') unless $self->get_fields;
522              
523 57         213 for my $object ($self->get_fields, $self->get_indices, $self->get_constraints) {
524 327 100       1147 return $object->error unless $object->is_valid;
525             }
526              
527 54         260 return 1;
528             }
529              
530             =head2 is_trivial_link
531              
532             True if table has no data (non-key) fields and only uses single key joins.
533              
534             =cut
535              
536             has is_trivial_link => (is => 'lazy', init_arg => undef);
537              
538             around is_trivial_link => carp_ro('is_trivial_link');
539              
540             sub _build_is_trivial_link {
541 3     3   23 my $self = shift;
542 3 100       40 return 0 if $self->is_data;
543              
544 2         15 my %fk = ();
545              
546 2         5 foreach my $field ($self->get_fields) {
547 5 100       105 next unless $field->is_foreign_key;
548 4         62 $fk{ $field->foreign_key_reference->reference_table }++;
549             }
550              
551 2         46 foreach my $referenced (keys %fk) {
552 3 100       10 if ($fk{$referenced} > 1) {
553 1         12 return 0;
554             }
555             }
556              
557 1         7 return 1;
558             }
559              
560             =head2 is_data
561              
562             Returns true if the table has some non-key fields.
563              
564             =cut
565              
566             has is_data => (is => 'lazy', init_arg => undef);
567              
568             around is_data => carp_ro('is_data');
569              
570             sub _build_is_data {
571 4     4   36 my $self = shift;
572              
573 4         11 foreach my $field ($self->get_fields) {
574 9 100 100     166 if (!$field->is_primary_key and !$field->is_foreign_key) {
575 2         36 return 1;
576             }
577             }
578              
579 2         62 return 0;
580             }
581              
582             =head2 can_link
583              
584             Determine whether the table can link two arg tables via many-to-many.
585              
586             my $ok = $table->can_link($table1,$table2);
587              
588             =cut
589              
590             has _can_link => (is => 'ro', init_arg => undef, default => quote_sub(q{ +{} }));
591              
592             sub can_link {
593 3     3 1 714 my ($self, $table1, $table2) = @_;
594              
595             return $self->_can_link->{ $table1->name }{ $table2->name }
596 3 50       76 if defined $self->_can_link->{ $table1->name }{ $table2->name };
597              
598 3 50       111 if ($self->is_data == 1) {
599 0         0 $self->_can_link->{ $table1->name }{ $table2->name } = [0];
600 0         0 $self->_can_link->{ $table2->name }{ $table1->name } = [0];
601 0         0 return $self->_can_link->{ $table1->name }{ $table2->name };
602             }
603              
604 3         28 my %fk = ();
605              
606 3         8 foreach my $field ($self->get_fields) {
607 7 100       124 if ($field->is_foreign_key) {
608 6         31 push @{ $fk{ $field->foreign_key_reference->reference_table } }, $field->foreign_key_reference;
  6         83  
609             }
610             }
611              
612 3 100 66     61 if (!defined($fk{ $table1->name }) or !defined($fk{ $table2->name })) {
613 1         28 $self->_can_link->{ $table1->name }{ $table2->name } = [0];
614 1         26 $self->_can_link->{ $table2->name }{ $table1->name } = [0];
615 1         34 return $self->_can_link->{ $table1->name }{ $table2->name };
616             }
617              
618             # trivial traversal, only one way to link the two tables
619 2 100 100     30 if ( scalar(@{ $fk{ $table1->name } } == 1)
  2 50 50     43  
    50 50        
    50 50        
620 1         28 and scalar(@{ $fk{ $table2->name } } == 1)) {
621 1         58 $self->_can_link->{ $table1->name }{ $table2->name } = [ 'one2one', $fk{ $table1->name }, $fk{ $table2->name } ];
622 1         23 $self->_can_link->{ $table1->name }{ $table2->name } = [ 'one2one', $fk{ $table2->name }, $fk{ $table1->name } ];
623              
624             # non-trivial traversal. one way to link table2,
625             # many ways to link table1
626 1         27 } elsif (scalar(@{ $fk{ $table1->name } } > 1)
627 1         27 and scalar(@{ $fk{ $table2->name } } == 1)) {
628 0         0 $self->_can_link->{ $table1->name }{ $table2->name } = [ 'many2one', $fk{ $table1->name }, $fk{ $table2->name } ];
629 0         0 $self->_can_link->{ $table2->name }{ $table1->name } = [ 'one2many', $fk{ $table2->name }, $fk{ $table1->name } ];
630              
631             # non-trivial traversal. one way to link table1,
632             # many ways to link table2
633 1         24 } elsif (scalar(@{ $fk{ $table1->name } } == 1)
634 0         0 and scalar(@{ $fk{ $table2->name } } > 1)) {
635 0         0 $self->_can_link->{ $table1->name }{ $table2->name } = [ 'one2many', $fk{ $table1->name }, $fk{ $table2->name } ];
636 0         0 $self->_can_link->{ $table2->name }{ $table1->name } = [ 'many2one', $fk{ $table2->name }, $fk{ $table1->name } ];
637              
638             # non-trivial traversal. many ways to link table1 and table2
639 1         28 } elsif (scalar(@{ $fk{ $table1->name } } > 1)
640 1         26 and scalar(@{ $fk{ $table2->name } } > 1)) {
641 1         26 $self->_can_link->{ $table1->name }{ $table2->name } = [ 'many2many', $fk{ $table1->name }, $fk{ $table2->name } ];
642 1         25 $self->_can_link->{ $table2->name }{ $table1->name } = [ 'many2many', $fk{ $table2->name }, $fk{ $table1->name } ];
643              
644             # one of the tables didn't export a key
645             # to this table, no linking possible
646             } else {
647 0         0 $self->_can_link->{ $table1->name }{ $table2->name } = [0];
648 0         0 $self->_can_link->{ $table2->name }{ $table1->name } = [0];
649             }
650              
651 2         48 return $self->_can_link->{ $table1->name }{ $table2->name };
652             }
653              
654             =head2 name
655              
656             Get or set the table's name.
657              
658             Errors ("No table name") if you try to set a blank name.
659              
660             If provided an argument, checks the schema object for a table of
661             that name and disallows the change if one exists (setting the error to
662             "Can't use table name "%s": table exists").
663              
664             my $table_name = $table->name('foo');
665              
666             =cut
667              
668             has name => (
669             is => 'rw',
670             isa => sub { throw("No table name") unless $_[0] },
671             );
672              
673             around name => sub {
674             my $orig = shift;
675             my $self = shift;
676              
677             if (my ($arg) = @_) {
678             if (my $schema = $self->schema) {
679             return $self->error(qq[Can't use table name "$arg": table exists])
680             if $schema->get_table($arg);
681             }
682             }
683              
684             return ex2err($orig, $self, @_);
685             };
686              
687             =head2 schema
688              
689             Get or set the table's schema object.
690              
691             my $schema = $table->schema;
692              
693             =cut
694              
695             has schema => (is => 'rw', isa => schema_obj('Schema'), weak_ref => 1);
696              
697             around schema => \&ex2err;
698              
699             sub primary_key {
700              
701             =pod
702              
703             =head2 primary_key
704              
705             Gets or sets the table's primary key(s). Takes one or more field
706             names (as a string, list or array[ref]) as an argument. If the field
707             names are present, it will create a new PK if none exists, or it will
708             add to the fields of an existing PK (and will unique the field names).
709             Returns the C object representing
710             the primary key.
711              
712             These are equivalent:
713              
714             $table->primary_key('id');
715             $table->primary_key(['name']);
716             $table->primary_key('id','name']);
717             $table->primary_key(['id','name']);
718             $table->primary_key('id,name');
719             $table->primary_key(qw[ id name ]);
720              
721             my $pk = $table->primary_key;
722              
723             =cut
724              
725 1675     1675 1 7636 my $self = shift;
726 1675         5379 my $fields = parse_list_arg(@_);
727              
728 1675         4845 my $constraint;
729 1675 100       5183 if (@$fields) {
730 213         628 for my $f (@$fields) {
731 222 100       961 return $self->error(qq[Invalid field "$f"])
732             unless $self->get_field($f);
733             }
734              
735 207         4747 my $has_pk;
736 207         807 for my $c ($self->get_constraints) {
737 98 100       4159 if ($c->type eq PRIMARY_KEY) {
738 88         1980 $has_pk = 1;
739 88         192 $c->fields(@{ $c->fields }, @$fields);
  88         364  
740 88         313 $constraint = $c;
741             }
742             }
743              
744 207 100       940 unless ($has_pk) {
745 119 50       613 $constraint = $self->add_constraint(
746             type => PRIMARY_KEY,
747             fields => $fields,
748             ) or return;
749             }
750             }
751              
752 1669 100       4207 if ($constraint) {
753 207         904 return $constraint;
754             } else {
755 1462         6114 for my $c ($self->get_constraints) {
756 1226 100       42405 return $c if $c->type eq PRIMARY_KEY;
757             }
758             }
759              
760 476         3568 return;
761             }
762              
763             =head2 options
764              
765             Get or append to the table's options (e.g., table types for MySQL).
766             Returns an array or array reference.
767              
768             my @options = $table->options;
769              
770             =cut
771              
772             with ListAttr options => (append => 1);
773              
774             =head2 order
775              
776             Get or set the table's order.
777              
778             my $order = $table->order(3);
779              
780             =cut
781              
782             has order => (is => 'rw', default => quote_sub(q{ 0 }));
783              
784             around order => sub {
785             my ($orig, $self, $arg) = @_;
786              
787             if (defined $arg && $arg =~ /^\d+$/) {
788             return $self->$orig($arg);
789             }
790              
791             return $self->$orig;
792             };
793              
794             =head2 field_names
795              
796             Read-only method to return a list or array ref of the field names. Returns undef
797             or an empty list if the table has no fields set. Useful if you want to
798             avoid the overload magic of the Field objects returned by the get_fields method.
799              
800             my @names = $constraint->field_names;
801              
802             =cut
803              
804             sub field_names {
805 3     3 1 741 my $self = shift;
806 3         15 my @fields = map { $_->name } $self->get_fields;
  13         362  
807              
808 3 50       45 if (@fields) {
809 3 50       43 return wantarray ? @fields : \@fields;
810             } else {
811 0         0 $self->error('No fields');
812 0         0 return;
813             }
814             }
815              
816             sub equals {
817              
818             =pod
819              
820             =head2 equals
821              
822             Determines if this table is the same as another
823              
824             my $isIdentical = $table1->equals( $table2 );
825              
826             =cut
827              
828 0     0 1 0 my $self = shift;
829 0         0 my $other = shift;
830 0         0 my $case_insensitive = shift;
831              
832 0 0       0 return 0 unless $self->SUPER::equals($other);
833 0 0       0 return 0
    0          
834             unless $case_insensitive
835             ? uc($self->name) eq uc($other->name)
836             : $self->name eq $other->name;
837 0 0       0 return 0
838             unless $self->_compare_objects(scalar $self->options, scalar $other->options);
839 0 0       0 return 0
840             unless $self->_compare_objects(scalar $self->extra, scalar $other->extra);
841              
842             # Fields
843             # Go through our fields
844 0         0 my %checkedFields;
845 0         0 foreach my $field ($self->get_fields) {
846 0         0 my $otherField = $other->get_field($field->name, $case_insensitive);
847 0 0       0 return 0 unless $field->equals($otherField, $case_insensitive);
848 0         0 $checkedFields{ $field->name } = 1;
849             }
850              
851             # Go through the other table's fields
852 0         0 foreach my $otherField ($other->get_fields) {
853 0 0       0 next if $checkedFields{ $otherField->name };
854 0         0 return 0;
855             }
856              
857             # Constraints
858             # Go through our constraints
859 0         0 my %checkedConstraints;
860             CONSTRAINT:
861 0         0 foreach my $constraint ($self->get_constraints) {
862 0         0 foreach my $otherConstraint ($other->get_constraints) {
863 0 0       0 if ($constraint->equals($otherConstraint, $case_insensitive)) {
864 0         0 $checkedConstraints{$otherConstraint} = 1;
865 0         0 next CONSTRAINT;
866             }
867             }
868 0         0 return 0;
869             }
870              
871             # Go through the other table's constraints
872             CONSTRAINT2:
873 0         0 foreach my $otherConstraint ($other->get_constraints) {
874 0 0       0 next if $checkedFields{$otherConstraint};
875 0         0 foreach my $constraint ($self->get_constraints) {
876 0 0       0 if ($otherConstraint->equals($constraint, $case_insensitive)) {
877 0         0 next CONSTRAINT2;
878             }
879             }
880 0         0 return 0;
881             }
882              
883             # Indices
884             # Go through our indices
885 0         0 my %checkedIndices;
886             INDEX:
887 0         0 foreach my $index ($self->get_indices) {
888 0         0 foreach my $otherIndex ($other->get_indices) {
889 0 0       0 if ($index->equals($otherIndex, $case_insensitive)) {
890 0         0 $checkedIndices{$otherIndex} = 1;
891 0         0 next INDEX;
892             }
893             }
894 0         0 return 0;
895             }
896              
897             # Go through the other table's indices
898             INDEX2:
899 0         0 foreach my $otherIndex ($other->get_indices) {
900 0 0       0 next if $checkedIndices{$otherIndex};
901 0         0 foreach my $index ($self->get_indices) {
902 0 0       0 if ($otherIndex->equals($index, $case_insensitive)) {
903 0         0 next INDEX2;
904             }
905             }
906 0         0 return 0;
907             }
908              
909 0         0 return 1;
910             }
911              
912             =head1 LOOKUP METHODS
913              
914             The following are a set of shortcut methods for getting commonly used lists of
915             fields and constraints. They all return lists or array refs of Field or
916             Constraint objects.
917              
918             =over 4
919              
920             =item pkey_fields
921              
922             The primary key fields.
923              
924             =item fkey_fields
925              
926             All foreign key fields.
927              
928             =item nonpkey_fields
929              
930             All the fields except the primary key.
931              
932             =item data_fields
933              
934             All non key fields.
935              
936             =item unique_fields
937              
938             All fields with unique constraints.
939              
940             =item unique_constraints
941              
942             All this tables unique constraints.
943              
944             =item fkey_constraints
945              
946             All this tables foreign key constraints. (See primary_key method to get the
947             primary key constraint)
948              
949             =back
950              
951             =cut
952              
953             sub pkey_fields {
954 3     3 1 1673 my $me = shift;
955 3         17 my @fields = grep { $_->is_primary_key } $me->get_fields;
  14         754  
956 3 50       238 return wantarray ? @fields : \@fields;
957             }
958              
959             sub fkey_fields {
960 1     1 1 1461 my $me = shift;
961 1         1 my @fields;
962 1         5 push @fields, $_->fields foreach $me->fkey_constraints;
963 1 50       4 return wantarray ? @fields : \@fields;
964             }
965              
966             sub nonpkey_fields {
967 1     1 1 956 my $me = shift;
968 1         9 my @fields = grep { !$_->is_primary_key } $me->get_fields;
  4         106  
969 1 50       10 return wantarray ? @fields : \@fields;
970             }
971              
972             sub data_fields {
973 3     3 1 3032 my $me = shift;
974 3   100     17 my @fields = grep { !$_->is_foreign_key and !$_->is_primary_key } $me->get_fields;
  14         700  
975 3 50       187 return wantarray ? @fields : \@fields;
976             }
977              
978             sub unique_fields {
979 1     1 1 1519 my $me = shift;
980 1         2 my @fields;
981 1         4 push @fields, $_->fields foreach $me->unique_constraints;
982 1 50       5 return wantarray ? @fields : \@fields;
983             }
984              
985             sub unique_constraints {
986 2     2 1 1248 my $me = shift;
987 2         6 my @cons = grep { $_->type eq UNIQUE } $me->get_constraints;
  6         146  
988 2 50       70 return wantarray ? @cons : \@cons;
989             }
990              
991             sub fkey_constraints {
992 2     2 1 4 my $me = shift;
993 2         5 my @cons = grep { $_->type eq FOREIGN_KEY } $me->get_constraints;
  6         176  
994 2 50       52 return wantarray ? @cons : \@cons;
995             }
996              
997             # Must come after all 'has' declarations
998             around new => \&ex2err;
999              
1000             1;
1001              
1002             =pod
1003              
1004             =head1 AUTHORS
1005              
1006             Ken Youens-Clark Ekclark@cpan.orgE,
1007             Allen Day Eallenday@ucla.eduE.
1008              
1009             =cut