Compare commits

...

110 Commits
2.0.2 ... 2.0.7

Author SHA1 Message Date
Benjamin Eberlei
b7a15316a0 Release 2.0.7 2011-08-17 21:47:50 +00:00
Benjamin Eberlei
2b878fc15d Bump dependency DBAL to 2.0.7 2011-08-17 21:46:43 +00:00
Benjamin Eberlei
4fea26c833 Fix: YamlDriver does not support orphanRemoval 2011-08-17 21:23:13 +02:00
Benjamin Eberlei
bf3ae5f2cf Merge branch 'DDC-1302' into 2.0.x 2011-07-31 11:36:02 +02:00
Benjamin Eberlei
2836d14c31 DDC-1302 - Fix bug in XmlDriver not handling orphan removal 2011-07-31 11:35:50 +02:00
Benjamin Eberlei
a342c87a32 Merge branch 'DDC-1276' into 2.0.x 2011-07-26 22:18:21 +02:00
Benjamin Eberlei
192eedc6a7 DDC-1276 - Fix bug where merge managed and new entitiy share the same collection that is cascaded, cleared during the process and then empty afterwards. 2011-07-26 22:17:13 +02:00
Benjamin Eberlei
ed78cdb937 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-07-12 22:52:35 +02:00
Benjamin Eberlei
793c383aa2 Merge branch 'DDC-1240' into 2.0.x 2011-07-12 22:52:18 +02:00
Benjamin Eberlei
7595b021cc DDC-1240 - Fix optimistic lock exception loosing the message 2011-07-12 22:52:09 +02:00
Benjamin Eberlei
f1bcb3cb80 Merge branch 'DDC-1257' into 2.0.x 2011-07-09 15:15:53 +02:00
Benjamin Eberlei
35ea4ed1fd DDC-1257 - Fix bug where validation callbacks are added multiple times in EntityGenerator 2011-07-09 15:15:34 +02:00
Benjamin Eberlei
ac8a36cda3 Merge branch 'DDC-1251' into 2.0.x 2011-07-09 14:55:12 +02:00
Benjamin Eberlei
0917ed5ced DDC-1251 - Fix bug in token parsing of EntityGenerator 2011-07-09 14:54:56 +02:00
Benjamin Eberlei
8068f34c66 DDC-1022 - Call __wakeup() with the same semantics then ClassMetadata::newInstance() does inside UnitOfWork 2011-07-09 14:34:21 +02:00
Benjamin Eberlei
91a9d4f27c Merge branch 'DDC-1230' into 2.0.x 2011-06-28 21:38:54 +02:00
Benjamin Eberlei
7c8590ea74 DDC-1230 - Fix bug where UnitOfWork does not set STATE_REMOVE when calling EntityManager#remove() on an entity 2011-06-28 21:38:44 +02:00
Benjamin Eberlei
d1cea4f77c Merge branch 'DDC-1224' into 2.0.x 2011-06-26 10:12:08 +02:00
Benjamin Eberlei
ae958e73d1 DDC-1224 - Bugfix with temporary table ids and tables in schema (in postgresql) 2011-06-26 10:11:57 +02:00
Benjamin Eberlei
3b841883d3 Merge branch 'DDC-1211' into 2.0.x 2011-06-19 10:27:21 +02:00
Benjamin Eberlei
cfe36f9a31 DDC-1211 - Fix bug with empty numeric literal 2011-06-19 10:26:36 +02:00
Benjamin Eberlei
d2eea18977 Merge branch 'DDC-1189' into 2.0.x 2011-06-19 09:44:21 +02:00
Benjamin Eberlei
247887ec0e DDC-1189 - Bugfix with PersistentCollection#clear() in combination with lazy loading 2011-06-19 09:43:33 +02:00
Benjamin Eberlei
2b309a3682 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-06-16 22:47:28 +02:00
Benjamin Eberlei
5ebe7ca89e Merge branch 'DDC-1172' into 2.0.x 2011-06-16 22:47:08 +02:00
Benjamin Eberlei
c582b7790a DDC-1172 - Adjust patch to 2.0.x code base 2011-06-16 22:43:06 +02:00
Benjamin Eberlei
a98a21b269 DDC-1172 - Handle sequence dropping in SchemaTool. 2011-06-16 22:34:56 +02:00
Benjamin Eberlei
5c9b3d0b92 Bump Dev Version to 2.0.7-DEV 2011-06-15 21:45:09 +00:00
Benjamin Eberlei
7f3bdab34c Release 2.0.6 2011-06-15 21:44:59 +00:00
Benjamin Eberlei
e075ab6958 Update dependency of DBAL to 2.0.6 2011-06-15 21:43:17 +00:00
Benjamin Eberlei
a1bc743568 Merge branch 'DDC-1208' into 2.0.x 2011-06-15 18:33:24 +02:00
Benjamin Eberlei
20d8ebfd43 DDC-1208 - Allow namespace separator in <discriminator-mapping /> 2011-06-15 18:33:12 +02:00
Fabien Potencier
3587f3bcb3 Update Symfony2 vendors 2011-06-15 11:44:04 +02:00
Benjamin Eberlei
ec87cb779c Merge branch 'DDC-1163' into 2.0.x 2011-06-05 16:20:56 +02:00
Benjamin Eberlei
ac40ce8042 DDC-1163 - Fix nasty bug with inheritance in UnitOfWork::executeUpdates() and executeRemovals() 2011-06-05 16:20:41 +02:00
Benjamin Eberlei
d4302b32e1 Merge branch 'DDC-1192' into 2.0.x 2011-06-05 14:50:35 +02:00
Benjamin Eberlei
3c95b0ec35 DDC-1192 - Fix notice in XmlDriver, removed unnecessary code. 2011-06-05 14:50:25 +02:00
Benjamin Eberlei
c12c6e82b6 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-06-05 10:09:26 +02:00
Benjamin Eberlei
505f7bd252 Merge branch 'DDC-1193' into 2.0.x 2011-06-05 10:08:29 +02:00
Benjamin Eberlei
d5459616d2 DDC-733, DDC-1193 - Proxy has only _load() in 2.0.x - Change to __load() for consinstent code. 2011-06-05 10:08:05 +02:00
Benjamin Eberlei
97d9fb7efa DDC-733, DDC-1193 - Proxy has only _load() in 2.0.x 2011-06-05 10:06:56 +02:00
Benjamin Eberlei
2da1fadaf1 DDC-1193 - Fix previous commit. 2011-06-05 10:05:25 +02:00
Benjamin Eberlei
a612ca7231 DDC-1193 - Fix bug with cascade remove and proxy classes. 2011-06-05 10:05:12 +02:00
Benjamin Eberlei
bd4faa6a7d DDC-733 - Add UnitOfWork::initializeObject() method. 2011-06-05 10:04:23 +02:00
Benjamin Eberlei
be03811753 Merge pull request #66 from fabpot/feat-doctrine-mapping-configuration
Feat doctrine mapping configuration
2011-06-04 23:18:52 -07:00
Fabien Potencier
636fa34136 Made orm:convert-mapping command more configurable (allow to change the extension of the generated files for instance) 2011-06-05 08:03:41 +02:00
Benjamin Eberlei
016810af7f [DDC-952] Add Persister hydration performance tests. 2011-05-14 16:09:40 +02:00
Benjamin Eberlei
178fe38a39 Bump Dev Version to 2.0.6-DEV 2011-05-14 13:36:43 +00:00
Benjamin Eberlei
35a318148c Release 2.0.5 2011-05-14 13:36:31 +00:00
Benjamin Eberlei
c63115efa9 Bump DBAL dependency to 2.0.5 2011-05-14 15:32:31 +02:00
Benjamin Eberlei
7cba650aff DDC-1136 - trailing character for backup files. 2011-05-14 11:58:27 +02:00
Benjamin Eberlei
d9475cbfd0 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-05-14 08:49:01 +02:00
Benjamin Eberlei
ee1708b04a Merge branch 'DDC-1151' into 2.0.x 2011-05-14 08:48:32 +02:00
Benjamin Eberlei
a8057dfe26 DDC-1151 - Slight modification necessary for 2.0.x 2011-05-14 08:46:51 +02:00
Benjamin Eberlei
60e7b8eff4 DDC-1151 - Fix missing table quotes when adding foreign keys in SchemaTool 2011-05-14 08:45:50 +02:00
Guilherme Blanco
28291f0fa7 Merge pull request #56 from stof/DDC-1146
DDC 1146
2011-05-11 15:47:20 -07:00
Christophe Coevoet
eecd9afc09 [DDC-1146] Updated the Symfony2 vendors 2011-05-12 00:28:36 +02:00
Benjamin Eberlei
8f9f85da39 Merge branch 'DDC-1129' into 2.0.x 2011-05-01 11:46:16 +02:00
Benjamin Eberlei
5d7063b2e1 [DDC-1129] Fix bug in version changeset computation aswell as inline ClassMetadata::isCollectionValuedAssociation to increase performance by 2-5% 2011-05-01 11:46:00 +02:00
Benjamin Eberlei
cc26080a00 Merge branch 'DDC-1091' into 2.0.x 2011-05-01 11:02:21 +02:00
Benjamin Eberlei
2b900e2c26 [DDC-1091] Fix bug with custom string functions in StringPrimary 2011-05-01 11:02:08 +02:00
Benjamin Eberlei
aedda4a21d Merge branch 'DDC-1102' into 2.0.x 2011-05-01 10:02:12 +02:00
Benjamin Eberlei
de6f0e4594 DDC-1102 - Typo in EntityGenerator 2011-05-01 10:02:03 +02:00
Benjamin Eberlei
d1191c3f74 Merge pull request #39 from francisbesset/parent_object_not_found.
[2.0.x] Fixed an undefined index by a HydrationException
2011-04-30 15:08:10 -07:00
Guilherme Blanco
bd117fc9eb Merge pull request #49 from fabpot/namespace-parsing-fix.
[DDC-1134] Entity generator: Namespace parsing fix
2011-04-30 12:49:36 -07:00
Benjamin Eberlei
ac04ce4114 Merge branch 'DBAL-115' into 2.0.x 2011-04-30 17:19:31 +02:00
Benjamin Eberlei
8d39f2a36d [DBAL-115] REALLY fix issues with SchemaTool::getDropSchemaSQL(). 2011-04-30 17:19:15 +02:00
Benjamin Eberlei
e86cbd65fa [DBAL-115] Bugfix in SchemaTool not quoting table names when dropping schema. 2011-04-30 17:17:34 +02:00
Benjamin Eberlei
410dd69c5b Merge branch 'DDC-1133' into 2.0.x 2011-04-30 14:24:29 +02:00
Benjamin Eberlei
222a90fc8a DDC-1133 - Ducktype AnnotationReader in AnnotationDriver 2011-04-30 14:24:20 +02:00
Benjamin Eberlei
c8e2ee05d1 Merge branch 'DDC-1109' into 2.0.x 2011-04-30 12:51:30 +02:00
Benjamin Eberlei
7c9c7369fb [DDC-1109] ltrim discriminator map for convenience. 2011-04-30 12:51:10 +02:00
Benjamin Eberlei
8ec9ee82f9 Merge branch '2.0.x' of github.com:doctrine/doctrine2 into 2.0.x 2011-04-30 12:28:29 +02:00
Benjamin Eberlei
33c896c31f Merge branch 'DDC-1108' into 2.0.x 2011-04-30 12:28:14 +02:00
Benjamin Eberlei
9ee3cc98ae [DDC-1108] Fix bug with single char named input parameters in DQL lexer. 2011-04-30 12:27:55 +02:00
Benjamin Eberlei
12bde174c5 Merge branch 'DDC-1132' into 2.0.x 2011-04-30 11:23:30 +02:00
Benjamin Eberlei
7634d45a29 [DDC-1132] Fix many to many table detection. 2011-04-30 11:20:25 +02:00
Benjamin Eberlei
b2873ab236 [DDC-1132] Fix many to many table detection. 2011-04-30 11:20:25 +02:00
Fabien Potencier
2978cad198 Fix namespace/class parsing in the entity generator 2011-04-30 10:42:38 +02:00
Benjamin Eberlei
c49467b7fa build.xml: Cleanup .git directory in Symfony Components 2011-04-07 15:11:52 -04:00
Benjamin Eberlei
095b8fa930 Bump Dev Version to 2.0.5-DEV 2011-04-07 15:04:05 -04:00
Benjamin Eberlei
8a2b1058c3 Release 2.0.4 2011-04-07 15:03:49 -04:00
Benjamin Eberlei
2bdceefb2d Bump dependencies, Doctrine Common to 2.0.2 and DBAL to 2.0.4 2011-04-07 20:53:19 +02:00
Benjamin Eberlei
71bcdce031 Merge branch 'DDC-1040' into 2.0.x 2011-04-03 23:08:24 +02:00
Benjamin Eberlei
f6a700062d [DDC-1040] Bugfix with named parameters and multiple entities passed as parameter. 2011-04-03 23:08:07 +02:00
Benjamin Eberlei
fb4db2782c [DDC-1040] Add regression tests for entity as multiple named/positional parameters. 2011-04-03 23:06:47 +02:00
Benjamin Eberlei
39ec8de08b Merge branch 'DDC-1093' into 2.0.x 2011-04-03 20:29:41 +02:00
Benjamin Eberlei
7a469581e1 [DDC-1093] Fix docblock type hint 2011-04-03 20:29:32 +02:00
Benjamin Eberlei
1f8cdb77be Merge branch 'DDC-1087' into 2.0.x 2011-04-03 09:12:10 +02:00
Benjamin Eberlei
af5bcc148d [DDC-1087] Add missing resolution to IS NULL in EntityRepository when passing a null value as a criteria. 2011-04-03 09:11:54 +02:00
Benjamin Eberlei
06870fd87f Merge branch 'DDC-1077' into 2.0.x 2011-03-27 21:12:24 +02:00
Benjamin Eberlei
26af92f452 [DDC-1077] Bugfix in not handling literals in Select Expressions. 2011-03-27 21:12:05 +02:00
Benjamin Eberlei
97d97a8a89 Merge branch 'DDC-1079' into 2.0.x 2011-03-27 14:06:05 +02:00
Benjamin Eberlei
3df673cb6a [DDC-1079] Bugfix for shortcut for ArithmeticExpressions in SimpleSelectExpression that lead to literals not being valid. Problem was that ScalarExpression() did not handle AggregateExpressions() at all, which is now fixed. 2011-03-27 14:05:33 +02:00
Francis Besset
85474a0c7a Fixed an undefined index by a HydrationException 2011-03-21 20:33:32 +01:00
Benjamin Eberlei
1c05831b20 Merge ModifyLimitQueryFix into 2.0.x 2011-03-20 16:06:36 -04:00
Benjamin Eberlei
26126a10cd Bump Dev Version to 2.0.4-DEV 2011-03-20 16:04:07 -04:00
Benjamin Eberlei
b6c5de3ef5 Release 2.0.3 2011-03-20 16:03:54 -04:00
Benjamin Eberlei
48fe910978 Update DBAL dependency to 2.0.3 2011-03-20 16:03:11 -04:00
Benjamin Eberlei
0df6086960 Bump Version to 2.0.3-DEV 2011-03-20 15:51:51 -04:00
Benjamin Eberlei
3d406afa38 Merge branch 'DDC-992' into 2.0.x 2011-03-20 17:14:17 +01:00
Benjamin Eberlei
526f21ad3d [DDC-992] Fix criteria usage of column names clashing with field or associations by prefixing with table names or alias. 2011-03-20 17:14:04 +01:00
Benjamin Eberlei
31722cf8f6 [DDC-1053] Fix rebase/merge mistake in tests. 2011-03-20 14:10:33 +01:00
Benjamin Eberlei
758a09dfe8 Merge branch 'DDC-1053' into 2.0.x 2011-03-20 14:09:15 +01:00
Benjamin Eberlei
ba00dd13b6 [DDC-1053] Fix bug with usage of identification variables in GroupByItem. 2011-03-20 14:08:57 +01:00
Benjamin Eberlei
ff65aeed60 Merge branch 'DDC-1052' into 2.0.x 2011-03-20 13:08:48 +01:00
Benjamin Eberlei
3a5d70fbf3 [DDC-1052] Fix bug with versioning and inheritance 2011-03-20 13:08:16 +01:00
Benjamin Eberlei
68257a8c93 Merge branch 'DDC-1070' into 2.0.x 2011-03-20 12:23:43 +01:00
Benjamin Eberlei
3b4596691f [DDC-1070] Fix in AbstractQuery::iterate() method not respecting hydrator and parameters. 2011-03-20 12:23:21 +01:00
Benjamin Eberlei
ecb409412f Bump Dev Version to 2.0.3-DEV 2011-03-05 04:12:43 -05:00
58 changed files with 1642 additions and 229 deletions

