Form-Sensible-Reflector-MySQL
view release on metacpan or search on metacpan
lib/Form/Sensible/Reflector/MySQL.pm view on Meta::CPAN
}
else {
@rv = keys %{ $self->{table_metadata}->{ $form->{name} } };
}
return @rv;
}
# Should numbers be allowed to contain commas?
sub get_field_definition {
my ($self, $form, $dbh, $fieldname) = @_;
my $mysql_type = $self->{table_metadata}->{ $form->{name} }->{$fieldname}->{Type};
DEBUG $fieldname .': '.$mysql_type;
my $f = {
name => $fieldname,
field_class => 'Number'
};
# db defaults - not no_db_defaults
if ( not( $self->no_db_defaults )
and $self->{table_metadata}->{ $form->{name} }->{$fieldname}->{Default}
and $mysql_type ne 'timestamp' # avoid a value of CURRENT_TIMESTAMP
){
$self->{defaults}->{$fieldname} =
$self->{table_metadata}->{ $form->{name} }->{$fieldname}->{Default};
DEBUG "Set $fieldname to default ", $self->{defaults}->{$fieldname};
}
# Numeric types - http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html
# NB display width with zero-padding for INT(M) -
# Cf http://alexander.kirk.at/2007/08/24/what-does-size-in-intsize-of-mysql-mean/
if ($mysql_type =~ /^tinyint/){
$f->{integer_only} = 1;
$f->{lower_bound} = $mysql_type =~ /unsigned/? 0 : -128;
$f->{upper_bound} = $mysql_type =~ /unsigned/? 255 : 127;
}
elsif ($mysql_type =~ /^smallint/){
$f->{integer_only} = 1;
$f->{lower_bound} = $mysql_type =~ /unsigned/? 0 : -32768;
$f->{upper_bound} = $mysql_type =~ /unsigned/? 65535 : 32767;
}
elsif ($mysql_type =~ /^mediumint/){
$f->{integer_only} = 1;
$f->{lower_bound} = $mysql_type =~ /unsigned/? 0 : -8388608;
$f->{upper_bound} = $mysql_type =~ /unsigned/? 16777215 : 8388607;
}
elsif ($mysql_type =~ /^int/){
$f->{integer_only} = 1;
$f->{lower_bound} = $mysql_type =~ /unsigned/? 0 : -2147483648;
$f->{upper_bound} = $mysql_type =~ /unsigned/? 4294967295 : 2147483647;
}
# Treat massive integers as strings or nothing works
elsif ($mysql_type =~ /^bigint/){
$f->{field_type} = 'Text';
$f->{validation} = { code => $mysql_type =~ /unsigned/ ?
sub {
use Math::BigInt;
my $n = Math::BigInt->new( $_[0] );
# return '_FIELDNAME_ is an invalid unsigned big integer' if $n eq 'NaN';
return $self->i18n->{ubigint}->{nan} if $n eq 'NaN';
return $self->i18n->{ubigint}->{not_int} if not $n->is_int;
return $self->i18n->{ubigint}->{too_high} if $n > 8446744073709551615;
return $self->i18n->{ubigint}->{too_low} if $n < 0;
return 0;
}
: sub {
use Math::BigInt ':constant';
my $n = Math::BigInt->new( $_[0] );
return $self->i18n->{sbigint}->{nan} if $n eq 'NaN';
return $self->i18n->{sbigint}->{not_int} if not $n->is_int;
return $self->i18n->{sbigint}->{too_high} if $n > 9223372036854775807;
return $self->i18n->{sbigint}->{too_low} if $n < -9223372036854775808;
return 0;
}
};
}
elsif ($mysql_type =~ /^(double|real)/){
$f->{field_type} = 'Text';
$f->{validation} = { code => sub {
use Math::BigFloat ':constant';
my $n = Math::BigFloat->new( $_[0] );
return $self->i18n->{double}->{nan} if $n eq 'NaN';
return $self->i18n->{double}->{oob}
if ($n <= -1.7976931348623157E+308 and $n >= -2.2250738585072014E-308)
or $n== 0
or ($n <= 2.2250738585072014E-308 and $n >= 1.7976931348623157E+3080);
return 0;
}
};
}
elsif ($mysql_type =~ /^(decimal|numeric) (?: \((\d+) (?:,(\d+))? \) )?$/x ){
my ($m, $d) = ($2, $3);
# $m apprently includes the decimal point:
$m = 0 if $m < 0;
$m ||= 65; #Â But not in 5.0.3-5.0.5, when is 64
$d ||= 0;
$f->{field_type} = 'Text';
$f->{validation} = { code => sub {
# Naively assume it's a nice decimal/number
my ($mym, $myd) = $_[0] =~ /^(\d+) (?: \. (\d+) )?$/x;
$mym ||= 0;
$myd ||= 0;
return $self->i18n->{decimal}->{nan}
if not $mym and not $myd and $_[0] !~ /^0*(\.0+)?$/x;
return $self->i18n->{decimal}->{too_long}.$m
if (length($mym) + length($myd)) > $m;
return $self->i18n->{decimal}->{post_point}.$d
if length($myd) > $d;
return 0;
}
};
}
# Floating-Point (Approximate-Value) Types
# Defaut range desc at http://help.scibit.com/mascon/masconMySQL_Field_Types.html
# and Fixed-Point (Exact-Value) Types
elsif ($mysql_type =~ /^(float|double precision)/){
my ($d, $e);
if ($mysql_type =~ /\((\d+),(\d+)\)/){
($d, $e) = ($1, $2);
}
elsif ( $mysql_type =~ /^(numeric|decimal)(\((\d+)\))?/ ){
($d, $e) = ($2, undef);
}
if (defined $d){
my $valid_re = $e?
qr/^-?\d{1,$d}(\.\d{0,$e})?$/
: qr/^-?\d{1,$d}$/;
$f->{validation} = {
code => sub {
return $self->i18n->{float}->{nan} unless $_[0] =~ $NUMBER_RE;
return $self->i18n->{float}->{invalid}.$d if $_[0] !~ $valid_re;
return 0;
}
};
my $max = '9' x $d;
$max .= '.' . ('9' x $e) if $e;
$f->{upper_bound} = $max;
if ($mysql_type =~ /unsigned/){
( run in 1.268 second using v1.01-cache-2.11-cpan-39bf76dae61 )