Apply joins and get last alias.

@param QueryBuilder $queryBuilder
@param JoinMap $joinMap
@return null|string
550933
public function apply($queryBuilder, JoinMap $joinMap): ?string
    {
        $alias = null;

        $executedAliases = $queryBuilder->getAllAliases();
        foreach ($joinMap->getJoinMap() as $path => $fields) {
            foreach ($fields as $fieldData) {
                $field         = $fieldData['field'];
                $hasSelect     = $fieldData['hasSelect'];
                $selectFields  = $fieldData['selectFields'];
                $joinType      = $fieldData['joinType'];
                $conditionType = $fieldData['conditionType'];
                $condition     = $fieldData['condition'];

                $pathAlias = str_replace('.', '_', $path);
                $alias     = $pathAlias . '_' . $field;
                $join      = $pathAlias . '.' . $field;

                if (in_array($alias, $executedAliases)) {
                    continue;
                }

                if ($hasSelect) {
                    if (!$selectFields) {
                        $queryBuilder->addSelect($alias);

                    } else {
                        $queryBuilder->addSelect(sprintf('PARTIAL %s.{%s}', $alias, implode(',', $selectFields)));
                    }
                }

                if ($joinType == JoinMap::JOIN_TYPE_LEFT) {
                    $queryBuilder->leftJoin($join, $alias, $conditionType, $condition);

                } elseif ($joinType == JoinMap::JOIN_TYPE_INNER) {
                    $queryBuilder->innerJoin($join, $alias, $conditionType, $condition);

                } else {
                    throw new \RuntimeException('Join type not defined or has wrong type.');
                }
            }
        }

        return $alias;
    }
631816
public QueryBuilder<T, ID> join(QueryBuilder<?, ?> joinedQueryBuilder, JoinType type, JoinWhereOperation operation)
			throws SQLException {
		addJoinInfo(type, null, null, joinedQueryBuilder, operation);
		return this;
	}
534126
private function createJoin(string $alias, string $field, string $joinType): string
    {
        $relationship = $alias . '.' . $field;
        $key = $relationship . '.' . $joinType;

        if (!isset($this->uniqueJoins[$key])) {
            $joinedAlias = $this->uniqueNameFactory->createAliasName($field);

            if ($joinType === 'innerJoin') {
                $this->queryBuilder->innerJoin($relationship, $joinedAlias);
            } else {
                $this->queryBuilder->leftJoin($relationship, $joinedAlias);
            }

            // TODO: For now we assume the query will always access some field on the relation, so we optimize SQL by
            // fetching those objects in a single SQL query. But this should be revisited by either exposing an option
            // to the API so the client could decide to select or not the relations, or even better to detect in GraphQL
            // query if it's actually used or not.
            $this->queryBuilder->addSelect($joinedAlias);

            $this->uniqueJoins[$key] = $joinedAlias;
        }

        return $this->uniqueJoins[$key];
    }
686705
protected final function checkSQL(QueryBuilder $sql) {
        $this->errors = $sql->lastError();
        if ($this->errors) {
            $this->lastSQL = $sql->lastSQL();
        } else {
            $this->lastSQL = $sql->getSqlString();
        }
        $this->lastValues = $sql->lastValues();
        $this->dumpSQL    = $sql->dumpSQL();
    }
1060247
protected function getQueryBuilder($alias = null, $indexBy = null)
    {
        $qb = $this->traitGetQueryBuilder($alias, $indexBy);

        $alias = $alias ?: $this->getAlias();

        return $qb
            ->addSelect('translation')
            ->leftJoin($alias . '.translations', 'translation');
    }
1125347
public function extendQueryBuilder(QueryBuilder $queryBuilder)
    {
        $queryBuilder
            ->setFirstResult($this->getFirstResult())
            ->setMaxResults($this->getLimit());

        return $this;
    }
1161897
protected function applySorting(QueryBuilder $queryBuilder, array $sorting = null)
    {
        if (null === $sorting) {
            return;
        }

        foreach ($sorting as $property => $order) {
            if (!empty($order)) {
                $queryBuilder->orderBy($this->getPropertyName($property), $order);
            }
        }
    }
539552
protected function addJoinTablesToQueryBuilder(QueryBuilder $queryBuilder)
    {
        $objectManager = $this->getObjectManager();
        $entityAlias   = $this->getEntityClassAlias();
        $classMetaData = $objectManager->getClassMetadata($this->getEntityClass());

        $assocMappings = $classMetaData->getAssociationMappings();

        foreach ($assocMappings as $fieldName => $assocMapping) {
            $join  = $entityAlias . '.' . $fieldName;
            $alias = self::JOIN_ALIAS_PREFIX . $fieldName;

            $queryBuilder->addSelect($alias);
            $queryBuilder->leftJoin($join, $alias);
        }
    }
