Details
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 )
Brought Paul's changes over to doctrine/orm in branch
DDC-604http://github.com/doctrine/orm/tree/DDC-604