/** * Join ::= left [JoinType] 'JOIN' right 'ON' JoinCondition * // If JoinType is omitted INNER is assumed. * left ::= Source * right ::= Source * * JoinType ::= Inner | LeftOuter | RightOuter * Inner ::= 'INNER' * LeftOuter ::= 'LEFT OUTER' * RightOuter ::= 'RIGHT OUTER' * * @param QOM\JoinInterface $join * @return string */ protected function convertJoin(QOM\JoinInterface $join) { $left = $this->convertSource($join->getLeft()); $right = $this->convertSource($join->getRight()); $condition = $this->convertJoinCondition($join->getJoinCondition()); return $this->generator->evalJoin($left, $right, $condition, $this->generator->evalJoinType($join->getJoinType())); }
/** * @param QOM\JoinInterface $source * @param boolean $root whether the method call is recursed for nested joins. If true, it will add a WHERE clause * that checks the workspace_name and type * * @return string * * @throws NotImplementedException if the right side of the join consists of another join */ public function walkJoinSource(QOM\JoinInterface $source, $root = true) { $this->source = $left = $source->getLeft(); // The $left variable is used for storing the leftmost selector if (!$source->getRight() instanceof QOM\SelectorInterface) { throw new NotImplementedException('The right side of the join should not consist of another join'); } if ($source->getLeft() instanceof QOM\SelectorInterface) { $leftAlias = $this->getTableAlias($source->getLeft()->getSelectorName()); $this->getTableAlias($source->getLeft()->getSelectorName()); $sql = "FROM phpcr_nodes {$leftAlias} "; } else { $sql = $this->walkJoinSource($left, false) . ' '; // One step left, until we're at the selector $leftAlias = $this->getTableAlias($this->getRightJoinSelector($source->getLeft()->getJoinCondition())); while (!$left instanceof QOM\SelectorInterface) { $left = $left->getLeft(); } } $rightAlias = $this->getTableAlias($source->getRight()->getSelectorName()); $nodeTypeClause = $this->sqlNodeTypeClause($rightAlias, $source->getRight()); switch ($source->getJoinType()) { case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER: $sql .= "INNER JOIN phpcr_nodes {$rightAlias} "; break; case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_LEFT_OUTER: $sql .= "LEFT JOIN phpcr_nodes {$rightAlias} "; break; case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_RIGHT_OUTER: $sql .= "RIGHT JOIN phpcr_nodes {$rightAlias} "; break; } $sql .= "ON ( {$leftAlias}.workspace_name = {$rightAlias}.workspace_name AND {$nodeTypeClause} "; $sql .= "AND " . $this->walkJoinCondition($source->getLeft(), $source->getRight(), $source->getJoinCondition()) . " "; $sql .= ") "; // close on-clause if ($root) { // The method call is not recursed when $root is true, so we can add a WHERE clause // TODO: revise this part for alternatives $sql .= "WHERE {$leftAlias}.workspace_name = ? AND {$leftAlias}.type IN ('" . $left->getNodeTypeName() . "'"; $subTypes = $this->nodeTypeManager->getSubtypes($left->getNodeTypeName()); foreach ($subTypes as $subType) { /* @var $subType \PHPCR\NodeType\NodeTypeInterface */ $sql .= ", '" . $subType->getName() . "'"; } $sql .= ')'; } return $sql; }
/** * @param QOM\JoinInterface $source * * @return string * * @throws NotImplementedException */ public function walkJoinSource(QOM\JoinInterface $source) { if (!$source->getLeft() instanceof QOM\SelectorInterface || !$source->getRight() instanceof QOM\SelectorInterface) { throw new NotImplementedException("Join with Joins"); } $this->source = $source->getLeft(); $leftAlias = $this->getTableAlias($source->getLeft()->getSelectorName()); $sql = "FROM phpcr_nodes {$leftAlias} "; $rightAlias = $this->getTableAlias($source->getRight()->getSelectorName()); $nodeTypeClause = $this->sqlNodeTypeClause($rightAlias, $source->getRight()); switch ($source->getJoinType()) { case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER: $sql .= "INNER JOIN phpcr_nodes {$rightAlias} "; break; case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_LEFT_OUTER: $sql .= "LEFT JOIN phpcr_nodes {$rightAlias} "; break; case QOM\QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_RIGHT_OUTER: $sql .= "RIGHT JOIN phpcr_nodes {$rightAlias} "; break; } $sql .= "ON ( {$leftAlias}.workspace_name = {$rightAlias}.workspace_name AND {$nodeTypeClause} "; $sql .= "AND " . $this->walkJoinCondition($source->getLeft(), $source->getRight(), $source->getJoinCondition()) . " "; $sql .= ") "; // close on-clause $sql .= "WHERE {$leftAlias}.workspace_name = ? AND {$leftAlias}.type IN ('" . $source->getLeft()->getNodeTypeName() . "'"; $subTypes = $this->nodeTypeManager->getSubtypes($source->getLeft()->getNodeTypeName()); foreach ($subTypes as $subType) { /* @var $subType \PHPCR\NodeType\NodeTypeInterface */ $sql .= ", '" . $subType->getName() . "'"; } $sql .= ')'; return $sql; }