Strip evil svn:keywords
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Schema / Field.pm
CommitLineData
3c5de62a 1package SQL::Translator::Schema::Field;
2
3# ----------------------------------------------------------------------
d4f84dd1 4# $Id: Field.pm 1440 2009-01-17 16:31:57Z jawnsy $
3c5de62a 5# ----------------------------------------------------------------------
478f608d 6# Copyright (C) 2002-2009 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
478f608d 51use vars qw($TABLE_COUNT $VIEW_COUNT);
65dd38c0 52
53# Stringify to our name, being careful not to pass any args through so we don't
54# accidentally set it to undef. We also have to tweak bool so the object is
55# still true when it doesn't have a name (which shouldn't happen!).
56use overload
57 '""' => sub { shift->name },
58 'bool' => sub { $_[0]->name || $_[0] },
59 fallback => 1,
60;
3c5de62a 61
9ab59f87 62use DBI qw(:sql_types);
63
64# Mapping from string to sql contstant
65our %type_mapping = (
66 integer => SQL_INTEGER,
67 int => SQL_INTEGER,
68
69 smallint => SQL_SMALLINT,
70 bigint => 9999, # DBI doesn't export a constatn for this. Le suck
71
72 double => SQL_DOUBLE,
73
74 decimal => SQL_DECIMAL,
75 numeric => SQL_NUMERIC,
76 dec => SQL_DECIMAL,
77
78 bit => SQL_BIT,
79
80 date => SQL_DATE,
81 datetime => SQL_DATETIME,
82 timestamp => SQL_TIMESTAMP,
83 time => SQL_TIME,
84
85 char => SQL_CHAR,
86 varchar => SQL_VARCHAR,
87 binary => SQL_BINARY,
88 varbinary => SQL_VARBINARY,
89 tinyblob => SQL_BLOB,
90 blob => SQL_BLOB,
91 text => SQL_LONGVARCHAR
92
93);
3c5de62a 94# ----------------------------------------------------------------------
9371be50 95
96__PACKAGE__->_attributes( qw/
97 table name data_type size is_primary_key is_nullable
b1789409 98 is_auto_increment default_value comments is_foreign_key
6b2dbb1a 99 is_unique order sql_data_type
9371be50 100/);
3c5de62a 101
102=pod
103
104=head2 new
105
106Object constructor.
107
0bf88ce5 108 my $field = SQL::Translator::Schema::Field->new(
109 name => 'foo',
110 table => $table,
b9dc0b40 111 );
3c5de62a 112
113=cut
114
3c5de62a 115# ----------------------------------------------------------------------
5ac417ad 116sub comments {
117
118=pod
119
120=head2 comments
121
122Get or set the comments on a field. May be called several times to
123set and it will accumulate the comments. Called in an array context,
124returns each comment individually; called in a scalar context, returns
125all the comments joined on newlines.
126
127 $field->comments('foo');
128 $field->comments('bar');
129 print join( ', ', $field->comments ); # prints "foo, bar"
130
131=cut
132
133 my $self = shift;
aadf4042 134
135 for my $arg ( @_ ) {
136 $arg = $arg->[0] if ref $arg;
c33df5c4 137 push @{ $self->{'comments'} }, $arg if $arg;
aadf4042 138 }
5ac417ad 139
c33df5c4 140 if ( @{ $self->{'comments'} || [] } ) {
141 return wantarray
142 ? @{ $self->{'comments'} || [] }
143 : join( "\n", @{ $self->{'comments'} || [] } );
144 }
145 else {
146 return wantarray ? () : '';
147 }
5ac417ad 148}
149
150
151# ----------------------------------------------------------------------
3c5de62a 152sub data_type {
153
154=pod
155
156=head2 data_type
157
43b9dc7a 158Get or set the field's data type.
3c5de62a 159
160 my $data_type = $field->data_type('integer');
161
162=cut
163
164 my $self = shift;
9ab59f87 165 if (@_) {
166 $self->{'data_type'} = $_[0];
167 $self->{'sql_data_type'} = $type_mapping{lc $_[0]} || SQL_UNKNOWN_TYPE unless exists $self->{sql_data_type};
168 }
3c5de62a 169 return $self->{'data_type'} || '';
170}
171
6b2dbb1a 172sub sql_data_type {
173
174=head2 sql_data_type
175
176Constant from DBI package representing this data type. See L<DBI/DBI Constants>
177for more details.
178
179=cut
180
181 my $self = shift;
182 $self->{sql_data_type} = shift if @_;
183 return $self->{sql_data_type} || 0;
184
185}
186
3c5de62a 187# ----------------------------------------------------------------------
43b9dc7a 188sub default_value {
189
190=pod
191
192=head2 default_value
193
194Get or set the field's default value. Will return undef if not defined
195and could return the empty string (it's a valid default value), so don't
196assume an error like other methods.
197
198 my $default = $field->default_value('foo');
199
200=cut
201
202 my ( $self, $arg ) = @_;
203 $self->{'default_value'} = $arg if defined $arg;
204 return $self->{'default_value'};
205}
206
207# ----------------------------------------------------------------------
9966eebc 208=pod
209
210=head2 extra
211
212Get or set the field's "extra" attibutes (e.g., "ZEROFILL" for MySQL).
213Accepts a hash(ref) of name/value pairs to store; returns a hash.
214
215 $field->extra( qualifier => 'ZEROFILL' );
216 my %extra = $field->extra;
217
218=cut
219
9966eebc 220
221# ----------------------------------------------------------------------
222sub foreign_key_reference {
223
224=pod
225
226=head2 foreign_key_reference
227
228Get or set the field's foreign key reference;
229
230 my $constraint = $field->foreign_key_reference( $constraint );
231
232=cut
233
234 my $self = shift;
235
236 if ( my $arg = shift ) {
237 my $class = 'SQL::Translator::Schema::Constraint';
238 if ( UNIVERSAL::isa( $arg, $class ) ) {
239 return $self->error(
240 'Foreign key reference for ', $self->name, 'already defined'
241 ) if $self->{'foreign_key_reference'};
242
243 $self->{'foreign_key_reference'} = $arg;
244 }
245 else {
246 return $self->error(
247 "Argument to foreign_key_reference is not an $class object"
248 );
249 }
250 }
251
252 return $self->{'foreign_key_reference'};
253}
254
255# ----------------------------------------------------------------------
43b9dc7a 256sub is_auto_increment {
257
258=pod
259
260=head2 is_auto_increment
261
262Get or set the field's C<is_auto_increment> attribute.
263
b9dc0b40 264 my $is_auto = $field->is_auto_increment(1);
43b9dc7a 265
266=cut
267
268 my ( $self, $arg ) = @_;
269
270 if ( defined $arg ) {
271 $self->{'is_auto_increment'} = $arg ? 1 : 0;
272 }
273
274 unless ( defined $self->{'is_auto_increment'} ) {
275 if ( my $table = $self->table ) {
276 if ( my $schema = $table->schema ) {
277 if (
278 $schema->database eq 'PostgreSQL' &&
279 $self->data_type eq 'serial'
280 ) {
281 $self->{'is_auto_increment'} = 1;
282 }
283 }
284 }
285 }
286
287 return $self->{'is_auto_increment'} || 0;
288}
289
290# ----------------------------------------------------------------------
9966eebc 291sub is_foreign_key {
292
293=pod
294
295=head2 is_foreign_key
296
297Returns whether or not the field is a foreign key.
298
299 my $is_fk = $field->is_foreign_key;
300
301=cut
302
303 my ( $self, $arg ) = @_;
304
305 unless ( defined $self->{'is_foreign_key'} ) {
306 if ( my $table = $self->table ) {
307 for my $c ( $table->get_constraints ) {
308 if ( $c->type eq FOREIGN_KEY ) {
309 my %fields = map { $_, 1 } $c->fields;
310 if ( $fields{ $self->name } ) {
311 $self->{'is_foreign_key'} = 1;
312 $self->foreign_key_reference( $c );
313 last;
314 }
315 }
316 }
317 }
318 }
319
320 return $self->{'is_foreign_key'} || 0;
321}
322
9966eebc 323# ----------------------------------------------------------------------
ec2ab48d 324sub is_nullable {
325
326=pod
327
328=head2 is_nullable
329
b9dc0b40 330Get or set whether the field can be null. If not defined, then
ec2ab48d 331returns "1" (assumes the field can be null). The argument is evaluated
332by Perl for True or False, so the following are eqivalent:
333
334 $is_nullable = $field->is_nullable(0);
335 $is_nullable = $field->is_nullable('');
336 $is_nullable = $field->is_nullable('0');
337
338While this is technically a field constraint, it's probably easier to
339represent this as an attribute of the field. In order keep things
340consistent, any other constraint on the field (unique, primary, and
341foreign keys; checks) are represented as table constraints.
342
343=cut
344
345 my ( $self, $arg ) = @_;
346
347 if ( defined $arg ) {
348 $self->{'is_nullable'} = $arg ? 1 : 0;
349 }
350
42c8fad4 351 if (
352 defined $self->{'is_nullable'} &&
353 $self->{'is_nullable'} == 1 &&
354 $self->is_primary_key
355 ) {
356 $self->{'is_nullable'} = 0;
357 }
358
ec2ab48d 359 return defined $self->{'is_nullable'} ? $self->{'is_nullable'} : 1;
360}
361
362# ----------------------------------------------------------------------
3c5de62a 363sub is_primary_key {
364
365=pod
366
367=head2 is_primary_key
368
ec2ab48d 369Get or set the field's C<is_primary_key> attribute. Does not create
370a table constraint (should it?).
3c5de62a 371
372 my $is_pk = $field->is_primary_key(1);
373
374=cut
375
376 my ( $self, $arg ) = @_;
377
378 if ( defined $arg ) {
379 $self->{'is_primary_key'} = $arg ? 1 : 0;
380 }
381
43b9dc7a 382 unless ( defined $self->{'is_primary_key'} ) {
383 if ( my $table = $self->table ) {
384 if ( my $pk = $table->primary_key ) {
385 my %fields = map { $_, 1 } $pk->fields;
386 $self->{'is_primary_key'} = $fields{ $self->name } || 0;
387 }
388 else {
389 $self->{'is_primary_key'} = 0;
390 }
391 }
392 }
393
3c5de62a 394 return $self->{'is_primary_key'} || 0;
395}
396
397# ----------------------------------------------------------------------
ee2766f4 398sub is_unique {
399
400=pod
401
402=head2 is_unique
403
404Determine whether the field has a UNIQUE constraint or not.
405
406 my $is_unique = $field->is_unique;
407
408=cut
409
410 my $self = shift;
411
412 unless ( defined $self->{'is_unique'} ) {
413 if ( my $table = $self->table ) {
414 for my $c ( $table->get_constraints ) {
415 if ( $c->type eq UNIQUE ) {
416 my %fields = map { $_, 1 } $c->fields;
417 if ( $fields{ $self->name } ) {
418 $self->{'is_unique'} = 1;
419 last;
420 }
421 }
422 }
423 }
424 }
425
426 return $self->{'is_unique'} || 0;
427}
428
429# ----------------------------------------------------------------------
ec2ab48d 430sub is_valid {
431
432=pod
433
434=head2 is_valid
435
436Determine whether the field is valid or not.
437
438 my $ok = $field->is_valid;
439
440=cut
441
442 my $self = shift;
443 return $self->error('No name') unless $self->name;
444 return $self->error('No data type') unless $self->data_type;
445 return $self->error('No table object') unless $self->table;
446 return 1;
447}
448
449# ----------------------------------------------------------------------
3c5de62a 450sub name {
451
452=pod
453
454=head2 name
455
456Get or set the field's name.
457
65dd38c0 458 my $name = $field->name('foo');
459
460The field object will also stringify to its name.
461
462 my $setter_name = "set_$field";
463
464Errors ("No field name") if you try to set a blank name.
3c5de62a 465
466=cut
467
468 my $self = shift;
43b9dc7a 469
65dd38c0 470 if ( @_ ) {
471 my $arg = shift || return $self->error( "No field name" );
43b9dc7a 472 if ( my $table = $self->table ) {
65dd38c0 473 return $self->error( qq[Can't use field name "$arg": field exists] )
43b9dc7a 474 if $table->get_field( $arg );
475 }
476
477 $self->{'name'} = $arg;
478 }
479
3c5de62a 480 return $self->{'name'} || '';
481}
482
4809213f 483sub full_name {
484
485=head2 full_name
486
487Read only method to return the fields name with its table name pre-pended.
488e.g. "person.foo".
489
490=cut
491
492 my $self = shift;
493 return $self->table.".".$self->name;
494}
495
3c5de62a 496# ----------------------------------------------------------------------
ec2ab48d 497sub order {
3c5de62a 498
499=pod
500
ec2ab48d 501=head2 order
3c5de62a 502
ec2ab48d 503Get or set the field's order.
3c5de62a 504
ec2ab48d 505 my $order = $field->order(3);
3c5de62a 506
507=cut
508
509 my ( $self, $arg ) = @_;
510
ec2ab48d 511 if ( defined $arg && $arg =~ /^\d+$/ ) {
512 $self->{'order'} = $arg;
3c5de62a 513 }
514
ec2ab48d 515 return $self->{'order'} || 0;
43b9dc7a 516}
517
518# ----------------------------------------------------------------------
c1e3c768 519sub schema {
520
521=head2 schema
522
523Shortcut to get the fields schema ($field->table->schema) or undef if it
524doesn't have one.
525
526 my $schema = $field->schema;
527
528=cut
529
530 my $self = shift;
531 if ( my $table = $self->table ) { return $table->schema || undef; }
532 return undef;
533}
534
535# ----------------------------------------------------------------------
43b9dc7a 536sub size {
537
538=pod
539
540=head2 size
541
542Get or set the field's size. Accepts a string, array or arrayref of
543numbers and returns a string.
544
545 $field->size( 30 );
546 $field->size( [ 255 ] );
547 $size = $field->size( 10, 2 );
548 print $size; # prints "10,2"
549
550 $size = $field->size( '10, 2' );
551 print $size; # prints "10,2"
552
553=cut
554
555 my $self = shift;
ec2ab48d 556 my $numbers = parse_list_arg( @_ );
43b9dc7a 557
558 if ( @$numbers ) {
559 my @new;
560 for my $num ( @$numbers ) {
561 if ( defined $num && $num =~ m/^\d+(?:\.\d+)?$/ ) {
562 push @new, $num;
563 }
564 }
565 $self->{'size'} = \@new if @new; # only set if all OK
566 }
567
ec2ab48d 568 return wantarray
aadf4042 569 ? @{ $self->{'size'} || [0] }
ec2ab48d 570 : join( ',', @{ $self->{'size'} || [0] } )
571 ;
43b9dc7a 572}
573
574# ----------------------------------------------------------------------
575sub table {
576
577=pod
578
579=head2 table
580
b9dc0b40 581Get or set the field's table object. As the table object stringifies this can
582also be used to get the table name.
43b9dc7a 583
584 my $table = $field->table;
b9dc0b40 585 print "Table name: $table";
43b9dc7a 586
587=cut
588
589 my $self = shift;
590 if ( my $arg = shift ) {
591 return $self->error('Not a table object') unless
592 UNIVERSAL::isa( $arg, 'SQL::Translator::Schema::Table' );
593 $self->{'table'} = $arg;
594 }
595
596 return $self->{'table'};
3c5de62a 597}
598
07d6e5f7 599sub parsed_field {
600
601=head2
602
603Returns the field exactly as the parser found it
604
605=cut
606
607 my $self = shift;
608
609 if (@_) {
610 my $value = shift;
611 $self->{parsed_field} = $value;
612 return $value || $self;
613 }
614 return $self->{parsed_field} || $self;
615}
616
ec2ab48d 617# ----------------------------------------------------------------------
abf315bb 618sub equals {
619
620=pod
621
622=head2 equals
623
624Determines if this field is the same as another
625
626 my $isIdentical = $field1->equals( $field2 );
627
628=cut
629
630 my $self = shift;
631 my $other = shift;
632 my $case_insensitive = shift;
633
634 return 0 unless $self->SUPER::equals($other);
635 return 0 unless $case_insensitive ? uc($self->name) eq uc($other->name) : $self->name eq $other->name;
6b2dbb1a 636
637 # Comparing types: use sql_data_type if both are not 0. Else use string data_type
638 if ($self->sql_data_type && $other->sql_data_type) {
639 return 0 unless $self->sql_data_type == $other->sql_data_type
640 } else {
641 return 0 unless lc($self->data_type) eq lc($other->data_type)
642 }
643
abf315bb 644 return 0 unless $self->size eq $other->size;
f5fd433f 645
646 {
647 my $lhs = $self->default_value;
648 $lhs = \'NULL' unless defined $lhs;
649 my $lhs_is_ref = ! ! ref $lhs;
650
651 my $rhs = $other->default_value;
652 $rhs = \'NULL' unless defined $rhs;
653 my $rhs_is_ref = ! ! ref $rhs;
654
655 # If only one is a ref, fail. -- rjbs, 2008-12-02
656 return 0 if $lhs_is_ref xor $rhs_is_ref;
657
658 my $effective_lhs = $lhs_is_ref ? $$lhs : $lhs;
659 my $effective_rhs = $rhs_is_ref ? $$rhs : $rhs;
660
661 return 0 if $effective_lhs ne $effective_rhs;
662 }
663
abf315bb 664 return 0 unless $self->is_nullable eq $other->is_nullable;
afb07483 665# return 0 unless $self->is_unique eq $other->is_unique;
abf315bb 666 return 0 unless $self->is_primary_key eq $other->is_primary_key;
65e7a069 667# return 0 unless $self->is_foreign_key eq $other->is_foreign_key;
abf315bb 668 return 0 unless $self->is_auto_increment eq $other->is_auto_increment;
669# return 0 unless $self->comments eq $other->comments;
4598b71c 670 return 0 unless $self->_compare_objects(scalar $self->extra, scalar $other->extra);
abf315bb 671 return 1;
672}
673
674# ----------------------------------------------------------------------
ec2ab48d 675sub DESTROY {
9966eebc 676#
677# Destroy cyclical references.
678#
ec2ab48d 679 my $self = shift;
9966eebc 680 undef $self->{'table'};
681 undef $self->{'foreign_key_reference'};
ec2ab48d 682}
683
3c5de62a 6841;
685
686# ----------------------------------------------------------------------
687
688=pod
689
690=head1 AUTHOR
691
6606c4c6 692Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
3c5de62a 693
694=cut