diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-27057-RelationsToTheSameTableInExtbase.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-27057-RelationsToTheSameTableInExtbase.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0fdc835cebe1c7da9ba905bd900e79a27257ba89
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-27057-RelationsToTheSameTableInExtbase.rst
@@ -0,0 +1,64 @@
+========================================================
+Feature: #27057 - Relations to the same table in Extbase
+========================================================
+
+Description
+===========
+
+It is now possible to use a domain model where an object is connected to another object of the same class directly
+
+.. code-block:: php
+
+	namespace \Vendor\Extension\Domain\Model;
+	class A {
+		/**
+		* @var \Vendor\Extension\Domain\Model\A
+		*/
+		protected $parent;
+
+as well as using a domain model where an object has multiple relations to objects of the same class
+
+.. code-block:: php
+
+	namespace \Vendor\Extension\Domain\Model;
+	class A {
+		/**
+		* @var \Vendor\Extension\Domain\Model\B
+		*/
+		protected $x;
+
+		/**
+		* @var \Vendor\Extension\Domain\Model\B
+		*/
+		protected $y;
+
+as well as indirectly
+
+.. code-block:: php
+
+	namespace \Vendor\Extension\Domain\Model;
+	class A {
+		/**
+		* @var \Vendor\Extension\Domain\Model\B
+		*/
+		protected $b;
+
+		/**
+		* @var \Vendor\Extension\Domain\Model\C
+		*/
+		protected $c;
+
+	namespace \Vendor\Extension\Domain\Model;
+	class B {
+		/**
+		* @var \Vendor\Extension\Domain\Model\C
+		*/
+		protected $c;
+
+Using this kind of relations was possible before only by overriding the Extbase query builder and doing manual queries because the Extbase query builder created wrong SQL statements. Now Extbase properly supports these cases.
+
+
+Impact
+======
+
+Extbase now correctly handles relations to objects of the same class.
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
index b1a6058bec0e060e0146b1d2fcd23b10410d0f25..0f51fe82bb4cb1dcd0816bc9332ab3f1f72f07f1 100644
--- a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
+++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
@@ -80,6 +80,16 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 		$this->environmentService = $environmentService;
 	}
 
+	/**
+	 * Maps domain model properties to their corresponding table aliases that are used in the query, e.g.:
+	 *
+	 * 'property1' => 'tableName',
+	 * 'property1.property2' => 'tableName1',
+	 *
+	 * @var array
+	 */
+	protected $tablePropertyMap = array();
+
 	/**
 	 * Constructor. takes the database handle from $GLOBALS['TYPO3_DB']
 	 */
@@ -202,6 +212,7 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 	 * @return array The SQL statement parts
 	 */
 	public function parseQuery(QueryInterface $query) {
+		$this->tablePropertyMap = array();
 		$sql = array();
 		$sql['keywords'] = array();
 		$sql['tables'] = array();
@@ -212,15 +223,17 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 		$sql['orderings'] = array();
 		$sql['limit'] = ((int)$query->getLimit() ?: NULL);
 		$sql['offset'] = ((int)$query->getOffset() ?: NULL);
+		$sql['tableAliasMap'] = array();
 		$source = $query->getSource();
 		$this->parseSource($source, $sql);
 		$this->parseConstraint($query->getConstraint(), $source, $sql);
 		$this->parseOrderings($query->getOrderings(), $source, $sql);
 
-		$tableNames = array_unique(array_keys($sql['tables'] + $sql['unions']));
-		foreach ($tableNames as $tableName) {
-			if (is_string($tableName) && !empty($tableName)) {
-				$this->addAdditionalWhereClause($query->getQuerySettings(), $tableName, $sql);
+		foreach ($sql['tableAliasMap'] as $tableAlias => $tableName) {
+			$additionalWhereClause = $this->getAdditionalWhereClause($query->getQuerySettings(), $tableName, $tableAlias);
+			if ($additionalWhereClause !== '') {
+				$additionalWhereClause = $this->addNullConditionToStatementIfRequired($sql, $additionalWhereClause, $tableAlias);
+				$sql['additionalWhereClause'][] = $additionalWhereClause;
 			}
 		}
 
@@ -240,14 +253,35 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 		if (!isset($sql['additionalWhereClause'])) {
 			throw new \InvalidArgumentException('Invalid statement given.', 1399512421);
 		}
-		$tableNames = array_unique(array_keys($sql['tables'] + $sql['unions']));
-		foreach ($tableNames as $tableName) {
-			if (is_string($tableName) && !empty($tableName)) {
-				$this->addVisibilityConstraintStatement($querySettings, $tableName, $sql);
+		foreach ($sql['tableAliasMap'] as $tableAlias => $tableName) {
+			$statement = $this->getVisibilityConstraintStatement($querySettings, $tableName, $tableAlias);
+			if ($statement !== '') {
+				$statement = $this->addNullConditionToStatementIfRequired($sql, $statement, $tableAlias);
+				$sql['additionalWhereClause'][] = $statement;
 			}
 		}
 	}
 
+	/**
+	 * If the given table alias is used in a UNION statement it is required to
+	 * add an additional condition that allows the fields of the joined table
+	 * to be NULL. Otherwise the condition would be too strict and filter out
+	 * records that are actually valid.
+	 *
+	 * @param array $sql The current SQL query parts.
+	 * @param string $statement The SQL statement to which the NULL condition should be added.
+	 * @param string $tableAlias The table alias used in the SQL statement.
+	 * @return string The statement including the NULL condition or the original statement.
+	 */
+	protected function addNullConditionToStatementIfRequired(array $sql, $statement, $tableAlias) {
+
+		if (isset($sql['unions'][$tableAlias])) {
+			$statement = '((' . $statement . ') OR ' . $tableAlias . '.uid' . ' IS NULL)';
+		}
+
+		return $statement;
+	}
+
 	/**
 	 * Transforms a Query Source into SQL and parameter arrays
 	 *
@@ -260,6 +294,7 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 			$className = $source->getNodeTypeName();
 			$tableName = $this->dataMapper->getDataMap($className)->getTableName();
 			$this->addRecordTypeConstraint($className, $sql);
+			$tableName = $this->getUniqueAlias($sql, $tableName);
 			$sql['fields'][$tableName] = $tableName . '.*';
 			$sql['tables'][$tableName] = $tableName;
 		} elseif ($source instanceof Qom\JoinInterface) {
@@ -323,8 +358,9 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 			if ($source instanceof Qom\SelectorInterface) {
 				$className = $source->getNodeTypeName();
 				$tableName = $this->dataMapper->convertClassNameToTableName($className);
+				$fullPropertyPath = '';
 				while (strpos($propertyName, '.') !== FALSE) {
-					$this->addUnionStatement($className, $tableName, $propertyName, $sql);
+					$this->addUnionStatement($className, $tableName, $propertyName, $sql, $fullPropertyPath);
 				}
 			} elseif ($source instanceof Qom\JoinInterface) {
 				$tableName = $source->getLeft()->getSelectorName();
@@ -378,8 +414,9 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 				$tableName = $this->dataMapper->convertClassNameToTableName($className);
 				$operand1 = $comparison->getOperand1();
 				$propertyName = $operand1->getPropertyName();
+				$fullPropertyPath = '';
 				while (strpos($propertyName, '.') !== FALSE) {
-					$this->addUnionStatement($className, $tableName, $propertyName, $sql);
+					$this->addUnionStatement($className, $tableName, $propertyName, $sql, $fullPropertyPath);
 				}
 				$columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
 				$dataMap = $this->dataMapper->getDataMap($className);
@@ -387,16 +424,7 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 				$typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : NULL;
 				if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
 					$relationTableName = $columnMap->getRelationTableName();
-					$relationTableMatchFields = $columnMap->getRelationTableMatchFields();
-					if (is_array($relationTableMatchFields)) {
-						$additionalWhere = array();
-						foreach ($relationTableMatchFields as $fieldName => $value) {
-							$additionalWhere[] = $fieldName . ' = ' . $this->databaseHandle->fullQuoteStr($value, $relationTableName);
-						}
-						$additionalWhereForMatchFields = ' AND ' . implode(' AND ', $additionalWhere);
-					} else {
-						$additionalWhereForMatchFields = '';
-					}
+					$additionalWhereForMatchFields = $this->getAdditionalMatchFieldsStatement($columnMap, $relationTableName, $relationTableName);
 					$sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=' . $parameterIdentifier . $additionalWhereForMatchFields . ')';
 				} elseif ($typeOfRelation === ColumnMap::RELATION_HAS_MANY) {
 					$parentKeyFieldName = $columnMap->getParentKeyFieldName();
@@ -457,8 +485,9 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 				// @todo Only necessary to differ from  Join
 				$className = $source->getNodeTypeName();
 				$tableName = $this->dataMapper->convertClassNameToTableName($className);
+				$fullPropertyPath = '';
 				while (strpos($propertyName, '.') !== FALSE) {
-					$this->addUnionStatement($className, $tableName, $propertyName, $sql);
+					$this->addUnionStatement($className, $tableName, $propertyName, $sql, $fullPropertyPath);
 				}
 			} elseif ($source instanceof Qom\JoinInterface) {
 				$tableName = $source->getJoinCondition()->getSelector1Name();
@@ -504,21 +533,68 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 		}
 	}
 
+	/**
+	 * Builds a condition for filtering records by the configured match field,
+	 * e.g. MM_match_fields, foreign_match_fields or foreign_table_field.
+	 *
+	 * @param ColumnMap $columnMap The column man for which the condition should be build.
+	 * @param string $childTableName The real name of the child record table.
+	 * @param string $childTableAlias The alias of the child record table used in the query.
+	 * @param string $parentTable The real name of the parent table (used for building the foreign_table_field condition).
+	 * @return string The match field conditions or an empty string.
+	 */
+	protected function getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $parentTable = NULL) {
+
+		$additionalWhereForMatchFields = '';
+
+		$relationTableMatchFields = $columnMap->getRelationTableMatchFields();
+		if (is_array($relationTableMatchFields) && !empty($relationTableMatchFields)) {
+			$additionalWhere = array();
+			foreach ($relationTableMatchFields as $fieldName => $value) {
+				$additionalWhere[] = $childTableAlias . '.' . $fieldName . ' = ' . $this->databaseHandle->fullQuoteStr($value, $childTableName);
+			}
+			$additionalWhereForMatchFields .= ' AND ' . implode(' AND ', $additionalWhere);
+		}
+
+		if (isset($parentTable)) {
+			$parentTableFieldName = $columnMap->getParentTableFieldName();
+			if (isset($parentTableFieldName) && $parentTableFieldName !== '') {
+				$additionalWhereForMatchFields .= ' AND ' . $childTableAlias . '.' . $parentTableFieldName . ' = ' . $this->databaseHandle->fullQuoteStr($parentTable, $childTableAlias);
+			}
+		}
+
+		return $additionalWhereForMatchFields;
+	}
+
 	/**
 	 * Adds additional WHERE statements according to the query settings.
 	 *
 	 * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
 	 * @param string $tableName The table name to add the additional where clause for
-	 * @param string &$sql
-	 * @return void
+	 * @param string $tableAlias The table alias used in the query.
+	 * @return string
 	 */
-	protected function addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, &$sql) {
+	protected function getAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, $tableAlias = NULL) {
+
+		$sysLanguageStatement = '';
 		if ($querySettings->getRespectSysLanguage()) {
-			$this->addSysLanguageStatement($tableName, $sql, $querySettings);
+			$sysLanguageStatement = $this->getSysLanguageStatement($tableName, $tableAlias, $querySettings);
 		}
+
+		$pageIdStatement = '';
 		if ($querySettings->getRespectStoragePage()) {
-			$this->addPageIdStatement($tableName, $sql, $querySettings->getStoragePageIds());
+			$pageIdStatement = $this->getPageIdStatement($tableName, $tableAlias, $querySettings->getStoragePageIds());
+		}
+
+		if ($sysLanguageStatement !== '' && $pageIdStatement !== '') {
+			$whereClause = $sysLanguageStatement . ' AND ' . $pageIdStatement;
+		} elseif ($sysLanguageStatement !== '') {
+			$whereClause = $sysLanguageStatement;
+		} else {
+			$whereClause = $pageIdStatement;
 		}
+
+		return $whereClause;
 	}
 
 	/**
@@ -526,10 +602,10 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 	 *
 	 * @param QuerySettingsInterface $querySettings
 	 * @param string $tableName The database table name
-	 * @param array &$sql The query parts
-	 * @return void
+	 * @param string $tableAlias
+	 * @return string
 	 */
-	protected function addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, array &$sql) {
+	protected function getVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, $tableAlias) {
 		$statement = '';
 		if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
 			$ignoreEnableFields = $querySettings->getIgnoreEnableFields();
@@ -542,10 +618,11 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 				$statement .= $this->getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted);
 			}
 			if (!empty($statement)) {
+				$statement = $this->replaceTableNameWithAlias($statement, $tableName, $tableAlias);
 				$statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
-				$sql['additionalWhereClause'][] = $statement;
 			}
 		}
+		return $statement;
 	}
 
 	/**
@@ -598,15 +675,16 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 	 * Builds the language field statement
 	 *
 	 * @param string $tableName The database table name
-	 * @param array &$sql The query parts
+	 * @param string $tableAlias The table alias used in the query.
 	 * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
-	 * @return void
+	 * @return string
 	 */
-	protected function addSysLanguageStatement($tableName, array &$sql, $querySettings) {
+	protected function getSysLanguageStatement($tableName, $tableAlias, $querySettings) {
+		$sysLanguageStatement = '';
 		if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
 			if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
 				// Select all entries for the current language
-				$additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . (int)$querySettings->getLanguageUid() . ',-1)';
+				$additionalWhereClause = $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . (int)$querySettings->getLanguageUid() . ',-1)';
 				// If any language is set -> get those entries which are not translated yet
 				// They will be removed by \TYPO3\CMS\Frontend\Page\PageRepository::getRecordOverlay if not matching overlay mode
 				if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
@@ -615,17 +693,17 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 
 					$mode = $querySettings->getLanguageMode();
 					if ($mode === 'strict') {
-						$additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=-1' .
-							' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = ' . (int)$querySettings->getLanguageUid() .
-							' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '=0' .
-							') OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
-							' AND ' . $tableName . '.uid IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
+						$additionalWhereClause = $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=-1' .
+							' OR (' . $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = ' . (int)$querySettings->getLanguageUid() .
+							' AND ' . $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '=0' .
+							') OR (' . $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
+							' AND ' . $tableAlias . '.uid IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
 							' FROM ' . $tableName .
 							' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
 							' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid();
 					} else {
-						$additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
-							' AND ' . $tableName . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
+						$additionalWhereClause .= ' OR (' . $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
+							' AND ' . $tableAlias . '.uid NOT IN (SELECT ' . $tableAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
 							' FROM ' . $tableName .
 							' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
 							' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid();
@@ -637,21 +715,23 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 					}
 					$additionalWhereClause .= '))';
 				}
-				$sql['additionalWhereClause'][] = '(' . $additionalWhereClause . ')';
+				$sysLanguageStatement = '(' . $additionalWhereClause . ')';
 			}
 		}
