DDC-604: array_merge in Query::_doExecute causes parameter reordering #5112

Closed
doctrinebot opened this Issue May 20, 2010 · 3 comments

1 participant

@doctrinebot

Jira issue originally created by user @hobodave:

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 )

@doctrinebot

Comment created by needle:

I've just added the fail case

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.0-BETA2 milestone Dec 6, 2015
@doctrinebot doctrinebot closed this Dec 6, 2015
@doctrinebot doctrinebot added the Bug label Dec 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment