Extend Field->equals() for numeric comparison
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Schema / Field.pm
index 4adc293..47f1b5d 100644 (file)
@@ -25,8 +25,9 @@ C<SQL::Translator::Schema::Field> is the field object.
 use Moo;
 use SQL::Translator::Schema::Constants;
 use SQL::Translator::Types qw(schema_obj);
-use SQL::Translator::Utils qw(parse_list_arg ex2err throw);
+use SQL::Translator::Utils qw(parse_list_arg ex2err throw carp_ro);
 use Sub::Quote qw(quote_sub);
+use Scalar::Util ();
 
 extends 'SQL::Translator::Schema::Object';
 
@@ -43,13 +44,14 @@ use overload
 
 use DBI qw(:sql_types);
 
-# Mapping from string to sql contstant
+# Mapping from string to sql constant
 our %type_mapping = (
   integer => SQL_INTEGER,
   int     => SQL_INTEGER,
 
+  tinyint => SQL_TINYINT,
   smallint => SQL_SMALLINT,
-  bigint => 9999, # DBI doesn't export a constatn for this. Le suck
+  bigint => SQL_BIGINT,
 
   double => SQL_DOUBLE,
 
@@ -74,6 +76,16 @@ our %type_mapping = (
 
 );
 
+has _numeric_sql_data_types => ( is => 'lazy' );
+
+sub _build__numeric_sql_data_types {
+    return {
+        map { $_ => 1 }
+            (SQL_INTEGER, SQL_TINYINT, SQL_SMALLINT, SQL_BIGINT, SQL_DOUBLE,
+             SQL_NUMERIC, SQL_DECIMAL, SQL_FLOAT, SQL_REAL)
+    };
+}
+
 =head2 new
 
 Object constructor.
@@ -98,7 +110,7 @@ all the comments joined on newlines.
 
 has comments => (
     is => 'rw',
-    coerce => sub { ref($_[0]) eq 'ARRAY' ? $_[0] : [$_[0]] },
+    coerce => quote_sub(q{ ref($_[0]) eq 'ARRAY' ? $_[0] : [$_[0]] }),
     default => quote_sub(q{ [] }),
 );
 
@@ -152,16 +164,6 @@ assume an error like other methods.
 
 has default_value => ( is => 'rw' );
 
-=head2 extra
-
-Get or set the field's "extra" attibutes (e.g., "ZEROFILL" for MySQL).
-Accepts a hash(ref) of name/value pairs to store;  returns a hash.
-
-  $field->extra( qualifier => 'ZEROFILL' );
-  my %extra = $field->extra;
-
-=cut
-
 =head2 foreign_key_reference
 
 Get or set the field's foreign key reference;
@@ -201,7 +203,7 @@ Get or set the field's C<is_auto_increment> attribute.
 
 has is_auto_increment => (
     is => 'rw',
-    coerce => sub { $_[0] ? 1 : 0 },
+    coerce => quote_sub(q{ $_[0] ? 1 : 0 }),
     builder => 1,
     lazy => 1,
 );
@@ -232,7 +234,7 @@ Returns whether or not the field is a foreign key.
 
 has is_foreign_key => (
     is => 'rw',
-    coerce => sub { $_[0] ? 1 : 0 },
+    coerce => quote_sub(q{ $_[0] ? 1 : 0 }),
     builder => 1,
     lazy => 1,
 );
@@ -258,7 +260,7 @@ sub _build_is_foreign_key {
 
 Get or set whether the field can be null.  If not defined, then
 returns "1" (assumes the field can be null).  The argument is evaluated
-by Perl for True or False, so the following are eqivalent:
+by Perl for True or False, so the following are equivalent:
 
   $is_nullable = $field->is_nullable(0);
   $is_nullable = $field->is_nullable('');
@@ -273,7 +275,7 @@ foreign keys; checks) are represented as table constraints.
 
 has is_nullable => (
     is => 'rw',
-    coerce => sub { $_[0] ? 1 : 0 },
+    coerce => quote_sub(q{ $_[0] ? 1 : 0 }),
     default => quote_sub(q{ 1 }),
  );
 
@@ -294,7 +296,7 @@ a table constraint (should it?).
 
 has is_primary_key => (
     is => 'rw',
-    coerce => sub { $_[0] ? 1 : 0 },
+    coerce => quote_sub(q{ $_[0] ? 1 : 0 }),
     lazy => 1,
     builder => 1,
 );
@@ -321,6 +323,8 @@ Determine whether the field has a UNIQUE constraint or not.
 
 has is_unique => ( is => 'lazy', init_arg => undef );
 
+around is_unique => carp_ro('is_unique');
+
 sub _build_is_unique {
     my ( $self ) = @_;
 
@@ -494,7 +498,7 @@ has table => ( is => 'rw', isa => schema_obj('Table'), weak_ref => 1 );
 
 around table => \&ex2err;
 
-=head2
+=head2 parsed_field
 
 Returns the field exactly as the parser found it
 
@@ -550,7 +554,14 @@ around equals => sub {
         my $effective_lhs = $lhs_is_ref ? $$lhs : $lhs;
         my $effective_rhs = $rhs_is_ref ? $$rhs : $rhs;
 
-        return 0 if $effective_lhs ne $effective_rhs;
+        if ( $self->_is_numeric_data_type
+             && Scalar::Util::looks_like_number($effective_lhs)
+             && Scalar::Util::looks_like_number($effective_rhs) ) {
+            return 0 if ($effective_lhs + 0) != ($effective_rhs + 0);
+        }
+        else {
+            return 0 if $effective_lhs ne $effective_rhs;
+        }
     }
 
     return 0 unless $self->is_nullable eq $other->is_nullable;
@@ -566,6 +577,11 @@ around equals => sub {
 # Must come after all 'has' declarations
 around new => \&ex2err;
 
+sub _is_numeric_data_type {
+    my $self = shift;
+    return $self->_numeric_sql_data_types->{ $self->sql_data_type };
+}
+
 1;
 
 =pod