diff --git a/lib/Doctrine/ORM/QueryBuilder.php b/lib/Doctrine/ORM/QueryBuilder.php
index 13d041e2b..3dfc2754b 100644
--- a/lib/Doctrine/ORM/QueryBuilder.php
+++ b/lib/Doctrine/ORM/QueryBuilder.php
@@ -96,6 +96,11 @@ class QueryBuilder
*/
private $_maxResults = null;
+ /**
+ * @var array Keeps root entity alias names for join entities.
+ */
+ private $joinRootAliases = array();
+
/**
* Initializes a new QueryBuilder that uses the given EntityManager.
*
@@ -219,6 +224,32 @@ class QueryBuilder
->setMaxResults($this->_maxResults);
}
+ /**
+ * Finds the root entity alias of the joined entity.
+ *
+ * @param string $alias The alias of the new join entity
+ * @param string $parentAlias The parent entity alias of the join relationship
+ * @return string
+ */
+ private function findRootAlias($alias, $parentAlias)
+ {
+ $rootAlias = null;
+
+ if (in_array($parentAlias, $this->getRootAliases())) {
+ $rootAlias = $parentAlias;
+ } elseif (isset($this->joinRootAliases[$parentAlias])) {
+ $rootAlias = $this->joinRootAliases[$parentAlias];
+ } else {
+ // Should never happen with correct joining order. Might be
+ // thoughtful to throw exception instead.
+ $rootAlias = $this->getRootAlias();
+ }
+
+ $this->joinRootAliases[$alias] = $rootAlias;
+
+ return $rootAlias;
+ }
+
/**
* Gets the FIRST root alias of the query. This is the first entity alias involved
* in the construction of the query.
@@ -667,11 +698,9 @@ class QueryBuilder
*/
public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
{
- $rootAlias = substr($join, 0, strpos($join, '.'));
+ $parentAlias = substr($join, 0, strpos($join, '.'));
- if ( ! in_array($rootAlias, $this->getRootAliases())) {
- $rootAlias = $this->getRootAlias();
- }
+ $rootAlias = $this->findRootAlias($alias, $parentAlias);
$join = new Expr\Join(
Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy
@@ -703,11 +732,9 @@ class QueryBuilder
*/
public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
{
- $rootAlias = substr($join, 0, strpos($join, '.'));
+ $parentAlias = substr($join, 0, strpos($join, '.'));
- if ( ! in_array($rootAlias, $this->getRootAliases())) {
- $rootAlias = $this->getRootAlias();
- }
+ $rootAlias = $this->findRootAlias($alias, $parentAlias);
$join = new Expr\Join(
Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php
new file mode 100644
index 000000000..77f32907e
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1757Test.php
@@ -0,0 +1,92 @@
+_em->createQueryBuilder();
+ /* @var $qb \Doctrine\ORM\QueryBuilder */
+
+ $qb->select('_a')
+ ->from(__NAMESPACE__ . '\DDC1757A', '_a')
+ ->from(__NAMESPACE__ . '\DDC1757B', '_b')
+ ->join('_b.c', '_c')
+ ->join('_c.d', '_d');
+
+ $q = $qb->getQuery();
+ $dql = $q->getDQL();
+
+ // Show difference between expected and actual queries on error
+ self::assertEquals("SELECT _a FROM " . __NAMESPACE__ . "\DDC1757A _a, " . __NAMESPACE__ . "\DDC1757B _b INNER JOIN _b.c _c INNER JOIN _c.d _d",
+ $dql,
+ "Wrong DQL query");
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC1757A
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+}
+
+/**
+ * @Entity
+ */
+class DDC1757B
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * @OneToOne(targetEntity="DDC1757C")
+ */
+ private $c;
+}
+
+/**
+ * @Entity
+ */
+class DDC1757C
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+
+ /**
+ * @OneToOne(targetEntity="DDC1757D")
+ */
+ private $d;
+}
+
+/**
+ * @Entity
+ */
+class DDC1757D
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+}