Doctrine 1
  1. Doctrine 1
  2. DC-550

Cannot update record from one large integer to another large integer (severe problem for 32bit systems, due to the low upper limit of the int data type)

    Details

      Description

      From what I understand, doctrine mostly stores integers as strings. To check whether an integer has been modified, the following code in Doctrine_Record is used:

          protected function _isValueModified($type, $old, $new)
          {
              if ($new instanceof Doctrine_Expression) {
                  return true;
              }
      
              if ($type == 'boolean' && (is_bool($old) || is_numeric($old)) && (is_bool($new) || is_numeric($new)) && $old == $new) {
                  return false;
              } else if (in_array($type, array('decimal', 'float')) && is_numeric($old) && is_numeric($new)) {
                  return $old * 100 != $new * 100;
              } else if (in_array($type, array('integer', 'int')) && is_numeric($old) && is_numeric($new)) {
                  return (int) $old !== (int) $new;  # <--- ********** THIS LINE CASTS STRING TO INT **********
              } else if ($type == 'timestamp' || $type == 'date') {
                  return strtotime($old) !== strtotime($new);
              } else {
                  return $old !== $new;
              }
          }
      

      On the line indicated above an integer, stored as a string, is cast to a PHP integer data type, and compared with the existing value of the field currently stored in the database. For values that fall within the int type range, this works fine. However, when changing a value falling above the range, which on 32bit systems is 2147483647, to another value falling above the range, these casts cause the code to evaluate both as 2147483647 and hence the field is not added to the _IsModified() array, and the value is not updated.

      Bearing in mind that validation to confirm whether these strings are in numeric format should already have occurred by this point in the process, is there any need to cast the strings at all? Thus, is the following a possible solution?

                  return $old !== $new;
      

      This seems to work fine for me in my limited trials although, admittedly, there may be some consequences about which I am not aware.

      Note that this issue is not so evident on 64bit systems, where the upper limit is much higher.

      1. Record.php.patch
        0.7 kB
        hal
      2. Record.php.patch
        0.7 kB
        hal

        Activity

        Hide
        hal added a comment -

        Patch for described problem (untested)

        Show
        hal added a comment - Patch for described problem (untested)

          People

          • Assignee:
            Jonathan H. Wage
            Reporter:
            hal
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: