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