View File

@@ -100,6 +100,9 @@
</copy>
<exec command="sed 's/${version}-DEV/${version}/' ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php > ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php" passthru="true" />
<exec command="mv ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php" passthru="true" />
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Yaml/.git" includeemptydirs="true"/>
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Console/.git" includeemptydirs="true"/>
</target>
<target name="build" depends="test, build-orm"/>
@@ -266,4 +269,4 @@
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineSymfonyYaml-${version}.tgz" dir="." passthru="true" />
<exec command="sudo pirum build ${project.pirum_dir}" passthru="true" />
</target>
</project>
</project>

View File

@@ -168,7 +168,7 @@
<xs:complexType name="discriminator-mapping">
<xs:attribute name="value" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="class" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="class" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="discriminator-map">

View File

@@ -476,10 +476,20 @@ abstract class AbstractQuery
* @param integer $hydrationMode The hydration mode to use.
* @return IterableResult
*/
public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
public function iterate(array $params = array(), $hydrationMode = null)
{
if ($hydrationMode !== null) {
$this->setHydrationMode($hydrationMode);
}
if ($params) {
$this->setParameters($params);
}
$stmt = $this->_doExecute();
return $this->_em->newHydrator($this->_hydrationMode)->iterate(
$this->_doExecute($params, $hydrationMode), $this->_resultSetMapping, $this->_hints
$stmt, $this->_resultSetMapping, $this->_hints
);
}

View File

@@ -96,12 +96,16 @@ class EntityManager
private $proxyFactory;
/**
* @var ExpressionBuilder The expression builder instance used to generate query expressions.
* The expression builder instance used to generate query expressions.
*
* @var Doctrine\ORM\Query\Expr
*/
private $expressionBuilder;
/**
* Whether the EntityManager is closed or not.
*
* @var bool
*/
private $closed = false;
@@ -163,7 +167,7 @@ class EntityManager
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
* </code>
*
* @return ExpressionBuilder
* @return Doctrine\ORM\Query\Expr
*/
public function getExpressionBuilder()
{

View File

@@ -39,9 +39,9 @@ class ObjectHydrator extends AbstractHydrator
* This local cache is maintained between hydration runs and not cleared.
*/
private $_ce = array();
/* The following parts are reinitialized on every hydration run. */
private $_identifierMap;
private $_resultPointers;
private $_idTemplate;
@@ -50,7 +50,7 @@ class ObjectHydrator extends AbstractHydrator
private $_initializedCollections = array();
private $_existingCollections = array();
//private $_createdEntities;
/** @override */
protected function _prepare()
@@ -59,7 +59,7 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultPointers =
$this->_idTemplate = array();
$this->_resultCounter = 0;
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
@@ -68,10 +68,14 @@ class ObjectHydrator extends AbstractHydrator
if ( ! isset($this->_ce[$className])) {
$this->_ce[$className] = $class;
}
// Remember which associations are "fetch joined", so that we know where to inject
// collection stubs or proxies and where not.
if (isset($this->_rsm->relationMap[$dqlAlias])) {
if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
}
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
$sourceClass = $this->_getClassMetadata($sourceClassName);
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
@@ -176,7 +180,7 @@ class ObjectHydrator extends AbstractHydrator
return $value;
}
/**
* Gets an entity instance.
*
@@ -186,7 +190,7 @@ class ObjectHydrator extends AbstractHydrator
*/
private function _getEntity(array $data, $dqlAlias)
{
$className = $this->_rsm->aliasMap[$dqlAlias];
$className = $this->_rsm->aliasMap[$dqlAlias];
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
@@ -194,7 +198,7 @@ class ObjectHydrator extends AbstractHydrator
}
return $this->_uow->createEntity($className, $data, $this->_hints);
}
private function _getEntityFromIdentityMap($className, array $data)
{
$class = $this->_ce[$className];
@@ -208,7 +212,7 @@ class ObjectHydrator extends AbstractHydrator
return $this->_uow->tryGetByIdHash($data[$class->identifier[0]], $class->rootEntityName);
}
}
/**
* Gets a ClassMetadata instance from the local cache.
* If the instance is not yet in the local cache, it is loaded into the
@@ -266,7 +270,7 @@ class ObjectHydrator extends AbstractHydrator
// Hydrate the data chunks
foreach ($rowData as $dqlAlias => $data) {
$entityName = $this->_rsm->aliasMap[$dqlAlias];
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
// It's a joined result
@@ -277,7 +281,7 @@ class ObjectHydrator extends AbstractHydrator
// Get a reference to the parent object to which the joined element belongs.
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias])) {
$first = reset($this->_resultPointers);
$first = reset($this->_resultPointers);
$parentObject = $this->_resultPointers[$parentAlias][key($first)];
} else if (isset($this->_resultPointers[$parentAlias])) {
$parentObject = $this->_resultPointers[$parentAlias];
@@ -302,11 +306,11 @@ class ObjectHydrator extends AbstractHydrator
} else if ( ! isset($this->_existingCollections[$collKey])) {
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
}
$indexExists = isset($this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]);
$index = $indexExists ? $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] : false;
$indexIsValid = $index !== false ? isset($reflFieldValue[$index]) : false;
if ( ! $indexExists || ! $indexIsValid) {
if (isset($this->_existingCollections[$collKey])) {
// Collection exists, only look for the element in the identity map.

View File

@@ -1137,7 +1137,8 @@ class ClassMetadataInfo
*/
public function getTemporaryIdTableName()
{
return $this->table['name'] . '_id_tmp';
// replace dots with underscores because PostgreSQL creates temporary tables in a special schema
return str_replace('.', '_', $this->table['name'] . '_id_tmp');
}
/**
@@ -1479,6 +1480,7 @@ class ClassMetadataInfo
if (strpos($className, '\\') === false && strlen($this->namespace)) {
$className = $this->namespace . '\\' . $className;
}
$className = ltrim($className, '\\');
$this->discriminatorMap[$value] = $className;
if ($this->name == $className) {
$this->discriminatorValue = $value;

View File

@@ -67,10 +67,10 @@ class AnnotationDriver implements Driver
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
* docblock annotations.
*
* @param $reader The AnnotationReader to use.
* @param AnnotationReader $reader The AnnotationReader to use, duck-typed.
* @param string|array $paths One or multiple paths where mapping classes can be found.
*/
public function __construct(AnnotationReader $reader, $paths = null)
public function __construct($reader, $paths = null)
{
$this->_reader = $reader;
if ($paths) {

View File

@@ -67,6 +67,26 @@ class DatabaseDriver implements Driver
$this->_sm = $schemaManager;
}
/**
* Set tables manually instead of relying on the reverse engeneering capabilities of SchemaManager.
*
* @param array $entityTables
* @param array $manyToManyTables
* @return void
*/
public function setTables($entityTables, $manyToManyTables)
{
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
foreach ($entityTables AS $table) {
$className = Inflector::classify(strtolower($table->getName()));
$this->classToTableNames[$className] = $table->getName();
$this->tables[$table->getName()] = $table;
}
foreach ($manyToManyTables AS $table) {
$this->manyToManyTables[$table->getName()] = $table;
}
}
private function reverseEngineerMappingFromDatabase()
{
if ($this->tables !== null) {
@@ -77,7 +97,7 @@ class DatabaseDriver implements Driver
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
}
$this->tables = array();
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
foreach ($tables AS $tableName => $table) {
/* @var $table Table */
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
@@ -95,11 +115,7 @@ class DatabaseDriver implements Driver
sort($pkColumns);
sort($allForeignKeyColumns);
if ($pkColumns == $allForeignKeyColumns) {
if (count($table->getForeignKeys()) > 2) {
throw new \InvalidArgumentException("ManyToMany table '" . $tableName . "' with more or less than two foreign keys are not supported by the Database Reverese Engineering Driver.");
}
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
$this->manyToManyTables[$tableName] = $table;
} else {
// lower-casing is necessary because of Oracle Uppercase Tablenames,
@@ -191,8 +207,10 @@ class DatabaseDriver implements Driver
foreach ($this->manyToManyTables AS $manyTable) {
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
// foreign key maps to the table of the current entity, many to many association probably exists
if (strtolower($tableName) == strtolower($foreignKey->getForeignTableName())) {
$myFk = $foreignKey;
$otherFk = null;
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
if ($foreignKey != $myFk) {
$otherFk = $foreignKey;
@@ -200,6 +218,12 @@ class DatabaseDriver implements Driver
}
}
if (!$otherFk) {
// the definition of this many to many table does not contain
// enough foreign key information to continue reverse engeneering.
continue;
}
$localColumn = current($myFk->getColumns());
$associationMapping = array();
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));

View File

@@ -262,8 +262,8 @@ class XmlDriver extends AbstractFileDriver
$mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade);
}
if (isset($oneToOneElement->{'orphan-removal'})) {
$mapping['orphanRemoval'] = (bool)$oneToOneElement->{'orphan-removal'};
if (isset($oneToOneElement['orphan-removal'])) {
$mapping['orphanRemoval'] = (bool)$oneToOneElement['orphan-removal'];
}
$metadata->mapOneToOne($mapping);
@@ -287,8 +287,8 @@ class XmlDriver extends AbstractFileDriver
$mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
}
if (isset($oneToManyElement->{'orphan-removal'})) {
$mapping['orphanRemoval'] = (bool)$oneToManyElement->{'orphan-removal'};
if (isset($oneToManyElement['orphan-removal'])) {
$mapping['orphanRemoval'] = (bool)$oneToManyElement['orphan-removal'];
}
if (isset($oneToManyElement->{'order-by'})) {
@@ -325,9 +325,6 @@ class XmlDriver extends AbstractFileDriver
$joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'});
} else if (isset($manyToOneElement->{'join-columns'})) {
foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
if (!isset($joinColumnElement['name'])) {
$joinColumnElement['name'] = $name;
}
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
}
}

View File

@@ -266,6 +266,10 @@ class YamlDriver extends AbstractFileDriver
$mapping['cascade'] = $oneToOneElement['cascade'];
}
if (isset($oneToOneElement['orphanRemoval'])) {
$mapping['orphanRemoval'] = (bool)$oneToOneElement['orphanRemoval'];
}
$metadata->mapOneToOne($mapping);
}
}
@@ -283,6 +287,10 @@ class YamlDriver extends AbstractFileDriver
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']);
}
if (isset($oneToManyElement['orphanRemoval'])) {
$mapping['orphanRemoval'] = (bool)$oneToManyElement['orphanRemoval'];
}
if (isset($oneToManyElement['cascade'])) {
$mapping['cascade'] = $oneToManyElement['cascade'];
}
@@ -450,6 +458,6 @@ class YamlDriver extends AbstractFileDriver
*/
protected function _loadMappingFile($file)
{
return \Symfony\Component\Yaml\Yaml::load($file);
return \Symfony\Component\Yaml\Yaml::parse($file);
}
}

View File

@@ -33,6 +33,7 @@ class OptimisticLockException extends ORMException
public function __construct($msg, $entity)
{
parent::__construct($msg);
$this->entity = $entity;
}

View File

@@ -576,6 +576,7 @@ final class PersistentCollection implements Collection
}
}
$this->coll->clear();
$this->initialized = true; // direct call, {@link initialize()} is too expensive
if ($this->association['isOwningSide']) {
$this->changed();
$this->em->getUnitOfWork()->scheduleCollectionDeletion($this);

View File

@@ -358,7 +358,7 @@ class BasicEntityPersister
$result = $this->_conn->executeUpdate($sql, $params, $types);
if ($this->_class->isVersioned && ! $result) {
if ($versioned && ! $result) {
throw OptimisticLockException::lockFailed($entity);
}
}
@@ -750,9 +750,10 @@ class BasicEntityPersister
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
$joinTableConditions = array();
if ($assoc['isOwningSide']) {
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
@@ -761,10 +762,11 @@ class BasicEntityPersister
}
} else {
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
// TRICKY: since the association is inverted source and target are flipped
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
@@ -1169,18 +1171,16 @@ class BasicEntityPersister
$conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
} else if ($assoc !== null) {
if ($assoc['type'] == ClassMetadata::MANY_TO_MANY) {
$owningAssoc = $assoc['isOwningSide'] ? $assoc : $this->_em->getClassMetadata($assoc['targetEntity'])
->associationMappings[$assoc['mappedBy']];
$conditionSql .= $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform) . '.' . $field;
} else {
$conditionSql .= $field;
}
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
// very careless developers could potentially open up this normally hidden api for userland attacks,
// therefore checking for spaces and function calls which are not allowed.
// found a join column condition, not really a "field"
$conditionSql .= $field;
} else {
throw ORMException::unrecognizedField($field);
}
$conditionSql .= ' = ?';
$conditionSql .= ($value === null) ? ' IS NULL' : ' = ?';
}
return $conditionSql;
}
@@ -1197,8 +1197,13 @@ class BasicEntityPersister
$criteria = array();
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
$tableAlias = isset($owningAssoc['inherited']) ?
$this->_getSQLTableAlias($owningAssoc['inherited'])
: $this->_getSQLTableAlias($this->_class->name);
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
}
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
@@ -1221,6 +1226,10 @@ class BasicEntityPersister
$params = $types = array();
foreach ($criteria AS $field => $value) {
if ($value === null) {
continue; // skip null values.
}
$type = null;
if (isset($this->_class->fieldMappings[$field])) {
$type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType();

View File

@@ -209,7 +209,7 @@ class ProxyFactory
$methods .= $parameterString . ')';
$methods .= PHP_EOL . ' {' . PHP_EOL;
$methods .= ' $this->_load();' . PHP_EOL;
$methods .= ' $this->__load();' . PHP_EOL;
$methods .= ' return parent::' . $method->getName() . '(' . $argumentString . ');';
$methods .= PHP_EOL . ' }' . PHP_EOL;
}
@@ -269,17 +269,26 @@ class <proxyClassName> extends \<className> implements \Doctrine\ORM\Proxy\Proxy
$this->_entityPersister = $entityPersister;
$this->_identifier = $identifier;
}
private function _load()
/** @private */
public function __load()
{
if (!$this->__isInitialized__ && $this->_entityPersister) {
$this->__isInitialized__ = true;
if (method_exists($this, "__wakeup")) {
// call this after __isInitialized__to avoid infinite recursion
// but before loading to emulate what ClassMetadata::newInstance()
// provides.
$this->__wakeup();
}
if ($this->_entityPersister->load($this->_identifier, $this) === null) {
throw new \Doctrine\ORM\EntityNotFoundException();
}
unset($this->_entityPersister, $this->_identifier);
}
}
<methods>
public function __sleep()

View File

@@ -249,7 +249,12 @@ final class Query extends AbstractQuery
$idValues = $class->getIdentifierValues($value);
}
$sqlPositions = $paramMappings[$key];
$sqlParams += array_combine((array)$sqlPositions, $idValues);
$cSqlPos = count($sqlPositions);
$cIdValues = count($idValues);
$idValues = array_values($idValues);
for ($i = 0; $i < $cSqlPos; $i++) {
$sqlParams[$sqlPositions[$i]] = $idValues[ ($i % $cIdValues) ];
}
} else {
foreach ($paramMappings[$key] as $position) {
$sqlParams[$position] = $value;

View File

@@ -55,7 +55,7 @@ abstract class Base
public function add($arg)
{
if ( ! empty($arg) || ($arg instanceof self && $arg->count() > 0)) {
if ( $arg !== null || ($arg instanceof self && $arg->count() > 0)) {
// If we decide to keep Expr\Base instances, we can use this check
if ( ! is_string($arg)) {
$class = get_class($arg);

View File

@@ -126,7 +126,7 @@ class Lexer extends \Doctrine\Common\Lexer
'[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}',
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
"'(?:[^']|'')*'",
'\?[1-9][0-9]*|:[a-z][a-z0-9_]+'
'\?[1-9][0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
);
}

View File

@@ -1324,6 +1324,10 @@ class Parser
$token = $this->_lexer->lookahead;
$identVariable = $this->IdentificationVariable();
if (!isset($this->_queryComponents[$identVariable])) {
$this->semanticalError('Cannot group by undefined identification variable.');
}
return $identVariable;
}
@@ -1633,7 +1637,7 @@ class Parser
return $this->StateFieldPathExpression();
} else if ($lookahead == Lexer::T_INTEGER || $lookahead == Lexer::T_FLOAT) {
return $this->SimpleArithmeticExpression();
} else if ($this->_isFunction()) {
} else if ($this->_isFunction() || $this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
// We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator)
$this->_lexer->peek(); // "("
$peek = $this->_peekBeyondClosingParenthesis();
@@ -1641,8 +1645,12 @@ class Parser
if ($this->_isMathOperator($peek)) {
return $this->SimpleArithmeticExpression();
}
return $this->FunctionDeclaration();
if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
return $this->AggregateExpression();
} else {
return $this->FunctionDeclaration();
}
} else if ($lookahead == Lexer::T_STRING) {
return $this->StringPrimary();
} else if ($lookahead == Lexer::T_INPUT_PARAMETER) {
@@ -1717,7 +1725,8 @@ class Parser
$expression = $this->PartialObjectExpression();
$identVariable = $expression->identificationVariable;
} else if ($this->_lexer->lookahead['type'] == Lexer::T_INTEGER ||
$this->_lexer->lookahead['type'] == Lexer::T_FLOAT) {
$this->_lexer->lookahead['type'] == Lexer::T_FLOAT ||
$this->_lexer->lookahead['type'] == Lexer::T_STRING) {
// Shortcut: ScalarExpression => SimpleArithmeticExpression
$expression = $this->SimpleArithmeticExpression();
} else {
@@ -1786,15 +1795,8 @@ class Parser
}
$this->_lexer->peek();
$beyond = $this->_peekBeyondClosingParenthesis();
if ($this->_isMathOperator($beyond)) {
$expression = $this->ScalarExpression();
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
$expression = $this->AggregateExpression();
} else {
$expression = $this->FunctionDeclaration();
}
$expression = $this->ScalarExpression();
$expr = new AST\SimpleSelectExpression($expression);
@@ -2299,7 +2301,8 @@ class Parser
if ($peek['value'] == '.') {
return $this->StateFieldPathExpression();
} else if ($peek['value'] == '(') {
return $this->FunctionsReturningStrings();
// do NOT directly go to FunctionsReturningString() because it doesnt check for custom functions.
return $this->FunctionDeclaration();
} else {
$this->syntaxError("'.' or '('");
}

View File

@@ -75,8 +75,7 @@ class QueryException extends \Doctrine\ORM\ORMException
public static function invalidPathExpression($pathExpr)
{
return new self(
"Invalid PathExpression '" . $pathExpr->identificationVariable .
"." . implode('.', $pathExpr->parts) . "'."
"Invalid PathExpression '" . $pathExpr->identificationVariable . "." . $pathExpr->field . "'."
);
}

View File

@@ -927,7 +927,8 @@ class SqlWalker implements TreeWalker
$expr instanceof AST\SimpleArithmeticExpression ||
$expr instanceof AST\ArithmeticTerm ||
$expr instanceof AST\ArithmeticFactor ||
$expr instanceof AST\ArithmeticPrimary
$expr instanceof AST\ArithmeticPrimary ||
$expr instanceof AST\Literal
) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
@@ -936,7 +937,11 @@ class SqlWalker implements TreeWalker
}
$columnAlias = 'sclr' . $this->_aliasCounter++;
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
if ($expr instanceof AST\Literal) {
$sql .= $this->walkLiteral($expr) . ' AS ' .$columnAlias;
} else {
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
}
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
@@ -1197,9 +1202,25 @@ class SqlWalker implements TreeWalker
*/
public function walkGroupByClause($groupByClause)
{
return ' GROUP BY ' . implode(
', ', array_map(array($this, 'walkGroupByItem'), $groupByClause->groupByItems)
);
$sql = '';
foreach ($groupByClause->groupByItems AS $groupByItem) {
if (is_string($groupByItem)) {
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
if ($sql != '') {
$sql .= ', ';
}
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
$sql .= $this->walkGroupByItem($groupByItem);
}
} else {
if ($sql != '') {
$sql .= ', ';
}
$sql .= $this->walkGroupByItem($groupByItem);
}
}
return ' GROUP BY ' . $sql;
}
/**

View File

@@ -137,8 +137,7 @@ EOT
$toType = strtolower($input->getArgument('to-type'));
$cme = new ClassMetadataExporter();
$exporter = $cme->getExporter($toType, $destPath);
$exporter = $this->getExporter($toType, $destPath);
$exporter->setOverwriteExistingFiles( ($input->getOption('force') !== false) );
if ($toType == 'annotation') {
@@ -167,4 +166,11 @@ EOT
$output->write('No Metadata Classes to process.' . PHP_EOL);
}
}
protected function getExporter($toType, $destPath)
{
$cme = new ClassMetadataExporter();
return $cme->getExporter($toType, $destPath);
}
}

View File

@@ -70,10 +70,10 @@ class ConvertDoctrine1Schema
if (is_dir($path)) {
$files = glob($path . '/*.yml');
foreach ($files as $file) {
$schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::load($file));
$schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::parse($file));
}
} else {
$schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::load($path));
$schema = array_merge($schema, (array) \Symfony\Component\Yaml\Yaml::parse($path));
}
}

View File

@@ -179,11 +179,11 @@ public function <methodName>()
$this->_isNew = !file_exists($path) || (file_exists($path) && $this->_regenerateEntityIfExists);
if ( ! $this->_isNew) {
$this->_parseTokensInEntityFile($path);
$this->_parseTokensInEntityFile(file_get_contents($path));
}
if ($this->_backupExisting && file_exists($path)) {
$backupPath = dirname($path) . DIRECTORY_SEPARATOR . "~" . basename($path);
$backupPath = dirname($path) . DIRECTORY_SEPARATOR . basename($path) . "~";
if (!copy($path, $backupPath)) {
throw new \RuntimeException("Attempt to backup overwritten entitiy file but copy operation failed.");
}
@@ -400,28 +400,46 @@ public function <methodName>()
/**
* @todo this won't work if there is a namespace in brackets and a class outside of it.
* @param string $path
* @param string $src
*/
private function _parseTokensInEntityFile($path)
private function _parseTokensInEntityFile($src)
{
$tokens = token_get_all(file_get_contents($path));
$tokens = token_get_all($src);
$lastSeenNamespace = "";
$lastSeenClass = false;
$inNamespace = false;
$inClass = false;
for ($i = 0; $i < count($tokens); $i++) {
$token = $tokens[$i];
if ($token[0] == T_NAMESPACE) {
$lastSeenNamespace = $tokens[$i+2][1] . "\\";
} else if ($token[0] == T_NS_SEPARATOR) {
$lastSeenNamespace .= $tokens[$i+1][1] . "\\";
} else if ($token[0] == T_CLASS) {
$lastSeenClass = $lastSeenNamespace . $tokens[$i+2][1];
if (in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
continue;
}
if ($inNamespace) {
if ($token[0] == T_NS_SEPARATOR || $token[0] == T_STRING) {
$lastSeenNamespace .= $token[1];
} else if (is_string($token) && in_array($token, array(';', '{'))) {
$inNamespace = false;
}
}
if ($inClass) {
$inClass = false;
$lastSeenClass = $lastSeenNamespace . '\\' . $token[1];
$this->_staticReflection[$lastSeenClass]['properties'] = array();
$this->_staticReflection[$lastSeenClass]['methods'] = array();
}
if ($token[0] == T_NAMESPACE) {
$lastSeenNamespace = "";
$inNamespace = true;
} else if ($token[0] == T_CLASS) {
$inClass = true;
} else if ($token[0] == T_FUNCTION) {
if ($tokens[$i+2][0] == T_STRING) {
$this->_staticReflection[$lastSeenClass]['methods'][] = $tokens[$i+2][1];
} else if ($tokens[$i+2][0] == T_AMPERSAND && $tokens[$i+3][0] == T_STRING) {
} else if ($tokens[$i+2] == "&" && $tokens[$i+3][0] == T_STRING) {
$this->_staticReflection[$lastSeenClass]['methods'][] = $tokens[$i+3][1];
}
} else if (in_array($token[0], array(T_VAR, T_PUBLIC, T_PRIVATE, T_PROTECTED)) && $tokens[$i+2][0] != T_FUNCTION) {
@@ -502,7 +520,7 @@ public function <methodName>()
}
if ($metadata->isMappedSuperclass) {
$lines[] = ' * @' . $this->_annotationsPrefix . 'MappedSupperClass';
$lines[] = ' * @' . $this->_annotationsPrefix . 'MappedSuperClass';
} else {
$lines[] = ' * @' . $this->_annotationsPrefix . 'Entity';
}
@@ -661,6 +679,7 @@ public function <methodName>()
if ($this->_hasMethod($methodName, $metadata)) {
return;
}
$this->_staticReflection[$metadata->name]['methods'][] = $methodName;
$var = sprintf('_%sMethodTemplate', $type);
$template = self::$$var;
@@ -693,6 +712,7 @@ public function <methodName>()
if ($this->_hasMethod($methodName, $metadata)) {
return;
}
$this->_staticReflection[$metadata->name]['methods'][] = $methodName;
$replacements = array(
'<name>' => $this->_annotationsPrefix . $name,

View File

@@ -185,7 +185,7 @@ class SchemaTool
// Add a FK constraint on the ID column
$table->addUnnamedForeignKeyConstraint(
$this->_em->getClassMetadata($class->rootEntityName)->getTableName(),
$this->_em->getClassMetadata($class->rootEntityName)->getQuotedTableName($this->_platform),
array($columnName), array($columnName), array('onDelete' => 'CASCADE')
);
}
@@ -424,6 +424,7 @@ class SchemaTool
$localColumns = array();
$foreignColumns = array();
$fkOptions = array();
$foreignTableName = $class->getQuotedTableName($this->_platform);
foreach ($joinColumns as $joinColumn) {
$columnName = $joinColumn['name'];
@@ -483,7 +484,7 @@ class SchemaTool
}
$theJoinTable->addUnnamedForeignKeyConstraint(
$class->getTableName(), $localColumns, $foreignColumns, $fkOptions
$foreignTableName, $localColumns, $foreignColumns, $fkOptions
);
}
@@ -542,58 +543,55 @@ class SchemaTool
}
/**
*
* Get SQL to drop the tables defined by the passed classes.
*
* @param array $classes
* @return array
*/
public function getDropSchemaSQL(array $classes)
{
$visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->_platform);
$schema = $this->getSchemaFromMetadata($classes);
$sm = $this->_em->getConnection()->getSchemaManager();
$fullSchema = $sm->createSchema();
foreach ($fullSchema->getTables() AS $table) {
if (!$schema->hasTable($table->getName())) {
foreach ($table->getForeignKeys() AS $foreignKey) {
/* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */
if ($schema->hasTable($foreignKey->getForeignTableName())) {
$visitor->acceptForeignKey($table, $foreignKey);
}
}
} else {
$visitor->acceptTable($table);
foreach ($table->getForeignKeys() AS $foreignKey) {
$visitor->acceptForeignKey($table, $foreignKey);
}
}
}
$sql = array();
$orderedTables = array();
foreach ($classes AS $class) {
if ($class->isIdGeneratorSequence() && !$class->isMappedSuperclass && $class->name == $class->rootEntityName && $this->_platform->supportsSequences()) {
$sql[] = $this->_platform->getDropSequenceSQL($class->sequenceGeneratorDefinition['sequenceName']);
if ($this->_platform->supportsSequences()) {
foreach ($schema->getSequences() AS $sequence) {
$visitor->acceptSequence($sequence);
}
foreach ($schema->getTables() AS $table) {
/* @var $sequence Table */
foreach ($table->getIndexes() AS $index) {
if ($index->isPrimary()) {
$columns = $index->getColumns();
if (count($columns) == 1) {
$checkSequence = $table->getName() . "_" . $columns[0] . "_seq";
if ($fullSchema->hasSequence($checkSequence)) {
$visitor->acceptSequence($fullSchema->getSequence($checkSequence));
}
}
}
}
}
}
$commitOrder = $this->_getCommitOrder($classes);
$associationTables = $this->_getAssociationTables($commitOrder);
// Drop association tables first
foreach ($associationTables as $associationTable) {
if (!in_array($associationTable, $orderedTables)) {
$orderedTables[] = $associationTable;
}
}
// Drop tables in reverse commit order
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
$class = $commitOrder[$i];
if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName)
|| $class->isMappedSuperclass) {
continue;
}
if (!in_array($class->getTableName(), $orderedTables)) {
$orderedTables[] = $class->getTableName();
}
}
$dropTablesSql = array();
foreach ($orderedTables AS $tableName) {
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
$foreignKeys = $sm->listTableForeignKeys($tableName);
foreach ($foreignKeys AS $foreignKey) {
$sql[] = $this->_platform->getDropForeignKeySQL($foreignKey, $tableName);
}
$dropTablesSql[] = $this->_platform->getDropTableSQL($tableName);
}
return array_merge($sql, $dropTablesSql);
return $visitor->getQueries();
}
/**
@@ -636,44 +634,4 @@ class SchemaTool
return $schemaDiff->toSql($this->_platform);
}
}
private function _getCommitOrder(array $classes)
{
$calc = new CommitOrderCalculator;
// Calculate dependencies
foreach ($classes as $class) {
$calc->addClass($class);
foreach ($class->associationMappings as $assoc) {
if ($assoc['isOwningSide']) {
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
if ( ! $calc->hasClass($targetClass->name)) {
$calc->addClass($targetClass);
}
// add dependency ($targetClass before $class)
$calc->addDependency($targetClass, $class);
}
}
}
return $calc->getCommitOrder();
}
private function _getAssociationTables(array $classes)
{
$associationTables = array();
foreach ($classes as $class) {
foreach ($class->associationMappings as $assoc) {
if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) {
$associationTables[] = $assoc['joinTable']['name'];
}
}
}
return $associationTables;
}
}

View File

@@ -399,8 +399,11 @@ class UnitOfWork implements PropertyChangedListener
$actualData = array();
foreach ($class->reflFields as $name => $refProp) {
$value = $refProp->getValue($entity);
if ($class->isCollectionValuedAssociation($name) && $value !== null
if (isset($class->associationMappings[$name])
&& ($class->associationMappings[$name]['type'] & ClassMetadata::TO_MANY)
&& $value !== null
&& ! ($value instanceof PersistentCollection)) {
// If $value is not a Collection then use an ArrayCollection.
if ( ! $value instanceof Collection) {
$value = new ArrayCollection($value);
@@ -419,7 +422,7 @@ class UnitOfWork implements PropertyChangedListener
$coll->setDirty( ! $coll->isEmpty());
$class->reflFields[$name]->setValue($entity, $coll);
$actualData[$name] = $coll;
} else if ( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) {
} else if ( (! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) && ($name !== $class->versionField) ) {
$actualData[$name] = $value;
}
}
@@ -738,7 +741,7 @@ class UnitOfWork implements PropertyChangedListener
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
foreach ($this->entityUpdates as $oid => $entity) {
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
if ($hasPreUpdateLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
@@ -778,7 +781,7 @@ class UnitOfWork implements PropertyChangedListener
$hasListeners = $this->evm->hasListeners(Events::postRemove);
foreach ($this->entityDeletions as $oid => $entity) {
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
$persister->delete($entity);
unset(
$this->entityDeletions[$oid],
@@ -972,7 +975,7 @@ class UnitOfWork implements PropertyChangedListener
if ($this->isInIdentityMap($entity)) {
$this->removeFromIdentityMap($entity);
}
unset($this->entityInsertions[$oid]);
unset($this->entityInsertions[$oid], $this->entityStates[$oid]);
return; // entity has not been persisted yet, so nothing more to do.
}
@@ -987,6 +990,7 @@ class UnitOfWork implements PropertyChangedListener
}
if ( ! isset($this->entityDeletions[$oid])) {
$this->entityDeletions[$oid] = $entity;
$this->entityStates[$oid] = self::STATE_REMOVED;
}
}
@@ -1282,6 +1286,10 @@ class UnitOfWork implements PropertyChangedListener
}
$visited[$oid] = $entity; // mark visited
// Cascade first, because scheduleForDelete() removes the entity from the identity map, which
// can cause problems when a lazy proxy has to be initialized for the cascade operation.
$this->cascadeRemove($entity, $visited);
$class = $this->em->getClassMetadata(get_class($entity));
$entityState = $this->getEntityState($entity);
@@ -1305,7 +1313,6 @@ class UnitOfWork implements PropertyChangedListener
throw new UnexpectedValueException("Unexpected entity state: $entityState.");
}
$this->cascadeRemove($entity, $visited);
}
/**
@@ -1440,7 +1447,8 @@ class UnitOfWork implements PropertyChangedListener
}
if ($assoc2['isCascadeMerge']) {
$managedCol->initialize();
if (!$managedCol->isEmpty()) {
// clear and set dirty a managed collection if its not also the same collection to merge from.
if (!$managedCol->isEmpty() && $managedCol != $mergeCol) {
$managedCol->unwrap()->clear();
$managedCol->setDirty(true);
if ($assoc2['isOwningSide'] && $assoc2['type'] == ClassMetadata::MANY_TO_MANY && $class->isChangeTrackingNotify()) {
@@ -1639,6 +1647,10 @@ class UnitOfWork implements PropertyChangedListener
}
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection) {
if ($relatedEntities === $class->reflFields[$assoc['fieldName']]->getValue($managedCopy)) {
continue;
}
if ($relatedEntities instanceof PersistentCollection) {
// Unwrap so that foreach() does not initialize
$relatedEntities = $relatedEntities->unwrap();
@@ -1666,6 +1678,7 @@ class UnitOfWork implements PropertyChangedListener
if ( ! $assoc['isCascadePersist']) {
continue;
}
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
if ($relatedEntities instanceof PersistentCollection) {
@@ -1694,7 +1707,11 @@ class UnitOfWork implements PropertyChangedListener
if ( ! $assoc['isCascadeRemove']) {
continue;
}
//TODO: If $entity instanceof Proxy => Initialize ?
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
$entity->__load();
}
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection || is_array($relatedEntities)) {
// If its a PersistentCollection initialization is intended! No unwrap!
@@ -1845,8 +1862,8 @@ class UnitOfWork implements PropertyChangedListener
$idHash = $data[$class->identifier[0]];
$id = array($class->identifier[0] => $idHash);
}
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
$entity = $this->identityMap[$class->rootEntityName][$idHash];
$oid = spl_object_hash($entity);
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
@@ -2257,7 +2274,28 @@ class UnitOfWork implements PropertyChangedListener
{
return $this->collectionUpdates;
}
/**
* Helper method to initialize a lazy loading proxy or persistent collection.
*
* @param object
* @return void
*/
public function initializeObject($obj)
{
if ($obj instanceof Proxy) {
$obj->__load();
} else if ($obj instanceof PersistentCollection) {
$obj->initialize();
}
}
/**
* Helper method to show an object as string.
*
* @param object $obj
* @return string
*/
private static function objToStr($obj)
{
return method_exists($obj, '__toString') ? (string)$obj : get_class($obj).'@'.spl_object_hash($obj);

View File

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

View File

@@ -56,6 +56,7 @@ class ECommerceProduct
private $related;
public $isCloned = false;
public $wakeUp = false;
public function __construct()
{
@@ -166,4 +167,12 @@ class ECommerceProduct
{
$this->isCloned = true;
}
/**
* Testing docblock contents here
*/
public function __wakeup()
{
$this->wakeUp = true;
}
}

View File

@@ -140,6 +140,40 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertFalse($user2->address instanceof \Doctrine\ORM\Proxy\Proxy);
}
/**
* @group DDC-1230
*/
public function testRemove()
{
$user = new CmsUser;
$user->name = 'Guilherme';
$user->username = 'gblanco';
$user->status = 'developer';
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
$this->_em->persist($user);
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($user));
$this->_em->remove($user);
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
$this->_em->persist($user);
$this->_em->flush();
$id = $user->getId();
$this->_em->remove($user);
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_REMOVED, $this->_em->getUnitOfWork()->getEntityState($user));
$this->_em->flush();
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
$this->assertNull($this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $id));
}
public function testOneToManyOrphanRemoval()
{
$user = new CmsUser;
@@ -827,36 +861,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_addresses where id=".$addressId.""));
}
public function testClearingCollectionDoesNotInitialize()
{
$user = new CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin E.";
$user->status = 'active';
$grp = new CmsGroup();
$grp->setName("The Dudes");
$grp->addUser($user);
$user->addGroup($grp);
$this->_em->persist($user);
$this->_em->persist($grp);
$this->_em->flush();
$this->_em->clear();
$this->assertEquals(1, $this->_em->getConnection()->fetchColumn("select count(*) from cms_users_groups"));
$user2 = $this->_em->find(get_class($user), $user->id);
$this->assertFalse($user2->groups->isInitialized());
$user2->groups->clear();
$this->assertFalse($user2->groups->isInitialized());
$this->_em->flush();
$this->assertFalse($user2->groups->isInitialized());
$this->assertEquals(0, $this->_em->getConnection()->fetchColumn("select count(*) from cms_users_groups"));
}
public function testGetPartialReferenceToUpdateObjectWithoutLoadingIt()
{
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);

View File

@@ -410,4 +410,29 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
$this->assertType('Doctrine\ORM\Proxy\Proxy', $ref, "A proxy can be generated only if no subclasses exists for the requested reference.");
}
/**
* @group DDC-992
*/
public function testGetSubClassManyToManyCollection()
{
$manager = new CompanyManager();
$manager->setName('gblanco');
$manager->setSalary(1234);
$manager->setTitle('Awesome!');
$manager->setDepartment('IT');
$person = new CompanyPerson();
$person->setName('friend');
$manager->addFriend($person);
$this->_em->persist($manager);
$this->_em->persist($person);
$this->_em->flush();
$this->_em->clear();
$manager = $this->_em->find('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
$this->assertEquals(1, count($manager->getFriends()));
}
}

View File

@@ -104,9 +104,42 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertArrayHasKey('user', $metadatas['CmsGroups']->associationMappings);
}
public function testIgnoreManyToManyTableWithoutFurtherForeignKeyDetails()
{
$tableB = new \Doctrine\DBAL\Schema\Table("dbdriver_bar");
$tableB->addColumn('id', 'integer');
$tableB->setPrimaryKey(array('id'));
$tableA = new \Doctrine\DBAL\Schema\Table("dbdriver_baz");
$tableA->addColumn('id', 'integer');
$tableA->setPrimaryKey(array('id'));
$tableMany = new \Doctrine\DBAL\Schema\Table("dbdriver_bar_baz");
$tableMany->addColumn('bar_id', 'integer');
$tableMany->addColumn('baz_id', 'integer');
$tableMany->addForeignKeyConstraint('dbdriver_bar', array('bar_id'), array('id'));
$metadatas = $this->convertToClassMetadata(array($tableA, $tableB), array($tableMany));
$this->assertEquals(0, count($metadatas['DbdriverBaz']->associationMappings), "no association mappings should be detected.");
}
protected function convertToClassMetadata(array $entityTables, array $manyTables = array())
{
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_sm);
$driver->setTables($entityTables, $manyTables);
$metadatas = array();
foreach ($driver->getAllClassNames() AS $className) {
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
return $metadatas;
}
/**
*
* @param string $className
* @return ClassMetadata
*/

View File

@@ -290,5 +290,17 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertType('Doctrine\Tests\Models\CMS\CmsAddress', $address);
$this->assertEquals($addressId, $address->id);
}
/**
* @group DDC-1087
*/
public function testIsNullCriteria()
{
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$users = $repos->findBy(array('status' => null, 'username' => 'romanb'));
$params = $this->_sqlLoggerStack->queries[$this->_sqlLoggerStack->currentQuery]['params'];
$this->assertEquals(1, count($params), "Should only execute with one parameter.");
$this->assertEquals(array('romanb'), $params);
}
}

View File

@@ -342,4 +342,39 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa
$this->assertEquals('Developers_New1', $user->groups[0]->name);
$this->assertEquals('Developers_New2', $user->groups[1]->name);
}
/**
* @group DDC-733
*/
public function testInitializePersistentCollection()
{
$user = $this->addCmsUserGblancoWithGroups(2);
$this->_em->clear();
$user = $this->_em->find(get_class($user), $user->id);
$this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
$this->_em->getUnitOfWork()->initializeObject($user->groups);
$this->assertTrue($user->groups->isInitialized(), "Collection should be initialized after calling UnitOfWork::initializeObject()");
}
/**
* @group DDC-1189
* @group DDC-956
*/
public function testClearBeforeLazyLoad()
{
$user = $this->addCmsUserGblancoWithGroups(4);
$this->_em->clear();
$user = $this->_em->find(get_class($user), $user->id);
$user->groups->clear();
$this->assertEquals(0, count($user->groups));
$this->_em->flush();
$user = $this->_em->find(get_class($user), $user->id);
$this->assertEquals(0, count($user->groups));
}
}

View File

@@ -4,6 +4,8 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\CMS\CmsUser,
Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
require_once __DIR__ . '/../../TestInit.php';
@@ -135,6 +137,39 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$users = $q->getResult();
}
/**
* @group DDC-1070
*/
public function testIterateResultAsArrayAndParams()
{
$article1 = new CmsArticle;
$article1->topic = "Doctrine 2";
$article1->text = "This is an introduction to Doctrine 2.";
$article2 = new CmsArticle;
$article2->topic = "Symfony 2";
$article2->text = "This is an introduction to Symfony 2.";
$this->_em->persist($article1);
$this->_em->persist($article2);
$this->_em->flush();
$this->_em->clear();
$articleId = $article1->id;
$query = $this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1");
$articles = $query->iterate(array(1 => 'Doctrine 2'), Query::HYDRATE_ARRAY);
$found = array();
foreach ($articles AS $article) {
$found[] = $article;
}
$this->assertEquals(1, count($found));
$this->assertEquals(array(
array(array('id' => $articleId, 'topic' => 'Doctrine 2', 'text' => 'This is an introduction to Doctrine 2.', 'version' => 1))
), $found);
}
public function testIterateResult_IterativelyBuildUpUnitOfWork()
{
$article1 = new CmsArticle;

View File

@@ -97,4 +97,54 @@ class ReferenceProxyTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertTrue($clone->isCloned);
$this->assertFalse($entity->isCloned);
}
/**
* @group DDC-733
*/
public function testInitializeProxy()
{
$id = $this->createProduct();
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$this->assertFalse($entity->__isInitialized__, "Pre-Condition: Object is unitialized proxy.");
$this->_em->getUnitOfWork()->initializeObject($entity);
$this->assertTrue($entity->__isInitialized__, "Should be initialized after called UnitOfWork::initializeObject()");
}
/**
* @group DDC-1163
*/
public function testInitializeChangeAndFlushProxy()
{
$id = $this->createProduct();
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$entity->setName('Doctrine 2 Cookbook');
$this->_em->flush();
$this->_em->clear();
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$this->assertEquals('Doctrine 2 Cookbook', $entity->getName());
}
/**
* @group DDC-1022
*/
public function testWakeupCalledOnProxy()
{
$id = $this->createProduct();
/* @var $entity Doctrine\Tests\Models\ECommerce\ECommerceProduct */
$entity = $this->_em->getReference('Doctrine\Tests\Models\ECommerce\ECommerceProduct' , $id);
$this->assertFalse($entity->wakeUp);
$entity->setName('Doctrine 2 Cookbook');
$this->assertTrue($entity->wakeUp, "Loading the proxy should call __wakeup().");
}
}

View File

@@ -50,4 +50,19 @@ class CompanySchemaTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertFalse($table->getColumn('pricePerHour')->getNotnull());
$this->assertFalse($table->getColumn('maxPrice')->getNotnull());
}
/**
* @group DBAL-115
*/
public function testDropPartSchemaWithForeignKeys()
{
if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$this->markTestSkipped("Foreign Key test");
}
$sql = $this->_schemaTool->getDropSchemaSQL(array(
$this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyManager'),
));
$this->assertEquals(3, count($sql));
}
}

View File

@@ -80,4 +80,25 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals("CREATE TABLE boolean_model (id INT NOT NULL, booleanField BOOLEAN NOT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("CREATE SEQUENCE boolean_model_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[1]);
}
public function testGetDropSchemaSql()
{
$classes = array(
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'),
);
$tool = new SchemaTool($this->_em);
$sql = $tool->getDropSchemaSQL($classes);
$this->assertEquals(13, count($sql));
$dropSequenceSQLs = 0;
foreach ($sql AS $stmt) {
if (strpos($stmt, "DROP SEQUENCE") === 0) {
$dropSequenceSQLs++;
}
}
$this->assertEquals(4, $dropSequenceSQLs, "Expect 4 sequences to be dropped.");
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsUser;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1040
*/
class DDC1040Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testReuseNamedEntityParameter()
{
$user = new CmsUser();
$user->name = "John Galt";
$user->username = "jgalt";
$user->status = "inactive";
$article = new CmsArticle();
$article->topic = "This is John Galt speaking!";
$article->text = "Yadda Yadda!";
$article->setAuthor($user);
$this->_em->persist($user);
$this->_em->persist($article);
$this->_em->flush();
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.user = :author";
$this->_em->createQuery($dql)
->setParameter('author', $user)
->getResult();
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.user = :author AND a.user = :author";
$this->_em->createQuery($dql)
->setParameter('author', $user)
->getResult();
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = :topic AND a.user = :author AND a.user = :author AND a.text = :text";
$farticle = $this->_em->createQuery($dql)
->setParameter('author', $user)
->setParameter('topic', 'This is John Galt speaking!')
->setParameter('text', 'Yadda Yadda!')
->getSingleResult();
$this->assertSame($article, $farticle);
}
public function testUseMultiplePositionalParameters()
{
$user = new CmsUser();
$user->name = "John Galt";
$user->username = "jgalt";
$user->status = "inactive";
$article = new CmsArticle();
$article->topic = "This is John Galt speaking!";
$article->text = "Yadda Yadda!";
$article->setAuthor($user);
$this->_em->persist($user);
$this->_em->persist($article);
$this->_em->flush();
$dql = "SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.topic = ?1 AND a.user = ?2 AND a.user = ?3 AND a.text = ?4";
$farticle = $this->_em->createQuery($dql)
->setParameter(1, 'This is John Galt speaking!')
->setParameter(2, $user)
->setParameter(3, $user)
->setParameter(4, 'Yadda Yadda!')
->getSingleResult();
$this->assertSame($article, $farticle);
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1129
*/
class DDC1129Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testVersionFieldIgnoredInChangesetComputation()
{
$article = new \Doctrine\Tests\Models\CMS\CmsArticle();
$article->text = "I don't know.";
$article->topic = "Who is John Galt?";
$this->_em->persist($article);
$this->_em->flush();
$this->assertEquals(1, $article->version);
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsArticle');
$uow = $this->_em->getUnitOfWork();
$uow->computeChangeSet($class, $article);
$changeSet = $uow->getEntityChangeSet($article);
$this->assertEquals(0, count($changeSet), "No changesets should be computed.");
$article->text = "This is John Galt speaking.";
$this->_em->flush();
$this->assertEquals(2, $article->version);
$uow->computeChangeSet($class, $article);
$changeSet = $uow->getEntityChangeSet($article);
$this->assertEquals(0, count($changeSet), "No changesets should be computed.");
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1151
*/
class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function testQuoteForeignKey()
{
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != 'postgresql') {
$this->markTestSkipped("This test is useful for all databases, but designed only for postgresql.");
}
$sql = $this->_schemaTool->getCreateSchemaSql(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151User'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151Group'),
));
$this->assertEquals("CREATE TABLE \"User\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("CREATE TABLE ddc1151user_ddc1151group (ddc1151user_id INT NOT NULL, ddc1151group_id INT NOT NULL, PRIMARY KEY(ddc1151user_id, ddc1151group_id))", $sql[1]);
$this->assertEquals("CREATE INDEX IDX_88A3259AC5AD08A ON ddc1151user_ddc1151group (ddc1151user_id)", $sql[2]);
$this->assertEquals("CREATE INDEX IDX_88A32597357E0B1 ON ddc1151user_ddc1151group (ddc1151group_id)", $sql[3]);
$this->assertEquals("CREATE TABLE \"Group\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[4]);
$this->assertEquals("CREATE SEQUENCE User_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[5]);
$this->assertEquals("CREATE SEQUENCE Group_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[6]);
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151user_id) REFERENCES \"User\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
}
}
/**
* @Entity
* @Table(name="`User`")
*/
class DDC1151User
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @ManyToMany(targetEntity="DDC1151Group") */
public $groups;
}
/**
* @Entity
* @Table(name="`Group`")
*/
class DDC1151Group
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}

