Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-604

array_merge in Query::_doExecute causes parameter reordering

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.0-BETA1
    • Fix Version/s: 2.0-BETA2
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      Hi all,
      I think there is a bug with the doExecute method from the Query class.

      foreach ($this->_params as $key => $value) { 
                  if ( ! isset($paramMappings[$key])) { 
                      throw QueryException::unknownParameter($key); 
                  } 
                  if (isset($this->_paramTypes[$key])) { 
                      foreach ($paramMappings[$key] as $position) { 
                          $types[$position] = $this->_paramTypes[$key]; 
                      } 
                  } 
                  if (is_object($value) && 
      $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) { 
                      $values = 
      $this->_em->getUnitOfWork()->getEntityIdentifier($value); 
                      $sqlPositions = $paramMappings[$key]; 
                      $sqlParams = array_merge($sqlParams, 
      array_combine((array)$sqlPositions, $values)); 
                  } else { 
                      foreach ($paramMappings[$key] as $position) { 
                          $sqlParams[$position] = $value; 
                      } 
                  } 
              } 
      

      When constructing the $sqlParams array, array_merge is used for params wich
      are objects. Php documentation says that numeric key are renumbered. So we
      loose the position of the parameter.
      I solved this problem by replacing the array_merge with that :
      $sqlParams = $sqlParams + array_combine((array)$sqlPositions, $values);
      But I'm not sure it doesn't have unwanted effects.
      I created a fork on github for this bug, hope it could be usefull.

      Edit a fail case :

      SQL (for postgres):

      CREATE TABLE first_class
      (
        id serial NOT NULL,
        "text" character varying,
        second_class_id integer,
        CONSTRAINT first_class_pkey PRIMARY KEY (id),
        CONSTRAINT first_class_second_class_id_fkey FOREIGN KEY (second_class_id)
            REFERENCES second_class (id) MATCH SIMPLE
            ON UPDATE NO ACTION ON DELETE NO ACTION
      );
      
      CREATE TABLE second_class
      (
        id serial NOT NULL,
        CONSTRAINT second_class_pkey PRIMARY KEY (id)
      );
      
      INSERT INTO second_class(
                  id)
          VALUES (1);
      

      FirstClass.php

      /**
       * @Entity
       * @Table(name="first_class")
       */
      class FirstClass {
        /**
         * @Id
         * @Column(name="id",type="integer")
         */
        private $id;
        /** @Column(name="text",type="string") */
        private $text;
        /**
         * @OneToOne(targetEntity="SecondClass")
         * @JoinColumn(name="second_class_id", referencedColumnName="id")
         */
        private $secondClassInstance;
      }
      

      SecondClass.php

      /**
       * @Entity
       * @Table(name="second_class")
       */
      class SecondClass {
        /**
         * @Id
         * @Column(name="id",type="integer")
         */
        private $id;
      }
      

      Test Case :

      $secondClassInstance = $doctrineEntityManager->find('SecondClass',1);
      
      $query = $doctrineEntityManager->createQuery("SELECT f FROM FirstClass f WHERE f.text = :text AND f.secondClassInstance = :instance")->setParameters(array('instance'=>$secondClassInstance,'text'=>'Un texte en francais',));
      echo $query->getSQL();
      $query->execute();
      

      When you execute this query it fails. When printing the $sqlParams variable from _doExecute you can see the folowing :
      Array ( [0] => 1 [1] => Un texte en francais )

        Activity

        Hide
        David Abdemoulaie added a comment -

        Brought Paul's changes over to doctrine/orm in branch DDC-604 http://github.com/doctrine/orm/tree/DDC-604

        Show
        David Abdemoulaie added a comment - Brought Paul's changes over to doctrine/orm in branch DDC-604 http://github.com/doctrine/orm/tree/DDC-604
        Hide
        Paul Fariello added a comment -

        I've just added the fail case

        Show
        Paul Fariello added a comment - I've just added the fail case

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            David Abdemoulaie
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: