Compare commits

...

46 Commits

Author SHA1 Message Date
Benjamin Eberlei
57705e0d78 Release 2.4.0 2013-09-07 18:19:56 +02:00
Benjamin Eberlei
82bb6b78cd Travis should prefer dist. 2013-09-07 13:20:35 +02:00
Benjamin Eberlei
64c56b21aa Remove minimum stability from 2.4 composer.json 2013-09-07 13:08:14 +02:00
Benjamin Eberlei
b04e2e6364 Adjust composer.json to pending 2.4 stable release 2013-09-07 12:59:17 +02:00
Benjamin Eberlei
a70f9b7f49 Fix branch alias 2013-09-07 12:57:56 +02:00
Benjamin Eberlei
c88a7c1ffe New Build process
- Switch from Phing to Ant
- Remove PEAR packaging
- Add Composer archiving
2013-09-07 12:57:38 +02:00
Benjamin Eberlei
c206728c96 Merge branch 'DDC-2638' into 2.4 2013-09-07 09:04:34 +02:00
Attila Fulop
e8d420c641 Fix for entity generator discriminator column 2013-09-07 09:04:26 +02:00
Benjamin Eberlei
fdcab7eae8 Merge branch 'DDC-2640' into 2.4 2013-09-07 09:01:01 +02:00
Maks Feltrin
45d7d5234f DO NOT OVERRIDE CUSTOM TREE WALKERS IN getIterator() 2013-09-07 09:00:06 +02:00
Benjamin Eberlei
159ca79b81 Merge origin/2.4 into local branch 2013-09-07 08:55:15 +02:00
Benjamin Eberlei
2b148a27e0 Merge Oracle test fixes to 2.4 branch 2013-09-07 08:54:23 +02:00
Guilherme Blanco
0aef57f60c Fixing missing table aliases when using Many2Many persister. 2013-08-26 10:29:45 -04:00
Benjamin Eberlei
fef1e0286c Merge branch 'DDC-2235' into 2.4 2013-08-20 10:08:21 +02:00
Guilherme Blanco
4a38534150 Fixed DDC-2235. 2013-08-20 10:08:07 +02:00
Benjamin Eberlei
1de22adb16 Merge branch 'DDC-2506' into 2.4 2013-08-20 09:56:54 +02:00
Guilherme Blanco
62b4160887 Fixed DDC-2506 by manually updating code. Closes PR #708. 2013-08-20 09:56:39 +02:00
Benjamin Eberlei
dbb7c4d2bf Merge branch 'DDC-2607' into 2.4 2013-08-20 09:51:19 +02:00
Dustin Thomson
e8978ee365 Modified executeInserts method in JoinedSubclassPersister to only check for the presence of columns in a composite primary key 2013-08-20 09:51:01 +02:00
Benjamin Eberlei
c095b88804 Merge branch 'DDC-2578' into 2.4 2013-08-10 18:14:24 +02:00
Guilherme Blanco
efe4208ba6 Kept BC. 2013-08-10 18:14:07 +02:00
Guilherme Blanco
453a56670d Modified Hydrators to be per-query instances instead of a singleton-like approach. 2013-08-10 18:14:07 +02:00
Benjamin Eberlei
ec36e2c866 Merge branch 'DDC-2579' into 2.4 2013-08-10 17:54:37 +02:00
Fabio B. Silva
e250572cb4 fix DDC-2579 2013-08-10 17:53:50 +02:00
Benjamin Eberlei
758955e183 Merge branch 'DDC-2582' into 2.4 2013-08-10 17:48:20 +02:00
Guilherme Blanco
5b8d6a1486 CS fixes. 2013-08-10 17:48:03 +02:00
Guilherme Blanco
3f1003fee9 Fixed DDC-1884. 2013-08-10 17:48:03 +02:00
Benjamin Eberlei
7e241e89b8 Merge branch 'DDC-2548' into 2.4 2013-08-10 17:43:40 +02:00
Michaël Gallego
67c1e1d2b1 Allow to have non-distinct queries 2013-08-10 17:43:26 +02:00
Benjamin Eberlei
261eacdbfc Merge branch 'DDC-2565' into 2.4 2013-08-10 17:27:47 +02:00
Austin Morris
43df821691 convert PersistentCollection functional tests to unit tests 2013-08-10 17:27:30 +02:00
Austin Morris
11d09702da remove redundant require_once for TestInit.php 2013-08-10 17:27:30 +02:00
Austin Morris
f9f14139cf do not initialize coll on add() 2013-08-10 17:27:30 +02:00
Austin Morris
39f4d46d36 Initialize coll when using Collection methods inside PersistentCollection 2013-08-10 17:27:30 +02:00
Austin Morris
1dae8d318f PersistentCollection - initialize coll - create failing tests 2013-08-10 17:27:30 +02:00
Benjamin Eberlei
a361a7c1cb Merge branch 'DDC-2542' into 2.4 2013-08-10 17:02:34 +02:00
Roger Llopart Pla
6a73608baf Fixed name colision. 2013-08-10 17:02:10 +02:00
Roger Llopart Pla
f9955152b2 Added a test which verifies that the tree walkers are kept. 2013-08-10 17:02:10 +02:00
Roger Llopart Pla
5aad1df149 Added docblock. 2013-08-10 17:02:10 +02:00
Roger Llopart Pla
243832555b Appending the Paginator tree walker hint, instead of removing all the other hints. 2013-08-10 17:02:10 +02:00
Benjamin Eberlei
ae12fa6b5b Merge branch 'DDC-2577' into 2.4 2013-08-10 16:28:35 +02:00
Konstantin.Myakshin
edaf9b6813 Skip not mapped public properties in SchemaValidator 2013-08-10 16:28:27 +02:00
Benjamin Eberlei
b324a21abf Merge branch 'DDC-2587' into 2.4 2013-08-10 16:25:04 +02:00
J. Bruni
ff34aaaa2c Updated EntityGeneratorTest::testEntityTypeAlias 2013-08-10 16:24:43 +02:00
J. Bruni
9767a814a6 Updated EntityGeneratorTest::testEntityTypeAlias 2013-08-10 16:24:43 +02:00
J Bruni
e6007575e1 Corrected PHP type for "decimal" mapping type
"Basic Mapping" documentation says:
"decimal: Type that maps a SQL DECIMAL to a PHP string."
2013-08-10 16:24:43 +02:00
34 changed files with 964 additions and 225 deletions

View File

@@ -16,7 +16,7 @@ before_script:
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
- composer install --prefer-source --dev
- composer install --prefer-dist --dev
script: phpunit --configuration tests/travis/$DB.travis.xml

View File

@@ -1,11 +1,3 @@
# Project Name
project.name=DoctrineORM
# Dependency minimum versions
dependencies.common=2.2.0beta1
dependencies.dbal=2.2.0beta1
dependencies.sfconsole=2.0.0
# Version class and file
project.version_class = Doctrine\ORM\Version
project.version_class = Doctrine\\ORM\\Version
project.version_file = lib/Doctrine/ORM/Version.php

199
build.xml
View File

@@ -1,114 +1,101 @@
<?xml version="1.0"?>
<project name="DoctrineORM" default="build" basedir=".">
<taskdef classname="phing.tasks.ext.d51PearPkg2Task" name="d51pearpkg2" />
<import file="${project.basedir}/lib/vendor/doctrine-build-common/packaging.xml" />
<property file="build.properties" />
<!--
Fileset for artifacts shared across all distributed packages.
-->
<fileset id="shared-artifacts" dir=".">
<include name="LICENSE"/>
<include name="UPGRADE*" />
<include name="doctrine-mapping.xsd" />
</fileset>
<!--
Fileset for command line scripts
-->
<fileset id="bin-scripts" dir="./bin">
<include name="doctrine"/>
<include name="doctrine-pear.php"/>
<include name="doctrine.bat"/>
</fileset>
<!--
Fileset for the sources of the Doctrine Common dependency.
-->
<fileset id="common-sources" dir="./lib/vendor/doctrine-common/lib">
<include name="Doctrine/Common/**"/>
</fileset>
<!--
Fileset for the sources of the Doctrine DBAL dependency.
-->
<fileset id="dbal-sources" dir="./lib/vendor/doctrine-dbal/lib">
<include name="Doctrine/DBAL/**"/>
</fileset>
<!--
Fileset for the sources of the Doctrine ORM.
-->
<fileset id="orm-sources" dir="./lib">
<include name="Doctrine/ORM/**"/>
</fileset>
<!--
Fileset for source of the Symfony YAML and Console components.
-->
<fileset id="symfony-sources" dir="./lib/vendor">
<include name="Symfony/Component/**"/>
<exclude name="**/.git/**" />
</fileset>
<!--
Builds ORM package, preparing it for distribution.
-->
<target name="copy-files" depends="prepare">
<copy todir="${build.dir}/${project.name}-${version}">
<fileset refid="shared-artifacts"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}">
<fileset refid="common-sources"/>
<fileset refid="dbal-sources"/>
<fileset refid="orm-sources"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}/Doctrine">
<fileset refid="symfony-sources"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}/bin">
<fileset refid="bin-scripts"/>
</copy>
<target name="php">
<exec executable="which" outputproperty="php_executable">
<arg value="php" />
</exec>
</target>
<!--
Builds distributable PEAR packages.
-->
<target name="define-pear-package" depends="copy-files">
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/${project.name}-${version}">
<name>DoctrineORM</name>
<summary>Doctrine Object Relational Mapper</summary>
<channel>pear.doctrine-project.org</channel>
<description>The Doctrine ORM package is the primary package containing the object relational mapper.</description>
<lead user="jwage" name="Jonathan H. Wage" email="jonwage@gmail.com" />
<lead user="guilhermeblanco" name="Guilherme Blanco" email="guilhermeblanco@gmail.com" />
<lead user="romanb" name="Roman Borschel" email="roman@code-factory.org" />
<lead user="beberlei" name="Benjamin Eberlei" email="kontakt@beberlei.de" />
<license>LGPL</license>
<version release="${pear.version}" api="${pear.version}" />
<stability release="${pear.stability}" api="${pear.stability}" />
<notes>-</notes>
<dependencies>
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
<package name="DoctrineCommon" channel="pear.doctrine-project.org" minimum_version="${dependencies.common}" />
<package name="DoctrineDBAL" channel="pear.doctrine-project.org" minimum_version="${dependencies.dbal}" />
<package name="Console" channel="pear.symfony.com" minimum_version="2.0.0" />
<package name="Yaml" channel="pear.symfony.com" minimum_version="2.0.0" />
</dependencies>
<dirroles key="bin">script</dirroles>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Symfony/Component/Yaml/</ignore>
<ignore>Symfony/Component/Console/</ignore>
<release>
<install as="doctrine" name="bin/doctrine" />
<install as="doctrine.php" name="bin/doctrine-pear.php" />
<install as="doctrine.bat" name="bin/doctrine.bat" />
</release>
<replacement path="bin/doctrine" type="pear-config" from="@php_bin@" to="php_bin" />
<replacement path="bin/doctrine.bat" type="pear-config" from="@bin_dir@" to="bin_dir" />
</d51pearpkg2>
<target name="prepare">
<mkdir dir="build" />
</target>
<target name="build" depends="check-git-checkout-clean,prepare,php,composer">
<exec executable="${php_executable}">
<arg value="build/composer.phar" />
<arg value="archive" />
<arg value="--dir=build" />
</exec>
</target>
<target name="composer" depends="php,composer-check,composer-download">
<exec executable="${php_executable}">
<arg value="build/composer.phar" />
<arg value="install" />
</exec>
</target>
<target name="composer-check" depends="prepare">
<available file="build/composer.phar" property="composer.present"/>
</target>
<target name="composer-download" unless="composer.present">
<exec executable="wget">
<arg value="-Obuild/composer.phar" />
<arg value="http://getcomposer.org/composer.phar" />
</exec>
</target>
<target name="make-release" depends="check-git-checkout-clean,prepare,php">
<replace file="${project.version_file}" token="-DEV" value="" failOnNoReplacements="true" />
<exec executable="${php_executable}" outputproperty="doctrine.current_version" failonerror="true">
<arg value="-r" />
<arg value="require_once '${project.version_file}';echo ${project.version_class}::VERSION;" />
</exec>
<exec executable="${php_executable}" outputproperty="doctrine.next_version" failonerror="true">
<arg value="-r" />
<arg value="$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}'));
if (count($parts) != 3) {
throw new \InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given');
}
$parts[2]++;
echo implode('.', $parts);
" />
</exec>
<git-commit file="${project.version_file}" message="Release ${doctrine.current_version}" />
<git-tag version="${doctrine.current_version}" />
<replace file="${project.version_file}" token="${doctrine.current_version}" value="${doctrine.next_version}-DEV" />
<git-commit file="${project.version_file}" message="Bump version to ${doctrine.next_version}" />
</target>
<target name="check-git-checkout-clean">
<exec executable="git" failonerror="true">
<arg value="diff-index" />
<arg value="--quiet" />
<arg value="HEAD" />
</exec>
</target>
<macrodef name="git-commit">
<attribute name="file" default="NOT SET"/>
<attribute name="message" default="NOT SET"/>
<sequential>
<exec executable="git">
<arg value="add" />
<arg value="@{file}" />
</exec>
<exec executable="git">
<arg value="commit" />
<arg value="-m" />
<arg value="@{message}" />
</exec>
</sequential>
</macrodef>
<macrodef name="git-tag">
<attribute name="version" default="NOT SET" />
<sequential>
<exec executable="git">
<arg value="tag" />
<arg value="-m" />
<arg value="v@{version}" />
<arg value="v@{version}" />
</exec>
</sequential>
</macrodef>
</project>

View File