View File

@@ -0,0 +1,215 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1163
*/
class DDC1163Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163Product'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163SpecialProduct'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163ProxyHolder'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1163Tag'),
));
}
public function testIssue()
{
$this->createSpecialProductAndProxyHolderReferencingIt();
$this->_em->clear();
$this->createProxyForSpecialProduct();
$this->setPropertyAndAssignTagToSpecialProduct();
// fails
$this->_em->flush();
}
private function createSpecialProductAndProxyHolderReferencingIt()
{
$specialProduct = new DDC1163SpecialProduct();
$this->_em->persist($specialProduct);
$proxyHolder = new DDC1163ProxyHolder();
$this->_em->persist($proxyHolder);
$proxyHolder->setSpecialProduct($specialProduct);
$this->_em->flush();
$this->productId = $specialProduct->getId();
$this->proxyHolderId = $proxyHolder->getId();
}
/**
* We want Doctrine to instantiate a lazy-load proxy for the previously created
* 'SpecialProduct' and register it.
*
* When Doctrine loads the 'ProxyHolder', it will do just that because the 'ProxyHolder'
* references the 'SpecialProduct'.
*/
private function createProxyForSpecialProduct()
{
/* @var $proxyHolder ProxyHolder */
$proxyHolder = $this->_em->find(__NAMESPACE__ . '\\DDC1163ProxyHolder', $this->proxyHolderId);
$this->assertInstanceOf(__NAMESPACE__.'\\DDC1163SpecialProduct', $proxyHolder->getSpecialProduct());
}
private function setPropertyAndAssignTagToSpecialProduct()
{
/* @var $specialProduct SpecialProduct */
$specialProduct = $this->_em->find(__NAMESPACE__ . '\\DDC1163SpecialProduct', $this->productId);
$this->assertInstanceOf(__NAMESPACE__.'\\DDC1163SpecialProduct', $specialProduct);
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $specialProduct);
$specialProduct->setSubclassProperty('foobar');
// this screams violation of law of demeter ;)
$this->assertEquals(
__NAMESPACE__.'\\DDC1163SpecialProduct',
$this->_em->getUnitOfWork()->getEntityPersister(get_class($specialProduct))->getClassMetadata()->name
);
$tag = new DDC1163Tag('Foo');
$this->_em->persist($tag);
$tag->setProduct($specialProduct);
}
}
/**
* @Entity
*/
class DDC1163ProxyHolder
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var SpecialProduct
* @OneToOne(targetEntity="DDC1163SpecialProduct")
*/
private $specialProduct;
public function getId()
{
return $this->id;
}
public function setSpecialProduct(DDC1163SpecialProduct $specialProduct)
{
$this->specialProduct = $specialProduct;
}
public function getSpecialProduct()
{
return $this->specialProduct;
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"special" = "DDC1163SpecialProduct"})
*/
abstract class DDC1163Product
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
public function getId()
{
return $this->id;
}
}
/**
* @Entity
*/
class DDC1163SpecialProduct extends DDC1163Product
{
/**
* @var string
* @Column(name="subclass_property", type="string", nullable=true)
*/
private $subclassProperty;
/**
* @param string $value
*/
public function setSubclassProperty($value)
{
$this->subclassProperty = $value;
}
}
/**
* @Entity
*/
class DDC1163Tag
{
/**
* @var int
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
* @Column(name="name", type="string")
*/
private $name;
/**
* @var Product
* @ManyToOne(targetEntity="DDC1163Product", inversedBy="tags")
* @JoinColumns({
* @JoinColumn(name="product_id", referencedColumnName="id")
* })
*/
private $product;
/**
* @param string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* @param Product $product
*/
public function setProduct(DDC1163Product $product)
{
$this->product = $product;
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
use DateTime, Doctrine\DBAL\Types\Type;
class DDC1193Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Company'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Person'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1193Account')
));
}
/**
* @group DDC-1193
*/
public function testIssue()
{
$company = new DDC1193Company();
$person = new DDC1193Person();
$account = new DDC1193Account();
$person->account = $account;
$person->company = $company;
$company->member = $person;
$this->_em->persist($company);
$this->_em->flush();
$companyId = $company->id;
$accountId = $account->id;
$this->_em->clear();
$company = $this->_em->find(get_class($company), $companyId);
$this->assertTrue($this->_em->getUnitOfWork()->isInIdentityMap($company), "Company is in identity map.");
$this->assertFalse($company->member->__isInitialized__, "Pre-Condition");
$this->assertTrue($this->_em->getUnitOfWork()->isInIdentityMap($company->member), "Member is in identity map.");
$this->_em->remove($company);
$this->_em->flush();
$this->assertEquals(count($this->_em->getRepository(get_class($account))->findAll()), 0);
}
}
/** @Entity */
class DDC1193Company {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/** @OneToOne(targetEntity="DDC1193Person", cascade={"persist", "remove"}) */
public $member;
}
/** @Entity */
class DDC1193Person {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @OneToOne(targetEntity="DDC1193Account", cascade={"persist", "remove"})
*/
public $account;
}
/** @Entity */
class DDC1193Account {
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsGroup;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1276
*/
class DDC1276Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testIssue()
{
$user = new CmsUser();
$user->name = "Benjamin";
$user->username = "beberlei";
$user->status = "active";
$this->_em->persist($user);
for ($i = 0; $i < 2; $i++) {
$group = new CmsGroup();
$group->name = "group".$i;
$user->groups[] = $group;
$this->_em->persist($group);
}
$this->_em->flush();
$this->_em->clear();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->id);
$cloned = clone $user;
$this->assertSame($user->groups, $cloned->groups);
$this->assertEquals(2, count($user->groups));
$this->_em->merge($cloned);
$this->assertEquals(2, count($user->groups));
$this->_em->flush();
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-992
*/
class DDC992Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Role'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Parent'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC992Child'),
));
} catch(\Exception $e) {
}
}
public function testIssue()
{
$role = new DDC992Role();
$role->name = "Parent";
$child = new DDC992Role();
$child->name = "child";
$role->extendedBy[] = $child;
$child->extends[] = $role;
$this->_em->persist($role);
$this->_em->persist($child);
$this->_em->flush();
$this->_em->clear();
$child = $this->_em->getRepository(get_class($role))->find($child->roleID);
$parents = count($child->extends);
$this->assertEquals(1, $parents);
foreach ($child->extends AS $parent) {
$this->assertEquals($role->getRoleID(), $parent->getRoleID());
}
}
public function testOneToManyChild()
{
$parent = new DDC992Parent();
$child = new DDC992Child();
$child->parent = $parent;
$parent->childs[] = $child;
$this->_em->persist($parent);
$this->_em->persist($child);
$this->_em->flush();
$this->_em->clear();
$parentRepository = $this->_em->getRepository(get_class($parent));
$childRepository = $this->_em->getRepository(get_class($child));
$parent = $parentRepository->find($parent->id);
$this->assertEquals(1, count($parent->childs));
$this->assertEquals(0, count($parent->childs[0]->childs()));
$child = $parentRepository->findOneBy(array("id" => $child->id));
$this->assertSame($parent->childs[0], $child);
$this->_em->clear();
$child = $parentRepository->find($child->id);
$this->assertEquals(0, count($child->childs));
$this->_em->clear();
$child = $childRepository->find($child->id);
$this->assertEquals(0, count($child->childs));
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorMap({"child" = "DDC992Child", "parent" = "DDC992Parent"})
*/
class DDC992Parent
{
/** @Id @GeneratedValue @Column(type="integer") */
public $id;
/** @ManyToOne(targetEntity="DDC992Parent", inversedBy="childs") */
public $parent;
/** @OneToMany(targetEntity="DDC992Child", mappedBy="parent") */
public $childs;
}
/**
* @Entity
*/
class DDC992Child extends DDC992Parent
{
public function childs()
{
return $this->childs;
}
}
/**
* @Entity
*/
class DDC992Role
{
public function getRoleID()
{
return $this->roleID;
}
/**
* @Id @Column(name="roleID", type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $roleID;
/**
* @Column (name="name", type="string", length="45")
*/
public $name;
/**
* @ManyToMany (targetEntity="DDC992Role", mappedBy="extends")
*/
public $extendedBy;
/**
* @ManyToMany (targetEntity="DDC992Role", inversedBy="extendedBy")
* @JoinTable (name="RoleRelations",
* joinColumns={@JoinColumn(name="roleID", referencedColumnName="roleID")},
* inverseJoinColumns={@JoinColumn(name="extendsRoleID", referencedColumnName="roleID")}
* )
*/
public $extends;
public function __construct() {
$this->extends = new ArrayCollection;
$this->extendedBy = new ArrayCollection;
}
}

View File

@@ -186,6 +186,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
$this->assertTrue($class->associationMappings['phonenumbers']['orphanRemoval']);
// Test Order By
$this->assertEquals(array('number' => 'ASC'), $class->associationMappings['phonenumbers']['orderBy']);
@@ -329,7 +330,7 @@ class User
public $address;
/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist"})
* @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
* @OrderBy({"number"="ASC"})
*/
public $phonenumbers;
@@ -425,7 +426,7 @@ class User
1 => 'persist',
),
'mappedBy' => 'user',
'orphanRemoval' => false,
'orphanRemoval' => true,
'orderBy' =>
array(
'number' => 'ASC',

View File

@@ -232,6 +232,17 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException');
$cm->mapField(array('fieldName' => 'name', 'columnName' => 'name'));
}
/**
* @group DDC-1224
*/
public function testGetTemporaryTableNameSchema()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->setTableName('foo.bar');
$this->assertEquals('foo_bar_id_tmp', $cm->getTemporaryIdTableName());
}
public function testDefaultTableName()
{

View File

@@ -60,7 +60,7 @@ $metadata->mapOneToMany(array(
1 => 'persist',
),
'mappedBy' => 'user',
'orphanRemoval' => false,
'orphanRemoval' => true,
'orderBy' =>
array(
'number' => 'ASC',

View File

@@ -35,7 +35,7 @@
<join-column name="address_id" referenced-column-name="id" on-delete="CASCADE" on-update="CASCADE"/>
</one-to-one>
<one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user">
<one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user" orphan-removal="true">
<cascade>
<cascade-persist/>
</cascade>

View File

@@ -33,6 +33,7 @@ Doctrine\Tests\ORM\Mapping\User:
oneToMany:
phonenumbers:
targetEntity: Phonenumber
orphanRemoval: true
mappedBy: user
orderBy:
number: ASC

View File

@@ -0,0 +1,63 @@
<?php
namespace Doctrine\Tests\ORM\Performance;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Query;
require_once __DIR__ . '/../../TestInit.php';
class InheritancePersisterPerformanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('company');
parent::setUp();
}
public function testCompanyContract()
{
$person = new \Doctrine\Tests\Models\Company\CompanyEmployee();
$person->setName('Poor Sales Guy');
$person->setDepartment('Sales');
$person->setSalary(100);
$this->_em->persist($person);
for ($i = 0; $i < 33; $i++) {
$fix = new \Doctrine\Tests\Models\Company\CompanyFixContract();
$fix->setFixPrice(1000);
$fix->setSalesPerson($person);
$fix->markCompleted();
$this->_em->persist($fix);
$flex = new \Doctrine\Tests\Models\Company\CompanyFlexContract();
$flex->setSalesPerson($person);
$flex->setHoursWorked(100);
$flex->setPricePerHour(100);
$flex->markCompleted();
$this->_em->persist($flex);
$ultra = new \Doctrine\Tests\Models\Company\CompanyFlexUltraContract();
$ultra->setSalesPerson($person);
$ultra->setHoursWorked(150);
$ultra->setPricePerHour(150);
$ultra->setMaxPrice(7000);
$this->_em->persist($ultra);
}
$this->_em->flush();
$this->_em->clear();
$start = microtime(true);
$contracts = $this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyContract')->findAll();
echo "99 CompanyContract: " . number_format(microtime(true) - $start, 6) . "\n";
$this->assertEquals(99, count($contracts));
$this->_em->clear();
$start = microtime(true);
$contracts = $this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyContract')->findAll();
echo "99 CompanyContract: " . number_format(microtime(true) - $start, 6) . "\n";
$this->assertEquals(99, count($contracts));
}
}

View File

@@ -0,0 +1,118 @@
<?php
namespace Doctrine\Tests\ORM\Performance;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Query;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsComment;
require_once __DIR__ . '/../../TestInit.php';
class PersisterPerformanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testFindCmsArticle()
{
$author = new CmsUser();
$author->name = "beberlei";
$author->status = "active";
$author->username = "beberlei";
$this->_em->persist($author);
$ids = array();
for ($i = 0; $i < 100; $i++) {
$article = new CmsArticle();
$article->text = "foo";
$article->topic = "bar";
$article->user = $author;
$this->_em->persist($article);
$ids[] = $article;
}
$this->_em->flush();
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsArticle')->findAll();
echo "100 CmsArticle findAll(): " . number_format(microtime(true) - $start, 6) . "\n";
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsArticle')->findAll();
echo "100 CmsArticle findAll(): " . number_format(microtime(true) - $start, 6) . "\n";
$this->_em->clear();
$start = microtime(true);
for ($i = 0; $i < 100; $i++) {
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsArticle')->find($ids[$i]->id);
}
echo "100 CmsArticle find(): " . number_format(microtime(true) - $start, 6) . "\n";
$this->_em->clear();
$start = microtime(true);
for ($i = 0; $i < 100; $i++) {
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsArticle')->find($ids[$i]->id);
}
echo "100 CmsArticle find(): " . number_format(microtime(true) - $start, 6) . "\n";
}
public function testFindCmsGroup()
{
for ($i = 0; $i < 100; $i++) {
$group = new CmsGroup();
$group->name = "foo" . $i;
$this->_em->persist($group);
}
$this->_em->flush();
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsGroup')->findAll();
echo "100 CmsGroup: " . number_format(microtime(true) - $start, 6) . "\n";
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsGroup')->findAll();
echo "100 CmsGroup: " . number_format(microtime(true) - $start, 6) . "\n";
}
public function testFindCmsUser()
{
for ($i = 0; $i < 100; $i++) {
$user = new CmsUser();
$user->name = "beberlei";
$user->status = "active";
$user->username = "beberlei".$i;
$this->_em->persist($user);
}
$this->_em->flush();
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findAll();
echo "100 CmsUser: " . number_format(microtime(true) - $start, 6) . "\n";
$this->_em->clear();
$start = microtime(true);
$articles = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser')->findAll();
echo "100 CmsUser: " . number_format(microtime(true) - $start, 6) . "\n";
}
}

