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