All Schema objects now have an extra attribute. Added parsing support (and
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Schema / Field.pm
CommitLineData
3c5de62a 1package SQL::Translator::Schema::Field;
2
3# ----------------------------------------------------------------------
b1789409 4# $Id: Field.pm,v 1.22 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::Field - SQL::Translator field object
28
29=head1 SYNOPSIS
30
31 use SQL::Translator::Schema::Field;
32 my $field = SQL::Translator::Schema::Field->new(
b9dc0b40 33 name => 'foo',
34 table => $table,
3c5de62a 35 );
36
37=head1 DESCRIPTION
38
39C<SQL::Translator::Schema::Field> is the field object.
40
41=head1 METHODS
42
43=cut
44
45use strict;
43b9dc7a 46use SQL::Translator::Schema::Constants;
ec2ab48d 47use SQL::Translator::Utils 'parse_list_arg';
3c5de62a 48
b6a880d1 49use base 'SQL::Translator::Schema::Object';
50
3c5de62a 51use vars qw($VERSION $TABLE_COUNT $VIEW_COUNT);
52
b1789409 53$VERSION = sprintf "%d.%02d", q$Revision: 1.22 $ =~ /(\d+)\.(\d+)/;
65dd38c0 54
55# Stringify to our name, being careful not to pass any args through so we don't
56# accidentally set it to undef. We also have to tweak bool so the object is
57# still true when it doesn't have a name (which shouldn't happen!).
58use overload
59 '""' => sub { shift->name },
60 'bool' => sub { $_[0]->name || $_[0] },
61 fallback => 1,
62;
3c5de62a 63
64# ----------------------------------------------------------------------
9371be50 65
66__PACKAGE__->_attributes( qw/
67 table name data_type size is_primary_key is_nullable
b1789409 68 is_auto_increment default_value comments is_foreign_key
9371be50 69 is_unique order
70/);
3c5de62a 71
72=pod
73
74=head2 new
75
76Object constructor.
77
0bf88ce5 78 my $field = SQL::Translator::Schema::Field->new(
79 name => 'foo',
80 table => $table,
b9dc0b40 81 );
3c5de62a 82
83=cut
84
3c5de62a 85# ----------------------------------------------------------------------
5ac417ad 86sub comments {
87
88=pod
89
90=head2 comments
91
92Get or set the comments on a field. May be called several times to
93set and it will accumulate the comments. Called in an array context,
94returns each comment individually; called in a scalar context, returns
95all the comments joined on newlines.
96
97 $field->comments('foo');
98 $field->comments('bar');
99 print join( ', ', $field->comments ); # prints "foo, bar"
100
101=cut
102
103 my $self = shift;
aadf4042 104
105 for my $arg ( @_ ) {
106 $arg = $arg->[0] if ref $arg;
c33df5c4 107 push @{ $self->{'comments'} }, $arg if $arg;
aadf4042 108 }
5ac417ad 109
c33df5c4 110 if ( @{ $self->{'comments'} || [] } ) {
111 return wantarray
112 ? @{ $self->{'comments'} || [] }
113 : join( "\n", @{ $self->{'comments'} || [] } );
114 }
115 else {
116 return wantarray ? () : '';
117 }
5ac417ad 118}
119
120
121# ----------------------------------------------------------------------
3c5de62a 122sub data_type {
123
124=pod
125
126=head2 data_type
127
43b9dc7a 128Get or set the field's data type.
3c5de62a 129
130 my $data_type = $field->data_type('integer');
131
132=cut
133
134 my $self = shift;
135 $self->{'data_type'} = shift if @_;
136 return $self->{'data_type'} || '';
137}
138
139# ----------------------------------------------------------------------
43b9dc7a 140sub default_value {
141
142=pod
143
144=head2 default_value
145
146Get or set the field's default value. Will return undef if not defined
147and could return the empty string (it's a valid default value), so don't
148assume an error like other methods.
149
150 my $default = $field->default_value('foo');
151
152=cut
153
154 my ( $self, $arg ) = @_;
155 $self->{'default_value'} = $arg if defined $arg;
156 return $self->{'default_value'};
157}
158
159# ----------------------------------------------------------------------
9966eebc 160=pod
161
162=head2 extra
163
164Get or set the field's "extra" attibutes (e.g., "ZEROFILL" for MySQL).
165Accepts a hash(ref) of name/value pairs to store; returns a hash.
166
167 $field->extra( qualifier => 'ZEROFILL' );
168 my %extra = $field->extra;
169
170=cut
171
9966eebc 172
173# ----------------------------------------------------------------------
174sub foreign_key_reference {
175
176=pod
177
178=head2 foreign_key_reference
179
180Get or set the field's foreign key reference;
181
182 my $constraint = $field->foreign_key_reference( $constraint );
183
184=cut
185
186 my $self = shift;
187
188 if ( my $arg = shift ) {
189 my $class = 'SQL::Translator::Schema::Constraint';
190 if ( UNIVERSAL::isa( $arg, $class ) ) {
191 return $self->error(
192 'Foreign key reference for ', $self->name, 'already defined'
193 ) if $self->{'foreign_key_reference'};
194
195 $self->{'foreign_key_reference'} = $arg;
196 }
197 else {
198 return $self->error(
199 "Argument to foreign_key_reference is not an $class object"
200 );
201 }
202 }
203
204 return $self->{'foreign_key_reference'};
205}
206
207# ----------------------------------------------------------------------
43b9dc7a 208sub is_auto_increment {
209
210=pod
211
212=head2 is_auto_increment
213
214Get or set the field's C<is_auto_increment> attribute.
215
b9dc0b40 216 my $is_auto = $field->is_auto_increment(1);
43b9dc7a 217
218=cut
219
220 my ( $self, $arg ) = @_;
221
222 if ( defined $arg ) {
223 $self->{'is_auto_increment'} = $arg ? 1 : 0;
224 }
225
226 unless ( defined $self->{'is_auto_increment'} ) {
227 if ( my $table = $self->table ) {
228 if ( my $schema = $table->schema ) {
229 if (
230 $schema->database eq 'PostgreSQL' &&
231 $self->data_type eq 'serial'
232 ) {
233 $self->{'is_auto_increment'} = 1;
234 }
235 }
236 }
237 }
238
239 return $self->{'is_auto_increment'} || 0;
240}
241
242# ----------------------------------------------------------------------
9966eebc 243sub is_foreign_key {
244
245=pod
246
247=head2 is_foreign_key
248
249Returns whether or not the field is a foreign key.
250
251 my $is_fk = $field->is_foreign_key;
252
253=cut
254
255 my ( $self, $arg ) = @_;
256
257 unless ( defined $self->{'is_foreign_key'} ) {
258 if ( my $table = $self->table ) {
259 for my $c ( $table->get_constraints ) {
260 if ( $c->type eq FOREIGN_KEY ) {
261 my %fields = map { $_, 1 } $c->fields;
262 if ( $fields{ $self->name } ) {
263 $self->{'is_foreign_key'} = 1;
264 $self->foreign_key_reference( $c );
265 last;
266 }
267 }
268 }
269 }
270 }
271
272 return $self->{'is_foreign_key'} || 0;
273}
274
9966eebc 275# ----------------------------------------------------------------------
ec2ab48d 276sub is_nullable {
277
278=pod
279
280=head2 is_nullable
281
b9dc0b40 282Get or set whether the field can be null. If not defined, then
ec2ab48d 283returns "1" (assumes the field can be null). The argument is evaluated
284by Perl for True or False, so the following are eqivalent:
285
286 $is_nullable = $field->is_nullable(0);
287 $is_nullable = $field->is_nullable('');
288 $is_nullable = $field->is_nullable('0');
289
290While this is technically a field constraint, it's probably easier to
291represent this as an attribute of the field. In order keep things
292consistent, any other constraint on the field (unique, primary, and
293foreign keys; checks) are represented as table constraints.
294
295=cut
296
297 my ( $self, $arg ) = @_;
298
299 if ( defined $arg ) {
300 $self->{'is_nullable'} = $arg ? 1 : 0;
301 }
302
42c8fad4 303 if (
304 defined $self->{'is_nullable'} &&
305 $self->{'is_nullable'} == 1 &&
306 $self->is_primary_key
307 ) {
308 $self->{'is_nullable'} = 0;
309 }
310
ec2ab48d 311 return defined $self->{'is_nullable'} ? $self->{'is_nullable'} : 1;
312}
313
314# ----------------------------------------------------------------------
3c5de62a 315sub is_primary_key {
316
317=pod
318
319=head2 is_primary_key
320
ec2ab48d 321Get or set the field's C<is_primary_key> attribute. Does not create
322a table constraint (should it?).
3c5de62a 323
324 my $is_pk = $field->is_primary_key(1);
325
326=cut
327
328 my ( $self, $arg ) = @_;
329
330 if ( defined $arg ) {
331 $self->{'is_primary_key'} = $arg ? 1 : 0;
332 }
333
43b9dc7a 334 unless ( defined $self->{'is_primary_key'} ) {
335 if ( my $table = $self->table ) {
336 if ( my $pk = $table->primary_key ) {
337 my %fields = map { $_, 1 } $pk->fields;
338 $self->{'is_primary_key'} = $fields{ $self->name } || 0;
339 }
340 else {
341 $self->{'is_primary_key'} = 0;
342 }
343 }
344 }
345
3c5de62a 346 return $self->{'is_primary_key'} || 0;
347}
348
349# ----------------------------------------------------------------------
ee2766f4 350sub is_unique {
351
352=pod
353
354=head2 is_unique
355
356Determine whether the field has a UNIQUE constraint or not.
357
358 my $is_unique = $field->is_unique;
359
360=cut
361
362 my $self = shift;
363
364 unless ( defined $self->{'is_unique'} ) {
365 if ( my $table = $self->table ) {
366 for my $c ( $table->get_constraints ) {
367 if ( $c->type eq UNIQUE ) {
368 my %fields = map { $_, 1 } $c->fields;
369 if ( $fields{ $self->name } ) {
370 $self->{'is_unique'} = 1;
371 last;
372 }
373 }
374 }
375 }
376 }
377
378 return $self->{'is_unique'} || 0;
379}
380
381# ----------------------------------------------------------------------
ec2ab48d 382sub is_valid {
383
384=pod
385
386=head2 is_valid
387
388Determine whether the field is valid or not.
389
390 my $ok = $field->is_valid;
391
392=cut
393
394 my $self = shift;
395 return $self->error('No name') unless $self->name;
396 return $self->error('No data type') unless $self->data_type;
397 return $self->error('No table object') unless $self->table;
398 return 1;
399}
400
401# ----------------------------------------------------------------------
3c5de62a 402sub name {
403
404=pod
405
406=head2 name
407
408Get or set the field's name.
409
65dd38c0 410 my $name = $field->name('foo');
411
412The field object will also stringify to its name.
413
414 my $setter_name = "set_$field";
415
416Errors ("No field name") if you try to set a blank name.
3c5de62a 417
418=cut
419
420 my $self = shift;
43b9dc7a 421
65dd38c0 422 if ( @_ ) {
423 my $arg = shift || return $self->error( "No field name" );
43b9dc7a 424 if ( my $table = $self->table ) {
65dd38c0 425 return $self->error( qq[Can't use field name "$arg": field exists] )
43b9dc7a 426 if $table->get_field( $arg );
427 }
428
429 $self->{'name'} = $arg;
430 }
431
3c5de62a 432 return $self->{'name'} || '';
433}
434
4809213f 435sub full_name {
436
437=head2 full_name
438
439Read only method to return the fields name with its table name pre-pended.
440e.g. "person.foo".
441
442=cut
443
444 my $self = shift;
445 return $self->table.".".$self->name;
446}
447
3c5de62a 448# ----------------------------------------------------------------------
ec2ab48d 449sub order {
3c5de62a 450
451=pod
452
ec2ab48d 453=head2 order
3c5de62a 454
ec2ab48d 455Get or set the field's order.
3c5de62a 456
ec2ab48d 457 my $order = $field->order(3);
3c5de62a 458
459=cut
460
461 my ( $self, $arg ) = @_;
462
ec2ab48d 463 if ( defined $arg && $arg =~ /^\d+$/ ) {
464 $self->{'order'} = $arg;
3c5de62a 465 }
466
ec2ab48d 467 return $self->{'order'} || 0;
43b9dc7a 468}
469
470# ----------------------------------------------------------------------
c1e3c768 471sub schema {
472
473=head2 schema
474
475Shortcut to get the fields schema ($field->table->schema) or undef if it
476doesn't have one.
477
478 my $schema = $field->schema;
479
480=cut
481
482 my $self = shift;
483 if ( my $table = $self->table ) { return $table->schema || undef; }
484 return undef;
485}
486
487# ----------------------------------------------------------------------
43b9dc7a 488sub size {
489
490=pod
491
492=head2 size
493
494Get or set the field's size. Accepts a string, array or arrayref of
495numbers and returns a string.
496
497 $field->size( 30 );
498 $field->size( [ 255 ] );
499 $size = $field->size( 10, 2 );
500 print $size; # prints "10,2"
501
502 $size = $field->size( '10, 2' );
503 print $size; # prints "10,2"
504
505=cut
506
507 my $self = shift;
ec2ab48d 508 my $numbers = parse_list_arg( @_ );
43b9dc7a 509
510 if ( @$numbers ) {
511 my @new;
512 for my $num ( @$numbers ) {
513 if ( defined $num && $num =~ m/^\d+(?:\.\d+)?$/ ) {
514 push @new, $num;
515 }
516 }
517 $self->{'size'} = \@new if @new; # only set if all OK
518 }
519
ec2ab48d 520 return wantarray
aadf4042 521 ? @{ $self->{'size'} || [0] }
ec2ab48d 522 : join( ',', @{ $self->{'size'} || [0] } )
523 ;
43b9dc7a 524}
525
526# ----------------------------------------------------------------------
527sub table {
528
529=pod
530
531=head2 table
532
b9dc0b40 533Get or set the field's table object. As the table object stringifies this can
534also be used to get the table name.
43b9dc7a 535
536 my $table = $field->table;
b9dc0b40 537 print "Table name: $table";
43b9dc7a 538
539=cut
540
541 my $self = shift;
542 if ( my $arg = shift ) {
543 return $self->error('Not a table object') unless
544 UNIVERSAL::isa( $arg, 'SQL::Translator::Schema::Table' );
545 $self->{'table'} = $arg;
546 }
547
548 return $self->{'table'};
3c5de62a 549}
550
ec2ab48d 551# ----------------------------------------------------------------------
552sub DESTROY {
9966eebc 553#
554# Destroy cyclical references.
555#
ec2ab48d 556 my $self = shift;
9966eebc 557 undef $self->{'table'};
558 undef $self->{'foreign_key_reference'};
ec2ab48d 559}
560
3c5de62a 5611;
562
563# ----------------------------------------------------------------------
564
565=pod
566
567=head1 AUTHOR
568
6606c4c6 569Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
3c5de62a 570
571=cut