Doctrine DBAL
  1. Doctrine DBAL
  2. DBAL-394

Unsigned integers are not respected by the schema tool for assocations

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 2.3
    • Fix Version/s: 2.4
    • Component/s: Schema Managers
    • Labels:
      None

      Description

      Before commenting, I've done so much debugging and searching into this issue and if I missed something major, I apologise.

      From what I understand, the ORM doesn't care about unsigned. That's fair enough. That leaves it to DBAL to handle it.

      However, it's not possible to successfully use something like the following table without having the schema manager complain.

      CREATE TABLE `account` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '(DC2Type:unsigned_integer)',
        `user_id` int(10) unsigned DEFAULT NULL COMMENT '(DC2Type:unsigned_integer)',
        PRIMARY KEY (`id`),
        KEY `IDX_7D3656A461220EA6` (`user_id`)
      ) ENGINE=InnoDB
      

      In that code, I'm using a custom type "unsigned_integer" that extends the DBAL integer type with this:

          public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
          {
              $fieldDeclaration['unsigned'] = true;
      
              return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration);
          }
      

      The reason for this is because the ORM won't map unsigned ints for me. Combined with this is an event listener for the class metadata. Something like this:

          /**
           * Maps additional metadata.
           *
           * Specifically, if there exist an unsigned integer field, attach the
           * "unsigned" option to it. This is required because the Doctrine ORM does
           * not do this and we are using "UNSIGNED INT"s in our MySQL columns.
           * Without this. the Doctrine Schema Tool will complain about column
           * differences.
           *
           * Note: there is no performance impact in doing this because the class
           * metadata should be cached after the first request.
           *
           * @param LoadClassMetadataEventArgs $eventArgs
           */
          public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
          {
              foreach ($eventArgs->getClassMetadata()->fieldMappings as &$mapping) {
                  if (isset($mapping['type']) && UnsignedIntegerType::UNSIGNED_INTEGER === $mapping['type']) {
                      if (!isset($mapping['options'])) {
                          $mapping['options'] = array();
                      }
      
                      $mapping['options']['unsigned'] = true;
                  }
              }
          }
      

      Now, in the example table above, the schema tool will honour the "id" column, however it won't honour the association join column no matter what I do. My attempts include adding an event listener for class meta data as above (basically tricking the ORM) and also adding an event listener for the schema events.

      The other day on GitHub there was a commit (https://github.com/doctrine/doctrine2/commit/a27be2fab61b1cfde4d2ecbc729a4a68816fca76) to help with this, but it's still not all working.

      Also, comments and issues on the Jira tracker have said how there's legacy code related to "unsigned" and "default", but I can't tell what's legacy and what's allowed, especially when there's a commit like that one above.

      By the way, I have found that the simple unsigned field mapping works. E.g.:

          fields:
              counter:
                  type: integer
                  column: counter
                  options:
                      unsigned: true
      

      If it helps at all, here's the YAML mapping file for the above table/entity:

      Account:
          type: entity
          table: account
          id:
              id:
                  type: unsigned_integer
                  generator:
                      strategy: AUTO
          manyToOne:
              creator:
                  targetEntity: User
                  joinColumn:
                      name: user_id
                      referencedColumnName: id # Note: user table id is also unsigned_integer
      

      Is it possible to 1) fix this or 2) let me know if I'm just doing something wrong?

      Note: as I said above, I know that Doctrine DBAL and ORM does not care so much for unsigned ints because of portability, etc. but it seems that because of that commit above (24 days ago), there's a half-implememented/legacy solution going on here.

      Cheers,
      Jon

        Issue Links

          Activity

          Hide
          Benjamin Eberlei added a comment -

          This was fixed in 657a54da

          Show
          Benjamin Eberlei added a comment - This was fixed in 657a54da
          Hide
          Gaetan Rousseau added a comment - - edited

          This was not fixed. We can use the option "unsigned" for the fields but not the id.

          If someone has a solution or if you can fix this, that would be really cool !

          Show
          Gaetan Rousseau added a comment - - edited This was not fixed. We can use the option "unsigned" for the fields but not the id. If someone has a solution or if you can fix this, that would be really cool !
          Hide
          Gaetan Rousseau added a comment -

          After some research with a co-worker we've found a solution to our little problem.

          To fix this you just have to add these lines in the YamlDriver (Doctrine/ORM/Mapping/Driver/YamlDriver.php) in the function "loadMetadataForClass", line 265 in the 2.3.3 version of Doctrine ORM :

          if (isset($idElement['options'])) {
             $mapping['options'] = $idElement['options'];
          }
          

          Just before the :

          $metadata->mapField($mapping);
          

          And that an example of schema :

          Entities\Test:
            type: entity
            table: Test
            id:
              id:
                type: integer
                options:
                  unsigned: true
                generator:
                  strategy: AUTO
            fields:
              testField:
                type: smallint
                options:
                  unsigned: true
          

          With this, the id can be unsigned without using special type of column, and yes just with this little if
          It has been tested in more complexes schemas and all is going well.

          In fact, maybe it could be interesting to use the function "columnToArray" like it's used for the other fields.
          In the two cases you must care about what you put in your "options" section.

          Show
          Gaetan Rousseau added a comment - After some research with a co-worker we've found a solution to our little problem. To fix this you just have to add these lines in the YamlDriver (Doctrine/ORM/Mapping/Driver/YamlDriver.php) in the function "loadMetadataForClass", line 265 in the 2.3.3 version of Doctrine ORM : if (isset($idElement['options'])) { $mapping['options'] = $idElement['options']; } Just before the : $metadata->mapField($mapping); And that an example of schema : Entities\Test: type: entity table: Test id: id: type: integer options: unsigned: true generator: strategy: AUTO fields: testField: type: smallint options: unsigned: true With this, the id can be unsigned without using special type of column, and yes just with this little if It has been tested in more complexes schemas and all is going well. In fact, maybe it could be interesting to use the function "columnToArray" like it's used for the other fields. In the two cases you must care about what you put in your "options" section.
          Hide
          Benjamin Eberlei added a comment -

          Gaetan Rousseau i just now found this additional bug report here in the comments. I opened DDC-2661 for it and fixed it. Will be included in 2.4.1. Please don't report additional bugs in already closed issues in the future, because they can easily get lost.

          Show
          Benjamin Eberlei added a comment - Gaetan Rousseau i just now found this additional bug report here in the comments. I opened DDC-2661 for it and fixed it. Will be included in 2.4.1. Please don't report additional bugs in already closed issues in the future, because they can easily get lost.
          Hide
          Doctrine Bot added a comment -

          A related Github Pull-Request [GH-816] was closed:
          https://github.com/doctrine/doctrine2/pull/816

          Show
          Doctrine Bot added a comment - A related Github Pull-Request [GH-816] was closed: https://github.com/doctrine/doctrine2/pull/816

            People

            • Assignee:
              Benjamin Eberlei
              Reporter:
              Jonathan Ingram
            • Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: