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

Open
opened 2026-01-22 12:48:52 +01:00 by admin · 0 comments
Owner

Originally created by @doctrinebot on GitHub (May 20, 2010).

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 )

Originally created by @doctrinebot on GitHub (May 20, 2010). 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 )
admin added the Bug label 2026-01-22 12:48:52 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#741