@@ -11,16 +11,15 @@
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
],
"minimum-stability": "dev",
"require": {
"php": ">=5.3.2",
"ext-pdo": "*",
"doctrine/collections": "~1.1",
"doctrine/dbal": ">=2.4-beta,<2.5-dev",
"symfony/console": "2.*"
"doctrine/dbal": "~2.4",
"symfony/console": "~2.0"
},
"require-dev": {
"symfony/yaml": "2.1",
"symfony/yaml": "~2.1",
"satooshi/php-coveralls": "dev-master"
},
"suggest": {
@@ -34,5 +33,8 @@
"branch-alias": {
"dev-master": "2.4.x-dev"
}
},
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor"]
}
}

View File

@@ -701,6 +701,18 @@ abstract class AbstractQuery
return isset($this->_hints[$name]) ? $this->_hints[$name] : false;
}
/**
* Check if the query has a hint
*
* @param string $name The name of the hint
*
* @return bool False if the query does not have any hint
*/
public function hasHint($name)
{
return isset($this->_hints[$name]);
}
/**
* Return the key value map of query hints that are currently set.
*
@@ -787,7 +799,7 @@ abstract class AbstractQuery
return $stmt;
}
$data = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
$data = $this->_em->newHydrator($this->_hydrationMode)->hydrateAll(
$stmt, $this->_resultSetMapping, $this->_hints
);

View File

@@ -99,13 +99,6 @@ use Doctrine\Common\Util\ClassUtils;
*/
private $eventManager;
/**
* The maintained (cached) hydrators. One instance per type.
*
* @var array
*/
private $hydrators = array();
/**
* The proxy factory used to create dynamic proxies.
*
@@ -840,17 +833,15 @@ use Doctrine\Common\Util\ClassUtils;
* This method caches the hydrator instances which is used for all queries that don't
* selectively iterate over the result.
*
* @deprecated
*
* @param int $hydrationMode
*
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
public function getHydrator($hydrationMode)
{
if ( ! isset($this->hydrators[$hydrationMode])) {
$this->hydrators[$hydrationMode] = $this->newHydrator($hydrationMode);
}
return $this->hydrators[$hydrationMode];
return $this->newHydrator($hydrationMode);
}
/**

View File

@@ -146,6 +146,7 @@ class ArrayHydrator extends AbstractHydrator
$baseElement =& $this->_resultPointers[$parent];
} else {
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
continue;
}
@@ -167,6 +168,7 @@ class ArrayHydrator extends AbstractHydrator
if ( ! $indexExists || ! $indexIsValid) {
$element = $data;
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
} else {
@@ -183,9 +185,15 @@ class ArrayHydrator extends AbstractHydrator
} else {
$oneToOne = true;
if ( ! isset($nonemptyComponents[$dqlAlias]) && ! isset($baseElement[$relationAlias])) {
if (
( ! isset($nonemptyComponents[$dqlAlias])) &&
( ! isset($baseElement[$relationAlias]))
) {
$baseElement[$relationAlias] = null;
} else if ( ! isset($baseElement[$relationAlias])) {
} else if (
( ! isset($baseElement[$relationAlias])) ||
( ! isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]))
) {
$baseElement[$relationAlias] = $data;
}
}
@@ -195,7 +203,6 @@ class ArrayHydrator extends AbstractHydrator
if ($coll !== null) {
$this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne);
}
} else {
// It's a root result element
@@ -204,22 +211,21 @@ class ArrayHydrator extends AbstractHydrator
// if this row has a NULL value for the root result id then make it a null result.
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
if ($this->_rsm->isMixed) {
$result[] = array($entityKey => null);
} else {
$result[] = null;
}
$result[] = $this->_rsm->isMixed
? array($entityKey => null)
: null;
$resultKey = $this->_resultCounter;
++$this->_resultCounter;
continue;
}
// Check for an existing element
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $rowData[$dqlAlias];
if ($this->_rsm->isMixed) {
$element = array($entityKey => $element);
}
$element = $this->_rsm->isMixed
? array($entityKey => $rowData[$dqlAlias])
: $rowData[$dqlAlias];
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
@@ -227,6 +233,7 @@ class ArrayHydrator extends AbstractHydrator
} else {
$resultKey = $this->_resultCounter;
$result[] = $element;
++$this->_resultCounter;
}
@@ -234,11 +241,13 @@ class ArrayHydrator extends AbstractHydrator
} else {
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
$resultKey = $index;
/*if ($this->_rsm->isMixed) {
$result[] =& $result[$index];
++$this->_resultCounter;
}*/
}
$this->updateResultPointer($result, $index, $dqlAlias, false);
}
}
@@ -247,11 +256,9 @@ class ArrayHydrator extends AbstractHydrator
if (isset($scalars)) {
if ( ! isset($resultKey) ) {
// this only ever happens when no object is fetched (scalar result only)
if (isset($this->_rsm->indexByMap['scalars'])) {
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
} else {
$resultKey = $this->_resultCounter - 1;
}
$resultKey = isset($this->_rsm->indexByMap['scalars'])
? $row[$this->_rsm->indexByMap['scalars']]
: $this->_resultCounter - 1;
}
foreach ($scalars as $name => $value) {
@@ -279,6 +286,12 @@ class ArrayHydrator extends AbstractHydrator
return;
}
if ($oneToOne) {
$this->_resultPointers[$dqlAlias] =& $coll;
return;
}
if ($index !== false) {
$this->_resultPointers[$dqlAlias] =& $coll[$index];
@@ -289,12 +302,6 @@ class ArrayHydrator extends AbstractHydrator
return;
}
if ($oneToOne) {
$this->_resultPointers[$dqlAlias] =& $coll;
return;
}
end($coll);
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];

View File

@@ -757,6 +757,8 @@ final class PersistentCollection implements Collection, Selectable
*/
public function key()
{
$this->initialize();
return $this->coll->key();
}
@@ -765,6 +767,8 @@ final class PersistentCollection implements Collection, Selectable
*/
public function current()
{
$this->initialize();
return $this->coll->current();
}
@@ -773,6 +777,8 @@ final class PersistentCollection implements Collection, Selectable
*/
public function next()
{
$this->initialize();
return $this->coll->next();
}

View File

@@ -567,8 +567,8 @@ class BasicEntityPersister
$tableName = $this->quoteStrategy->getTableName($class, $this->platform);
$idColumns = $this->quoteStrategy->getIdentifierColumnNames($class, $this->platform);
$id = array_combine($idColumns, $identifier);
$types = array_map(function ($identifier) use ($class, $em) {
$types = array_map(function ($identifier) use ($class, $em) {
if (isset($class->fieldMappings[$identifier])) {
return $class->fieldMappings[$identifier]['type'];
}
@@ -580,7 +580,7 @@ class BasicEntityPersister
}
if (isset($targetMapping->associationMappings[$targetMapping->identifier[0]])) {
$types[] = $targetMapping->associationMappings[$targetMapping->identifier[0]]['type'];
return $targetMapping->associationMappings[$targetMapping->identifier[0]]['type'];
}
throw ORMException::unrecognizedField($targetMapping->identifier[0]);

View File

@@ -197,7 +197,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
foreach ($data as $columnName => $value) {
if (!isset($id[$columnName])) {
if (!is_array($id) || !isset($id[$columnName])) {
$stmt->bindValue($paramIndex++, $value, $this->columnTypes[$columnName]);
}
}

View File

@@ -235,7 +235,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
foreach ($joinColumns as $joinColumn) {
$columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
$referencedName = $joinColumn['referencedColumnName'];
$conditions[] = $columnName . ' = ?';
$conditions[] = 't.' . $columnName . ' = ?';
$params[] = ($class->containsForeignIdentifier)
? $id[$class->getFieldForColumn($referencedName)]
: $id[$class->fieldNames[$referencedName]];
@@ -361,12 +361,13 @@ class ManyToManyPersister extends AbstractCollectionPersister
$params = array();
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
$whereClauses[] = $joinTableColumn . ' = ?';
$whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?';
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
$params[] = ($targetClass->containsForeignIdentifier)
? $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])]
: $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
continue;
}
@@ -377,9 +378,12 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
if ($addFilters) {
$quotedJoinTable .= ' t';
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping);
if ($filterSql) {
$quotedJoinTable .= ' t ' . $joinTargetEntitySQL;
$quotedJoinTable .= ' ' . $joinTargetEntitySQL;
$whereClauses[] = $filterSql;
}
}

View File

@@ -41,13 +41,20 @@ class RangeVariableDeclaration extends Node
public $aliasIdentificationVariable;
/**
* @param string $abstractSchemaName
* @param string $aliasIdentificationVar
* @var boolean
*/
public function __construct($abstractSchemaName, $aliasIdentificationVar)
public $isRoot;
/**
* @param string $abstractSchemaName
* @param string $aliasIdentificationVar
* @param boolean $isRoot
*/
public function __construct($abstractSchemaName, $aliasIdentificationVar, $isRoot = true)
{
$this->abstractSchemaName = $abstractSchemaName;
$this->abstractSchemaName = $abstractSchemaName;
$this->aliasIdentificationVariable = $aliasIdentificationVar;
$this->isRoot = $isRoot;
}
/**

View File

@@ -1544,6 +1544,9 @@ class Parser
public function IdentificationVariableDeclaration()
{
$rangeVariableDeclaration = $this->RangeVariableDeclaration();
$rangeVariableDeclaration->isRoot = true;
$indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null;
$joins = array();
@@ -1622,15 +1625,19 @@ class Parser
$this->match(Lexer::T_JOIN);
$next = $this->lexer->glimpse();
$joinDeclaration = ($next['type'] === Lexer::T_DOT)
? $this->JoinAssociationDeclaration()
: $this->RangeVariableDeclaration();
$joinDeclaration = ($next['type'] === Lexer::T_DOT) ? $this->JoinAssociationDeclaration() : $this->RangeVariableDeclaration();
$adhocConditions = $this->lexer->isNextToken(Lexer::T_WITH);
$join = new AST\Join($joinType, $joinDeclaration);
// Create AST node
$join = new AST\Join($joinType, $joinDeclaration);
// Describe non-root join declaration
if ($joinDeclaration instanceof AST\RangeVariableDeclaration) {
$joinDeclaration->isRoot = false;
$adhocConditions = true;
}
// Check for ad-hoc Join conditions
if ($this->lexer->isNextToken(Lexer::T_WITH) || $joinDeclaration instanceof AST\RangeVariableDeclaration) {
if ($adhocConditions) {
$this->match(Lexer::T_WITH);
$join->conditionalExpression = $this->ConditionalExpression();

View File

@@ -842,7 +842,9 @@ class SqlWalker implements TreeWalker
$class = $this->em->getClassMetadata($rangeVariableDeclaration->abstractSchemaName);
$dqlAlias = $rangeVariableDeclaration->aliasIdentificationVariable;
$this->rootAliases[] = $dqlAlias;
if ($rangeVariableDeclaration->isRoot) {
$this->rootAliases[] = $dqlAlias;
}
$sql = $this->quoteStrategy->getTableName($class,$this->platform) . ' '
. $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
@@ -858,13 +860,14 @@ class SqlWalker implements TreeWalker
* Walks down a JoinAssociationDeclaration AST node, thereby generating the appropriate SQL.
*
* @param AST\JoinAssociationDeclaration $joinAssociationDeclaration
* @param int $joinType
* @param int $joinType
* @param AST\ConditionalExpression $condExpr
*
* @return string
*
* @throws QueryException
*/
public function walkJoinAssociationDeclaration($joinAssociationDeclaration, $joinType = AST\Join::JOIN_TYPE_INNER)
public function walkJoinAssociationDeclaration($joinAssociationDeclaration, $joinType = AST\Join::JOIN_TYPE_INNER, $condExpr = null)
{
$sql = '';
@@ -979,6 +982,13 @@ class SqlWalker implements TreeWalker
break;
}
// Handle WITH clause
if ($condExpr !== null) {
// Phase 2 AST optimization: Skip processing of ConditionalExpression
// if only one ConditionalTerm is defined
$sql .= ' AND (' . $this->walkConditionalExpression($condExpr) . ')';
}
// FIXME: these should either be nested or all forced to be left joins (DDC-XXX)
if ($targetClass->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
@@ -1058,24 +1068,37 @@ class SqlWalker implements TreeWalker
switch (true) {
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\RangeVariableDeclaration):
$class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName);
$condExprConjunction = $class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER
$class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName);
$dqlAlias = $joinDeclaration->aliasIdentificationVariable;
$tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
$condition = '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')';
$condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER)
? ' AND '
: ' ON ';
$sql .= $this->walkRangeVariableDeclaration($joinDeclaration)
. $condExprConjunction . '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')';
$sql .= $this->walkRangeVariableDeclaration($joinDeclaration);
$conditions = array($condition);
// Apply remaining inheritance restrictions
$discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($dqlAlias));
if ($discrSql) {
$conditions[] = $discrSql;
}
// Apply the filters
$filterExpr = $this->generateFilterConditionSQL($class, $tableAlias);
if ($filterExpr) {
$conditions[] = $filterExpr;
}
$sql .= $condExprConjunction . implode(' AND ', $conditions);
break;
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\JoinAssociationDeclaration):
$sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType);
// Handle WITH clause
if (($condExpr = $join->conditionalExpression) !== null) {
// Phase 2 AST optimization: Skip processing of ConditionalExpression
// if only one ConditionalTerm is defined
$sql .= ' AND (' . $this->walkConditionalExpression($condExpr) . ')';
}
$sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType, $join->conditionalExpression);
break;
}

View File