View File

@@ -251,6 +251,23 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidDQL("SELECT (SELECT (SUM(u.id) / COUNT(u.id)) FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
}
/**
* @group DDC-1079
*/
public function testSelectLiteralInSubselect()
{
$this->assertValidDQL('SELECT (SELECT 1 FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u');
$this->assertValidDQL('SELECT (SELECT 0 FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u');
}
/**
* @group DDC-1077
*/
public function testConstantValueInSelect()
{
$this->assertValidDQL("SELECT u.name, 'foo' AS bar FROM Doctrine\Tests\Models\CMS\CmsUser u", true);
}
public function testDuplicateAliasInSubselectPart()
{
$this->assertInvalidDQL("SELECT (SELECT SUM(u.id) / COUNT(u.id) AS foo FROM Doctrine\Tests\Models\CMS\CmsUser u2) foo FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
@@ -465,6 +482,16 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidDQL('SELECT u, u.id + ?1 AS someNumber FROM Doctrine\Tests\Models\CMS\CmsUser u');
}
/**
* @group DDC-1091
*/
public function testCustomFunctionsReturningStringInStringPrimary()
{
$this->_em->getConfiguration()->addCustomStringFunction('CC', 'Doctrine\ORM\Query\AST\Functions\ConcatFunction');
$this->assertValidDQL("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CC('%', u.name) LIKE '%foo%'", true);
}
/**
* @group DDC-505
*/
@@ -495,6 +522,38 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertInvalidDQL('SELECT g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
}
/**
* @group DDC-1108
*/
public function testInputParameterSingleChar()
{
$this->assertValidDQL('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :q');
}
/**
* @group DDC-1053
*/
public function testGroupBy()
{
$this->assertValidDQL('SELECT g.id, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g.id');
}
/**
* @group DDC-1053
*/
public function testGroupByIdentificationVariable()
{
$this->assertValidDQL('SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g');
}
/**
* @group DDC-1053
*/
public function testGroupByUnknownIdentificationVariable()
{
$this->assertInvalidDQL('SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY m');
}
}
/** @Entity */

View File

@@ -42,7 +42,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free();
} catch (\Exception $e) {
$this->fail($e->getMessage());
$this->fail($e->getMessage() ."\n".$e->getTraceAsString());
}
}
@@ -170,6 +170,17 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}*/
/**
* @group DDC-1077
*/
public function testConstantValueInSelect()
{
$this->assertSqlGeneration(
"SELECT u.name, 'foo' AS bar FROM Doctrine\Tests\Models\CMS\CmsUser u",
"SELECT c0_.name AS name0, 'foo' AS sclr1 FROM cms_users c0_"
);
}
public function testSupportsOrderByWithAscAsDefault()
{
$this->assertSqlGeneration(
@@ -851,6 +862,28 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
'SELECT f0_.id AS id0, f0_.extension AS extension1, f0_.name AS name2 FROM "file" f0_ INNER JOIN Directory d1_ ON f0_.parentDirectory_id = d1_.id WHERE f0_.id = ?'
);
}
/**
* @group DDC-1053
*/
public function testGroupBy()
{
$this->assertSqlGeneration(
'SELECT g.id, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g.id',
'SELECT c0_.id AS id0, count(c1_.id) AS sclr1 FROM cms_groups c0_ INNER JOIN cms_users_groups c2_ ON c0_.id = c2_.group_id INNER JOIN cms_users c1_ ON c1_.id = c2_.user_id GROUP BY c0_.id'
);
}
/**
* @group DDC-1053
*/
public function testGroupByIdentificationVariable()
{
$this->assertSqlGeneration(
'SELECT g, count(u.id) FROM Doctrine\Tests\Models\CMS\CmsGroup g JOIN g.users u GROUP BY g',
'SELECT c0_.id AS id0, c0_.name AS name1, count(c1_.id) AS sclr2 FROM cms_groups c0_ INNER JOIN cms_users_groups c2_ ON c0_.id = c2_.group_id INNER JOIN cms_users c1_ ON c1_.id = c2_.user_id GROUP BY c0_.id'
);
}
}

View File

@@ -589,4 +589,32 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(2, $expr->count(), "Modifying the second query should affect the first one.");
}
/**
* @group DDC-1211
*/
public function testEmptyStringLiteral()
{
$expr = $this->_em->getExpressionBuilder();
$qb = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where($expr->eq('u.username', $expr->literal("")));
$this->assertEquals("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = ''", $qb->getDQL());
}
/**
* @group DDC-1211
*/
public function testEmptyNumericLiteral()
{
$expr = $this->_em->getExpressionBuilder();
$qb = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where($expr->eq('u.username', $expr->literal(0)));
$this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 0', $qb->getDQL());
}
}

View File

@@ -122,7 +122,7 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
$this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/~EntityGeneratorBook.php");
$this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/EntityGeneratorBook.php~");
$book = $this->newInstance($metadata);
$reflClass = new \ReflectionClass($metadata->name);
@@ -200,6 +200,54 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($cm->idGenerator, $metadata->idGenerator);
$this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
}
/**
* @dataProvider getParseTokensInEntityFileData
*/
public function testParseTokensInEntityFile($php, $classes)
{
$r = new \ReflectionObject($this->_generator);
$m = $r->getMethod('_parseTokensInEntityFile');
$m->setAccessible(true);
$p = $r->getProperty('_staticReflection');
$p->setAccessible(true);
$ret = $m->invoke($this->_generator, $php);
$this->assertEquals($classes, array_keys($p->getValue($this->_generator)));
}
public function getParseTokensInEntityFileData()
{
return array(
array(
'<?php namespace Foo\Bar; class Baz {}',
array('Foo\Bar\Baz'),
),
array(
'<?php namespace Foo\Bar; use Foo; class Baz {}',
array('Foo\Bar\Baz'),
),
array(
'<?php namespace /*Comment*/ Foo\Bar; /** Foo */class /* Comment */ Baz {}',
array('Foo\Bar\Baz'),
),
array(
'
<?php namespace
/*Comment*/
Foo\Bar
;
/** Foo */
class
/* Comment */
Baz {}
',
array('Foo\Bar\Baz'),
),
);
}
}
class EntityGeneratorAuthor {}