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