Added TTSchema changes.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Schema / Table.pm
CommitLineData
3c5de62a 1package SQL::Translator::Schema::Table;
2
3# ----------------------------------------------------------------------
b1789409 4# $Id: Table.pm,v 1.29 2004-11-05 15:03:10 grommit Exp $
3c5de62a 5# ----------------------------------------------------------------------
6606c4c6 6# Copyright (C) 2002-4 SQLFairy Authors
3c5de62a 7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License as
10# published by the Free Software Foundation; version 2.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15# General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20# 02111-1307 USA
21# -------------------------------------------------------------------
22
23=pod
24
25=head1 NAME
26
27SQL::Translator::Schema::Table - SQL::Translator table object
28
29=head1 SYNOPSIS
30
31 use SQL::Translator::Schema::Table;
0f3cc5c0 32 my $table = SQL::Translator::Schema::Table->new( name => 'foo' );
3c5de62a 33
34=head1 DESCSIPTION
35
36C<SQL::Translator::Schema::Table> is the table object.
37
38=head1 METHODS
39
40=cut
41
42use strict;
30f4ec44 43use SQL::Translator::Utils 'parse_list_arg';
0f3cc5c0 44use SQL::Translator::Schema::Constants;
3c5de62a 45use SQL::Translator::Schema::Constraint;
46use SQL::Translator::Schema::Field;
47use SQL::Translator::Schema::Index;
c8515c9f 48use Data::Dumper;
3c5de62a 49
b6a880d1 50use base 'SQL::Translator::Schema::Object';
51
0f3cc5c0 52use vars qw( $VERSION $FIELD_ORDER );
3c5de62a 53
b1789409 54$VERSION = sprintf "%d.%02d", q$Revision: 1.29 $ =~ /(\d+)\.(\d+)/;
65dd38c0 55
56
57# Stringify to our name, being careful not to pass any args through so we don't
58# accidentally set it to undef. We also have to tweak bool so the object is
59# still true when it doesn't have a name (which shouldn't happen!).
60use overload
61 '""' => sub { shift->name },
62 'bool' => sub { $_[0]->name || $_[0] },
63 fallback => 1,
64;
3c5de62a 65
66# ----------------------------------------------------------------------
9371be50 67
68__PACKAGE__->_attributes( qw/schema name comments options order/ );
3c5de62a 69
70=pod
71
72=head2 new
73
74Object constructor.
75
43b9dc7a 76 my $table = SQL::Translator::Schema::Table->new(
77 schema => $schema,
78 name => 'foo',
79 );
3c5de62a 80
81=cut
82
3c5de62a 83# ----------------------------------------------------------------------
3c5de62a 84sub add_constraint {
85
86=pod
87
88=head2 add_constraint
89
0f3cc5c0 90Add a constraint to the table. Returns the newly created
91C<SQL::Translator::Schema::Constraint> object.
3c5de62a 92
870024f3 93 my $c1 = $table->add_constraint(
94 name => 'pk',
95 type => PRIMARY_KEY,
96 fields => [ 'foo_id' ],
3c5de62a 97 );
98
dfdb0568 99 my $c2 = SQL::Translator::Schema::Constraint->new( name => 'uniq' );
100 $c2 = $table->add_constraint( $constraint );
43b9dc7a 101
3c5de62a 102=cut
103
43b9dc7a 104 my $self = shift;
105 my $constraint_class = 'SQL::Translator::Schema::Constraint';
106 my $constraint;
107
108 if ( UNIVERSAL::isa( $_[0], $constraint_class ) ) {
109 $constraint = shift;
110 $constraint->table( $self );
111 }
112 else {
113 my %args = @_;
114 $args{'table'} = $self;
115 $constraint = $constraint_class->new( \%args ) or
b1789409 116 return $self->error( $constraint_class->error );
43b9dc7a 117 }
118
dfdb0568 119 #
120 # If we're trying to add a PK when one is already defined,
121 # then just add the fields to the existing definition.
122 #
3dd9026c 123 my $ok = 1;
dfdb0568 124 my $pk = $self->primary_key;
125 if ( $pk && $constraint->type eq PRIMARY_KEY ) {
126 $self->primary_key( $constraint->fields );
b1789409 127 $pk->name($constraint->name) if $constraint->name;
128 my %extra = $constraint->extra;
129 $pk->extra(%extra) if keys %extra;
dfdb0568 130 $constraint = $pk;
3dd9026c 131 $ok = 0;
dfdb0568 132 }
2ccf2299 133 elsif ( $constraint->type eq PRIMARY_KEY ) {
134 for my $fname ( $constraint->fields ) {
135 if ( my $f = $self->get_field( $fname ) ) {
136 $f->is_primary_key( 1 );
137 }
138 }
139 }
3dd9026c 140 #
141 # See if another constraint of the same type
be53b4c8 142 # covers the same fields. -- This doesn't work! ky
3dd9026c 143 #
be53b4c8 144# elsif ( $constraint->type ne CHECK_C ) {
145# my @field_names = $constraint->fields;
146# for my $c (
147# grep { $_->type eq $constraint->type }
148# $self->get_constraints
149# ) {
150# my %fields = map { $_, 1 } $c->fields;
151# for my $field_name ( @field_names ) {
152# if ( $fields{ $field_name } ) {
153# $constraint = $c;
154# $ok = 0;
155# last;
156# }
157# }
158# last unless $ok;
159# }
160# }
dfdb0568 161
162 if ( $ok ) {
163 push @{ $self->{'constraints'} }, $constraint;
164 }
165
3c5de62a 166 return $constraint;
167}
168
169# ----------------------------------------------------------------------
170sub add_index {
171
172=pod
173
174=head2 add_index
175
0f3cc5c0 176Add an index to the table. Returns the newly created
177C<SQL::Translator::Schema::Index> object.
3c5de62a 178
870024f3 179 my $i1 = $table->add_index(
3c5de62a 180 name => 'name',
181 fields => [ 'name' ],
182 type => 'normal',
183 );
184
dfdb0568 185 my $i2 = SQL::Translator::Schema::Index->new( name => 'id' );
186 $i2 = $table->add_index( $index );
43b9dc7a 187
3c5de62a 188=cut
189
43b9dc7a 190 my $self = shift;
191 my $index_class = 'SQL::Translator::Schema::Index';
192 my $index;
193
194 if ( UNIVERSAL::isa( $_[0], $index_class ) ) {
195 $index = shift;
196 $index->table( $self );
197 }
198 else {
199 my %args = @_;
200 $args{'table'} = $self;
201 $index = $index_class->new( \%args ) or return
202 $self->error( $index_class->error );
203 }
204
3c5de62a 205 push @{ $self->{'indices'} }, $index;
206 return $index;
207}
208
209# ----------------------------------------------------------------------
210sub add_field {
211
212=pod
213
214=head2 add_field
215
43b9dc7a 216Add an field to the table. Returns the newly created
217C<SQL::Translator::Schema::Field> object. The "name" parameter is
218required. If you try to create a field with the same name as an
219existing field, you will get an error and the field will not be created.
3c5de62a 220
870024f3 221 my $f1 = $table->add_field(
0f3cc5c0 222 name => 'foo_id',
223 data_type => 'integer',
224 size => 11,
3c5de62a 225 );
226
870024f3 227 my $f2 = SQL::Translator::Schema::Field->new(
43b9dc7a 228 name => 'name',
229 table => $table,
230 );
870024f3 231 $f2 = $table->add_field( $field2 ) or die $table->error;
43b9dc7a 232
3c5de62a 233=cut
234
dfdb0568 235 my $self = shift;
43b9dc7a 236 my $field_class = 'SQL::Translator::Schema::Field';
237 my $field;
238
239 if ( UNIVERSAL::isa( $_[0], $field_class ) ) {
240 $field = shift;
241 $field->table( $self );
242 }
243 else {
244 my %args = @_;
245 $args{'table'} = $self;
246 $field = $field_class->new( \%args ) or return
247 $self->error( $field_class->error );
248 }
249
30f4ec44 250 $field->order( ++$FIELD_ORDER );
65dd38c0 251 # We know we have a name as the Field->new above errors if none given.
252 my $field_name = $field->name;
43b9dc7a 253
254 if ( exists $self->{'fields'}{ $field_name } ) {
870024f3 255 return $self->error(qq[Can't create field: "$field_name" exists]);
43b9dc7a 256 }
257 else {
258 $self->{'fields'}{ $field_name } = $field;
43b9dc7a 259 }
260
3c5de62a 261 return $field;
262}
263
264# ----------------------------------------------------------------------
88b8377e 265sub comments {
266
267=pod
268
269=head2 comments
270
271Get or set the comments on a table. May be called several times to
272set and it will accumulate the comments. Called in an array context,
273returns each comment individually; called in a scalar context, returns
274all the comments joined on newlines.
275
276 $table->comments('foo');
277 $table->comments('bar');
278 print join( ', ', $table->comments ); # prints "foo, bar"
279
280=cut
281
eb3b8ae4 282 my $self = shift;
283 my @comments = ref $_[0] ? @{ $_[0] } : @_;
b891fb49 284
eb3b8ae4 285 for my $arg ( @comments ) {
b891fb49 286 $arg = $arg->[0] if ref $arg;
eb3b8ae4 287 push @{ $self->{'comments'} }, $arg if defined $arg && $arg;
b891fb49 288 }
88b8377e 289
eb3b8ae4 290 if ( @{ $self->{'comments'} || [] } ) {
291 return wantarray
292 ? @{ $self->{'comments'} }
293 : join( "\n", @{ $self->{'comments'} } )
294 ;
295 }
296 else {
297 return wantarray ? () : undef;
298 }
88b8377e 299}
300
301# ----------------------------------------------------------------------
0f3cc5c0 302sub get_constraints {
303
304=pod
305
306=head2 get_constraints
307
308Returns all the constraint objects as an array or array reference.
309
310 my @constraints = $table->get_constraints;
311
312=cut
313
314 my $self = shift;
315
316 if ( ref $self->{'constraints'} ) {
317 return wantarray
318 ? @{ $self->{'constraints'} } : $self->{'constraints'};
319 }
320 else {
321 $self->error('No constraints');
322 return wantarray ? () : undef;
323 }
324}
325
326# ----------------------------------------------------------------------
327sub get_indices {
3c5de62a 328
329=pod
330
0f3cc5c0 331=head2 get_indices
3c5de62a 332
0f3cc5c0 333Returns all the index objects as an array or array reference.
3c5de62a 334
0f3cc5c0 335 my @indices = $table->get_indices;
3c5de62a 336
337=cut
338
339 my $self = shift;
0f3cc5c0 340
341 if ( ref $self->{'indices'} ) {
342 return wantarray
343 ? @{ $self->{'indices'} }
344 : $self->{'indices'};
345 }
346 else {
347 $self->error('No indices');
348 return wantarray ? () : undef;
349 }
350}
351
352# ----------------------------------------------------------------------
43b9dc7a 353sub get_field {
354
355=pod
356
357=head2 get_field
358
359Returns a field by the name provided.
360
361 my $field = $table->get_field('foo');
362
363=cut
364
365 my $self = shift;
366 my $field_name = shift or return $self->error('No field name');
367 return $self->error( qq[Field "$field_name" does not exist] ) unless
368 exists $self->{'fields'}{ $field_name };
369 return $self->{'fields'}{ $field_name };
370}
371
372# ----------------------------------------------------------------------
0f3cc5c0 373sub get_fields {
374
375=pod
376
377=head2 get_fields
378
379Returns all the field objects as an array or array reference.
380
381 my @fields = $table->get_fields;
382
383=cut
384
385 my $self = shift;
386 my @fields =
30f4ec44 387 map { $_->[1] }
388 sort { $a->[0] <=> $b->[0] }
389 map { [ $_->order, $_ ] }
0f3cc5c0 390 values %{ $self->{'fields'} || {} };
391
392 if ( @fields ) {
393 return wantarray ? @fields : \@fields;
394 }
395 else {
396 $self->error('No fields');
397 return wantarray ? () : undef;
398 }
3c5de62a 399}
400
401# ----------------------------------------------------------------------
402sub is_valid {
403
404=pod
405
406=head2 is_valid
407
408Determine whether the view is valid or not.
409
410 my $ok = $view->is_valid;
411
412=cut
413
414 my $self = shift;
43b9dc7a 415 return $self->error('No name') unless $self->name;
0f3cc5c0 416 return $self->error('No fields') unless $self->get_fields;
417
418 for my $object (
419 $self->get_fields, $self->get_indices, $self->get_constraints
420 ) {
421 return $object->error unless $object->is_valid;
422 }
423
424 return 1;
3c5de62a 425}
426
870024f3 427# ----------------------------------------------------------------------
65157eda 428sub is_trivial_link {
429
430=pod
431
719915f2 432=head2 is_trivial_link
433
434True if table has no data (non-key) fields and only uses single key joins.
65157eda 435
436=cut
437
438 my $self = shift;
439 return 0 if $self->is_data;
440 return $self->{'is_trivial_link'} if defined $self->{'is_trivial_link'};
441
442 $self->{'is_trivial_link'} = 1;
443
444 my %fk = ();
445
446 foreach my $field ( $self->get_fields ) {
447 next unless $field->is_foreign_key;
448 $fk{$field->foreign_key_reference->reference_table}++;
449 }
450
451 foreach my $referenced (keys %fk){
f9c5e794 452 if($fk{$referenced} > 1){
453 $self->{'is_trivial_link'} = 0;
454 last;
65157eda 455 }
3d6c9056 456 }
65157eda 457
458 return $self->{'is_trivial_link'};
459
460}
461
69c7a62f 462sub is_data {
69c7a62f 463
870024f3 464=pod
465
466=head2 is_data
467
719915f2 468Returns true if the table has some non-key fields.
469
870024f3 470=cut
471
472 my $self = shift;
473 return $self->{'is_data'} if defined $self->{'is_data'};
69c7a62f 474
870024f3 475 $self->{'is_data'} = 0;
69c7a62f 476
870024f3 477 foreach my $field ( $self->get_fields ) {
478 if ( !$field->is_primary_key and !$field->is_foreign_key ) {
479 $self->{'is_data'} = 1;
480 return $self->{'is_data'};
481 }
482 }
483
484 return $self->{'is_data'};
69c7a62f 485}
486
870024f3 487# ----------------------------------------------------------------------
69c7a62f 488sub can_link {
489
490=pod
491
492=head2 can_link
493
494Determine whether the table can link two arg tables via many-to-many.
495
496 my $ok = $table->can_link($table1,$table2);
497
498=cut
499
870024f3 500 my ( $self, $table1, $table2 ) = @_;
501
502 return $self->{'can_link'}{ $table1->name }{ $table2->name }
503 if defined $self->{'can_link'}{ $table1->name }{ $table2->name };
504
505 if ( $self->is_data == 1 ) {
506 $self->{'can_link'}{ $table1->name }{ $table2->name } = [0];
507 $self->{'can_link'}{ $table2->name }{ $table1->name } = [0];
508 return $self->{'can_link'}{ $table1->name }{ $table2->name };
509 }
510
511 my %fk = ();
512
513 foreach my $field ( $self->get_fields ) {
514 if ( $field->is_foreign_key ) {
515 push @{ $fk{ $field->foreign_key_reference->reference_table } },
516 $field->foreign_key_reference;
517 }
518 }
519
520 if ( !defined( $fk{ $table1->name } ) or !defined( $fk{ $table2->name } ) )
521 {
522 $self->{'can_link'}{ $table1->name }{ $table2->name } = [0];
523 $self->{'can_link'}{ $table2->name }{ $table1->name } = [0];
524 return $self->{'can_link'}{ $table1->name }{ $table2->name };
525 }
526
527 # trivial traversal, only one way to link the two tables
528 if ( scalar( @{ $fk{ $table1->name } } == 1 )
529 and scalar( @{ $fk{ $table2->name } } == 1 ) )
530 {
531 $self->{'can_link'}{ $table1->name }{ $table2->name } =
532 [ 'one2one', $fk{ $table1->name }, $fk{ $table2->name } ];
533 $self->{'can_link'}{ $table1->name }{ $table2->name } =
534 [ 'one2one', $fk{ $table2->name }, $fk{ $table1->name } ];
535
536 # non-trivial traversal. one way to link table2,
537 # many ways to link table1
538 }
539 elsif ( scalar( @{ $fk{ $table1->name } } > 1 )
540 and scalar( @{ $fk{ $table2->name } } == 1 ) )
541 {
542 $self->{'can_link'}{ $table1->name }{ $table2->name } =
543 [ 'many2one', $fk{ $table1->name }, $fk{ $table2->name } ];
544 $self->{'can_link'}{ $table2->name }{ $table1->name } =
545 [ 'one2many', $fk{ $table2->name }, $fk{ $table1->name } ];
546
547 # non-trivial traversal. one way to link table1,
548 # many ways to link table2
549 }
550 elsif ( scalar( @{ $fk{ $table1->name } } == 1 )
551 and scalar( @{ $fk{ $table2->name } } > 1 ) )
552 {
553 $self->{'can_link'}{ $table1->name }{ $table2->name } =
554 [ 'one2many', $fk{ $table1->name }, $fk{ $table2->name } ];
555 $self->{'can_link'}{ $table2->name }{ $table1->name } =
556 [ 'many2one', $fk{ $table2->name }, $fk{ $table1->name } ];
557
558 # non-trivial traversal. many ways to link table1 and table2
559 }
560 elsif ( scalar( @{ $fk{ $table1->name } } > 1 )
561 and scalar( @{ $fk{ $table2->name } } > 1 ) )
562 {
563 $self->{'can_link'}{ $table1->name }{ $table2->name } =
564 [ 'many2many', $fk{ $table1->name }, $fk{ $table2->name } ];
565 $self->{'can_link'}{ $table2->name }{ $table1->name } =
566 [ 'many2many', $fk{ $table2->name }, $fk{ $table1->name } ];
567
568 # one of the tables didn't export a key
569 # to this table, no linking possible
570 }
571 else {
572 $self->{'can_link'}{ $table1->name }{ $table2->name } = [0];
573 $self->{'can_link'}{ $table2->name }{ $table1->name } = [0];
574 }
575
576 return $self->{'can_link'}{ $table1->name }{ $table2->name };
69c7a62f 577}
578
43b9dc7a 579# ----------------------------------------------------------------------
dfdb0568 580sub name {
581
582=pod
583
584=head2 name
585
870024f3 586Get or set the table's name.
dfdb0568 587
65dd38c0 588Errors ("No table name") if you try to set a blank name.
589
590If provided an argument, checks the schema object for a table of
591that name and disallows the change if one exists (setting the error to
592"Can't use table name "%s": table exists").
dfdb0568 593
594 my $table_name = $table->name('foo');
595
596=cut
597
598 my $self = shift;
599
65dd38c0 600 if ( @_ ) {
601 my $arg = shift || return $self->error( "No table name" );
dfdb0568 602 if ( my $schema = $self->schema ) {
870024f3 603 return $self->error( qq[Can't use table name "$arg": table exists] )
dfdb0568 604 if $schema->get_table( $arg );
605 }
606 $self->{'name'} = $arg;
607 }
608
609 return $self->{'name'} || '';
610}
611
612# ----------------------------------------------------------------------
43b9dc7a 613sub schema {
614
615=pod
616
617=head2 schema
618
870024f3 619Get or set the table's schema object.
43b9dc7a 620
621 my $schema = $table->schema;
622
623=cut
624
625 my $self = shift;
626 if ( my $arg = shift ) {
627 return $self->error('Not a schema object') unless
628 UNIVERSAL::isa( $arg, 'SQL::Translator::Schema' );
629 $self->{'schema'} = $arg;
630 }
631
632 return $self->{'schema'};
633}
634
635# ----------------------------------------------------------------------
636sub primary_key {
637
638=pod
639
870024f3 640=head2 primary_key
43b9dc7a 641
870024f3 642Gets or sets the table's primary key(s). Takes one or more field
5e84ac85 643names (as a string, list or array[ref]) as an argument. If the field
644names are present, it will create a new PK if none exists, or it will
645add to the fields of an existing PK (and will unique the field names).
646Returns the C<SQL::Translator::Schema::Constraint> object representing
647the primary key.
648
649These are eqivalent:
43b9dc7a 650
651 $table->primary_key('id');
5e84ac85 652 $table->primary_key(['name']);
653 $table->primary_key('id','name']);
43b9dc7a 654 $table->primary_key(['id','name']);
655 $table->primary_key('id,name');
656 $table->primary_key(qw[ id name ]);
657
658 my $pk = $table->primary_key;
659
660=cut
661
30f4ec44 662 my $self = shift;
663 my $fields = parse_list_arg( @_ );
43b9dc7a 664
5e84ac85 665 my $constraint;
43b9dc7a 666 if ( @$fields ) {
667 for my $f ( @$fields ) {
668 return $self->error(qq[Invalid field "$f"]) unless
669 $self->get_field($f);
670 }
671
672 my $has_pk;
673 for my $c ( $self->get_constraints ) {
674 if ( $c->type eq PRIMARY_KEY ) {
675 $has_pk = 1;
676 $c->fields( @{ $c->fields }, @$fields );
5e84ac85 677 $constraint = $c;
43b9dc7a 678 }
679 }
680
681 unless ( $has_pk ) {
5e84ac85 682 $constraint = $self->add_constraint(
43b9dc7a 683 type => PRIMARY_KEY,
684 fields => $fields,
88b8377e 685 ) or return;
43b9dc7a 686 }
687 }
688
5e84ac85 689 if ( $constraint ) {
690 return $constraint;
691 }
692 else {
693 for my $c ( $self->get_constraints ) {
694 return $c if $c->type eq PRIMARY_KEY;
695 }
43b9dc7a 696 }
697
dfdb0568 698 return;
43b9dc7a 699}
700
701# ----------------------------------------------------------------------
702sub options {
703
704=pod
705
706=head2 options
707
870024f3 708Get or set the table's options (e.g., table types for MySQL). Returns
43b9dc7a 709an array or array reference.
710
711 my @options = $table->options;
712
713=cut
714
715 my $self = shift;
30f4ec44 716 my $options = parse_list_arg( @_ );
43b9dc7a 717
718 push @{ $self->{'options'} }, @$options;
719
720 if ( ref $self->{'options'} ) {
721 return wantarray ? @{ $self->{'options'} || [] } : $self->{'options'};
722 }
723 else {
724 return wantarray ? () : [];
725 }
726}
727
30f4ec44 728# ----------------------------------------------------------------------
729sub order {
730
731=pod
732
733=head2 order
734
870024f3 735Get or set the table's order.
30f4ec44 736
737 my $order = $table->order(3);
738
739=cut
740
741 my ( $self, $arg ) = @_;
742
743 if ( defined $arg && $arg =~ /^\d+$/ ) {
744 $self->{'order'} = $arg;
745 }
746
747 return $self->{'order'} || 0;
748}
749
750# ----------------------------------------------------------------------
719915f2 751sub field_names {
752
753=head2 field_names
754
755Read-only method to return a list or array ref of the field names. Returns undef
756or an empty list if the table has no fields set. Usefull if you want to
757avoid the overload magic of the Field objects returned by the get_fields method.
758
759 my @names = $constraint->field_names;
760
761=cut
762
763 my $self = shift;
764 my @fields =
765 map { $_->name }
766 sort { $a->order <=> $b->order }
767 values %{ $self->{'fields'} || {} };
768
769 if ( @fields ) {
770 return wantarray ? @fields : \@fields;
771 }
772 else {
773 $self->error('No fields');
774 return wantarray ? () : undef;
775 }
776}
777
778# ----------------------------------------------------------------------
779
780=head1 LOOKUP METHODS
781
782The following are a set of shortcut methods for getting commonly used lists of
783fields and constraints. They all return lists or array refs of Field or
784Constraint objects.
785
786=over 4
787
788=item pkey_fields
789
790The primary key fields.
791
792=item fkey_fields
793
794All foreign key fields.
795
796=item nonpkey_fields
797
798All the fields except the primary key.
799
800=item data_fields
801
802All non key fields.
803
804=item unique_fields
805
806All fields with unique constraints.
807
808=item unique_constraints
809
810All this tables unique constraints.
811
812=item fkey_constraints
813
814All this tables foreign key constraints. (See primary_key method to get the
815primary key constraint)
816
817=back
818
819=cut
820
821sub pkey_fields {
822 my $me = shift;
823 my @fields = grep { $_->is_primary_key } $me->get_fields;
824 return wantarray ? @fields : \@fields;
825}
826
827# ----------------------------------------------------------------------
828sub fkey_fields {
829 my $me = shift;
830 my @fields;
831 push @fields, $_->fields foreach $me->fkey_constraints;
832 return wantarray ? @fields : \@fields;
833}
834
835# ----------------------------------------------------------------------
836sub nonpkey_fields {
837 my $me = shift;
838 my @fields = grep { !$_->is_primary_key } $me->get_fields;
839 return wantarray ? @fields : \@fields;
840}
841
842# ----------------------------------------------------------------------
843sub data_fields {
844 my $me = shift;
845 my @fields =
846 grep { !$_->is_foreign_key and !$_->is_primary_key } $me->get_fields;
847 return wantarray ? @fields : \@fields;
848}
849
850# ----------------------------------------------------------------------
851sub unique_fields {
852 my $me = shift;
853 my @fields;
854 push @fields, $_->fields foreach $me->unique_constraints;
855 return wantarray ? @fields : \@fields;
856}
857
858# ----------------------------------------------------------------------
859sub unique_constraints {
860 my $me = shift;
861 my @cons = grep { $_->type eq UNIQUE } $me->get_constraints;
862 return wantarray ? @cons : \@cons;
863}
864
865# ----------------------------------------------------------------------
866sub fkey_constraints {
867 my $me = shift;
868 my @cons = grep { $_->type eq FOREIGN_KEY } $me->get_constraints;
869 return wantarray ? @cons : \@cons;
870}
871
872# ----------------------------------------------------------------------
30f4ec44 873sub DESTROY {
874 my $self = shift;
875 undef $self->{'schema'}; # destroy cyclical reference
876 undef $_ for @{ $self->{'constraints'} };
877 undef $_ for @{ $self->{'indices'} };
878 undef $_ for values %{ $self->{'fields'} };
879}
880
3c5de62a 8811;
882
883# ----------------------------------------------------------------------
884
885=pod
886
870024f3 887=head1 AUTHORS
3c5de62a 888
870024f3 889Ken Y. Clark E<lt>kclark@cpan.orgE<gt>,
890Allen Day E<lt>allenday@ucla.eduE<gt>.
3c5de62a 891
892=cut