@@ -152,7 +152,7 @@ class EntityGenerator
Type::SMALLINT => 'integer',
Type::TEXT => 'string',
Type::BLOB => 'string',
Type::DECIMAL => 'float',
Type::DECIMAL => 'string',
Type::JSON_ARRAY => 'array',
Type::SIMPLE_ARRAY => 'array',
);
@@ -911,7 +911,7 @@ public function __construct()
protected function generateDiscriminatorColumnAnnotation($metadata)
{
if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
$discrColumn = $metadata->discriminatorValue;
$discrColumn = $metadata->discriminatorColumn;
$columnDefinition = 'name="' . $discrColumn['name']
. '", type="' . $discrColumn['type']
. '", length=' . $discrColumn['length'];

26
lib/Doctrine/ORM/Tools/Pagination/Paginator.php Normal file → Executable file
View File

@@ -121,7 +121,7 @@ class Paginator implements \Countable, \IteratorAggregate
/* @var $countQuery Query */
$countQuery = $this->cloneQuery($this->query);
if ( ! $countQuery->getHint(CountWalker::HINT_DISTINCT)) {
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
}
@@ -134,7 +134,7 @@ class Paginator implements \Countable, \IteratorAggregate
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$countQuery->setResultSetMapping($rsm);
} else {
$countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\CountWalker'));
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
}
$countQuery->setFirstResult(null)->setMaxResults(null);
@@ -165,7 +165,7 @@ class Paginator implements \Countable, \IteratorAggregate
if ($this->useOutputWalker($subQuery)) {
$subQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
} else {
$subQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker'));
$this->appendTreeWalker($subQuery, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker');
}
$subQuery->setFirstResult($offset)->setMaxResults($length);
@@ -178,7 +178,7 @@ class Paginator implements \Countable, \IteratorAggregate
return new \ArrayIterator(array());
}
$whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\WhereInWalker'));
$this->appendTreeWalker($whereInQuery, 'Doctrine\ORM\Tools\Pagination\WhereInWalker');
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids));
$whereInQuery->setFirstResult(null)->setMaxResults(null);
$whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids);
@@ -231,4 +231,22 @@ class Paginator implements \Countable, \IteratorAggregate
return $this->useOutputWalkers;
}
/**
* Appends a custom tree walker to the tree walkers hint.
*
* @param Query $query
* @param string $walkerClass
*/
private function appendTreeWalker(Query $query, $walkerClass)
{
$hints = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS);
if ($hints === false) {
$hints = array();
}
$hints[] = $walkerClass;
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
}
}

View File

@@ -241,6 +241,11 @@ class SchemaValidator
continue;
}
if ( ! isset($class->fieldMappings[$publicAttr->getName()]) &&
! isset($class->associationMappings[$publicAttr->getName()])) {
continue;
}
$ce[] = "Field '".$publicAttr->getName()."' in class '".$class->name."' must be private ".
"or protected. Public fields may break lazy-loading.";
}

View File

@@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.4.0-DEV';
const VERSION = '2.4.0';
/**
* Compares a Doctrine version with the current one.

View File

@@ -0,0 +1,42 @@
<?php
namespace Doctrine\Tests\Models\Taxi;
/**
* @Entity
* @Table(name="taxi_car")
*/
class Car
{
/**
* @Id
* @Column(type="string", length=25)
* @GeneratedValue(strategy="NONE")
*/
private $brand;
/**
* @Column(type="string", length=255);
*/
private $model;
/**
* @OneToMany(targetEntity="Ride", mappedBy="car")
*/
private $freeCarRides;
/**
* @OneToMany(targetEntity="PaidRide", mappedBy="car")
*/
private $carRides;
public function setBrand($brand)
{
$this->brand = $brand;
}
public function setModel($model)
{
$this->model = $model;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Doctrine\Tests\Models\Taxi;
/**
* @Entity
* @Table(name="taxi_driver")
*/
class Driver
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @Column(type="string", length=255);
*/
private $name;
/**
* @OneToMany(targetEntity="Ride", mappedBy="driver")
*/
private $freeDriverRides;
/**
* @OneToMany(targetEntity="PaidRide", mappedBy="driver")
*/
private $driverRides;
public function setName($name)
{
$this->name = $name;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Doctrine\Tests\Models\Taxi;
/**
* Same as Ride but with an extra column that is not part of the composite primary key
*
* @Entity
* @Table(name="taxi_paid_ride")
*/
class PaidRide
{
/**
* @Id
* @ManyToOne(targetEntity="Driver", inversedBy="driverRides")
* @JoinColumn(name="driver_id", referencedColumnName="id")
*/
private $driver;
/**
* @Id
* @ManyToOne(targetEntity="Car", inversedBy="carRides")
* @JoinColumn(name="car", referencedColumnName="brand")
*/
private $car;
/**
* @Column(type="decimal", precision=6, scale=2)
*/
private $fare;
public function __construct(Driver $driver, Car $car)
{
$this->driver = $driver;
$this->car = $car;
}
public function setFare($fare)
{
$this->fare = $fare;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Doctrine\Tests\Models\Taxi;
/**
* Test model that contains only Id-columns
*
* @Entity
* @Table(name="taxi_ride")
*/
class Ride
{
/**
* @Id
* @ManyToOne(targetEntity="Driver", inversedBy="freeDriverRides")
* @JoinColumn(name="driver_id", referencedColumnName="id")
*/
private $driver;
/**
* @Id
* @ManyToOne(targetEntity="Car", inversedBy="freeCarRides")
* @JoinColumn(name="car", referencedColumnName="brand")
*/
private $car;
public function __construct(Driver $driver, Car $car)
{
$this->driver = $driver;
$this->car = $car;
}
}

View File

@@ -719,7 +719,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$selectClause = $rsm->generateSelectClause();
$this->assertEquals('u.id AS id, u.status AS status, u.username AS username, u.name AS name, u.email_id AS email_id', $selectClause);
$this->assertSQLEquals('u.id AS id, u.status AS status, u.username AS username, u.name AS name, u.email_id AS email_id', $selectClause);
}
/**
@@ -735,7 +735,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$selectClause = $rsm->generateSelectClause();
$this->assertEquals('u.id AS id1, u.status AS status, u.username AS username2, u.name AS name, u.email_id AS email_id', $selectClause);
$this->assertSQLEquals('u.id AS id1, u.status AS status, u.username AS username2, u.name AS name, u.email_id AS email_id', $selectClause);
}
/**
@@ -748,7 +748,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$selectClause = $rsm->generateSelectClause(array('u' => 'u1'));
$this->assertEquals('u1.id AS id, u1.status AS status, u1.username AS username, u1.name AS name, u1.email_id AS email_id', $selectClause);
$this->assertSQLEquals('u1.id AS id, u1.status AS status, u1.username AS username, u1.name AS name, u1.email_id AS email_id', $selectClause);
}
/**
@@ -761,7 +761,7 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$selectClause = $rsm->generateSelectClause();
$this->assertEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', $selectClause);
$this->assertSQLEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', $selectClause);
}
/**
@@ -772,6 +772,6 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$rsm = new ResultSetMappingBuilder($this->_em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
$rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$this->assertEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', (string)$rsm);
$this->assertSQLEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', (string)$rsm);
}
}

View File

@@ -128,14 +128,14 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
$train = $this->_em->find(get_class($train), $train->id);
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.driver_id AS driver_id2, t3.id AS id4, t3.name AS name5, t0.owner_id AS owner_id6, t7.id AS id8, t7.name AS name9 FROM Train t0 LEFT JOIN TrainDriver t3 ON t0.driver_id = t3.id INNER JOIN TrainOwner t7 ON t0.owner_id = t7.id WHERE t0.id = ?",
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
);
$this->_em->clear();
$driver = $this->_em->find(get_class($driver), $driver->id);
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.name AS name2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM TrainOwner t0 LEFT JOIN Train t3 ON t3.owner_id = t0.id WHERE t0.id IN (?)",
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
);
@@ -156,13 +156,13 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
$waggon = $this->_em->find(get_class($waggon), $waggon->id);
// The last query is the eager loading of the owner of the train
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.name AS name2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM TrainOwner t0 LEFT JOIN Train t3 ON t3.owner_id = t0.id WHERE t0.id IN (?)",
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
);
// The one before is the fetching of the waggon and train
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.train_id AS train_id2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM Waggon t0 INNER JOIN Train t3 ON t0.train_id = t3.id WHERE t0.id = ?",
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery - 1]['sql']
);
@@ -177,7 +177,7 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
$waggon = $this->_em->find(get_class($owner), $owner->id);
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.name AS name2, t3.id AS id4, t3.driver_id AS driver_id5, t3.owner_id AS owner_id6 FROM TrainOwner t0 LEFT JOIN Train t3 ON t3.owner_id = t0.id WHERE t0.id = ?",
$this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['sql']
);

View File

@@ -139,6 +139,18 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertTrue($query->getParameters()->isEmpty());
}
public function testQueryWalkerIsKept()
{
$dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u";
$query = $this->_em->createQuery($dql);
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\Tests\ORM\Functional\CustomPaginationTestTreeWalker'));
$paginator = new Paginator($query, true);
$paginator->setUseOutputWalkers(false);
$this->assertCount(1, $paginator->getIterator());
$this->assertEquals(1, $paginator->count());
}
public function populate()
{
for ($i = 0; $i < 3; $i++) {
@@ -166,3 +178,22 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
);
}
}
class CustomPaginationTestTreeWalker extends Query\TreeWalkerAdapter
{
public function walkSelectStatement(Query\AST\SelectStatement $selectStatement)
{
$condition = new Query\AST\ConditionalPrimary();
$path = new Query\AST\PathExpression(Query\AST\PathExpression::TYPE_STATE_FIELD, 'u', 'name');
$path->type = Query\AST\PathExpression::TYPE_STATE_FIELD;
$condition->simpleConditionalExpression = new Query\AST\ComparisonExpression(
$path,
'=',
new Query\AST\Literal(Query\AST\Literal::STRING, 'Name1')
);
$selectStatement->whereClause = new Query\AST\WhereClause($condition);
}
}

View File

@@ -35,8 +35,8 @@ class DDC1430Test extends \Doctrine\Tests\OrmFunctionalTestCase
->orderBy('o.id')
->getQuery();
$this->assertEquals('SELECT o.id, o.date, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o.id, o.date ORDER BY o.id ASC', $query->getDQL());
$this->assertEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, COUNT(d1_.id) AS sclr2 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at ORDER BY d0_.order_id ASC', $query->getSQL());
$this->assertSQLEquals('SELECT o.id, o.date, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o.id, o.date ORDER BY o.id ASC', $query->getDQL());
$this->assertSQLEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, COUNT(d1_.id) AS sclr2 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at ORDER BY d0_.order_id ASC', $query->getSQL());
$result = $query->getResult();
@@ -67,8 +67,8 @@ class DDC1430Test extends \Doctrine\Tests\OrmFunctionalTestCase
->getQuery();
$this->assertEquals('SELECT o, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o.id, o.date, o.status ORDER BY o.id ASC', $query->getDQL());
$this->assertEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, d0_.order_status AS order_status2, COUNT(d1_.id) AS sclr3 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at, d0_.order_status ORDER BY d0_.order_id ASC', $query->getSQL());
$this->assertSQLEquals('SELECT o, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o.id, o.date, o.status ORDER BY o.id ASC', $query->getDQL());
$this->assertSQLEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, d0_.order_status AS order_status2, COUNT(d1_.id) AS sclr3 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at, d0_.order_status ORDER BY d0_.order_id ASC', $query->getSQL());
$result = $query->getResult();
@@ -96,8 +96,8 @@ class DDC1430Test extends \Doctrine\Tests\OrmFunctionalTestCase
->getQuery();
$this->assertEquals('SELECT o, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o ORDER BY o.id ASC', $query->getDQL());
$this->assertEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, d0_.order_status AS order_status2, COUNT(d1_.id) AS sclr3 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at, d0_.order_status ORDER BY d0_.order_id ASC', $query->getSQL());
$this->assertSQLEquals('SELECT o, COUNT(p.id) AS p_count FROM Doctrine\Tests\ORM\Functional\Ticket\DDC1430Order o LEFT JOIN o.products p GROUP BY o ORDER BY o.id ASC', $query->getDQL());
$this->assertSQLEquals('SELECT d0_.order_id AS order_id0, d0_.created_at AS created_at1, d0_.order_status AS order_status2, COUNT(d1_.id) AS sclr3 FROM DDC1430Order d0_ LEFT JOIN DDC1430OrderProduct d1_ ON d0_.order_id = d1_.order_id GROUP BY d0_.order_id, d0_.created_at, d0_.order_status ORDER BY d0_.order_id ASC', $query->getSQL());
$result = $query->getResult();
@@ -294,4 +294,4 @@ class DDC1430OrderProduct
$this->value = $value;
}
}
}

View File

@@ -35,7 +35,7 @@ class DDC1595Test extends \Doctrine\Tests\OrmFunctionalTestCase
$entity1 = $repository->find($e1->id);
// DDC-1596
$this->assertEquals(
$this->assertSQLEquals(
"SELECT t0.id AS id1, t0.type FROM base t0 WHERE t0.id = ? AND t0.type IN ('Entity1')",
$sqlLogger->queries[count($sqlLogger->queries)]['sql']
);
@@ -52,8 +52,8 @@ class DDC1595Test extends \Doctrine\Tests\OrmFunctionalTestCase
$entity1 = $repository->find($e1->id);
$entities = $entity1->getEntities()->count();
$this->assertEquals(
"SELECT COUNT(*) FROM entity1_entity2 t WHERE parent = ?",
$this->assertSQLEquals(
"SELECT COUNT(*) FROM entity1_entity2 t WHERE t.parent = ?",
$sqlLogger->queries[count($sqlLogger->queries)]['sql']
);
}
@@ -108,4 +108,4 @@ class DDC1595InheritedEntity1 extends DDC1595BaseInheritance
*/
class DDC1595InheritedEntity2 extends DDC1595BaseInheritance
{
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Taxi\Car,
Doctrine\Tests\Models\Taxi\Driver,
Doctrine\Tests\Models\Taxi\Ride,
Doctrine\Tests\Models\Taxi\PaidRide;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1884
* @author Sander Coolen <sander@jibber.nl>
*/
class DDC1884Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('taxi');
parent::setUp();
list($bimmer, $crysler, $merc, $volvo) = $this->createCars('Doctrine\Tests\Models\Taxi\Car');
list($john, $foo) = $this->createDrivers('Doctrine\Tests\Models\Taxi\Driver');
$this->_em->flush();
$ride1 = new Ride($john, $bimmer);
$ride2 = new Ride($john, $merc);
$ride3 = new Ride($john, $volvo);
$ride4 = new Ride($foo, $merc);
$this->_em->persist($ride1);
$this->_em->persist($ride2);
$this->_em->persist($ride3);
$this->_em->persist($ride4);
$ride5 = new PaidRide($john, $bimmer);
$ride5->setFare(10.50);
$ride6 = new PaidRide($john, $merc);
$ride6->setFare(16.00);
$ride7 = new PaidRide($john, $volvo);
$ride7->setFare(20.70);
$ride8 = new PaidRide($foo, $merc);
$ride8->setFare(32.15);
$this->_em->persist($ride5);
$this->_em->persist($ride6);
$this->_em->persist($ride7);
$this->_em->persist($ride8);
$this->_em->flush();
}
private function createCars($class)
{
$bimmer = new $class;
$bimmer->setBrand('BMW');
$bimmer->setModel('7-Series');
$crysler = new $class;
$crysler->setBrand('Crysler');
$crysler->setModel('300');
$merc = new $class;
$merc->setBrand('Mercedes');
$merc->setModel('C-Class');
$volvo = new $class;
$volvo->setBrand('Volvo');
$volvo->setModel('XC90');
$this->_em->persist($bimmer);
$this->_em->persist($crysler);
$this->_em->persist($merc);
$this->_em->persist($volvo);
return array($bimmer, $crysler, $merc, $volvo);
}
private function createDrivers($class)
{
$john = new $class;
$john->setName('John Doe');
$foo = new $class;
$foo->setName('Foo Bar');
$this->_em->persist($foo);
$this->_em->persist($john);
return array($john, $foo);
}
/**
* 1) Ride contains only columns that are part of its composite primary key
* 2) We use fetch joins here
*/
public function testSelectFromInverseSideWithCompositePkAndSolelyIdentifierColumnsUsingFetchJoins()
{
$qb = $this->_em->createQueryBuilder();
$result = $qb->select('d, dr, c')
->from('Doctrine\Tests\Models\Taxi\Driver', 'd')
->leftJoin('d.freeDriverRides', 'dr')
->leftJoin('dr.car', 'c')
->where('d.name = ?1')
->setParameter(1, 'John Doe')
->getQuery()
->getArrayResult();
$this->assertCount(1, $result);
$this->assertArrayHasKey('freeDriverRides', $result[0]);
$this->assertCount(3, $result[0]['freeDriverRides']);
}
/**
* 1) PaidRide contains an extra column that is not part of the composite primary key
* 2) Again we will use fetch joins
*/
public function testSelectFromInverseSideWithCompositePkUsingFetchJoins()
{
$qb = $this->_em->createQueryBuilder();
$result = $qb->select('d, dr, c')
->from('Doctrine\Tests\Models\Taxi\Driver', 'd')
->leftJoin('d.driverRides', 'dr')
->leftJoin('dr.car', 'c')
->where('d.name = ?1')
->setParameter(1, 'John Doe')
->getQuery()->getArrayResult();
$this->assertCount(1, $result);
$this->assertArrayHasKey('driverRides', $result[0]);
$this->assertCount(3, $result[0]['driverRides']);
}
/**
* The other way around will fail too
*/
public function testSelectFromOwningSideUsingFetchJoins()
{
$qb = $this->_em->createQueryBuilder();
$result = $qb->select('r, d, c')
->from('Doctrine\Tests\Models\Taxi\PaidRide', 'r')
->leftJoin('r.driver', 'd')
->leftJoin('r.car', 'c')
->where('d.name = ?1')
->setParameter(1, 'John Doe')
->getQuery()->getArrayResult();
$this->assertCount(3, $result);
$this->assertArrayHasKey('driver', $result[0]);
$this->assertArrayHasKey('car', $result[0]);
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* @group DDC-2579
*/
class DDC2579Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
Type::addType(DDC2579Type::NAME, DDC2579Type::CLASSNAME);
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(DDC2579Entity::CLASSNAME),
$this->_em->getClassMetadata(DDC2579EntityAssoc::CLASSNAME),
$this->_em->getClassMetadata(DDC2579AssocAssoc::CLASSNAME),
));
}
public function testIssue()
{
$id = new DDC2579Id("foo");
$assoc = new DDC2579AssocAssoc($id);
$assocAssoc = new DDC2579EntityAssoc($assoc);
$entity = new DDC2579Entity($assocAssoc);
$repository = $this->_em->getRepository(DDC2579Entity::CLASSNAME);
$this->_em->persist($assoc);
$this->_em->persist($assocAssoc);
$this->_em->persist($entity);
$this->_em->flush();
$entity->value++;
$this->_em->persist($entity);
$this->_em->flush();
$this->_em->clear();
$id = $entity->id;
$value = $entity->value;
$criteria = array('assoc' => $assoc, 'id' => $id);
$entity = $repository->findOneBy($criteria);
$this->assertInstanceOf(DDC2579Entity::CLASSNAME, $entity);
$this->assertEquals($value, $entity->value);
$this->_em->remove($entity);
$this->_em->flush();
$this->_em->clear();
$this->assertNull($repository->findOneBy($criteria));
$this->assertCount(0, $repository->findAll());
}
}
/**
* @Entity
*/
class DDC2579Entity
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(type="ddc2579")
*/
public $id;
/**
* @Id
* @ManyToOne(targetEntity="DDC2579EntityAssoc")
* @JoinColumn(name="relation_id", referencedColumnName="association_id")
*/
public $assoc;
/**
* @Column(type="integer")
*/
public $value;
public function __construct(DDC2579EntityAssoc $assoc, $value = 0)
{
$this->id = $assoc->assocAssoc->associationId;
$this->assoc = $assoc;
$this->value = $value;
}
}
/**
* @Entity
*/
class DDC2579EntityAssoc
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @ManyToOne(targetEntity="DDC2579AssocAssoc")
* @JoinColumn(name="association_id", referencedColumnName="associationId")
*/
public $assocAssoc;
public function __construct(DDC2579AssocAssoc $assocAssoc)
{
$this->assocAssoc = $assocAssoc;
}
}
/**
* @Entity
*/
class DDC2579AssocAssoc
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(type="ddc2579")
*/
public $associationId;
public function __construct(DDC2579Id $id)
{
$this->associationId = $id;
}
}
class DDC2579Type extends StringType
{
const NAME = 'ddc2579';
const CLASSNAME = __CLASS__;
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return (string)$value;
}
public function convertToPhpValue($value, AbstractPlatform $platform)
{
return new DDC2579Id($value);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return self::NAME;
}
}
class DDC2579Id
{
const CLASSNAME = __CLASS__;
private $val;
public function __construct($val)
{
$this->val = $val;
}
public function __toString()
{
return $this->val;
}
}

View File

@@ -6,16 +6,21 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\PersistentCollection;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\EntityManagerMock;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
require_once __DIR__ . '/../TestInit.php';
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\OrmTestCase;
/**
* Tests the lazy-loading capabilities of the PersistentCollection.
* Tests the lazy-loading capabilities of the PersistentCollection and the initialization of collections.
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @author Austin Morris <austin.morris@gmail.com>
*/
class PersistentCollectionTest extends \Doctrine\Tests\OrmTestCase
class PersistentCollectionTest extends OrmTestCase
{
/**
* @var PersistentCollection
*/
protected $collection;
private $_connectionMock;
private $_emMock;
@@ -27,6 +32,17 @@ class PersistentCollectionTest extends \Doctrine\Tests\OrmTestCase
$this->_emMock = EntityManagerMock::create($this->_connectionMock);
}
/**
* Set up the PersistentCollection used for collection initialization tests.
*/
public function setUpPersistentCollection()
{
$classMetaData = $this->_emMock->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCart');
$this->collection = new PersistentCollection($this->_emMock, $classMetaData, new ArrayCollection);
$this->collection->setInitialized(false);
$this->collection->setOwner(new ECommerceCart(), $classMetaData->getAssociationMapping('products'));
}
public function testCanBePutInLazyLoadingMode()
{
$class = $this->_emMock->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
@@ -34,4 +50,34 @@ class PersistentCollectionTest extends \Doctrine\Tests\OrmTestCase
$collection->setInitialized(false);
$this->assertFalse($collection->isInitialized());
}
/**
* Test that PersistentCollection::current() initializes the collection.
*/
public function testCurrentInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->current();
$this->assertTrue($this->collection->isInitialized());
}
/**
* Test that PersistentCollection::key() initializes the collection.
*/
public function testKeyInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->key();
$this->assertTrue($this->collection->isInitialized());
}
/**
* Test that PersistentCollection::next() initializes the collection.
*/
public function testNextInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->next();
$this->assertTrue($this->collection->isInitialized());
}
}

