[Rt-commit] [svn] r1771 - in DBIx-SearchBuilder/trunk: . SearchBuilder t

jesse at pallas.eruditorum.org jesse at pallas.eruditorum.org
Wed Nov 10 01:58:16 EST 2004


Author: jesse
Date: Wed Nov 10 01:58:15 2004
New Revision: 1771

Modified:
   DBIx-SearchBuilder/trunk/   (props changed)
   DBIx-SearchBuilder/trunk/Changes
   DBIx-SearchBuilder/trunk/SearchBuilder.pm
   DBIx-SearchBuilder/trunk/SearchBuilder/Record.pm
   DBIx-SearchBuilder/trunk/t/01records.t
Log:
 r8977 at tinbook:  jesse | 2004-11-10T06:59:18.707372Z
     - SearchBuilder now truncates strings before inserting them into character
       types in the database as mysql generally does. Additionally, it truncates
       things at utf8 character boundaries...as mysql does not.
 
 
 


Modified: DBIx-SearchBuilder/trunk/Changes
==============================================================================
--- DBIx-SearchBuilder/trunk/Changes	(original)
+++ DBIx-SearchBuilder/trunk/Changes	Wed Nov 10 01:58:15 2004
@@ -10,8 +10,11 @@
     - Refactoring of DBIx::SearchBuilder::Record::Cachable for performance
       improvement
     - Added a FlushCache method to DBIx::SearchBuilder::Record::Cachable.
-
     - Started to flesh out a...test suite
+    - SearchBuilder now truncates strings before inserting them into character
+      types in the database as mysql generally does. Additionally, it truncates
+      things at utf8 character boundaries...as mysql does not.
+    
 
 
 1.12

Modified: DBIx-SearchBuilder/trunk/SearchBuilder.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder.pm	Wed Nov 10 01:58:15 2004
@@ -5,7 +5,7 @@
 use strict;
 use vars qw($VERSION);
 
-$VERSION = "1.12";
+$VERSION = "1.13_01";
 
 =head1 NAME
 