+		return $sysLanguageStatement;
 	}
 
 	/**
 	 * Builds the page ID checking statement
 	 *
 	 * @param string $tableName The database table name
-	 * @param array &$sql The query parts
+	 * @param string $tableAlias The table alias used in the query.
 	 * @param array $storagePageIds list of storage page ids
 	 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException
-	 * @return void
+	 * @return string
 	 */
-	protected function addPageIdStatement($tableName, array &$sql, array $storagePageIds) {
+	protected function getPageIdStatement($tableName, $tableAlias, array $storagePageIds) {
+		$pageIdStatement = '';
 		$tableColumns = $this->tableColumnCache->get($tableName);
 		if ($tableColumns === FALSE) {
 			$tableColumns = $this->databaseHandle->admin_get_fields($tableName);
@@ -661,15 +741,16 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 			$rootLevel = (int)$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'];
 			if ($rootLevel) {
 				if ($rootLevel === 1) {
-					$sql['additionalWhereClause'][] = $tableName . '.pid = 0';
+					$pageIdStatement = $tableAlias . '.pid = 0';
 				}
 			} else {
 				if (empty($storagePageIds)) {
 					throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException('Missing storage page ids.', 1365779762);
 				}
-				$sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', $storagePageIds) . ')';
+				$pageIdStatement = $tableAlias . '.pid IN (' . implode(', ', $storagePageIds) . ')';
 			}
 		}
+		return $pageIdStatement;
 	}
 
 	/**
@@ -695,35 +776,72 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 			$sql['fields'][$leftTableName] = $rightTableName . '.*';
 		}
 		$this->addRecordTypeConstraint($rightClassName, $sql);
+		$leftTableName = $this->getUniqueAlias($sql, $leftTableName);
 		$sql['tables'][$leftTableName] = $leftTableName;
+		$rightTableName = $this->getUniqueAlias($sql, $rightTableName);
 		$sql['unions'][$rightTableName] = 'LEFT JOIN ' . $rightTableName;
 		$joinCondition = $join->getJoinCondition();
 		if ($joinCondition instanceof Qom\EquiJoinCondition) {
 			$column1Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftClassName);
 			$column2Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightClassName);
-			$sql['unions'][$rightTableName] .= ' ON ' . $joinCondition->getSelector1Name() . '.' . $column1Name . ' = ' . $joinCondition->getSelector2Name() . '.' . $column2Name;
+			$sql['unions'][$rightTableName] .= ' ON ' . $leftTableName . '.' . $column1Name . ' = ' . $rightTableName . '.' . $column2Name;
 		}
 		if ($rightSource instanceof Qom\JoinInterface) {
 			$this->parseJoin($rightSource, $sql);
 		}
 	}
 
+	/**
+	 * Generates a unique alias for the given table and the given property path.
+	 * The property path will be mapped to the generated alias in the tablePropertyMap.
+	 *
+	 * @param array $sql The SQL satement parts, will be filled with the tableAliasMap.
+	 * @param string $tableName The name of the table for which the alias should be generated.
+	 * @param string $fullPropertyPath The full property path that is related to the given table.
+	 * @return string The generated table alias.
+	 */
+	protected function getUniqueAlias(array &$sql, $tableName, $fullPropertyPath = NULL) {
+
+		if (isset($fullPropertyPath) && isset($this->tablePropertyMap[$fullPropertyPath])) {
+			return $this->tablePropertyMap[$fullPropertyPath];
+		}
+
+		$alias = $tableName;
+		$i = 0;
+		while (isset($sql['tableAliasMap'][$alias])) {
+			$alias = $tableName . $i;
+			$i++;
+		}
+
+		$sql['tableAliasMap'][$alias] = $tableName;
+
+		if (isset($fullPropertyPath)) {
+			$this->tablePropertyMap[$fullPropertyPath] = $alias;
+		}
+
+		return $alias;
+	}
+
 	/**
 	 * 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
-	 * @param string &$tableName
-	 * @param array &$propertyPath
-	 * @param array &$sql
+	 * @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) {
+	protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql, &$fullPropertyPath) {
+
 		$explodedPropertyPath = explode('.', $propertyPath, 2);
 		$propertyName = $explodedPropertyPath[0];
 		$columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
-		$tableName = $this->dataMapper->convertClassNameToTableName($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) {
@@ -737,33 +855,64 @@ class Typo3DbQueryParser implements \TYPO3\CMS\Core\SingletonInterface {
 			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'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
+				$sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName;
 			} else {
-				$sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableName . '.uid';
+				$sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableAlias . '.uid';
 			}
-			$className = $this->dataMapper->getType($className, $propertyName);
+			$sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName);
 		} elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) {
 			if (isset($parentKeyFieldName)) {
-				$sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
+				$sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName;
 			} else {
-				$onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))';
-				$sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement;
+				$onStatement = '(FIND_IN_SET(' . $childTableAlias . '.uid, ' . $tableName . '.' . $columnName . '))';
+				$sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $onStatement;
 			}
-			$className = $this->dataMapper->getType($className, $propertyName);
+			$sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName);
 		} 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);
+			$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 = $childTableName;
+		$tableName = $childTableAlias;
+		$className = $this->dataMapper->getType($className, $propertyName);
+	}
+
+	/**
+	 * If the table name does not match the table alias all occurrences of
+	 * "tableName." are replaced with "tableAlias." in the given SQL statement.
+	 *
+	 * @param string $statement The SQL statement in which the values are replaced.
+	 * @param string $tableName The table name that is replaced.
+	 * @param string $tableAlias The table alias that replaced the table name.
+	 * @return string The modified SQL statement.
+	 */
+	protected function replaceTableNameWithAlias($statement, $tableName, $tableAlias) {
+
+		if ($tableAlias !== $tableName) {
+			$statement = str_replace($tableName . '.', $tableAlias . '.', $statement);
+		}
+
+		return $statement;
 	}
 
 	/**
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Model/Person.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Model/Person.php
index 71f39ec297452ea276ed5084eed36811a47d0fb0..cfd68fe6f6275835fca6d6e3256cc61db156990e 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Model/Person.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Model/Person.php
@@ -34,6 +34,16 @@ class Person extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
 	 */
 	protected $email = '';
 
+	/**
+	 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ExtbaseTeam\BlogExample\Domain\Model\Tag>
+	 */
+	protected $tags = NULL;
+
+	/**
+	 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ExtbaseTeam\BlogExample\Domain\Model\Tag>
+	 */
+	protected $tagsSpecial = NULL;
+
 	/**
 	 * Constructs a new Person
 	 *
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Repository/PostRepository.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Repository/PostRepository.php
index 17ae40f68303e82d2e4db2cbe5600453b548c491..d43f58a1127fd00bce9aaf63999fa7d133442847 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Repository/PostRepository.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Repository/PostRepository.php
@@ -16,6 +16,8 @@ namespace ExtbaseTeam\BlogExample\Domain\Repository;
 
 /**
  * A repository for blog posts
+ *
+ * @method \ExtbaseTeam\BlogExample\Domain\Model\Post findByUid($uid)
  */
 class PostRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
 
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Person.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Person.php
index 0911a0f741dfd1a39d3447177a8d8fc554c477fc..16f79fbf63a3e3af914b793048ae3d8e75022465 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Person.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Person.php
@@ -43,10 +43,50 @@ $TCA['tx_blogexample_domain_model_person'] = array(
 				'eval' => 'trim, required',
 				'max' => 256
 			)
-		)
+		),
+		'tags' => array(
+			'exclude' => 1,
+			'label' => 'LLL:EXT:blog_example/Resources/Private/Language/locallang_db.xml:tx_blogexample_domain_model_person.tags',
+			'config' => array(
+				'type' => 'inline',
+				'foreign_table' => 'tx_blogexample_domain_model_tag',
+				'MM' => 'tx_blogexample_domain_model_tag_mm',
+				'foreign_table_field' => 'tablenames',
+				'foreign_match_fields' => array(
+					'fieldname' => 'tags'
+				),
+				'maxitems' => 9999,
+				'appearance' => array(
+					'useCombination' => 1,
+					'useSortable' => 1,
+					'collapseAll' => 1,
+					'expandSingle' => 1,
+				)
+			)
+		),
+		'tags_special' => array(
+			'exclude' => 1,
+			'label' => 'LLL:EXT:blog_example/Resources/Private/Language/locallang_db.xml:tx_blogexample_domain_model_person.tags_special',
+			'config' => array(
+				'type' => 'inline',
+				'foreign_table' => 'tx_blogexample_domain_model_tag',
+				'MM' => 'tx_blogexample_domain_model_tag_mm',
+				'foreign_table_field' => 'tablenames',
+				'foreign_match_fields' => array(
+					'fieldname' => 'tags_special'
+				),
+				'maxitems' => 9999,
+				'appearance' => array(
+					'useCombination' => 1,
+					'useSortable' => 1,
+					'collapseAll' => 1,
+					'expandSingle' => 1,
+				)
+			)
+		),
 	),
 	'types' => array(
-		'1' => array('showitem' => 'firstname, lastname, email, avatar')
+		'1' => array('showitem' => 'firstname, lastname, email, avatar, tags, tags_special')
 	),
 	'palettes' => array(
 		'1' => array('showitem' => '')
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Resources/Private/Language/locallang_db.xml b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Resources/Private/Language/locallang_db.xml
index 01899a0d75286bf985eae2187369f01139c6c38b..d3d400a02576c17c9e7ce4e27fd15c76b2637aac 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Resources/Private/Language/locallang_db.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Resources/Private/Language/locallang_db.xml
@@ -28,6 +28,8 @@
 			<label index="tx_blogexample_domain_model_person.lastname">Lastname</label>
 			<label index="tx_blogexample_domain_model_person.email">E-Mail</label>
 			<label index="tx_blogexample_domain_model_person.avatar">Avatar</label>
+			<label index="tx_blogexample_domain_model_person.tags">Tags</label>
+			<label index="tx_blogexample_domain_model_person.tags_special">Special tags</label>
 			<label index="tx_blogexample_domain_model_comment">Comment</label>
 			<label index="tx_blogexample_domain_model_comment.date">Date</label>
 			<label index="tx_blogexample_domain_model_comment.author">Author</label>
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/ext_tables.sql b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/ext_tables.sql
index 10aa5bfdb9f5b4574838718f2a118fa1a952fbd8..67ef7cf09ae7384c4b145b4a7664636323df5800 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/ext_tables.sql
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/ext_tables.sql
@@ -35,7 +35,7 @@ CREATE TABLE tx_blogexample_domain_model_blog (
 
 	PRIMARY KEY (uid),
 	KEY parent (pid),
-	KEY t3ver_oid (t3ver_oid,t3ver_wsid),
+	KEY t3ver_oid (t3ver_oid,t3ver_wsid)
 );
 
 #
@@ -78,7 +78,7 @@ CREATE TABLE tx_blogexample_domain_model_post (
 
 	PRIMARY KEY (uid),
 	KEY parent (pid),
-	KEY t3ver_oid (t3ver_oid,t3ver_wsid),
+	KEY t3ver_oid (t3ver_oid,t3ver_wsid)
 );
 
 #
@@ -101,7 +101,7 @@ CREATE TABLE tx_blogexample_domain_model_comment (
 	hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
 
 	PRIMARY KEY (uid),
-	KEY parent (pid),
+	KEY parent (pid)
 );
 
 #
@@ -114,6 +114,8 @@ CREATE TABLE tx_blogexample_domain_model_person (
 	firstname varchar(255) DEFAULT '' NOT NULL,
 	lastname varchar(255) DEFAULT '' NOT NULL,
 	email varchar(255) DEFAULT '' NOT NULL,
+	tags int(11) unsigned DEFAULT '0' NOT NULL,
+	tags_special int(11) unsigned DEFAULT '0' NOT NULL,
 
 	tstamp int(11) unsigned DEFAULT '0' NOT NULL,
 	crdate int(11) unsigned DEFAULT '0' NOT NULL,
@@ -133,7 +135,7 @@ CREATE TABLE tx_blogexample_domain_model_person (
 
 	PRIMARY KEY (uid),
 	KEY parent (pid),
-	KEY t3ver_oid (t3ver_oid,t3ver_wsid),
+	KEY t3ver_oid (t3ver_oid,t3ver_wsid)
 );
 
 #
@@ -154,7 +156,22 @@ CREATE TABLE tx_blogexample_domain_model_tag (
 	sys_language_uid int(11) DEFAULT '0' NOT NULL,
 
 	PRIMARY KEY (uid),
-	KEY parent (pid),
+	KEY parent (pid)
+);
+
+#
+# Table structure for table 'tx_blogexample_domain_model_tag_mm'
+#
+CREATE TABLE tx_blogexample_domain_model_tag_mm (
+	uid_local int(11) unsigned DEFAULT '0' NOT NULL,
+	uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
+	tablenames varchar(255) DEFAULT '' NOT NULL,
+	fieldname varchar(255) DEFAULT '' NOT NULL,
+	sorting int(11) unsigned DEFAULT '0' NOT NULL,
+	sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL,
+
+	KEY uid_local (uid_local),
+	KEY uid_foreign (uid_foreign)
 );
 
 #
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php
index a359a83081b5adda9b81881082a0a4bd51438fd3..325d873833c4771d9fdc824adf6dc694698a033a 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php
@@ -21,7 +21,7 @@ class CountTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	/**
 	 * @var int number of all records
 	 */
-	protected $numberOfRecordsInFixture = 11;
+	protected $numberOfRecordsInFixture = 14;
 
 	/**
 	 * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
@@ -48,6 +48,11 @@ class CountTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 */
 	protected $blogRepository;
 
+	/**
+	 * @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository
+	 */
+	protected $postRepository;
+
 	/**
 	 * Sets up this test suite.
 	 */
@@ -57,8 +62,11 @@ class CountTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/core/Tests/Functional/Fixtures/pages.xml');
 		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml');
 		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-post-mm.xml');
 		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags-mm.xml');
 		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/persons.xml');
 
 		$this->objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
 		$this->persistentManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
@@ -147,6 +155,21 @@ class CountTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->assertSame(10, $query->count());
 	}
 
+	/**
+	 * Test if count works with subproperties in subselects that use the same table as the repository.
+	 *
+	 * @test
+	 */
+	public function subpropertyJoinSameTableCountTest() {
+		$query = $this->postRepository->createQuery();
+
+		$query->matching(
+			$query->equals('relatedPosts.title', 'Post2')
+		);
+
+		$this->assertSame(1, $query->count());
+	}
+
 	/**
 	 * Test if count works with subproperties in multiple left join.
 	 *
@@ -165,4 +188,36 @@ class CountTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->assertSame(10, $query->count());
 	}
 
+	/**
+	 * @test
+	 */
+	public function queryWithAndConditionsToTheSameTableReturnExpectedCount() {
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PersonRepository $personRepository */
+		$personRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PersonRepository::class);
+		$query = $personRepository->createQuery();
+		$query->matching(
+			$query->logicalAnd(
+				$query->equals('tags.name', 'TagForAuthor1'),
+				$query->equals('tagsSpecial.name', 'SpecialTagForAuthor1')
+			)
+		);
+		$this->assertSame(1, $query->count());
+	}
+
+	/**
+	 * @test
+	 */
+	public function queryWithOrConditionsToTheSameTableReturnExpectedCount() {
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PersonRepository $personRepository */
+		$personRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PersonRepository::class);
+		$query = $personRepository->createQuery();
+		$query->matching(
+			$query->logicalOr(
+				$query->equals('tags.name', 'TagForAuthor1'),
+				$query->equals('tagsSpecial.name', 'SpecialTagForAuthor1')
+			)
+		);
+		$this->assertSame(3, $query->count());
+	}
+
 }
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
index 1da71af92564c5d4293108737d3c19451b1e2538..f002eca62b36adde9252edf059b88ab5681a9f67 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml
@@ -20,4 +20,35 @@
 		<deleted>0</deleted>
 		<posts>1</posts>
 	</tx_blogexample_domain_model_blog>
+	<tx_blogexample_domain_model_blog>
+		<uid>3</uid>
+		<pid>0</pid>
+		<title>Blog3</title>
+		<description>Blog3 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<deleted>0</deleted>
+		<posts>1</posts>
+	</tx_blogexample_domain_model_blog>
+	<tx_blogexample_domain_model_blog>
+		<uid>4</uid>
+		<pid>0</pid>
+		<title>Blog4Hidden</title>
+		<description>Blog4 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<hidden>1</hidden>
+		<deleted>0</deleted>
+		<posts>1</posts>
+	</tx_blogexample_domain_model_blog>
+	<tx_blogexample_domain_model_blog>
+		<uid>5</uid>
+		<pid>0</pid>
+		<title>Blog5Deleted</title>
+		<description>Blog5 Description</description>
+		<logo></logo>
+		<l18n_diffsource></l18n_diffsource>
+		<deleted>1</deleted>
+		<posts>1</posts>
+	</tx_blogexample_domain_model_blog>
 </dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/persons.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/persons.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f140363391bf620ce883027e24b03b5048311ac0
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/persons.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+	<tx_blogexample_domain_model_person>
+		<uid>1</uid>
+		<pid>0</pid>
+		<firstname>Author</firstname>
+		<lastname>With tag and special tag</lastname>
+		<tags>1</tags>
+		<tags_special>1</tags_special>
+	</tx_blogexample_domain_model_person>
+	<tx_blogexample_domain_model_person>
+		<uid>2</uid>
+		<pid>0</pid>
+		<firstname>Author</firstname>
+		<lastname>With tag</lastname>
+		<tags>1</tags>
+		<tags_special>0</tags_special>
+	</tx_blogexample_domain_model_person>
+	<tx_blogexample_domain_model_person>
+		<uid>3</uid>
+		<pid>0</pid>
+		<firstname>Author</firstname>
+		<lastname>With special tag</lastname>
+		<tags>0</tags>
+		<tags_special>1</tags_special>
+	</tx_blogexample_domain_model_person>
+</dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-post-mm.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-post-mm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7eeccfbf009f9a533882081d6442ed72217a68d2
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-post-mm.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+	<!-- Blog post 2 is related to blog post 1 -->
+	<tx_blogexample_post_post_mm>
+		<uid_local>2</uid_local>
+		<uid_foreign>1</uid_foreign>
+		<sorting>1</sorting>
+		<sorting_foreign>1</sorting_foreign>
+	</tx_blogexample_post_post_mm>
+</dataset>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml
index 128edfe36f195dee642c97996d5aa37f7fbc2afa..222a5904d006da92b8528c5ac593ee9e01581b58 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml
@@ -123,4 +123,16 @@
 		<sorting>1</sorting>
 		<sorting_foreign>10</sorting_foreign>
 	</tx_blogexample_post_tag_mm>
+	<tx_blogexample_post_tag_mm>
+		<uid_local>12</uid_local>
+		<uid_foreign>12</uid_foreign>
+		<sorting>1</sorting>
+		<sorting_foreign>10</sorting_foreign>
+	</tx_blogexample_post_tag_mm>
+	<tx_blogexample_post_tag_mm>
+		<uid_local>13</uid_local>
+		<uid_foreign>12</uid_foreign>
+		<sorting>1</sorting>
+		<sorting_foreign>10</sorting_foreign>
+	</tx_blogexample_post_tag_mm>
 </dataset>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
index 598f423521e6ed12dcd2ce7e6855fa6609d2304f..4676719f4ea2fe3457ea62338c73bcbe11b515a3 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml
@@ -12,6 +12,7 @@
 		<l18n_diffsource></l18n_diffsource>
 		<sorting>1</sorting>
 		<deleted>0</deleted>
+		<related_posts>1</related_posts>
 	</tx_blogexample_domain_model_post>
 	<tx_blogexample_domain_model_post>
 		<uid>2</uid>
@@ -133,4 +134,72 @@
 		<sorting>11</sorting>
 		<deleted>0</deleted>
 	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>12</uid>
+		<pid>0</pid>
+		<blog>3</blog>
+		<author>0</author>
+		<tags>1</tags>
+		<categories>0</categories>
+		<title>post with tag</title>
+		<content>Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>1</sorting>
+		<deleted>0</deleted>
+		<hidden>0</hidden>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>13</uid>
+		<pid>0</pid>
+		<blog>3</blog>
+		<author>1</author>
+		<tags>0</tags>
+		<categories>0</categories>
+		<title>post with tagged author</title>
+		<content>Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>2</sorting>
+		<deleted>0</deleted>
+		<hidden>0</hidden>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>14</uid>
+		<pid>0</pid>
+		<blog>3</blog>
+		<author>1</author>
+		<tags>1</tags>
+		<categories>0</categories>
+		<title>post with tag and tagged author</title>
+		<content>Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>2</sorting>
+		<deleted>0</deleted>
+		<hidden>0</hidden>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>20</uid>
+		<pid>0</pid>
+		<blog>3</blog>
+		<tags>0</tags>
+		<categories>0</categories>
+		<title>post20 hidden</title>
+		<content>Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>11</sorting>
+		<deleted>0</deleted>
+		<hidden>1</hidden>
+	</tx_blogexample_domain_model_post>
+	<tx_blogexample_domain_model_post>
+		<uid>30</uid>
+		<pid>0</pid>
+		<blog>3</blog>
+		<tags>0</tags>
+		<categories>0</categories>
+		<title>post30 deleted</title>
+		<content>Lorem ipsum...</content>
+		<l18n_diffsource></l18n_diffsource>
+		<sorting>11</sorting>
+		<deleted>1</deleted>
+		<hidden>0</hidden>
+	</tx_blogexample_domain_model_post>
 </dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags-mm.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags-mm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..560562c6c83d60531ff48bdc7dca5125d957443a
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags-mm.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+	<tx_blogexample_domain_model_tag_mm>
+		<uid_local>1</uid_local>
+		<uid_foreign>11</uid_foreign>
+		<tablenames>tx_blogexample_domain_model_person</tablenames>
+		<fieldname>tags</fieldname>
+		<sorting>1</sorting>
+		<sorting_foreign>1</sorting_foreign>
+	</tx_blogexample_domain_model_tag_mm>
+	<tx_blogexample_domain_model_tag_mm>
+		<uid_local>1</uid_local>
+		<uid_foreign>13</uid_foreign>
+		<tablenames>tx_blogexample_domain_model_person</tablenames>
+		<fieldname>tags_special</fieldname>
+		<sorting>1</sorting>
+		<sorting_foreign>1</sorting_foreign>
+	</tx_blogexample_domain_model_tag_mm>
+	<tx_blogexample_domain_model_tag_mm>
+		<uid_local>2</uid_local>
+		<uid_foreign>11</uid_foreign>
+		<tablenames>tx_blogexample_domain_model_person</tablenames>
+		<fieldname>tags</fieldname>
+		<sorting>1</sorting>
+		<sorting_foreign>1</sorting_foreign>
+	</tx_blogexample_domain_model_tag_mm>
+	<tx_blogexample_domain_model_tag_mm>
+		<uid_local>3</uid_local>
+		<uid_foreign>13</uid_foreign>
+		<tablenames>tx_blogexample_domain_model_person</tablenames>
+		<fieldname>tags_special</fieldname>
+		<sorting>1</sorting>
+		<sorting_foreign>1</sorting_foreign>
+	</tx_blogexample_domain_model_tag_mm>
+</dataset>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml
index 71ef96979ad2613f8bf89ac1064653df70713c0c..e1a2b8c0cd3885dfb6668bdf7c8f0f1eabf1bc9f 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml
@@ -70,4 +70,25 @@
 		<name>Tag10</name>
 		<deleted>0</deleted>
 	</tx_blogexample_domain_model_tag>
+	<tx_blogexample_domain_model_tag>
+		<uid>11</uid>
+		<pid>0</pid>
+		<posts>0</posts>
+		<name>TagForAuthor1</name>
+		<deleted>0</deleted>
+	</tx_blogexample_domain_model_tag>
+	<tx_blogexample_domain_model_tag>
+		<uid>12</uid>
+		<pid>0</pid>
+		<posts>0</posts>
+		<name>Tag12</name>
+		<deleted>0</deleted>
+	</tx_blogexample_domain_model_tag>
+	<tx_blogexample_domain_model_tag>
+		<uid>13</uid>
+		<pid>0</pid>
+		<posts>0</posts>
+		<name>SpecialTagForAuthor1</name>
+		<deleted>0</deleted>
+	</tx_blogexample_domain_model_tag>
 </dataset>
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/InTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/InTest.php
index bc5eb4a72b874589777d4e2c178a66dc8404afbb..5ba238c56ff2b11ecadbbfc496453825d6a14102 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/InTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/InTest.php
@@ -156,7 +156,9 @@ class InTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function inConditionWorksWithQueryResult() {
-		$queryResult = $this->blogRepository->findAll();
+		$query = $this->blogRepository->createQuery();
+		$query->matching($query->in('uid', array(1,2)));
+		$queryResult = $query->execute();
 
 		$inQuery = $this->postRepository->createQuery();
 
@@ -172,7 +174,9 @@ class InTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function inConditionWorksWithQueryResultOnSecondCall() {
-		$queryResult = $this->blogRepository->findAll();
+		$query = $this->blogRepository->createQuery();
+		$query->matching($query->in('uid', array(1,2)));
+		$queryResult = $query->execute();
 
 		$inQuery = $this->postRepository->createQuery();
 
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
index b2c2f688e278ee0a4264b51f39741bac63c99d8e..f6ccb93f3973e408611e82f9b3f70d6a38324994 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
@@ -38,12 +38,23 @@ class QueryParserTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 */
 	protected $objectManager;
 
+	/**
+	 * @var \ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository
+	 */
+	protected $blogRepository;
+
 	/**
 	 * Sets up this test suite.
 	 */
 	protected function setUp() {
 		parent::setUp();
 
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/tags-mm.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/persons.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
+		$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/post-tag-mm.xml');
+
 		$this->objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
 		$this->queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
 		$this->blogRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository::class);
@@ -119,4 +130,42 @@ class QueryParserTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->assertNotSame($hashWithCaseSensitiveFalse, $hashWithCaseSensitiveTrue);
 	}
 
+	/**
+	 * @test
+	 */
+	public function queryWithMultipleRelationsToIdenticalTablesReturnsExpectedResultForOrQuery() {
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
+		$postRepository = $this->objectManager->get('ExtbaseTeam\\BlogExample\\Domain\\Repository\\PostRepository');
+		$query = $postRepository->createQuery();
+		$query->matching(
+			$query->logicalAnd(
+				$query->equals('blog', 3),
+				$query->logicalOr(
+					$query->equals('tags.name', 'Tag12'),
+					$query->equals('author.tags.name', 'TagForAuthor1')
+				)
+			)
+		);
+		$result = $query->execute()->toArray();
+		$this->assertEquals(3, count($result));
+	}
+
+	/**
+	 * @test
+	 */
+	public function queryWithMultipleRelationsToIdenticalTablesReturnsExpectedResultForAndQuery() {
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
+		$postRepository = $this->objectManager->get('ExtbaseTeam\\BlogExample\\Domain\\Repository\\PostRepository');
+		$query = $postRepository->createQuery();
+		$query->matching(
+			$query->logicalAnd(
+				$query->equals('blog', 3),
+				$query->equals('tags.name', 'Tag12'),
+				$query->equals('author.tags.name', 'TagForAuthor1')
+			)
+		);
+		$result = $query->execute()->toArray();
+		$this->assertEquals(1, count($result));
+	}
+
 }
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
index a23e5ca2000a853c2f404d90573397e65ea97245..5982ef89b8644a9fee5b88a9bfb9cd5a14720aaf 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php
@@ -19,11 +19,6 @@ use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
 
 class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 
-	/**
-	 * @var int number of all records
-	 */
-	protected $numberOfRecordsInFixture = 11;
-
 	/**
 	 * @var \ExtbaseTeam\BlogExample\Domain\Model\Blog
 	 */
@@ -70,10 +65,10 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function attachPostToBlogAtTheEnd() {
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$countPostsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid());
 
 		$newPostTitle = 'sdufhisdhuf';
+		/** @var \ExtbaseTeam\BlogExample\Domain\Model\Post $newPost */
 		$newPost = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Post::class);
 		$newPost->setBlog($this->blog);
 		$newPost->setTitle($newPostTitle);
@@ -82,12 +77,12 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->blog->addPost($newPost);
 		$this->updateAndPersistBlog();
 
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame(($this->numberOfRecordsInFixture + 1), $countPosts);
+		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid());
+		$this->assertSame(($countPostsOriginal + 1), $countPosts);
 
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid(), '', 'sorting DESC');
 		$this->assertSame($newPostTitle, $post['title']);
-		$this->assertSame((string)($this->numberOfRecordsInFixture), $post['sorting']);
+		$this->assertSame((string)($countPostsOriginal + 1), $post['sorting']);
 	}
 
 	/**
@@ -96,8 +91,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function removeLastPostFromBlog() {
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$countPostsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
 
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('sorting', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid(), '', 'sorting DESC');
 		$this->assertEquals(10, $post['sorting']);
@@ -112,7 +106,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->updateAndPersistBlog();
 
 		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
-		$this->assertEquals(($this->numberOfRecordsInFixture - 1), $countPosts);
+		$this->assertEquals(($countPostsOriginal - 1), $countPosts);
 
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', 'tx_blogexample_domain_model_post', 'uid =' . $latestPost->getUid() . ' AND deleted=0');
 		$this->assertSame(NULL, $post['uid']);
@@ -128,8 +122,10 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function addPostToBlogInTheMiddle() {
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$countPostsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
+
+		/** @var \ExtbaseTeam\BlogExample\Domain\Model\Post $newPost */
+		$newPost = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Post::class);
 
 		$posts = clone $this->blog->getPosts();
 		$this->blog->getPosts()->removeAll($posts);
@@ -138,7 +134,6 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		foreach ($posts as $post) {
 			$this->blog->addPost($post);
 			if ($counter == 5) {
-				$newPost = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Post::class);
 				$newPost->setBlog($this->blog);
 				$newPost->setTitle($newPostTitle);
 				$newPost->setContent('Bla Bla Bla');
@@ -148,8 +143,8 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		}
 		$this->updateAndPersistBlog();
 
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post',  'deleted=0');
-		$this->assertSame(($this->numberOfRecordsInFixture + 1), $countPosts);
+		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
+		$this->assertSame(($countPostsOriginal + 1), $countPosts);
 
 		//last post
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid(), '', 'sorting DESC');
@@ -157,7 +152,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->assertSame('11', $post['sorting']);
 
 		// check sorting of the post added in the middle
-		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'uid=' . ($this->numberOfRecordsInFixture + 1));
+		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'uid=' . $newPost->getUid());
 		$this->assertSame($newPostTitle, $post['title']);
 		$this->assertSame('6', $post['sorting']);
 	}
@@ -168,8 +163,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function removeMiddlePostFromBlog() {
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$countPostsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
 
 		$posts = clone $this->blog->getPosts();
 		$counter = 1;
@@ -182,7 +176,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->updateAndPersistBlog();
 
 		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
-		$this->assertSame(($this->numberOfRecordsInFixture - 1), $countPosts);
+		$this->assertSame(($countPostsOriginal - 1), $countPosts);
 
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid(), '', 'sorting DESC');
 		$this->assertSame('Post10', $post['title']);
@@ -195,8 +189,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function movePostFromEndToTheMiddle() {
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$countPostsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
 
 		$posts = clone $this->blog->getPosts();
 		$postsArray = $posts->toArray();
@@ -218,7 +211,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->updateAndPersistBlog();
 
 		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_post', 'deleted=0');
-		$this->assertSame($this->numberOfRecordsInFixture, $countPosts);
+		$this->assertSame($countPostsOriginal, $countPosts);
 
 		$post = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('title,sorting', 'tx_blogexample_domain_model_post', 'blog =' . $this->blog->getUid(), '', 'sorting DESC');
 		$this->assertSame('Post9', $post['title']);
@@ -235,12 +228,14 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 * @test
 	 */
 	public function attachTagToPostAtTheEnd() {
-		$count = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag');
-		$this->assertSame(10, $count);
+		$countOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag');
 
 		$newTagTitle = 'sdufhisdhuf';
-		$newTag = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Tag::class, $newTagTitle);
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Model\Tag $newTag */
+		$newTag = $this->objectManager->get('ExtbaseTeam\\BlogExample\\Domain\\Model\\Tag', $newTagTitle);
+
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$post->addTag($newTag);
@@ -249,22 +244,21 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->persistentManager->persistAll();
 
 		$count = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag');
-		$this->assertSame(11, $count);
+		$this->assertSame(($countOriginal + 1), $count);
 
 		$tag = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid_foreign', 'tx_blogexample_post_tag_mm', 'uid_local =' . $post->getUid(), '', 'sorting DESC');
-		$this->assertSame('11', $tag['uid_foreign']);
+		$this->assertSame($newTag->getUid(), (int)$tag['uid_foreign']);
 	}
 
-
 	/**
 	 * Tests removing object from the end of sorted M:M relation (Post:Tag)
 	 *
 	 * @test
 	 */
-	public  function removeLastTagFromPost() {
-		$count = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag');
-		$this->assertSame(10, $count);
+	public function removeLastTagFromPost() {
+		$countOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag', 'deleted=0');
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$tags = $post->getTags();
@@ -278,8 +272,8 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$postRepository->update($post);
 		$this->persistentManager->persistAll();
 
-		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag', 'deleted=0' );
-		$this->assertEquals(10, $countPosts);
+		$countPosts = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_domain_model_tag', 'deleted=0');
+		$this->assertEquals($countOriginal, $countPosts);
 
 		$tag = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid_foreign', 'tx_blogexample_post_tag_mm', 'uid_local =' . $post->getUid(), '', 'sorting DESC');
 		$this->assertSame('9', $tag['uid_foreign']);
@@ -293,20 +287,22 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	 *
 	 * @test
 	 */
-	public  function addTagToPostInTheMiddle() {
-		$countTags = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_post_tag_mm', 'uid_local=1');
-		$this->assertSame(10, $countTags);
+	public function addTagToPostInTheMiddle() {
+		$countTagsOriginal = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_post_tag_mm', 'uid_local=1');
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$tags = clone $post->getTags();
 		$post->setTags(new ObjectStorage());
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Model\Tag $newTag */
+		$newTag = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Tag::class, 'INSERTED TAG at position 6 : ' . strftime(''));
+
 		$counter = 1;
 		foreach ($tags as $tag) {
 			$post->addTag($tag);
 			if ($counter == 5) {
-				$newTag = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Model\Tag::class, 'INSERTED TAG at position 6 : ' . strftime(''));
 				$post->addTag($newTag);
 			}
 			$counter++;
@@ -316,16 +312,15 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$this->persistentManager->persistAll();
 
 		$countTags = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_post_tag_mm', 'uid_local=1');
-		$this->assertSame(11, $countTags);
+		$this->assertSame(($countTagsOriginal + 1), $countTags);
 
 		$tag = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid_foreign', 'tx_blogexample_post_tag_mm', 'uid_local =' . $post->getUid(), '', 'sorting DESC');
 		$this->assertSame('10', $tag['uid_foreign']);
 
 		$tag = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid_foreign', 'tx_blogexample_post_tag_mm', 'uid_local =' . $post->getUid() . ' AND sorting=6');
-		$this->assertSame('11', $tag['uid_foreign']);
+		$this->assertSame($newTag->getUid(), (int)$tag['uid_foreign']);
 	}
 
-
 	/**
 	 * Tests removing object from the middle of the sorted M:M relation (Post:Tag)
 	 *
@@ -335,6 +330,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$countTags = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_post_tag_mm', 'uid_local=1');
 		$this->assertSame(10, $countTags);
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$tags = clone $post->getTags();
@@ -369,6 +365,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$countTags = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'tx_blogexample_post_tag_mm', 'uid_local=1');
 		$this->assertSame(10, $countTags);
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$tags = clone $post->getTags();
@@ -413,6 +410,7 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 	public function timestampFieldIsUpdatedOnPostSave() {
 		$rawPost = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('*', 'tx_blogexample_domain_model_post', 'uid=1');
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 		$post->setTitle("newTitle");
@@ -471,9 +469,11 @@ class RelationTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 		$countCategories = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'sys_category_record_mm', 'uid_foreign=1 AND tablenames="tx_blogexample_domain_model_post" AND fieldname="categories"');
 		$this->assertSame(3, $countCategories);
 
+		/** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
 		$postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
 		$post = $postRepository->findByUid(1);
 
+		/** @var \TYPO3\CMS\Extbase\Domain\Model\Category $newCategory */
 		$newCategory = $this->objectManager->get(\TYPO3\CMS\Extbase\Domain\Model\Category::class);
 		$newCategory->setTitle('New Category');
 
diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
index 635f4f3ce543f07689263e42ba38467b62c7b4c1..cccd303c50bdfcd5879fc6a1d8145fc40142c626 100644
--- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php
@@ -25,10 +25,9 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		);
 		/** @var \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings|\PHPUnit_Framework_MockObject_MockObject $querySettings */
 		$querySettings = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
-		$sql = array();
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (0,-1))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (0,-1))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -40,13 +39,12 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$GLOBALS['TCA'][$table]['ctrl'] = array(
 			'languageField' => 'sys_language_uid'
 		);
-		$sql = array();
 		/** @var \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings|\PHPUnit_Framework_MockObject_MockObject $querySettings */
 		$querySettings = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class, array('dummy'));
 		$querySettings->setLanguageUid('1');
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$result = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (1,-1))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$result = '(' . $table . '.sys_language_uid IN (1,-1))';
 		$this->assertSame($result, $sql);
 	}
 
@@ -58,11 +56,10 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$GLOBALS['TCA'][$table]['ctrl'] = array(
 			'languageField' => 'sys_language_uid'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (0,-1))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (0,-1))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -75,12 +72,11 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 			'languageField' => 'sys_language_uid',
 			'delete' => 'deleted'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$querySettings->setLanguageUid(0);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (0,-1))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (0,-1))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -92,12 +88,11 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$GLOBALS['TCA'][$table]['ctrl'] = array(
 			'languageField' => 'sys_language_uid'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$querySettings->setLanguageUid(2);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (2,-1))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (2,-1))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -110,12 +105,11 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 			'languageField' => 'sys_language_uid',
 			'transOrigPointerField' => 'l10n_parent'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$querySettings->setLanguageUid(2);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array('(' . $table . '.sys_language_uid IN (2,-1) OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (SELECT ' . $table . '.l10n_parent FROM ' . $table . ' WHERE ' . $table . '.l10n_parent>0 AND ' . $table . '.sys_language_uid=2)))'));
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (2,-1) OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (SELECT ' . $table . '.l10n_parent FROM ' . $table . ' WHERE ' . $table . '.l10n_parent>0 AND ' . $table . '.sys_language_uid=2)))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -129,19 +123,16 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 			'transOrigPointerField' => 'l10n_parent',
 			'delete' => 'deleted'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$querySettings->setLanguageUid(2);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array(
-			'(' . $table . '.sys_language_uid IN (2,-1)' .
+		$sql= $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (2,-1)' .
 				' OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (' .
 				'SELECT ' . $table . '.l10n_parent FROM ' . $table .
 				' WHERE ' . $table . '.l10n_parent>0 AND ' .
 				$table . '.sys_language_uid=2 AND ' .
-				$table . '.deleted=0)))')
-		);
+				$table . '.deleted=0)))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -149,26 +140,22 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 	 * @test
 	 */
 	public function addSysLanguageStatementWorksInBackendContextWithSubselectionTakesDeleteStatementIntoAccountIfNecessary() {
-		$table = $this->getUniqueId('tx_coretest_table');
 		$table = 'tt_content';
 		$GLOBALS['TCA'][$table]['ctrl'] = array(
 			'languageField' => 'sys_language_uid',
 			'transOrigPointerField' => 'l10n_parent',
 			'delete' => 'deleted'
 		);
-		$sql = array();
 		$querySettings = new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings();
 		$querySettings->setLanguageUid(2);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
-		$mockTypo3DbQueryParser->_callRef('addSysLanguageStatement', $table, $sql, $querySettings);
-		$expectedSql = array('additionalWhereClause' => array(
-			'(' . $table . '.sys_language_uid IN (2,-1)' .
+		$sql = $mockTypo3DbQueryParser->_callRef('getSysLanguageStatement', $table, $table, $querySettings);
+		$expectedSql = '(' . $table . '.sys_language_uid IN (2,-1)' .
 				' OR (' . $table . '.sys_language_uid=0 AND ' . $table . '.uid NOT IN (' .
 				'SELECT ' . $table . '.l10n_parent FROM ' . $table .
 				' WHERE ' . $table . '.l10n_parent>0 AND ' .
 				$table . '.sys_language_uid=2 AND ' .
-				$table . '.deleted=0)))')
-		);
+				$table . '.deleted=0)))';
 		$this->assertSame($expectedSql, $sql);
 	}
 
@@ -230,14 +217,14 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
 	public function providerForVisibilityConstraintStatement() {
 		return array(
-			'in be: include all' => array('BE', TRUE, array(), TRUE, NULL),
-			'in be: ignore enable fields but do not include deleted' => array('BE', TRUE, array(), FALSE, array('tx_foo_table.deleted_column=0')),
-			'in be: respect enable fields but include deleted' => array('BE', FALSE, array(), TRUE, array('tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789)')),
-			'in be: respect enable fields and do not include deleted' => array('BE', FALSE, array(), FALSE, array('tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789) AND tx_foo_table.deleted_column=0')),
-			'in fe: include all' => array('FE', TRUE, array(), TRUE, NULL),
-			'in fe: ignore enable fields but do not include deleted' => array('FE', TRUE, array(), FALSE, array('tx_foo_table.deleted_column=0')),
-			'in fe: ignore only starttime and do not include deleted' => array('FE', TRUE, array('starttime'), FALSE, array('tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0')),
-			'in fe: respect enable fields and do not include deleted' => array('FE', FALSE, array(), FALSE, array('tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0 AND tx_foo_table.starttime_column<=123456789'))
+			'in be: include all' => array('BE', TRUE, array(), TRUE, ''),
+			'in be: ignore enable fields but do not include deleted' => array('BE', TRUE, array(), FALSE, 'tx_foo_table.deleted_column=0'),
+			'in be: respect enable fields but include deleted' => array('BE', FALSE, array(), TRUE, 'tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789)'),
+			'in be: respect enable fields and do not include deleted' => array('BE', FALSE, array(), FALSE, 'tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789) AND tx_foo_table.deleted_column=0'),
+			'in fe: include all' => array('FE', TRUE, array(), TRUE, ''),
+			'in fe: ignore enable fields but do not include deleted' => array('FE', TRUE, array(), FALSE, 'tx_foo_table.deleted_column=0'),
+			'in fe: ignore only starttime and do not include deleted' => array('FE', TRUE, array('starttime'), FALSE, 'tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0'),
+			'in fe: respect enable fields and do not include deleted' => array('FE', FALSE, array(), FALSE, 'tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0 AND tx_foo_table.starttime_column<=123456789')
 		);
 	}
 
@@ -261,7 +248,6 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$mockQuerySettings->expects($this->once())->method('getIgnoreEnableFields')->will($this->returnValue($ignoreEnableFields));
 		$mockQuerySettings->expects($this->once())->method('getEnableFieldsToBeIgnored')->will($this->returnValue($enableFieldsToBeIgnored));
 		$mockQuerySettings->expects($this->once())->method('getIncludeDeleted')->will($this->returnValue($deletedValue));
-		$sql = array();
 
 		/** @var $mockEnvironmentService \TYPO3\CMS\Extbase\Service\EnvironmentService | \PHPUnit_Framework_MockObject_MockObject */
 		$mockEnvironmentService = $this->getMock(\TYPO3\CMS\Extbase\Service\EnvironmentService::class, array('isEnvironmentInFrontendMode'));
@@ -269,17 +255,17 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
 		$mockTypo3DbQueryParser->_set('environmentService', $mockEnvironmentService);
-		$mockTypo3DbQueryParser->_callRef('addVisibilityConstraintStatement', $mockQuerySettings, $tableName, $sql);
-		$this->assertSame($expectedSql, $sql['additionalWhereClause']);
+		$resultSql = $mockTypo3DbQueryParser->_callRef('getVisibilityConstraintStatement', $mockQuerySettings, $tableName, $tableName);
+		$this->assertSame($expectedSql, $resultSql);
 		unset($GLOBALS['TCA'][$tableName]);
 	}
 
 	public function providerForRespectEnableFields() {
 		return array(
-			'in be: respectEnableFields=false' => array('BE', FALSE, NULL),
-			'in be: respectEnableFields=true' => array('BE', TRUE, array('tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789) AND tx_foo_table.deleted_column=0')),
-			'in FE: respectEnableFields=false' => array('FE', FALSE, NULL),
-			'in FE: respectEnableFields=true' => array('FE', TRUE, array('tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0 AND tx_foo_table.starttime_column<=123456789'))
+			'in be: respectEnableFields=false' => array('BE', FALSE, ''),
+			'in be: respectEnableFields=true' => array('BE', TRUE, 'tx_foo_table.disabled_column=0 AND (tx_foo_table.starttime_column<=123456789) AND tx_foo_table.deleted_column=0'),
+			'in FE: respectEnableFields=false' => array('FE', FALSE, ''),
+			'in FE: respectEnableFields=true' => array('FE', TRUE, 'tx_foo_table.deleted_column=0 AND tx_foo_table.disabled_column=0 AND tx_foo_table.starttime_column<=123456789')
 		);
 	}
 
@@ -303,7 +289,6 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$mockQuerySettings = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class, array('dummy'), array(), '', FALSE);
 		$mockQuerySettings->setIgnoreEnableFields(!$respectEnableFields);
 		$mockQuerySettings->setIncludeDeleted(!$respectEnableFields);
-		$sql = array();
 
 		/** @var $mockEnvironmentService \TYPO3\CMS\Extbase\Service\EnvironmentService | \PHPUnit_Framework_MockObject_MockObject */
 		$mockEnvironmentService = $this->getMock(\TYPO3\CMS\Extbase\Service\EnvironmentService::class, array('isEnvironmentInFrontendMode'));
@@ -311,8 +296,8 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
 		$mockTypo3DbQueryParser->_set('environmentService', $mockEnvironmentService);
-		$mockTypo3DbQueryParser->_callRef('addVisibilityConstraintStatement', $mockQuerySettings, $tableName, $sql);
-		$this->assertSame($expectedSql, $sql['additionalWhereClause']);
+		$actualSql = $mockTypo3DbQueryParser->_callRef('getVisibilityConstraintStatement', $mockQuerySettings, $tableName, $tableName);
+		$this->assertSame($expectedSql, $actualSql);
 		unset($GLOBALS['TCA'][$tableName]);
 	}
 
@@ -332,7 +317,6 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$mockQuerySettings->expects($this->once())->method('getIgnoreEnableFields')->will($this->returnValue(FALSE));
 		$mockQuerySettings->expects($this->once())->method('getEnableFieldsToBeIgnored')->will($this->returnValue(array()));
 		$mockQuerySettings->expects($this->once())->method('getIncludeDeleted')->will($this->returnValue(TRUE));
-		$sql = array();
 
 		/** @var $mockEnvironmentService \TYPO3\CMS\Extbase\Service\EnvironmentService | \PHPUnit_Framework_MockObject_MockObject */
 		$mockEnvironmentService = $this->getMock(\TYPO3\CMS\Extbase\Service\EnvironmentService::class, array('isEnvironmentInFrontendMode'));
@@ -340,7 +324,7 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
 		$mockTypo3DbQueryParser->_set('environmentService', $mockEnvironmentService);
-		$mockTypo3DbQueryParser->_callRef('addVisibilityConstraintStatement', $mockQuerySettings, $tableName, $sql);
+		$mockTypo3DbQueryParser->_callRef('getVisibilityConstraintStatement', $mockQuerySettings, $tableName, $tableName);
 		unset($GLOBALS['TCA'][$tableName]);
 	}
 	/**
@@ -352,17 +336,17 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 			'set Pid to zero if rootLevel = 1' => array(
 				'1',
 				$table,
-				array('additionalWhereClause' => array($table . '.pid = 0'))
+				$table . '.pid = 0'
 			),
 			'set Pid to given Pids if rootLevel = 0' => array(
 				'0',
 				$table,
-				array('additionalWhereClause' => array($table . '.pid IN (42, 27)'))
+				$table . '.pid IN (42, 27)'
 			),
 			'set no statement if rootLevel = -1' => array(
 				'-1',
 				$table,
-				array()
+				''
 			)
 		);
 	}
@@ -376,13 +360,12 @@ class Typo3DbQueryParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
 		$GLOBALS['TCA'][$table]['ctrl'] = array(
 			'rootLevel' => $rootLevel
 		);
-		$sql = array();
 		$storagePageIds = array(42,27);
 		$mockTypo3DbQueryParser = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class, array('dummy'), array(), '', FALSE);
 		$mockFrontendVariableCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, array(), array(), '', FALSE);
 		$mockTypo3DbQueryParser->_set('tableColumnCache', $mockFrontendVariableCache);
 		$mockFrontendVariableCache->expects($this->once())->method('get')->will($this->returnValue(array('pid' => '42')));
-		$mockTypo3DbQueryParser->_callRef('addPageIdStatement', $table, $sql, $storagePageIds);
+		$sql = $mockTypo3DbQueryParser->_callRef('getPageIdStatement', $table, $table, $storagePageIds);
 
 		$this->assertSame($expectedSql, $sql);
 	}