1187708
protected function compileJoins(Builder $query, $joins)
    {
        return collect($joins)->map(function ($join) use ($query) {
            $table = $this->wrapTable($join->table);

            return trim("{$join->type} join {$table} {$this->compileWheres($join)}");
        })->implode(' ');
    }
80552
public function getQuery(QueryBuilder $queryBuilder)
    {
        $rule = $this->getRule();
        $activeFrom = $rule->getActiveFrom();
        $activeUntil = $rule->getActiveUntil();

        $resultQueryBuilder = $queryBuilder;

        if (!is_null($activeFrom)) {
            $resultQueryBuilder = $resultQueryBuilder
                ->andWhere('l.dateLog >= :activeFrom')
                ->setParameter(
                    'activeFrom',
                    $activeFrom->format('Y-m-d H:i:s')
                );
        }
        if (!is_null($activeUntil)) {
            $resultQueryBuilder = $resultQueryBuilder
                ->andWhere('l.dateLog <= :activeUntil')
                ->setParameter(
                    'activeUntil',
                    $activeUntil->format('Y-m-d H:i:s')
                );
        }

        return $resultQueryBuilder;
    }
765938
public function getRawSQL(QueryBuilder $queryBuilder)
    {
        $sql = $queryBuilder->getSQL();
        foreach ($queryBuilder->getParameters() as $parameter => $value) {
            $sql = str_replace($parameter, "'$value'", $sql);
        }

        return $sql;
    }
203503
protected function applyQuerySort(QueryBuilder $queryBuilder, $alias = 'a')
    {
        $sort = $this->get('request')->get('sort');
        $order = $this->get('request')->get('order');

        if ($sort) {
            $repository = $this->get('orm.em')->getRepository($this->getEntityClass());
            // sort using the getQueryBuilderOrderedBy* magic method if defined
            $sortMethodName = 'getQueryBuilderOrderedBy'.ucfirst(strtolower($sort));
            if (method_exists($repository, $sortMethodName)) {
                $queryBuilder = call_user_method_array($sortMethodName, $repository, array($order, $queryBuilder));
            }
            // else sort by property name if exists
            elseif ($sort && property_exists($this->getEntityClass(), $sort)) {
                $queryBuilder->orderBy($alias.'.'.$sort, $order);
            }
        }
        // if empty sort use Gedmo Sortable annotation if enable
        elseif ($sort = $this->getSortableColumn()) {
            // pre order by group if defined
            if ($sortGroup = $this->getSortableGroup()) {
                $queryBuilder->orderBy($alias.'.'.$sortGroup);
            }
            $queryBuilder->addOrderBy($alias.'.'.$sort);
        }

        return $queryBuilder;
    }
814170
protected function performJoin(Builder $query = null)
    {
        $query = $query ?: $this->query;

        $throughParents = array_reverse($this->throughParents);
        $foreignKeys = array_reverse($this->foreignKeys);
        $localKeys = array_reverse($this->localKeys);

        $segments = explode(' as ', $query->getQuery()->from);

        $alias = $segments[1] ?? null;

        foreach ($throughParents as $i => $throughParent) {
            $predecessor = $throughParents[$i - 1] ?? $this->related;

            $prefix = $i === 0 && $alias ? $alias.'.' : '';

            $this->joinThroughParent($query, $throughParent, $predecessor, $foreignKeys[$i], $localKeys[$i], $prefix);
        }
    }
566543
private function getQuerySelectQuery(): QueryBuilder
    {
        $query = $this->connection->createQueryBuilder();
        $query->select('DISTINCT q.*, qt.*')
            ->from('ngbm_collection_query', 'q')
            ->innerJoin(
                'q',
                'ngbm_collection_query_translation',
                'qt',
                $query->expr()->andX(
                    $query->expr()->eq('qt.query_id', 'q.id'),
                    $query->expr()->eq('qt.status', 'q.status')
                )
            );

        return $query;
    }
146401
protected function _createJoinStatement(Select\Join $join )
    {
        $template = " %s JOIN %s%s ON %s";
        $alias = (is_null($join->getAlias())) ?
            null : " AS {$join->getAlias()}";

        return sprintf(
            $template,
            $join->getType(),
            $join->getTable(),
            $alias,
            $join->getOnClause()
        );
    }
757419
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className, $type)
    {
        $columnAlias = $this->getSQLColumnAlias($joinColumnName);

        $this->currentPersisterContext->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type);

        return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
    }
1322006
private function appendRelationOr(QueryBuilder $queryBuilder, $relation, $values, $alias)
    {
        $queryBuilder->leftJoin($relation, $alias)
            ->andWhere($alias . '.id IN (:' . $alias . ')');

        return [$alias => $values];
    }