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