View File

@@ -105,6 +105,8 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('bar', $q->getHint('foo'));
$this->assertEquals('baz', $q->getHint('bar'));
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz'), $q->getHints());
$this->assertTrue($q->hasHint('foo'));
$this->assertFalse($q->hasHint('barFooBaz'));
}
/**

View File

@@ -155,12 +155,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_managers c2_ INNER JOIN company_employees c3_ ON c2_.id = c3_.id INNER JOIN company_persons c4_ ON c2_.id = c4_.id AND (c0_.id = c4_.id)'
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id AND (c0_.id = c3_.id)'
);
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ INNER JOIN company_employees c3_ ON c2_.id = c3_.id INNER JOIN company_persons c4_ ON c2_.id = c4_.id ON (c0_.id = c4_.id)'
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id ON (c0_.id = c3_.id)'
);
}
@@ -2040,6 +2040,97 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}
/**
* @group DDC-2506
*/
public function testClassTableInheritanceJoinWithConditionAppliesToBaseTable()
{
$this->assertSqlGeneration(
'SELECT e.id FROM Doctrine\Tests\Models\Company\CompanyOrganization o JOIN o.events e WITH e.id = ?1',
'SELECT c0_.id AS id0 FROM company_organizations c1_ INNER JOIN company_events c0_ ON c1_.id = c0_.org_id AND (c0_.id = ?) LEFT JOIN company_auctions c2_ ON c0_.id = c2_.id LEFT JOIN company_raffles c3_ ON c0_.id = c3_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceLeftJoinWithCondition()
{
// Regression test for the bug
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceLeftJoinWithConditionAndWhere()
{
// Ensure other WHERE predicates are passed through to the main WHERE clause
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id WHERE e.salary > 1000',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.salary > 1000"
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceInnerJoinWithCondition()
{
// Test inner joins too
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e INNER JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id INNER JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceLeftJoinNonAssociationWithConditionAndWhere()
{
// Test that the discriminator IN() predicate is still added into
// the where clause when not joining onto that table
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c LEFT JOIN Doctrine\Tests\Models\Company\CompanyEmployee e WITH e.id = c.salesPerson WHERE c.completed = true',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_contracts c0_ LEFT JOIN company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceJoinCreatesOnCondition()
{
// Test that the discriminator IN() predicate is still added
// into the where clause when not joining onto a single table inheritance entity
// via a join association
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson s WHERE c.completed = true',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
/**
* @group DDC-2235
*/
public function testSingleTableInheritanceCreatesOnConditionAndWhere()
{
// Test that when joining onto an entity using single table inheritance via
// a join association that the discriminator IN() predicate is placed
// into the ON clause of the join
$this->assertSqlGeneration(
'SELECT e, COUNT(c) FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN e.contracts c WHERE e.department = :department',
"SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, COUNT(c2_.id) AS sclr5, c0_.discr AS discr6 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_contract_employees c3_ ON c1_.id = c3_.employee_id INNER JOIN company_contracts c2_ ON c2_.id = c3_.contract_id AND c2_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.department = ?",
array(),
array('department' => 'foobar')
);
}
/**
* @group DDC-1858
*/

View File

@@ -516,9 +516,9 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
)),
array(array(
'fieldName' => 'decimal',
'phpType' => 'float',
'phpType' => 'string',
'dbType' => 'decimal',
'value' => 33.33
'value' => '12.34'
),
));
}

View File

@@ -155,7 +155,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\CompositeKeyInheritance\JoinedChildClass',
'Doctrine\Tests\Models\CompositeKeyInheritance\SingleRootClass',
'Doctrine\Tests\Models\CompositeKeyInheritance\SingleChildClass',
)
),
'taxi' => array(
'Doctrine\Tests\Models\Taxi\PaidRide',
'Doctrine\Tests\Models\Taxi\Ride',
'Doctrine\Tests\Models\Taxi\Car',
'Doctrine\Tests\Models\Taxi\Driver',
),
);
/**
@@ -284,6 +290,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM SingleRootClass');
}
if (isset($this->_usedModelSets['taxi'])) {
$conn->executeUpdate('DELETE FROM taxi_paid_ride');
$conn->executeUpdate('DELETE FROM taxi_ride');
$conn->executeUpdate('DELETE FROM taxi_car');
$conn->executeUpdate('DELETE FROM taxi_driver');
}
$this->_em->clear();
}
@@ -467,6 +479,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
throw $e;
}
public function assertSQLEquals($expectedSql, $actualSql)
{
return $this->assertEquals(strtolower($expectedSql), strtolower($actualSql), "Lowercase comparison of SQL statements failed.");
}
/**
* Using the SQL Logger Stack this method retrieves the current query count executed in this test.
*