Skip to content

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
Something went wrong with that request. Please try again.