Modified: DBIx-SearchBuilder/trunk/SearchBuilder/Record.pm
==============================================================================
--- DBIx-SearchBuilder/trunk/SearchBuilder/Record.pm	(original)
+++ DBIx-SearchBuilder/trunk/SearchBuilder/Record.pm	Wed Nov 10 01:58:15 2004
@@ -632,10 +632,12 @@
 sub __Set {
     my $self = shift;
 
-    my %args = ( 'Field' => undef,
-                 'Value' => undef,
-                 'IsSQL' => undef,
-                 @_ );
+    my %args = (
+        'Field' => undef,
+        'Value' => undef,
+        'IsSQL' => undef,
+        @_
+    );
 
     $args{'Column'}        = $args{'Field'};
     $args{'IsSQLFunction'} = $args{'IsSQL'};
@@ -648,64 +650,86 @@
 
     unless ( defined( $args{'Column'} ) && $args{'Column'} ) {
         $ret->as_array( 0, 'No column specified' );
-        $ret->as_error( errno   => 5,
-                        do_backtrace => 0,
-                            message => "No column specified" );
-        return ($ret->return_value);
+        $ret->as_error(
+            errno        => 5,
+            do_backtrace => 0,
+            message      => "No column specified"
+        );
+        return ( $ret->return_value );
     }
     my $column = lc $args{'Column'};
-    if (     ( defined $self->__Value($column) )
-         and ( $args{'Value'} eq $self->__Value($column) ) ) {
+    if (    ( defined $self->__Value($column) )
+        and ( $args{'Value'} eq $self->__Value($column) ) )
+    {
         $ret->as_array( 0, "That is already the current value" );
-        $ret->as_error( errno   => 1,
-                        do_backtrace => 0,
-                            message => "That is already the current value" );
-        return ($ret->return_value);
+        $ret->as_error(
+            errno        => 1,
+            do_backtrace => 0,
+            message      => "That is already the current value"
+        );
+        return ( $ret->return_value );
     }
     elsif ( !defined( $args{'Value'} ) ) {
         $ret->as_array( 0, "No value passed to _Set" );
-        $ret->as_error( errno   => 2,
-                        do_backtrace => 0,
-                            message => "No value passed to _Set" );
-        return ($ret->return_value);
+        $ret->as_error(
+            errno        => 2,
+            do_backtrace => 0,
+            message      => "No value passed to _Set"
+        );
+        return ( $ret->return_value );
     }
-    else {
 
-        my $method = "Validate" . $args{'Column'};
-        unless ( $self->$method( $args{'Value'} ) ) {
-            $ret->as_array( 0, 'Illegal value for ' . $args{'Column'} );
-            $ret->as_error(errno   => 3,
-                        do_backtrace => 0,
-                               message => "Illegal value for " . $args{'Column'}
-            );
-            return ($ret->return_value);
-        }
 
-        $args{'Table'}       = $self->Table();
-        $args{'PrimaryKeys'} = { $self->PrimaryKeys() };
 
-        my $val = $self->_Handle->UpdateRecordValue(%args);
-        unless ($val) {
-            $ret->as_array( 0,
-                                $args{'Column'}
-                                  . " could not be set to "
-                                  . $args{'Value'} . "." );
-            $ret->as_error( errno   => 4,
-                        do_backtrace => 0,
-                                message => $args{'Column'}
-                                  . " could not be set to "
-                                  . $args{'Value'} . "." );
-            return ($ret->return_value);
-        }
-        if ( $args{'IsSQLFunction'} ) {
-            $self->Load( $self->Id );
-        }
-        else {
-            $self->{'values'}->{"$column"} = $args{'Value'};
-        }
+    # First, we truncate the value, if we need to.
+    #
+    
+
+    my $value = $self->TruncateValue ( $args{'Column'}, $args{'Value'});
+    unless ($value eq $args{'Value'}) {
+        $args{'OriginalValue'} = $args{'Value'};
+        $args{'Value'} = $value;
+    }
+
+
+
+    my $method = "Validate" . $args{'Column'};
+    unless ( $self->$method( $args{'Value'} ) ) {
+        $ret->as_array( 0, 'Illegal value for ' . $args{'Column'} );
+        $ret->as_error(
+            errno        => 3,
+            do_backtrace => 0,
+            message      => "Illegal value for " . $args{'Column'}
+        );
+        return ( $ret->return_value );
+    }
+
+    $args{'Table'}       = $self->Table();
+    $args{'PrimaryKeys'} = { $self->PrimaryKeys() };
+
+    my $val = $self->_Handle->UpdateRecordValue(%args);
+    unless ($val) {
+        my $message = 
+            $args{'Column'} . " could not be set to " . $args{'Value'} . "." ;
+        $ret->as_array( 0, $message);
+        $ret->as_error(
+            errno        => 4,
+            do_backtrace => 0,
+            message      => $message
+        );
+        return ( $ret->return_value );
+    }
+    # If we've performed some sort of "functional update"
+    # then we need to reload the object from the DB to know what's
+    # really going on. (ex SET Cost = Cost+5)
+    if ( $args{'IsSQLFunction'} ) {
+        $self->Load( $self->Id );
+    }
+    else {
+        $self->{'values'}->{"$column"} = $args{'Value'};
     }
     $ret->as_array( 1, "The new value has been set." );
-    return ($ret->return_value);
+    return ( $ret->return_value );
 }
 
 # }}}
@@ -733,6 +757,58 @@
 
 # }}}	
 
+# {{{ sub TruncateValue 
+
+=head2 TruncateValue  KEY VALUE
+
+Truncate a value that's about to be set so that it will fit inside the database'
+s idea of how big the column is. 
+
+(Actually, it looks at searchbuilder's concept of the database, not directly into the db).
+
+=cut
+
+sub TruncateValue {
+    my $self  = shift;
+    my $key   = shift;
+    my $value = shift;
+
+    my $metadata = $self->_ClassAccessible->{$key};
+
+    my $truncate_to;
+    if ( $metadata->{'length'} && !$metadata->{'is_numeric'} ) {
+        $truncate_to = $metadata->{'length'};
+    }
+    elsif ( $metadata->{'type'} =~ /char\((\d+)\)/ ) {
+        $truncate_to = $1;
+    }
+
+    return ($value) unless ($truncate_to);    # don't need to truncate
+
+    # Perl 5.6 didn't speak unicode
+    return substr( $value, 0, $truncate_to ) unless ( $] >= 5.007 );
+
+    require Encode;
+
+    if ( Encode::is_utf8($value) ) {
+        return Encode::decode(
+            utf8 => substr( Encode::encode( utf8 => $value ), 0, $truncate_to ),
+            Encode::FB_QUIET(),
+        );
+    }
+    else {
+        return Encode::encode(
+            utf8 => Encode::decode(
+                utf8 => substr( $value, 0, $truncate_to ),
+                Encode::FB_QUIET(),
+            )
+        );
+
+    }
+
+}
+# }}}
+
 # {{{ sub _Object 
 
 =head2 _Object
@@ -1026,6 +1102,11 @@
     my ($key);
     foreach $key ( keys %attribs ) {
         my $method = "Validate$key";
+
+            #Truncate things that are too long for their datatypes
+        my $value = $self->TruncateValue ($key => $attribs{$key});
+        $attribs{$key} = $value unless ($value eq $attribs{$key});
+
         unless ( $self->$method( $attribs{$key} ) ) {
             delete $attribs{$key};
         }

Modified: DBIx-SearchBuilder/trunk/t/01records.t
==============================================================================
--- DBIx-SearchBuilder/trunk/t/01records.t	(original)
+++ DBIx-SearchBuilder/trunk/t/01records.t	Wed Nov 10 01:58:15 2004
@@ -44,6 +44,47 @@
 
 is($rec->Name, 'Obra', "We did actually change the name");
 
+# Validate truncation on update
+
+($val,$msg) = $rec->SetName('1234567890123456789012345678901234567890');
+
+ok($val, $msg) ;
+
+is($rec->Name, '12345678901234', "Truncated on update");
+
+
+
+# Test unicode truncation:
+my $univalue = "這是個測試";
+
+($val,$msg) = $rec->SetName($univalue.$univalue);
+
+ok($val, $msg) ;
+
+is($rec->Name, '這是個測');
+
+
+
+# make sure we do _not_ truncate things which should not be truncated
+($val,$msg) = $rec->SetEmployeeId('1234567890');
+
+ok($val, $msg) ;
+
+is($rec->EmployeeId, '1234567890', "Did not truncate id on create");
+
+# make sure we do truncation on create
+my $newrec = TestApp::Address->new($handle);
+my $newid = $newrec->Create( Name => '1234567890123456789012345678901234567890',
+                             EmployeeId => '1234567890' );
+
+$newrec->Load($newid);
+
+ok ($newid, "Created a new record");
+is($newrec->Name, '12345678901234', "Truncated on create");
+is($newrec->EmployeeId, '1234567890', "Did not truncate id on create");
+
+
+
 package TestApp::Address;
 
 use base qw/DBIx::SearchBuilder::Record/;
@@ -62,7 +103,7 @@
         id =>
         {read => 1, type => 'int(11)', default => ''}, 
         Name => 
-        {read => 1, write => 1, type => 'varchar(36)', default => ''},
+        {read => 1, write => 1, type => 'varchar(14)', default => ''},
         Phone => 
         {read => 1, write => 1, type => 'varchar(18)', default => ''},
         EmployeeId => 


More information about the Rt-commit mailing list