/** * adds a union statement to the query, mostly for tables referenced in the where condition. * The property for which the union statement is generated will be appended. * * @param string &$className The name of the parent class, will be set to the child class after processing. * @param string &$tableName The name of the parent table, will be set to the table alias that is used in the union statement. * @param array &$propertyPath The remaining property path, will be cut of by one part during the process. * @param string $fullPropertyPath The full path the the current property, will be used to make table names unique. * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception * @throws InvalidRelationConfigurationException * @throws MissingColumnMapException */ protected function addUnionStatement(&$className, &$tableName, &$propertyPath, &$fullPropertyPath) { $explodedPropertyPath = explode('.', $propertyPath, 2); $propertyName = $explodedPropertyPath[0]; $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $realTableName = $this->dataMapper->convertClassNameToTableName($className); $tableName = isset($this->tablePropertyMap[$fullPropertyPath]) ? $this->tablePropertyMap[$fullPropertyPath] : $realTableName; $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); if ($columnMap === null) { throw new MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); if ($childTableName === null) { throw new InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925); } $fullPropertyPath .= $fullPropertyPath === '' ? $propertyName : '.' . $propertyName; $childTableAlias = $this->getUniqueAlias($childTableName, $fullPropertyPath); // If there is already exists a union with the current identifier we do not need to build it again and exit early. if (in_array($childTableAlias, $this->unionTableAliasCache, true)) { return; } if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { // @todo: no test for this part yet $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $childTableAlias . '.' . $parentKeyFieldName); } else { $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.' . $columnName, $childTableAlias . '.uid'); } $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, $joinConditionExpression); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { // @todo: no tests for this part yet if (isset($parentKeyFieldName)) { $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $childTableAlias . '.' . $parentKeyFieldName); } else { $joinConditionExpression = $this->queryBuilder->expr()->inSet($tableName . '.' . $columnName, $childTableAlias . '.uid'); } $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, $joinConditionExpression); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $relationTableAlias = $relationTableAlias = $this->getUniqueAlias($relationTableName, $fullPropertyPath . '_mm'); $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()); $this->queryBuilder->leftJoin($tableName, $relationTableName, $relationTableAlias, $joinConditionExpression); $joinConditionExpression = $this->queryBuilder->expr()->eq($relationTableAlias . '.' . $columnMap->getChildKeyFieldName(), $childTableAlias . '.uid'); $this->queryBuilder->leftJoin($relationTableAlias, $childTableName, $childTableAlias, $joinConditionExpression); $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->addGroupBy($this->tableName . '.uid'); } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725); } $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); }
/** * adds a union statement to the query, mostly for tables referenced in the where condition. * The property for which the union statement is generated will be appended. * * @param string &$className The name of the parent class, will be set to the child class after processing. * @param string &$tableName The name of the parent table, will be set to the table alias that is used in the union statement. * @param array &$propertyPath The remaining property path, will be cut of by one part during the process. * @param array &$sql The SQL statement parts, will be filled with the union statements. * @param string $fullPropertyPath The full path the the current property, will be used to make table names unique. * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException */ protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql, &$fullPropertyPath) { $explodedPropertyPath = explode('.', $propertyPath, 2); $propertyName = $explodedPropertyPath[0]; $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $realTableName = $this->dataMapper->convertClassNameToTableName($className); $tableName = isset($this->tablePropertyMap[$fullPropertyPath]) ? $this->tablePropertyMap[$fullPropertyPath] : $realTableName; $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); if ($columnMap === null) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); if ($childTableName === null) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925); } $fullPropertyPath .= $fullPropertyPath === '' ? $propertyName : '.' . $propertyName; $childTableAlias = $this->getUniqueAlias($sql, $childTableName, $fullPropertyPath); // If there is already exists a union with the current identifier we do not need to build it again and exit early. if (isset($sql['unions'][$childTableAlias])) { $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); return; } if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName; } else { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableAlias . '.uid'; } $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName; } else { $onStatement = '(FIND_IN_SET(' . $childTableAlias . '.uid, ' . $tableName . '.' . $columnName . '))'; $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $onStatement; } $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $relationTableAlias = $relationTableAlias = $this->getUniqueAlias($sql, $relationTableName, $fullPropertyPath . '_mm'); $sql['unions'][$relationTableAlias] = 'LEFT JOIN ' . $relationTableName . ' AS ' . $relationTableAlias . ' ON ' . $tableName . '.uid=' . $relationTableAlias . '.' . $columnMap->getParentKeyFieldName(); $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $relationTableAlias . '.' . $columnMap->getChildKeyFieldName() . '=' . $childTableAlias . '.uid'; $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $relationTableName, $relationTableAlias, $realTableName); } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725); } // @todo check if there is another solution for this $sql['keywords']['distinct'] = 'DISTINCT'; $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); }
/** * adds a union statement to the query, mostly for tables referenced in the where condition. * * @param string &$className * @param string &$tableName * @param array &$propertyPath * @param array &$sql * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException */ protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql) { $explodedPropertyPath = explode('.', $propertyPath, 2); $propertyName = $explodedPropertyPath[0]; $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $tableName = $this->dataMapper->convertClassNameToTableName($className); $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); if ($columnMap === NULL) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); if ($childTableName === NULL) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925); } if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; } else { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableName . '.uid'; } $className = $this->dataMapper->getType($className, $propertyName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; } else { $onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))'; $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement; } $className = $this->dataMapper->getType($className, $propertyName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.' . $columnMap->getParentKeyFieldName(); $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.' . $columnMap->getChildKeyFieldName() . '=' . $childTableName . '.uid'; $className = $this->dataMapper->getType($className, $propertyName); } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725); } // TODO check if there is another solution for this $sql['keywords']['distinct'] = 'DISTINCT'; $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableName; }