Compare commits

...

219 Commits
3.0.1 ... 2.3.4

Author SHA1 Message Date
Benjamin Eberlei
a41b02c080 Release 2.3.4 2013-05-11 09:51:12 +02:00
Benjamin Eberlei
8b3c206bc1 Bump dependency to 2.3.4 2013-05-11 09:47:19 +02:00
Benjamin Eberlei
e0feccc2e4 Merge branch 'DDC-2280' into 2.3 2013-05-09 18:17:03 +02:00
Benjamin Eberlei
818d3d27fe [DDC-2280] length attribute in <id> was not converted. 2013-05-09 18:16:55 +02:00
Benjamin Eberlei
98d3847a11 Merge branch 'DDC-2387' into 2.3 2013-05-09 12:11:23 +02:00
Benjamin Eberlei
63918f214b [DDC-2387] Fix DatabaseDriver not working with combinations of composite/association keys. 2013-05-09 12:11:04 +02:00
Benjamin Eberlei
acf21246c7 Merge branch 'DDC-2437' into 2.3 2013-05-09 11:04:14 +02:00
Vladislav Vlastovskiy
795e4a4b6b Added test complex inner join with indexBy 2013-05-09 11:03:36 +02:00
Vladislav Vlastovskiy
946a22f2c7 Swapped places indexBy and condition in accordance with EBNF 2013-05-09 11:03:36 +02:00
Benjamin Eberlei
bdd7482b3f Merge branch 'DDC-2423' into 2.3 2013-05-09 10:56:00 +02:00
Benjamin Eberlei
8e31107f86 [DDC-2423] Fixed bug with EntityGenerator not generating fetch="" attribute in association annotations. 2013-05-09 10:55:42 +02:00
Benjamin Eberlei
209090d338 Merge branch 'DDC-2267' into 2.3 2013-05-04 13:39:37 +02:00
Benjamin Eberlei
27117bbc98 [DDC-2267] Allow EntityManager#flush($entity) to be called on entities scheduled for removal. 2013-05-04 13:39:23 +02:00
Benjamin Eberlei
0f2be50d8f [DDC-2426] Missing length attribute in doctrine-mapping.xsd for <id> tag. 2013-05-04 12:59:02 +02:00
Benjamin Eberlei
193e74af05 Merge branch 'DDC-1984' into 2.3 2013-05-01 19:40:06 +02:00
Benjamin Eberlei
bb6e4f2074 [DDC-1984] Throw exception if passing null into UnitOfWork#lock() - which can happen when EntityManager#find() tries to lock entity that was just deleted by another process. 2013-05-01 19:39:48 +02:00
Benjamin Eberlei
6063fe4adf Merge branch 'DDC-2409' into 2.3 2013-05-01 11:01:17 +02:00
Benjamin Eberlei
846c6d2c5e Simplify condition of previous commit (5cdc73e) 2013-05-01 11:00:55 +02:00
Fabio B. Silva
1f257622a1 Fix DDC-2409 2013-05-01 11:00:55 +02:00
Benjamin Eberlei
84257c9454 Merge branch 'DBAL-483' into 2.3 2013-05-01 10:45:19 +02:00
Benjamin Eberlei
eedacc9822 [DBAL-483] Add sqlite check again as ALTER TABLE is only supported as of 2.4 2013-05-01 10:44:31 +02:00
Benjamin Eberlei
3d9099e33b [DBAL-483] Pass default values to DBAL mapping layer correctly to fix default comparision bug. 2013-05-01 10:42:53 +02:00
EuKov
ad7b5871bf Fixed typo in SQLFilter (use statement ClassMetadata) 2013-04-23 22:26:59 +02:00
Benjamin Eberlei
803f2740c9 [DDC-2346] Reapply changes lost in rebase onto 2.3 2013-04-14 09:52:39 +02:00
Stefan Kleff
ed3f375ef3 Added constant 2013-04-14 09:49:26 +02:00
Stefan Kleff
a188c88ef2 Added test based on e468ced00b 2013-04-14 09:48:09 +02:00
Benjamin Eberlei
86e40a692b Merge branch 'DDC-2252' into 2.3 2013-04-06 19:56:15 +02:00
Fabio B. Silva
36b79309bd Fix DDC-2252 2013-04-06 19:55:50 +02:00
Benjamin Eberlei
66b6b7169e Merge branch 'DDC-2224-2' into 2.3 2013-04-04 20:35:01 +02:00
Benjamin Eberlei
7c7a8abe40 [DDC-2224] Adjust ClassMetadata processing 2013-04-04 20:34:49 +02:00
Benjamin Eberlei
e5c68ab45c [DDC-2224] Rewrite instanceof feature with parameter needle ClassMetadata breaks caching of queries. 2013-04-04 20:32:04 +02:00
Benjamin Eberlei
868bb68cc8 Bump dev version to 2.3.4 2013-03-24 21:43:58 +01:00
Benjamin Eberlei
b3788c14ee Release 2.3.3 2013-03-24 21:43:58 +01:00
Benjamin Eberlei
3148d8aeac Bump Dbal Dependency to 2.3.3 2013-03-24 20:21:32 +01:00
Benjamin Eberlei
ae1f903080 Merge branch 'DDC-2090' into 2.3 2013-03-17 21:49:24 +01:00
Fabio B. Silva
07482bd624 Fix DDC-2090 2013-03-17 21:48:55 +01:00
Benjamin Eberlei
8d78b90bca Merge branch 'DDC-1666' into 2.3 2013-03-14 23:42:28 +01:00
Benjamin Eberlei
ca93400493 [DDC-1666] Fix bug where orphan removal on one-to-one associations lead to unique constraint errors when replacing an entity with a new one. 2013-03-14 23:42:04 +01:00
Benjamin Eberlei
7152e5f72f Merge branch 'DDC-2300' into 2.3 2013-03-14 23:22:01 +01:00
Benjamin Eberlei
279fcb6c81 [DDC-2300] Fix version xml mapping and serialization of ClassMetadata. 2013-03-14 23:20:46 +01:00
Benjamin Eberlei
7705105c5d Merge branch 'GH-593' into 2.3 2013-03-14 22:59:42 +01:00
Norbert Orzechowicz
cb70a8a8c4 Fix SimpleObjectHydrator behavior when column not exists in fieldMappings, relationMappings and metaMappings 2013-03-14 22:59:20 +01:00
Benjamin Eberlei
8a2d7374b1 Fix bugs in tests 2013-03-14 20:08:37 +01:00
Benjamin Eberlei
563fdb953b Merge branch 'DDC-2340' into 2.3 2013-03-12 22:53:10 +01:00
Benjamin Eberlei
3daf824c9e [DDC-2340] Fix bug with dirty collection matching + ordering. 2013-03-12 22:52:52 +01:00
Jean-Guilhem Rouel
aa4664687f Don't add empty expression to another one 2013-03-12 19:18:07 +01:00
Benjamin Eberlei
550c1cf98c Merge branch 'GH-572' into 2.3 2013-03-12 19:06:02 +01:00
Norbert Orzechowicz
33799d094c [DDC-2282] Fix pagination problem with SQL Server.
ORDER BY removed from all count queries when on SQL Server
Fixed SQLServer ORDER BY problem in paginator CountOutputWalker
Added test to check query with ORDER BY and SQLServerPlatform
2013-03-12 19:05:28 +01:00
Benjamin Eberlei
304acf0a1a Merge branch 'DDC-2310' into 2.3 2013-02-21 19:03:42 +01:00
Benjamin Eberlei
84996e0601 [DDC-2310] Fix regression introduced in SQL Server lock handling. 2013-02-21 19:03:12 +01:00
Benjamin Eberlei
fdd0af34e6 Merge branch 'DDC-2243' into 2.3 2013-01-20 20:35:21 +01:00
Benjamin Eberlei
f0312edb94 [DDC-2243] Fix bug where a bigint identifier would be casted to an integer, causing inconsistency with the string handling. 2013-01-20 20:34:09 +01:00
Benjamin Eberlei
6d25c4e08a Merge remote-tracking branch 'origin/2.3' into 2.3 2013-01-20 20:12:44 +01:00
Benjamin Eberlei
d9f51eb2fa Merge branch 'DDC-2246' into 2.3 2013-01-20 20:12:35 +01:00
Benjamin Eberlei
88cebe1263 [DDC-2246] Fix bug with UnitOfWork#getEntityState() and entities with foreign identifier. 2013-01-20 20:11:40 +01:00
Benjamin Eberlei
6829c464e8 Merge branch 'DDC-2231' into 2.3 2013-01-12 10:32:44 +01:00
Benjamin Eberlei
fc2eebdf75 DDC-2231 - Simplify test 2013-01-12 10:32:24 +01:00
Stefan Kleff
54193e7f82 Added test 2013-01-12 10:32:24 +01:00
Stefan Kleff
8001cad573 fixed indentation
Restored old way of injection to just inject it during a refresh
Added injection for initialized proxies
2013-01-12 10:32:24 +01:00
Stefan Kleff
c4c70d667a The EntityManager was not injected in uninitialized proxys which are ObjectManagerAware.
I ran into that problem while I had two objects in the identitymap while hydrating a collection: one was new a "real" entity and the other one was an uninitialized proxy. For "real" entities the em is injected in line 2427, for new entities it is injected in 2436->2364, but for proxies this is missing. According to the comment "inject ObjectManager into just loaded proxies." the code in line 2427 should do this, but in fact it is just used if it is a "real" entity or an already initialized proxy. Moving the injection to outside of the condition in line 2411 (if the entity is an unitialized proxy) solves this.
2013-01-12 10:32:24 +01:00
Benjamin Eberlei
f5bb8be884 Bump dev version to 2.3.3 2013-01-07 21:05:04 +01:00
Benjamin Eberlei
c5725dd6bb Release 2.3.2 2013-01-07 21:05:04 +01:00
Benjamin Eberlei
b59cd047ff Bump submodule of DBAL to 2.3.2 2013-01-07 21:04:49 +01:00
Benjamin Eberlei
019094655b Merge branch 'DDC-2175' into 2.3 2012-12-24 11:18:12 +01:00
Benjamin Eberlei
88e817660c [DDC-2175] Fix bug in JoinedSubclassPersister 2012-12-24 11:14:18 +01:00
Benjamin Eberlei
aee75d8f25 Merge branch '2.3' of github.com:doctrine/doctrine2 into 2.3 2012-12-23 20:34:54 +01:00
Benjamin Eberlei
50132ddc18 Merge branch 'DDC-2206' into 2.3 2012-12-23 20:34:14 +01:00
Benjamin Eberlei
f05bcbc17c [DDC-2206] Fix Setup::registerAutoloadPEAR() to work with Symfony namespaces from top PEAR directory 2012-12-23 20:33:21 +01:00
Benjamin Eberlei
f94b6c07c7 Fix MySQL test 2012-12-22 21:50:42 +01:00
Benjamin Eberlei
b68c6b3d2d Merge branch 'DDC-1690' into 2.3 2012-12-22 12:46:06 +01:00
Patrick Schwisow
0425e8452d [DDC-1690] Added an empty line as requested. 2012-12-22 12:37:03 +01:00
Patrick Schwisow
c120700d89 [DDC-1690] Created unit test 2012-12-22 12:37:02 +01:00
Patrick Schwisow
22dc20c320 Fix DDC-1690
Added the lines suggested by the original reporter.
2012-12-22 12:37:02 +01:00
Benjamin Eberlei
6d89875306 Merge remote-tracking branch 'origin/2.3' into 2.3 2012-12-16 13:00:27 +01:00
Benjamin Eberlei
b666a62979 Merge branch 'DDC-2199' into 2.3 2012-12-16 12:58:46 +01:00
Benjamin Eberlei
f2f8c4f2dd DDC-2199 / DDC-2192 - Versioned fields didnt work in XML/YAML mapping 2012-12-16 12:58:17 +01:00
Benjamin Eberlei
59aef2ca95 Bump dev version to 2.3.2 2012-12-04 23:04:25 +01:00
Benjamin Eberlei
173b398b34 Release 2.3.1 2012-12-04 23:04:25 +01:00
Benjamin Eberlei
de22e726a4 Update DBAL dependency 2012-12-04 22:10:45 +01:00
Benjamin Eberlei
dab2b505a4 Merge branch 'DDC-2182' into 2.3 2012-12-04 21:59:56 +01:00
Francis Besset
0672688088 Passed column options to the join column 2012-12-04 21:58:58 +01:00
Francis Besset
660f89f745 Fixed trailing spaces on SchemaTool 2012-12-04 21:57:41 +01:00
Francis Besset
e0aa01ddb6 Fixed typo 2012-12-04 21:55:47 +01:00
Benjamin Eberlei
287b29aeaa Merge branch 'DDC-2156' into 2.3 2012-11-27 22:26:17 +01:00
Benjamin Eberlei
86132283f1 Clarify BC break in DDC-2156 2012-11-27 22:26:09 +01:00
Benjamin Eberlei
f75c3b517d Merge branch 'DDC-2172' into 2.3 2012-11-27 21:57:14 +01:00
Fabio B. Silva
6e7e4dd35a Fix CS 2012-11-27 21:56:32 +01:00
Fabio B. Silva
faedbfc09a refactoring tests 2012-11-27 21:56:32 +01:00
Fabio B. Silva
45269fe4f2 Fix DDC-2172 2012-11-27 21:56:32 +01:00
Benjamin Eberlei
a3fea32e0e Merge branch 'DDC-2074' into 2.3 2012-11-25 20:16:21 +01:00
Jan Kramer
c90ed73b33 [DDC-2074] Fixed bug regarding clearing PC's without owner
When calling clear on a PC that has no owner (e.g. because it was
cloned), it can't be deleted as there is no metadata available.
In these cases, it shouldn't be scheduled for deletion.
2012-11-25 20:15:57 +01:00
Jan Kramer
83943e86a2 [DDC-2074] Added test for PersistentCollection#clear. 2012-11-25 20:15:57 +01:00
Benjamin Eberlei
1aab5feb4a Merge branch 'DDC-2158' into 2.3 2012-11-25 12:34:47 +01:00
Francisco Facioni
469bd02b41 added outer left join 2012-11-25 12:28:38 +01:00
Francisco Facioni
24f74bc935 regression fix for left joins (double ON) 2012-11-25 12:28:38 +01:00
Benjamin Eberlei
77d060ab74 Merge branch 'DDC-2109' into 2.3 2012-11-12 15:49:41 +01:00
Benjamin Eberlei
01148e52f3 [DDC-2109] Fix bug with ResolveTargetEntityListener and ManyToMany associations. 2012-11-12 15:49:31 +01:00
Benjamin Eberlei
5756021571 Merge branch 'DDC-1958' into 2.3 2012-11-12 15:42:38 +01:00
Miha Vrhovnik
006d3833f6 extracted pgsql sql generation into a helper method 2012-11-12 15:04:15 +01:00
Miha Vrhovnik
8865a5b90d The distinct query should replicate the fields in order by clause and the order by clause itself from inner query
This fixes DDC-1958
2012-11-12 15:04:15 +01:00
Benjamin Eberlei
d0698754b2 Merge branch 'DDC-2071' into 2.3 2012-11-12 12:32:57 +01:00
HarmenM
4ea7a5dde4 Modified the WhereInWalkerTest to be compatible with a single InputParameter. 2012-11-12 12:30:48 +01:00
HarmenM
ed11e61812 Update lib/Doctrine/ORM/Tools/Pagination/Paginator.php
Replaced the foreach loop adding all IDs as single parameters with a single parameter which injects the IDs as an array.
2012-11-12 12:30:48 +01:00
HarmenM
e7e69daabe Update lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php
replaced the for-loop which adds the InputParameters for a single InputParameter for use with an array instead of a set of scalars.
2012-11-12 12:30:47 +01:00
Benjamin Eberlei
c6eb04de14 Merge branch 'DDC-2079' into 2.3 2012-11-09 22:16:44 +01:00
Fabio B. Silva
8c2009c67e Fix typo 2012-11-09 22:15:41 +01:00
Fabio B. Silva
a7ed9e638b Fix DDC-2079 2012-11-09 22:15:41 +01:00
Benjamin Eberlei
643ed0b8f5 Merge branch 'DDC-2069' into 2.3 2012-11-09 22:12:08 +01:00
Fabio B. Silva
57db88b62a Fix DDC-2069 2012-11-09 22:11:27 +01:00
Benjamin Eberlei
3c944b34ca Merge branch 'DDC-2086' into 2.3 2012-11-09 22:09:53 +01:00
Jasper N. Brouwer
1618a3e393 Added testcase for DDC-2086 2012-11-09 22:09:10 +01:00
Jasper N. Brouwer
a1094d352c Prevented "Undefined index" notice when updating
While executing updates on an entity scheduled for update without
a change-set, an "Undefined index" notice is raised.
2012-11-09 22:09:10 +01:00
Benjamin Eberlei
e4ef9e03ae Merge branch 'DDC-2082' into 2.3 2012-11-09 22:02:00 +01:00
justin.randell
a3c98b1087 check for false as a return value from get_parent_class(), not null 2012-11-09 22:01:00 +01:00
Benjamin Eberlei
2ce877bf8a Merge branch 'DDC-2113' into 2.3 2012-11-09 21:56:56 +01:00
Vaughn Clayton
6d35fad70f [DDC-2113] Surround WHERE clause with parens if using SQLFilter 2012-11-09 21:56:12 +01:00
Benjamin Eberlei
612ed2b3a2 Merge branch 'DDC-2116' into 2.3 2012-11-09 21:54:19 +01:00
Markus Lanthaler
95a85d67ea Improve DocBlock annotations of generated entities
Currently, the DocBlock annotations for member variables contain the variable name as description which is redundant and should be removed. Furthermore the class is annotated with the FQN instead of just the name. This makes automatically generated documentation quite ugly.
2012-11-09 21:53:34 +01:00
Benjamin Eberlei
edaab11a86 Merge branch 'DDC-2115' into 2.3 2012-11-09 21:47:42 +01:00
TR
1627c974b9 Update lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
coding standards change
2012-11-09 21:47:01 +01:00
TR
c6118cb045 refactoring getIndividualValue for valid key value
refactoring getIndividualValue
2012-11-09 21:47:01 +01:00
TR
461d201e40 notice is thrown up if no identifier values found
wrapping the setting of value with an array_key_exists to prevent a notice from being thrown
2012-11-09 21:47:00 +01:00
Benjamin Eberlei
653aef2c83 Merge branch 'DDC-2122' into 2.3 2012-11-09 21:41:49 +01:00
Jeremy Marc
045d058cec Compare to null instead of using isset 2012-11-09 21:41:02 +01:00
Jeremy Marc
9dbf4d8480 Allow 0 id for Entity
When using a 0 id, it's throwing InvalidArgumentException (Binding entities to query parameters only allowed for entities that have an identifier.)
2012-11-09 21:41:02 +01:00
Benjamin Eberlei
2229a5e4c6 Merge branch 'DDC-2123' into 2.3 2012-11-09 21:33:51 +01:00
Gordon Stratton
bbf092c6fd Fix for invalid 'double-ON' SQL generation with entity inheritance type JOINED.
In SqlWalker::walkJoin(), SqlWalker::walkRangeVariableDeclaration() can be
called which may produce an 'ON' clause if the entity inheritance type is
JOINED. As walkJoin() may then produce another ON clause, this results in
invalid SQL (e.g. '... ON foo = bar ON (baz = quux) ...' when the inheritance
type is JOINED.

This adds a test and a fix for the problem, by checking for an inheritance type
of JOINED in walkJoin() and using AND instead of ON in the appropriate place.

It seems like this part of the code is begging to be refactored. This is my
first foray into Doctrine internals and can't see a way to do this without
stomping all over the rest of the code, but this section seems ripe for cleanup
by somebody who is familiar.
2012-11-09 21:32:52 +01:00
Benjamin Eberlei
6fee945fda Merge branch 'DDC-1241' into 2.3 2012-11-09 21:30:17 +01:00
nemekzg
974f18da0c Proposed fix for DDC-1241 2012-11-09 21:29:37 +01:00
Benjamin Eberlei
9b198be070 Merge branch 'DDC-2126' into 2.3 2012-11-09 21:03:42 +01:00
Benjamin Morel
b610855248 Fixed errors:
- Typo in variable name in JoinClassPathExpression;
 - Undefined class AST\ArithmeticPrimary (x2);
 - QueryException::invalidPathExpression() expects a PathExpression, not a string.
2012-11-09 21:02:55 +01:00
Benjamin Eberlei
994917aa23 Merge branch 'DDC-2121' into 2.3 2012-11-09 20:56:07 +01:00
Fabio B. Silva
d64be2888e Fix DDC-2121 2012-11-09 20:55:15 +01:00
Benjamin Eberlei
737e47e155 Merge branch 'DDC-2073' into 2.3 2012-11-09 20:45:35 +01:00
Matthieu Napoli
ef4ff8be81 Fix and test for DDC-2073 2012-11-09 20:44:12 +01:00
Matthieu Napoli
b53c81ae8d Fix and test for DDC-2073 2012-11-09 20:44:12 +01:00
Benjamin Eberlei
6bad010959 Merge branch 'DDC-2067' into 2.3 2012-10-12 21:49:45 +02:00
Benjamin Eberlei
26cfbdd08b [DDC-2067] Refactor and fix bug in boolean evaluation inside XML Driver. 2012-10-12 21:49:35 +02:00
Benjamin Eberlei
e8412b85df Merge branch 'DDC-2068' into 2.3 2012-10-12 20:36:29 +02:00
Oleksandr Kovalov
2e5d7416d8 Fixed bug with comment option not being added to column. 2012-10-12 20:36:18 +02:00
jakoch
1988944e7e fix typo 2012-10-12 20:31:16 +02:00
Benjamin Eberlei
564ec1ee2a Merge branch 'DDC-2028' into 2.3 2012-10-05 23:20:05 +02:00
Asmir Mustafic
cb0cddef83 spaces 2012-10-05 23:19:55 +02:00
Asmir Mustafic
8b2c92a6bd typo fix 2012-10-05 23:19:55 +02:00
Benjamin Eberlei
825a68bcba Merge branch 'DDC-2044' into 2.3 2012-10-05 20:25:31 +02:00
Marcin Radziwoński
abd11374ee Fixed unique-constraint name in XML Exporter 2012-10-05 20:24:46 +02:00
Benjamin Eberlei
518357d987 Merge branch 'DDC-2059' into 2.3 2012-10-05 20:06:06 +02:00
Benjamin Eberlei
4109f22000 [DDC-2059] Fix column and foreign key interfering with each other during reverse engineering. 2012-10-05 20:04:42 +02:00
Fabio B. Silva
c60e6523e9 Fix test case 2012-10-04 19:58:30 +02:00
Benjamin Eberlei
04262e2b73 Merge branch 'DDC-2012' into 2.3 2012-10-03 12:48:22 +02:00
Fabio B. Silva
084101e287 Fix DDC-2012 2012-10-03 12:47:38 +02:00
Benjamin Eberlei
ea2b288578 Bump dev version to 2.3.1 2012-09-20 08:03:35 +02:00
Benjamin Eberlei
b5e19dca18 Release 2.3.0 2012-09-20 08:03:34 +02:00
Benjamin Eberlei
585c9fd208 Bump versions 2012-09-20 08:00:34 +02:00
Benjamin Eberlei
c6101317cd Bump dev version to 2.3.0 2012-09-17 14:09:09 +02:00
Benjamin Eberlei
477642a171 Release 2.3.0-RC4 2012-09-17 14:09:09 +02:00
Benjamin Eberlei
75e968b250 Adjust MysqlSchemaToolTest to DBAL changes 2012-09-17 14:08:45 +02:00
Benjamin Eberlei
3294900faa Update dependencies 2012-09-17 13:53:37 +02:00
Benjamin Eberlei
2353736e8f Merge branch 'DDC-2015' into 2.3 2012-09-17 12:46:10 +02:00
Stefano Rodriguez
586aea0236 use of assertCount 2012-09-17 12:45:32 +02:00
Stefano Rodriguez
18a7fc5726 Fixes PersistentCollection::matching() when collection is not initialized and there are NEW entities in the collection 2012-09-17 12:45:32 +02:00
Stefano Rodriguez
44a56e8e49 Added a failing test case on PersistentCollection::matching() when collection is not initialized and there are NEW entities in the collection 2012-09-17 12:45:32 +02:00
Benjamin Eberlei
c2b82fa529 Merge branch 'DDC-2014' into 2.3 2012-09-17 12:43:19 +02:00
Thomas Rothe
d7da012918 added missing use statement 2012-09-17 12:43:09 +02:00
Thomas Rothe
85e5398354 Several fixes for comments
updated @param and @throws annotations
2012-09-17 12:43:09 +02:00
Benjamin Eberlei
3fd8392ccf Merge branch 'DDC-2026' into 2.3 2012-09-17 12:29:59 +02:00
Fabio B. Silva
0da0d02dec remove duplicate code 2012-09-17 12:29:49 +02:00
Benjamin Eberlei
387516f144 Merge branch 'DDC-2027' into 2.3 2012-09-17 12:28:23 +02:00
Cas
53e164ba5d Update lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
Allow 'nullable' attribute to be exported for fields, something which already worked in YamlExport. This addition saved me a lot of time during development, not having to manually re-factor after each export.

Don't know why this was missing, maybe it's me who is missing something, so let me know ;)
2012-09-17 12:27:47 +02:00
Benjamin Eberlei
4d9f24b2ee Bump dev version to 2.3.0 2012-09-05 20:16:47 +02:00
Benjamin Eberlei
a96bbbbe0a Release 2.3.0-RC3 2012-09-05 20:16:47 +02:00
Benjamin Eberlei
8edecfdcad Bump DBAL dependency 2012-09-05 19:38:05 +02:00
Benjamin Eberlei
741080dc17 Merge branch 'DDC-2003' into 2.3 2012-09-05 19:30:26 +02:00
Benjamin Eberlei
30ad1b0706 [DDC-2003] Remove unused variable 2012-09-05 19:29:19 +02:00
Josiah Truasheim
9cdee12ccf Refactored the SqlValueVisitor to move all type processing to the entity persister. 2012-09-05 19:29:19 +02:00
Josiah Truasheim
c76280be42 Fixed formatting issues identified by Stof 2012-09-05 19:29:19 +02:00
Josiah Truasheim
0dcfabbc4d Removed the closure keyword as it isn't supported in PHP 5.3 2012-09-05 19:29:19 +02:00
Josiah Truasheim
366c6a7dd6 Fixed DDC-2003 using closures to reference the functionality of the calling entity persister from the SQL value visitor. 2012-09-05 19:29:19 +02:00
Josiah Truasheim
2597192f22 Added a failing test for DDC-2003 2012-09-05 19:29:19 +02:00
Benjamin Eberlei
bbf527a273 Bump dev version to 2.3.0 2012-08-29 16:36:26 +02:00
Benjamin Eberlei
9308afc9a5 Release 2.3.0-RC2 2012-08-29 16:36:26 +02:00
Benjamin Eberlei
1a81444b04 Bump dev version to 2.3.0 2012-08-29 16:35:51 +02:00
Benjamin Eberlei
d181fbc98d Release 2.3.0-RC2 2012-08-29 16:35:51 +02:00
Benjamin Eberlei
114e233d87 Revert "Merge remote-tracking branch 'origin/master' into 2.3"
This reverts commit 131d3003a0, reversing
changes made to 9d909cd583.
2012-08-29 15:50:08 +02:00
Benjamin Eberlei
bdb36a71c5 Merge branch 'DDC-1918' into 2.3 2012-08-29 15:15:35 +02:00
Benjamin Eberlei
8c1d64372c Merge remote-tracking branch 'origin/2.3' into 2.3 2012-08-29 15:15:27 +02:00
Benjamin Eberlei
f4ba58358c [DDC-1918] Fix weird results at the end of paginator when using fetch joins 2012-08-29 15:14:40 +02:00
Benjamin Eberlei
131d3003a0 Merge remote-tracking branch 'origin/master' into 2.3 2012-08-29 14:01:18 +02:00
Benjamin Eberlei
48e94343fd Merge pull request #427 from chEbba/return-exception
Fix ORMInvalidArgumentException factory methods with return instead of throw
2012-08-29 04:57:32 -07:00
FabioBatSilva
9d909cd583 Fix DDC-1977 2012-08-29 13:40:18 +02:00
Kirill chEbba Chebunin
3aaa90e1a8 Fix ORMInvalidArgumentException factory methods with return instead of throw 2012-08-19 22:58:40 +04:00
Alexander
971865f271 Merge branch 'config' into 2.3 2012-08-14 22:51:23 +02:00
Alexander
af08f05164 Fix setCustomHydrationModes + added test 2012-08-14 22:47:35 +02:00
Martin Meredith
2e6b50bb53 Create the setCustomHydrationMode function
This allows multiple hydrators to be set at once, and also allows for
the customHydrationMode options to be set via DoctrineORMModule
2012-08-14 22:47:35 +02:00
Benjamin Eberlei
17862d9a2a Merge branch 'CriteriaExpressionBuilder' into 2.3 2012-08-01 21:40:25 +02:00
Benjamin Eberlei
c99c7b6694 Update EntityRepository and PersistentCollection to new Criteria#expr() method instead of having to implement themselves. 2012-08-01 21:39:39 +02:00
Guilherme Blanco
3f2ddc60d4 Merge pull request #416 from Majkl578/DDC-1961
[DDC-1961] Fixed parameter type support in Parameter
2012-07-31 07:34:24 -07:00
Michael Moravec
3b3d762277 [DDC-1961] Fixed parameter type support in Parameter 2012-07-31 16:30:27 +02:00
Benjamin Eberlei
992b51eba7 Bump dev version to 2.3.0 2012-07-29 13:03:10 +02:00
Benjamin Eberlei
5527e121ec Release 2.3.0-RC1 2012-07-29 13:03:10 +02:00
Benjamin Eberlei
c55394c616 Bump dependencies 2012-07-29 13:02:58 +02:00
Benjamin Eberlei
1676cf23c0 Merge branch 'DDC-1937' into 2.3 2012-07-29 11:56:59 +02:00
Benjamin Eberlei
6dd3078153 [DDC-1937] Fix bug with apc and annotation caching using a workaround. 2012-07-29 11:56:49 +02:00
Marco Pivetta
1e2eca1a7e DDC-1933 - Fixing cloning of QueryBuilder and adding related tests 2012-07-29 11:50:24 +02:00
Benjamin Eberlei
7029d3738d Merge branch 'DDC-1964' into 2.3 2012-07-29 11:26:55 +02:00
Benjamin Eberlei
7f68347c1f [DDC-1964] Fix issue with refresh and and object hydrator not setting field to null explicitly to override possible previous values. 2012-07-29 11:26:22 +02:00
Johannes M. Schmitt
e63575ea18 added failing test for refresh with eager fetching 2012-07-29 11:26:22 +02:00
Benjamin Eberlei
d7bdae3bbb Merge branch 'DDC-1939' into 2.3 2012-07-29 09:28:18 +02:00
Benjamin Eberlei
e2c40dc365 [DDC-1939] Add test for persistent collection delete with composite key 2012-07-29 09:27:50 +02:00
Marco Pivetta
dfa6ff64c4 DDC-1939 - Removing references to non-existing AssociationMapping class 2012-07-29 09:27:50 +02:00
Benjamin Eberlei
ef27721db2 Merge remote-tracking branch 'origin/2.3' into 2.3 2012-07-29 09:08:39 +02:00
Benjamin Eberlei
13d32e6de5 Merge remote-tracking branch 'origin/2.3' into 2.3 2012-07-29 09:08:19 +02:00
Benjamin Eberlei
bd1e6ac309 Merge pull request #410 from igorw/helper-set
[2.3] Use HelperSet in cli-config.php
2012-07-29 00:05:45 -07:00
Christophe Coevoet
369a30ad3d Added the new DBAL 2.3 types in the EntityGenerator typehint map 2012-07-29 09:02:35 +02:00
Guilherme Blanco
ac9df05c92 Fixed is_subclass_of comparing an interface which brought our requirement to 5.3.9. Changed to reflection approach which still keep us at the same dependency as before. 2012-07-26 22:01:37 +02:00
Igor Wiedler
2158a0788e [2.3] Use HelperSet in cli-config.php 2012-07-26 19:24:53 +02:00
Guilherme Blanco
2389f77d91 Fixed DefaultRepositoryClassName which should follow the Persistence interface, not ORM class. 2012-07-25 19:54:11 +02:00
Guilherme Blanco
5b55739990 Moved implementation from EntityRepository to EntityManager. This decouples ER implementation from EM, as it should be. 2012-07-24 00:23:59 +02:00
Christophe Coevoet
3e53d9d79c Changed commands to use command.name in the help 2012-07-24 00:21:31 +02:00
94 changed files with 2642 additions and 643 deletions

View File

@@ -1,5 +1,13 @@
# Upgrade to 2.3
## EntityManager#find() not calls EntityRepository#find() anymore
Previous to 2.3, calling ``EntityManager#find()`` would be delegated to
``EntityRepository#find()``. This has lead to some unexpected behavior in the
core of Doctrine when people have overwritten the find method in their
repositories. That is why this behavior has been reversed in 2.3, and
``EntityRepository#find()`` calls ``EntityManager#find()`` instead.
## EntityGenerator add*() method generation
When generating an add*() method for a collection the EntityGenerator will now not

View File

@@ -1,6 +1,6 @@
{
"name": "doctrine/orm",
"type": "library",
"type": "library","version":"2.3.4",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",
@@ -14,7 +14,7 @@
"require": {
"php": ">=5.3.2",
"ext-pdo": "*",
"doctrine/dbal": ">=2.3-dev,<2.5-dev",
"doctrine/dbal": "2.3.*",
"symfony/console": "2.*"
},
"suggest": {
@@ -26,7 +26,7 @@
"bin": ["bin/doctrine", "bin/doctrine.php"],
"extra": {
"branch-alias": {
"dev-master": "2.4.x-dev"
"dev-master": "2.3.x-dev"
}
}
}

View File

@@ -329,6 +329,7 @@
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="association-key" type="xs:boolean" default="false" />
<xs:attribute name="column-definition" type="xs:string" />
<xs:anyAttribute namespace="##other"/>

View File

@@ -26,6 +26,7 @@ use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Mapping;
/**
* Base contract for ORM queries. Base class for Query and NativeQuery.
@@ -259,6 +260,9 @@ abstract class AbstractQuery
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value)):
return $this->convertObjectParameterToScalarValue($value);
case ($value instanceof Mapping\ClassMetadata):
return $value->name;
default:
return $value;
}
@@ -281,7 +285,7 @@ abstract class AbstractQuery
$value = $values[$class->getSingleIdentifierFieldName()];
if ( ! $value) {
if (null === $value) {
throw new \InvalidArgumentException(
"Binding entities to query parameters only allowed for entities that have an identifier."
);

View File

@@ -25,6 +25,7 @@ use Doctrine\Common\Persistence\ObjectRepository;
use Doctrine\Common\Collections\Selectable;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\ExpressionBuilder;
/**
* An EntityRepository serves as a repository for entities with generic as well as
@@ -160,13 +161,14 @@ class EntityRepository implements ObjectRepository, Selectable
* Finds a single entity by a set of criteria.
*
* @param array $criteria
* @param array|null $orderBy
* @return object
*/
public function findOneBy(array $criteria)
public function findOneBy(array $criteria, array $orderBy = null)
{
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
return $persister->load($criteria, null, null, array(), 0, 1);
return $persister->load($criteria, null, null, array(), 0, 1, $orderBy);
}
/**
@@ -214,7 +216,7 @@ class EntityRepository implements ObjectRepository, Selectable
case 3:
return $this->$method(array($fieldName => $arguments[0]), $arguments[1], $arguments[2]);
case 4;
case 4:
return $this->$method(array($fieldName => $arguments[0]), $arguments[1], $arguments[2], $arguments[3]);
default:

View File

@@ -0,0 +1,66 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
/**
* Id generator that obtains IDs from special "identity" columns. These are columns
* that automatically get a database-generated, auto-incremented identifier on INSERT.
* This generator obtains the last insert id after such an insert.
*/
class BigIntegerIdentityGenerator extends AbstractIdGenerator
{
/**
* The name of the sequence to pass to lastInsertId(), if any.
*
* @var string
*/
private $sequenceName;
/**
* Constructor.
*
* @param string|null $seqName The name of the sequence to pass to lastInsertId()
* to obtain the last generated identifier within the current
* database session/connection, if any.
*/
public function __construct($sequenceName = null)
{
$this->sequenceName = $sequenceName;
}
/**
* {@inheritdoc}
*/
public function generate(EntityManager $em, $entity)
{
return (string)$em->getConnection()->lastInsertId($this->sequenceName);
}
/**
* {@inheritdoc}
*/
public function isPostInsertGenerator()
{
return true;
}
}

View File

@@ -28,17 +28,21 @@ use Doctrine\ORM\EntityManager;
*/
class IdentityGenerator extends AbstractIdGenerator
{
/** @var string The name of the sequence to pass to lastInsertId(), if any. */
private $_seqName;
/**
* The name of the sequence to pass to lastInsertId(), if any.
*
* @var string
*/
private $sequenceName;
/**
* @param string $seqName The name of the sequence to pass to lastInsertId()
* to obtain the last generated identifier within the current
* database session/connection, if any.
*/
public function __construct($seqName = null)
public function __construct($sequenceName = null)
{
$this->_seqName = $seqName;
$this->sequenceName = $sequenceName;
}
/**
@@ -46,7 +50,7 @@ class IdentityGenerator extends AbstractIdGenerator
*/
public function generate(EntityManager $em, $entity)
{
return (int)$em->getConnection()->lastInsertId($this->_seqName);
return (int)$em->getConnection()->lastInsertId($this->sequenceName);
}
/**

View File

@@ -27,6 +27,7 @@ use PDO,
Doctrine\ORM\Events,
Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection,
Doctrine\ORM\UnitOfWork,
Doctrine\ORM\Proxy\Proxy;
/**
@@ -65,8 +66,8 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultCounter = 0;
if ( ! isset($this->_hints['deferEagerLoad'])) {
$this->_hints['deferEagerLoad'] = true;
if ( ! isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) {
$this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] = true;
}
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
@@ -123,7 +124,7 @@ class ObjectHydrator extends AbstractHydrator
*/
protected function cleanup()
{
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
$eagerLoad = (isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) && $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] == true;
parent::cleanup();

View File

@@ -178,10 +178,13 @@ class SimpleObjectHydrator extends AbstractHydrator
// One solution is to load the association, but it might require extra efforts.
return array('name' => $column);
default:
case (isset($this->_rsm->metaMappings[$column])):
return array(
'name' => $this->_rsm->metaMappings[$column]
);
default:
return null;
}
}
}

View File

@@ -19,16 +19,17 @@
namespace Doctrine\ORM\Mapping;
use ReflectionException,
Doctrine\ORM\ORMException,
Doctrine\ORM\EntityManager,
Doctrine\DBAL\Platforms,
Doctrine\ORM\Events,
Doctrine\Common\Persistence\Mapping\ReflectionService,
Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface,
Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory,
Doctrine\ORM\Id\IdentityGenerator,
Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use ReflectionException;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\EntityManager;
use Doctrine\DBAL\Platforms;
use Doctrine\ORM\Events;
use Doctrine\Common\Persistence\Mapping\ReflectionService;
use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
use Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory;
use Doctrine\ORM\Id\IdentityGenerator;
use Doctrine\ORM\Id\BigIntegerIdentityGenerator;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
/**
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
@@ -418,9 +419,9 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
// Not pretty but necessary and the simplest solution that currently works.
$sequenceName = null;
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
if ($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
$fieldName = $class->getSingleIdentifierFieldName();
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
@@ -435,7 +436,12 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
}
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($sequenceName));
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === "bigint")
? new BigIntegerIdentityGenerator($sequenceName)
: new IdentityGenerator($sequenceName);
$class->setIdGenerator($generator);
break;
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:

View File

@@ -1188,7 +1188,7 @@ class ClassMetadataInfo implements ClassMetadata
// Complete fieldName and columnName mapping
if ( ! isset($mapping['columnName'])) {
$mapping['columnName'] = $this->namingStrategy->propertyToColumnName($mapping['fieldName'], $this->name);
$mapping['columnName'] = $this->namingStrategy->propertyToColumnName($mapping['fieldName']);
}
if ($mapping['columnName'][0] === '`') {
@@ -1421,6 +1421,10 @@ class ClassMetadataInfo implements ClassMetadata
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
if ($mapping['orphanRemoval']) {
unset($mapping['unique']);
}
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
}
@@ -1465,7 +1469,6 @@ class ClassMetadataInfo implements ClassMetadata
if ( ! isset($mapping['joinTable']['name'])) {
$mapping['joinTable']['name'] = $this->namingStrategy->joinTableName($mapping['sourceEntity'], $mapping['targetEntity'], $mapping['fieldName']);
}
if ( ! isset($mapping['joinTable']['joinColumns'])) {
$mapping['joinTable']['joinColumns'] = array(array(
'name' => $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity']),
@@ -1479,6 +1482,8 @@ class ClassMetadataInfo implements ClassMetadata
'onDelete' => 'CASCADE'));
}
$mapping['joinTableColumns'] = array();
foreach ($mapping['joinTable']['joinColumns'] as &$joinColumn) {
if (empty($joinColumn['name'])) {
$joinColumn['name'] = $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity'], $joinColumn['referencedColumnName']);
@@ -2725,7 +2730,7 @@ class ClassMetadataInfo implements ClassMetadata
// Association defined as Id field
$joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
$assocQuotedColumnNames = array_map(
function ($joinColumn) {
function ($joinColumn) use ($platform) {
return isset($joinColumn['quoted'])
? $platform->quoteIdentifier($joinColumn['name'])
: $joinColumn['name'];

View File

@@ -45,7 +45,7 @@ class DefaultNamingStrategy implements NamingStrategy
/**
* {@inheritdoc}
*/
public function propertyToColumnName($propertyName, $className = null)
public function propertyToColumnName($propertyName)
{
return $propertyName;
}

View File

@@ -197,43 +197,6 @@ class AnnotationDriver extends AbstractAnnotationDriver
}
}
$associationOverrides = array();
// Evaluate AssociationOverrides annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'])) {
$associationOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'];
foreach ($associationOverridesAnnot->value as $associationOverride) {
// Check for JoinColummn/JoinColumns annotations
if ($associationOverride->joinColumns) {
$joinColumns = array();
foreach ($associationOverride->joinColumns as $joinColumn) {
$joinColumns[] = $this->joinColumnToArray($joinColumn);
}
$associationOverrides[$associationOverride->name]['joinColumns'] = $joinColumns;
}
// Check for JoinTable annotations
if ($associationOverride->joinTable) {
$joinTable = null;
$joinTableAnnot = $associationOverride->joinTable;
$joinTable = array(
'name' => $joinTableAnnot->name,
'schema' => $joinTableAnnot->schema
);
foreach ($joinTableAnnot->joinColumns as $joinColumn) {
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
}
foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
}
$associationOverrides[$associationOverride->name]['joinTable'] = $joinTable;
}
}
}
// Evaluate InheritanceType annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) {
$inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType'];

View File

@@ -217,7 +217,8 @@ class DatabaseDriver implements MappingDriver
}
if ($ids) {
if (count($ids) == 1) {
// We need to check for the columns here, because we might have associations as id as well.
if (count($primaryKeyColumns) == 1) {
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
}
@@ -297,6 +298,10 @@ class DatabaseDriver implements MappingDriver
$associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
$associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);
if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) {
$associationMapping['fieldName'] = $associationMapping['fieldName'] . "2";
}
if ($primaryKeyColumns && in_array($localColumn, $primaryKeyColumns)) {
$associationMapping['id'] = true;
}

View File

@@ -60,7 +60,7 @@ class XmlDriver extends FileDriver
if (isset($xmlRoot['repository-class'])) {
$metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
}
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
if (isset($xmlRoot['read-only']) && $this->evaluateBoolean($xmlRoot['read-only'])) {
$metadata->markReadOnly();
}
} else if ($xmlRoot->getName() == 'mapped-superclass') {
@@ -230,18 +230,28 @@ class XmlDriver extends FileDriver
if (isset($xmlRoot->field)) {
foreach ($xmlRoot->field as $fieldMapping) {
$mapping = $this->columnToArray($fieldMapping);
if (isset($mapping['version'])) {
$metadata->setVersionMapping($mapping);
unset($mapping['version']);
}
$metadata->mapField($mapping);
}
}
foreach ($mappings as $mapping) {
$metadata->mapField($mapping);
if (isset($mapping['version'])) {
$metadata->setVersionMapping($mapping);
}
$metadata->mapField($mapping);
}
// Evaluate <id ...> mappings
$associationIds = array();
foreach ($xmlRoot->id as $idElement) {
if ((bool)$idElement['association-key'] == true) {
if (isset($idElement['association-key']) && $this->evaluateBoolean($idElement['association-key'])) {
$associationIds[(string)$idElement['name']] = true;
continue;
}
@@ -334,7 +344,7 @@ class XmlDriver extends FileDriver
}
if (isset($oneToOneElement['orphan-removal'])) {
$mapping['orphanRemoval'] = (bool)$oneToOneElement['orphan-removal'];
$mapping['orphanRemoval'] = $this->evaluateBoolean($oneToOneElement['orphan-removal']);
}
$metadata->mapOneToOne($mapping);
@@ -359,7 +369,7 @@ class XmlDriver extends FileDriver
}
if (isset($oneToManyElement['orphan-removal'])) {
$mapping['orphanRemoval'] = (bool)$oneToManyElement['orphan-removal'];
$mapping['orphanRemoval'] = $this->evaluateBoolean($oneToManyElement['orphan-removal']);
}
if (isset($oneToManyElement->{'order-by'})) {
@@ -433,7 +443,7 @@ class XmlDriver extends FileDriver
}
if (isset($manyToManyElement['orphan-removal'])) {
$mapping['orphanRemoval'] = (bool)$manyToManyElement['orphan-removal'];
$mapping['orphanRemoval'] = $this->evaluateBoolean($manyToManyElement['orphan-removal']);
}
if (isset($manyToManyElement['mapped-by'])) {
@@ -594,11 +604,11 @@ class XmlDriver extends FileDriver
);
if (isset($joinColumnElement['unique'])) {
$joinColumn['unique'] = ((string)$joinColumnElement['unique'] == "false") ? false : true;
$joinColumn['unique'] = $this->evaluateBoolean($joinColumnElement['unique']);
}
if (isset($joinColumnElement['nullable'])) {
$joinColumn['nullable'] = ((string)$joinColumnElement['nullable'] == "false") ? false : true;
$joinColumn['nullable'] = $this->evaluateBoolean($joinColumnElement['nullable']);
}
if (isset($joinColumnElement['on-delete'])) {
@@ -645,15 +655,15 @@ class XmlDriver extends FileDriver
}
if (isset($fieldMapping['unique'])) {
$mapping['unique'] = ((string) $fieldMapping['unique'] == "false") ? false : true;
$mapping['unique'] = $this->evaluateBoolean($fieldMapping['unique']);
}
if (isset($fieldMapping['nullable'])) {
$mapping['nullable'] = ((string) $fieldMapping['nullable'] == "false") ? false : true;
$mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']);
}
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
$mapping['version'] = $fieldMapping['version'];
$mapping['version'] = $this->evaluateBoolean($fieldMapping['version']);
}
if (isset($fieldMapping['column-definition'])) {
@@ -710,4 +720,12 @@ class XmlDriver extends FileDriver
return $result;
}
protected function evaluateBoolean($element)
{
$flag = (string)$element;
return ($flag === true || $flag == "true" || $flag == "1");
}
}

View File

@@ -198,6 +198,7 @@ class YamlDriver extends FileDriver
if (is_string($index['columns'])) {
$columns = explode(',', $index['columns']);
$columns = array_map('trim', $columns);
} else {
$columns = $index['columns'];
}
@@ -217,6 +218,7 @@ class YamlDriver extends FileDriver
if (is_string($unique['columns'])) {
$columns = explode(',', $unique['columns']);
$columns = array_map('trim', $columns);
} else {
$columns = $unique['columns'];
}
@@ -295,6 +297,11 @@ class YamlDriver extends FileDriver
}
}
if (isset($mapping['version'])) {
$metadata->setVersionMapping($mapping);
unset($mapping['version']);
}
$metadata->mapField($mapping);
}
}
@@ -628,7 +635,7 @@ class YamlDriver extends FileDriver
$mapping['type'] = $column['type'];
if (isset($params[1])) {
$column['length'] = substr($params[1], 0, strlen($params[1]) - 1);
$column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1);
}
}

View File

@@ -34,7 +34,7 @@ class MappingException extends \Doctrine\ORM\ORMException
public static function identifierRequired($entityName)
{
if (null !== ($parent = get_parent_class($entityName))) {
if (false !== ($parent = get_parent_class($entityName))) {
return new self(sprintf(
'No identifier/primary key specified for Entity "%s" sub class of "%s". Every Entity must have an identifier/primary key.',
$entityName, $parent
@@ -206,7 +206,7 @@ class MappingException extends \Doctrine\ORM\ORMException
public static function classIsNotAValidEntityOrMappedSuperClass($className)
{
if (null !== ($parent = get_parent_class($className))) {
if (false !== ($parent = get_parent_class($className))) {
return new self(sprintf(
'Class "%s" sub class of "%s" is not a valid entity or mapped super class.',
$className, $parent

View File

@@ -42,10 +42,9 @@ interface NamingStrategy
* Return a column name for a property
*
* @param string $propertyName A property
* @param string $className The fully-qualified class name
* @return string A column name
*/
function propertyToColumnName($propertyName, $className = null);
function propertyToColumnName($propertyName);
/**
* Return the default reference column name

View File

@@ -80,7 +80,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
/**
* {@inheritdoc}
*/
public function propertyToColumnName($propertyName, $className = null)
public function propertyToColumnName($propertyName)
{
return $this->underscore($propertyName);
}

View File

@@ -43,7 +43,7 @@ class ORMInvalidArgumentException extends \InvalidArgumentException
static public function entityWithoutIdentity($className, $entity)
{
throw new self(
return new self(
"The given entity of type '" . $className . "' (".self::objToStr($entity).") has no identity/no " .
"id values set. It cannot be added to the identity map."
);
@@ -70,30 +70,30 @@ class ORMInvalidArgumentException extends \InvalidArgumentException
static public function detachedEntityFoundThroughRelationship(array $assoc, $entry)
{
throw new self("A detached entity of type " . $assoc['targetEntity'] . " (" . self::objToStr($entry) . ") "
return new self("A detached entity of type " . $assoc['targetEntity'] . " (" . self::objToStr($entry) . ") "
. " was found through the relationship '" . $assoc['sourceEntity'] . "#" . $assoc['fieldName'] . "' "
. "during cascading a persist operation.");
}
static public function entityNotManaged($entity)
{
throw new self("Entity " . self::objToStr($entity) . " is not managed. An entity is managed if its fetched " .
return new self("Entity " . self::objToStr($entity) . " is not managed. An entity is managed if its fetched " .
"from the database or registered as new through EntityManager#persist");
}
static public function entityHasNoIdentity($entity, $operation)
{
throw new self("Entity has no identity, therefore " . $operation ." cannot be performed. " . self::objToStr($entity));
return new self("Entity has no identity, therefore " . $operation ." cannot be performed. " . self::objToStr($entity));
}
static public function entityIsRemoved($entity, $operation)
{
throw new self("Entity is removed, therefore " . $operation ." cannot be performed. " . self::objToStr($entity));
return new self("Entity is removed, therefore " . $operation ." cannot be performed. " . self::objToStr($entity));
}
static public function detachedEntityCannot($entity, $operation)
{
throw new self("A detached entity was found during " . $operation . " " . self::objToStr($entity));
return new self("A detached entity was found during " . $operation . " " . self::objToStr($entity));
}
public static function invalidObject($context, $given, $parameterIndex = 1)

View File

@@ -42,6 +42,7 @@ use Closure;
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @author Stefano Rodriguez <stefano.rodriguez@fubles.com>
* @todo Design for inheritance to allow custom implementations?
*/
final class PersistentCollection implements Collection, Selectable
@@ -654,7 +655,7 @@ final class PersistentCollection implements Collection, Selectable
$this->initialized = true; // direct call, {@link initialize()} is too expensive
if ($this->association['isOwningSide']) {
if ($this->association['isOwningSide'] && $this->owner) {
$this->changed();
$uow->scheduleCollectionDeletion($this);
@@ -804,6 +805,10 @@ final class PersistentCollection implements Collection, Selectable
*/
public function matching(Criteria $criteria)
{
if ($this->isDirty) {
$this->initialize();
}
if ($this->initialized) {
return $this->coll->matching($criteria);
}
@@ -812,9 +817,10 @@ final class PersistentCollection implements Collection, Selectable
throw new \RuntimeException("Matching Criteria on PersistentCollection only works on OneToMany assocations at the moment.");
}
$targetClass = $this->em->getClassMetadata(get_class($this->owner));
$id = $targetClass->getSingleIdReflectionProperty()->getValue($this->owner);
$id = $this->em
->getClassMetadata(get_class($this->owner))
->getSingleIdReflectionProperty()
->getValue($this->owner);
$builder = Criteria::expr();
$ownerExpression = $builder->eq($this->backRefFieldName, $id);
$expression = $criteria->getWhereExpression();

View File

@@ -88,7 +88,7 @@ class BasicEntityPersister
*/
static private $comparisonMap = array(
Comparison::EQ => '= %s',
Comparison::IS => '= %s',
Comparison::IS => 'IS %s',
Comparison::NEQ => '!= %s',
Comparison::GT => '> %s',
Comparison::GTE => '>= %s',
@@ -659,12 +659,13 @@ class BasicEntityPersister
* @param array $hints Hints for entity creation.
* @param int $lockMode
* @param int $limit Limit number of results
* @param array $orderBy Criteria to order by
* @return object The loaded and managed entity instance or NULL if the entity can not be found.
* @todo Check identity map? loadById method? Try to guess whether $criteria is the id?
*/
public function load(array $criteria, $entity = null, $assoc = null, array $hints = array(), $lockMode = 0, $limit = null)
public function load(array $criteria, $entity = null, $assoc = null, array $hints = array(), $lockMode = 0, $limit = null, array $orderBy = null)
{
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode, $limit);
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy);
list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->_conn->executeQuery($sql, $params, $types);
@@ -789,7 +790,7 @@ class BasicEntityPersister
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
return $hydrator->hydrateAll($stmt, $this->_rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -808,10 +809,23 @@ class BasicEntityPersister
return array(array(), array());
}
$valueVisitor = new SqlValueVisitor($this->_class);
$valueVisitor = new SqlValueVisitor();
$valueVisitor->dispatch($expression);
return $valueVisitor->getParamsAndTypes();
list($values, $types) = $valueVisitor->getParamsAndTypes();
$sqlValues = array();
foreach ($values as $value) {
$sqlValues[] = $this->getValue($value);
}
$sqlTypes = array();
foreach ($types as $type) {
list($field, $value) = $type;
$sqlTypes[] = $this->getType($field, $value);
}
return array($sqlValues, $sqlTypes);
}
/**
@@ -831,7 +845,7 @@ class BasicEntityPersister
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
return $hydrator->hydrateAll($stmt, $this->_rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -860,7 +874,7 @@ class BasicEntityPersister
*/
private function loadArrayFromStatement($assoc, $stmt)
{
$hints = array('deferEagerLoads' => true);
$hints = array(UnitOfWork::HINT_DEFEREAGERLOAD => true);
if (isset($assoc['indexBy'])) {
$rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.
@@ -885,7 +899,7 @@ class BasicEntityPersister
*/
private function loadCollectionFromStatement($assoc, $stmt, $coll)
{
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
$hints = array(UnitOfWork::HINT_DEFEREAGERLOAD => true, 'collection' => $coll);
if (isset($assoc['indexBy'])) {
$rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.
@@ -1686,7 +1700,11 @@ class BasicEntityPersister
$idValues = $class->getIdentifierValues($value);
}
$value = $idValues[key($idValues)];
$key = key($idValues);
if (null !== $key){
$value = $idValues[$key];
}
}
return $value;

View File

@@ -227,8 +227,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Make sure the table with the version column is updated even if no columns on that
// table were affected.
if ($isVersioned && ! isset($updateData[$versionedTable])) {
$this->_updateTable($entity, $this->quoteStrategy->getTableName($versionedClass, $this->_platform), array(), true);
if ($isVersioned) {
if ( ! isset($updateData[$versionedTable])) {
$this->_updateTable($entity, $this->quoteStrategy->getTableName($versionedClass, $this->_platform), array(), true);
}
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
$this->assignDefaultVersionValue($entity, $id);
@@ -468,7 +470,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
} else if ($this->_class->name != $this->_class->rootEntityName ||
! $this->_class->isIdGeneratorIdentity() || $this->_class->identifier[0] != $name) {
$columns[] = $this->quoteStrategy->getColumnName($name, $this->_class, $this->_platform);
$columns[] = $this->quoteStrategy->getColumnName($name, $this->_class, $this->_platform);
$this->_columnTypes[$name] = $this->_class->fieldMappings[$name]['type'];
}
}

View File

@@ -186,22 +186,22 @@ class ManyToManyPersister extends AbstractCollectionPersister
*/
protected function _getDeleteSQLParameters(PersistentCollection $coll)
{
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
$mapping = $coll->getMapping();
$params = array();
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
// Optimization for single column identifier
if (count($mapping['relationToSourceKeyColumns']) === 1) {
$params[] = array_pop($identifier);
return $params;
return array(reset($identifier));
}
// Composite identifier
$sourceClass = $this->_em->getClassMetadata(get_class($coll->getOwner()));
$params = array();
foreach ($mapping['relationToSourceKeyColumns'] as $srcColumn) {
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) {
$params[] = isset($sourceClass->fieldNames[$refColumnName])
? $identifier[$sourceClass->fieldNames[$refColumnName]]
: $identifier[$sourceClass->getFieldForColumn($columnName)];
}
return $params;

View File

@@ -46,19 +46,6 @@ class SqlValueVisitor extends ExpressionVisitor
*/
private $types = array();
/**
* @var \Doctrine\ORM\Mapping\ClassMetadata
*/
private $class;
/**
* @param \Doctrine\ORM\Mapping\ClassMetadata
*/
public function __construct(ClassMetadata $class)
{
$this->class = $class;
}
/**
* Convert a comparison expression into the target query language output
*
@@ -70,9 +57,9 @@ class SqlValueVisitor extends ExpressionVisitor
{
$value = $comparison->getValue()->getValue();
$field = $comparison->getField();
$this->values[] = $value;
$this->types[] = $this->getType($field, $value);
$this->types[] = array($field, $value);
}
/**
@@ -110,17 +97,4 @@ class SqlValueVisitor extends ExpressionVisitor
{
return array($this->values, $this->types);
}
private function getType($field, $value)
{
$type = isset($this->class->fieldMappings[$field])
? Type::getType($this->class->fieldMappings[$field]['type'])->getBindingType()
: \PDO::PARAM_STR;
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
return $type;
}
}

View File

@@ -40,6 +40,6 @@ class JoinClassPathExpression extends Node
public function dispatch($walker)
{
return $sqlWalker->walkJoinPathExpression($this);
return $walker->walkJoinPathExpression($this);
}
}

View File

@@ -104,19 +104,8 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$updateSql .= $sqlWalker->walkUpdateItem($updateItem);
//FIXME: parameters can be more deeply nested. traverse the tree.
//FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage.
if ($newValue instanceof AST\InputParameter) {
$parameterName = $newValue->name;
$parameter = $sqlWalker->getQuery()->getParameter($parameterName);
$value = $sqlWalker->getQuery()->processParameterValue($parameter->getValue());
$type = ($parameter->getValue() === $value)
? $parameter->getType()
: ParameterTypeInferer::inferType($value);
$this->_sqlParameters[$i]['parameters'][] = $value;
$this->_sqlParameters[$i]['types'][] = $type;
$this->_sqlParameters[$i][] = $newValue->name;
++$this->_numParametersInUpdateClause;
}
@@ -168,16 +157,18 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
);
// Execute UPDATE statements
for ($i=0, $count=count($this->_sqlStatements); $i<$count; ++$i) {
$parameters = array();
$types = array();
foreach ($this->_sqlStatements as $key => $statement) {
$paramValues = array();
$paramTypes = array();
if (isset($this->_sqlParameters[$i])) {
$parameters = isset($this->_sqlParameters[$i]['parameters']) ? $this->_sqlParameters[$i]['parameters'] : array();
$types = isset($this->_sqlParameters[$i]['types']) ? $this->_sqlParameters[$i]['types'] : array();
if (isset($this->_sqlParameters[$key])) {
foreach ($this->_sqlParameters[$key] as $parameterKey => $parameterName) {
$paramValues[] = $params[$parameterKey];
$paramTypes[] = isset($types[$parameterKey]) ? $types[$parameterKey] : ParameterTypeInferer::inferType($params[$parameterKey]);
}
}
$conn->executeUpdate($this->_sqlStatements[$i], $parameters, $types);
$conn->executeUpdate($statement, $paramValues, $paramTypes);
}
} catch (\Exception $exception) {
// FAILURE! Drop temporary table to avoid possible collisions

View File

@@ -83,7 +83,7 @@ abstract class Base
*/
public function add($arg)
{
if ( $arg !== null || ($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

@@ -141,7 +141,7 @@ class Join
{
return strtoupper($this->joinType) . ' JOIN ' . $this->join
. ($this->alias ? ' ' . $this->alias : '')
. ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : '')
. ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '');
. ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '')
. ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : '');
}
}

View File

@@ -19,9 +19,9 @@
namespace Doctrine\ORM\Query\Filter;
use Doctrine\ORM\EntityManager,
Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\ParameterTypeInferer;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\ParameterTypeInferer;
/**
* The base class that user defined filters should extend.

View File

@@ -750,7 +750,10 @@ class SqlWalker implements TreeWalker
$sqlParts = array();
foreach ($identificationVarDecls as $identificationVariableDecl) {
$sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration);
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
foreach ($identificationVariableDecl->joins as $join) {
$sql .= $this->walkJoin($join);
@@ -770,7 +773,7 @@ class SqlWalker implements TreeWalker
}
}
$sqlParts[] = $this->platform->appendLockHint($sql, $this->query->getHint(Query::HINT_LOCK_MODE));
$sqlParts[] = $sql;
}
return ' FROM ' . implode(', ', $sqlParts);
@@ -1007,8 +1010,13 @@ class SqlWalker implements TreeWalker
switch (true) {
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\RangeVariableDeclaration):
$class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName);
$condExprConjunction = $class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER
? ' AND '
: ' ON ';
$sql .= $this->walkRangeVariableDeclaration($joinDeclaration)
. ' ON (' . $this->walkConditionalExpression($join->conditionalExpression) . ')';
. $condExprConjunction . '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')';
break;
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\JoinAssociationDeclaration):
@@ -1147,7 +1155,7 @@ class SqlWalker implements TreeWalker
switch (true) {
case ($expr instanceof AST\PathExpression):
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
throw QueryException::invalidPathExpression($expr->type);
throw QueryException::invalidPathExpression($expr);
}
$fieldName = $expr->field;
@@ -1188,7 +1196,6 @@ class SqlWalker implements TreeWalker
case ($expr instanceof AST\SimpleArithmeticExpression):
case ($expr instanceof AST\ArithmeticTerm):
case ($expr instanceof AST\ArithmeticFactor):
case ($expr instanceof AST\ArithmeticPrimary):
case ($expr instanceof AST\Literal):
case ($expr instanceof AST\NullIfExpression):
case ($expr instanceof AST\CoalesceExpression):
@@ -1363,13 +1370,16 @@ class SqlWalker implements TreeWalker
$sqlParts = array ();
foreach ($identificationVarDecls as $subselectIdVarDecl) {
$sql = $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration);
$sql = $this->platform->appendLockHint(
$this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration),
$this->query->getHint(Query::HINT_LOCK_MODE)
);
foreach ($subselectIdVarDecl->joins as $join) {
$sql .= $this->walkJoin($join);
}
$sqlParts[] = $this->platform->appendLockHint($sql, $this->query->getHint(Query::HINT_LOCK_MODE));
$sqlParts[] = $sql;
}
return ' FROM ' . implode(', ', $sqlParts);
@@ -1422,7 +1432,6 @@ class SqlWalker implements TreeWalker
case ($expr instanceof AST\SimpleArithmeticExpression):
case ($expr instanceof AST\ArithmeticTerm):
case ($expr instanceof AST\ArithmeticFactor):
case ($expr instanceof AST\ArithmeticPrimary):
case ($expr instanceof AST\Literal):
case ($expr instanceof AST\NullIfExpression):
case ($expr instanceof AST\CoalesceExpression):
@@ -1609,7 +1618,7 @@ class SqlWalker implements TreeWalker
if (count($filterClauses)) {
if ($condSql) {
$condSql .= ' AND ';
$condSql = '(' . $condSql . ') AND ';
}
$condSql .= implode(' AND ', $filterClauses);
@@ -1907,31 +1916,22 @@ class SqlWalker implements TreeWalker
foreach ($instanceOfExpr->value as $parameter) {
if ($parameter instanceof AST\InputParameter) {
// We need to modify the parameter value to be its correspondent mapped value
$dqlParamKey = $parameter->name;
$dqlParam = $this->query->getParameter($dqlParamKey);
$paramValue = $this->query->processParameterValue($dqlParam->getValue());
if ( ! ($paramValue instanceof \Doctrine\ORM\Mapping\ClassMetadata)) {
throw QueryException::invalidParameterType('ClassMetadata', get_class($paramValue));
}
$entityClassName = $paramValue->name;
$sqlParameterList[] = $this->walkInputParameter($parameter);
} else {
// Get name from ClassMetadata to resolve aliases.
$entityClassName = $this->em->getClassMetadata($parameter)->name;
}
if ($entityClassName == $class->name) {
$sqlParameterList[] = $this->conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
if ($entityClassName == $class->name) {
$sqlParameterList[] = $this->conn->quote($class->discriminatorValue);
} else {
$discrMap = array_flip($class->discriminatorMap);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
if (!isset($discrMap[$entityClassName])) {
throw QueryException::instanceOfUnrelatedClass($entityClassName, $class->rootEntityName);
}
$sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
}
$sqlParameterList[] = $this->conn->quote($discrMap[$entityClassName]);
}
}

View File

@@ -157,6 +157,38 @@ class EntityGenerator
Type::SIMPLE_ARRAY => 'array',
);
/**
* @var array Hash-map to handle generator types string.
*/
protected static $generatorStrategyMap = array(
ClassMetadataInfo::GENERATOR_TYPE_AUTO => 'AUTO',
ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE => 'SEQUENCE',
ClassMetadataInfo::GENERATOR_TYPE_TABLE => 'TABLE',
ClassMetadataInfo::GENERATOR_TYPE_IDENTITY => 'IDENTITY',
ClassMetadataInfo::GENERATOR_TYPE_NONE => 'NONE',
ClassMetadataInfo::GENERATOR_TYPE_UUID => 'UUID',
ClassMetadataInfo::GENERATOR_TYPE_CUSTOM => 'CUSTOM'
);
/**
* @var array Hash-map to handle the change tracking policy string.
*/
protected static $changeTrackingPolicyMap = array(
ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT => 'DEFERRED_IMPLICIT',
ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT => 'DEFERRED_EXPLICIT',
ClassMetadataInfo::CHANGETRACKING_NOTIFY => 'NOTIFY',
);
/**
* @var array Hash-map to handle the inheritance type string.
*/
protected static $inheritanceTypeMap = array(
ClassMetadataInfo::INHERITANCE_TYPE_NONE => 'NONE',
ClassMetadataInfo::INHERITANCE_TYPE_JOINED => 'JOINED',
ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE => 'SINGLE_TABLE',
ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS => 'TABLE_PER_CLASS',
);
/**
* @var string
*/
@@ -672,7 +704,7 @@ public function __construct()
{
$lines = array();
$lines[] = '/**';
$lines[] = ' * '.$metadata->name;
$lines[] = ' * ' . $this->getClassName($metadata);
if ($this->generateAnnotations) {
$lines[] = ' *';
@@ -909,9 +941,14 @@ public function __construct()
$var = sprintf('%sMethodTemplate', $type);
$template = self::$$var;
$methodTypeHint = null;
$types = Type::getTypesMap();
$variableType = $typeHint ? $this->getType($typeHint) . ' ' : null;
$methodTypeHint = $typeHint && ! isset($types[$typeHint]) ? '\\' . $typeHint . ' ' : null;
if ($typeHint && ! isset($types[$typeHint])) {
$variableType = '\\' . ltrim($variableType, '\\');
$methodTypeHint = '\\' . $typeHint . ' ';
}
$replacements = array(
'<description>' => ucfirst($type) . ' ' . $fieldName,
@@ -991,9 +1028,9 @@ public function __construct()
$lines[] = $this->spaces . '/**';
if ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) {
$lines[] = $this->spaces . ' * @var \Doctrine\Common\Collections\ArrayCollection';
$lines[] = $this->spaces . ' * @var \Doctrine\Common\Collections\Collection';
} else {
$lines[] = $this->spaces . ' * @var ' . $associationMapping['targetEntity'];
$lines[] = $this->spaces . ' * @var \\' . ltrim($associationMapping['targetEntity'], '\\');
}
if ($this->generateAnnotations) {
@@ -1052,6 +1089,15 @@ public function __construct()
$typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false');
}
if (isset($associationMapping['fetch']) && $associationMapping['fetch'] !== ClassMetadataInfo::FETCH_LAZY) {
$fetchMap = array(
ClassMetadataInfo::FETCH_EXTRA_LAZY => 'EXTRA_LAZY',
ClassMetadataInfo::FETCH_EAGER => 'EAGER',
);
$typeOptions[] = 'fetch="' . $fetchMap[$associationMapping['fetch']] . '"';
}
$lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . '' . $type . '(' . implode(', ', $typeOptions) . ')';
if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) {
@@ -1080,17 +1126,23 @@ public function __construct()
$lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinTable(' . implode(', ', $joinTable) . ',';
$lines[] = $this->spaces . ' * joinColumns={';
$joinColumnsLines = array();
foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) {
$lines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn);
$joinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn);
}
$lines[] = implode(",". PHP_EOL, $joinColumnsLines);
$lines[] = $this->spaces . ' * },';
$lines[] = $this->spaces . ' * inverseJoinColumns={';
$inverseJoinColumnsLines = array();
foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn) {
$lines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn);
$inverseJoinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn);
}
$lines[] = implode(",". PHP_EOL, $inverseJoinColumnsLines);
$lines[] = $this->spaces . ' * }';
$lines[] = $this->spaces . ' * )';
}
@@ -1116,7 +1168,7 @@ public function __construct()
{
$lines = array();
$lines[] = $this->spaces . '/**';
$lines[] = $this->spaces . ' * @var ' . $this->getType($fieldMapping['type']) . ' $' . $fieldMapping['fieldName'];
$lines[] = $this->spaces . ' * @var ' . $this->getType($fieldMapping['type']);
if ($this->generateAnnotations) {
$lines[] = $this->spaces . ' *';
@@ -1203,63 +1255,45 @@ public function __construct()
return implode("\n", $lines);
}
private function getInheritanceTypeString($type)
/**
* @param integer $type The inheritance type used by the class and it's subclasses.
* @return string The literal string for the inheritance type.
* @throws \InvalidArgumentException When the inheritance type does not exists.
*/
protected function getInheritanceTypeString($type)
{
switch ($type) {
case ClassMetadataInfo::INHERITANCE_TYPE_NONE:
return 'NONE';
case ClassMetadataInfo::INHERITANCE_TYPE_JOINED:
return 'JOINED';
case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE:
return 'SINGLE_TABLE';
case ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS:
return 'PER_CLASS';
default:
throw new \InvalidArgumentException('Invalid provided InheritanceType: ' . $type);
if ( ! isset(self::$inheritanceTypeMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type));
}
return self::$inheritanceTypeMap[$type];
}
private function getChangeTrackingPolicyString($policy)
/**
* @param integer $type The policy used for change-tracking for the mapped class.
* @return string The literal string for the change-tracking type.
* @throws \InvalidArgumentException When the change-tracking type does not exists.
*/
protected function getChangeTrackingPolicyString($type)
{
switch ($policy) {
case ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT:
return 'DEFERRED_IMPLICIT';
case ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT:
return 'DEFERRED_EXPLICIT';
case ClassMetadataInfo::CHANGETRACKING_NOTIFY:
return 'NOTIFY';
default:
throw new \InvalidArgumentException('Invalid provided ChangeTrackingPolicy: ' . $policy);
if ( ! isset(self::$changeTrackingPolicyMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type));
}
return self::$changeTrackingPolicyMap[$type];
}
private function getIdGeneratorTypeString($type)
/**
* @param integer $type The generator to use for the mapped class.
* @return string The literal string for the generetor type.
* @throws \InvalidArgumentException When the generator type does not exists.
*/
protected function getIdGeneratorTypeString($type)
{
switch ($type) {
case ClassMetadataInfo::GENERATOR_TYPE_AUTO:
return 'AUTO';
case ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE:
return 'SEQUENCE';
case ClassMetadataInfo::GENERATOR_TYPE_TABLE:
return 'TABLE';
case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY:
return 'IDENTITY';
case ClassMetadataInfo::GENERATOR_TYPE_NONE:
return 'NONE';
default:
throw new \InvalidArgumentException('Invalid provided IdGeneratorType: ' . $type);
if ( ! isset(self::$generatorStrategyMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type));
}
return self::$generatorStrategyMap[$type];
}
}

View File

@@ -76,10 +76,12 @@ class XmlExporter extends AbstractExporter
}
if ($metadata->discriminatorColumn) {
$discriminatorColumnXml = $root->addChild('discriminiator-column');
$discriminatorColumnXml = $root->addChild('discriminator-column');
$discriminatorColumnXml->addAttribute('name', $metadata->discriminatorColumn['name']);
$discriminatorColumnXml->addAttribute('type', $metadata->discriminatorColumn['type']);
$discriminatorColumnXml->addAttribute('length', $metadata->discriminatorColumn['length']);
if (isset($metadata->discriminatorColumn['length'])) {
$discriminatorColumnXml->addAttribute('length', $metadata->discriminatorColumn['length']);
}
}
if ($metadata->discriminatorMap) {
@@ -109,9 +111,9 @@ class XmlExporter extends AbstractExporter
if (isset($metadata->table['uniqueConstraints'])) {
$uniqueConstraintsXml = $root->addChild('unique-constraints');
foreach ($metadata->table['uniqueConstraints'] as $unique) {
foreach ($metadata->table['uniqueConstraints'] as $name => $unique) {
$uniqueConstraintXml = $uniqueConstraintsXml->addChild('unique-constraint');
$uniqueConstraintXml->addAttribute('name', $unique['name']);
$uniqueConstraintXml->addAttribute('name', $name);
$uniqueConstraintXml->addAttribute('columns', implode(',', $unique['columns']));
}
}
@@ -138,9 +140,15 @@ class XmlExporter extends AbstractExporter
if (isset($field['columnName'])) {
$idXml->addAttribute('column', $field['columnName']);
}
if (isset($field['length'])) {
$idXml->addAttribute('length', $field['length']);
}
if (isset($field['associationKey']) && $field['associationKey']) {
$idXml->addAttribute('association-key', 'true');
}
if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
$generatorXml = $idXml->addChild('generator');
$generatorXml->addAttribute('strategy', $idGeneratorType);
@@ -180,6 +188,9 @@ class XmlExporter extends AbstractExporter
if (isset($field['columnDefinition'])) {
$fieldXml->addAttribute('column-definition', $field['columnDefinition']);
}
if (isset($field['nullable'])) {
$fieldXml->addAttribute('nullable', $field['nullable'] ? 'true' : 'false');
}
}
}
$orderMap = array(

View File

@@ -74,6 +74,10 @@ class CountOutputWalker extends SqlWalker
*/
public function walkSelectStatement(SelectStatement $AST)
{
if ($this->platform->getName() === "mssql") {
$AST->orderByClause = null;
}
$sql = parent::walkSelectStatement($AST);
// Find out the SQL alias of the identifier column of the root entity

View File

@@ -13,8 +13,9 @@
namespace Doctrine\ORM\Tools\Pagination;
use Doctrine\ORM\Query\SqlWalker,
Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
/**
* Wrap the query in order to select root entity IDs for pagination
@@ -85,7 +86,7 @@ class LimitSubqueryOutputWalker extends SqlWalker
*/
public function walkSelectStatement(SelectStatement $AST)
{
$sql = parent::walkSelectStatement($AST);
$innerSql = parent::walkSelectStatement($AST);
// Find out the SQL alias of the identifier column of the root entity
// It may be possible to make this work with multiple root entities but that
@@ -133,7 +134,12 @@ class LimitSubqueryOutputWalker extends SqlWalker
// Build the counter query
$sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result',
implode(', ', $sqlIdentifier), $sql);
implode(', ', $sqlIdentifier), $innerSql);
if ($this->platform instanceof PostgreSqlPlatform) {
//http://www.doctrine-project.org/jira/browse/DDC-1958
$this->getPostgresqlSql($AST, $sqlIdentifier, $innerSql, $sql);
}
// Apply the limit and offset
$sql = $this->platform->modifyLimitQuery(
@@ -150,4 +156,47 @@ class LimitSubqueryOutputWalker extends SqlWalker
return $sql;
}
/**
* Generate new SQL for postgresql if necessary
*
* @param SelectStatement $AST
* @param array sqlIdentifier
* @param string $sql
*/
public function getPostgresqlSql(SelectStatement $AST, array $sqlIdentifier, $innerSql, &$sql)
{
// For every order by, find out the SQL alias by inspecting the ResultSetMapping
$sqlOrderColumns = array();
$orderBy = array();
if (isset($AST->orderByClause)) {
foreach ($AST->orderByClause->orderByItems as $item) {
$possibleAliases = array_keys($this->rsm->fieldMappings, $item->expression->field);
foreach ($possibleAliases as $alias) {
if ($this->rsm->columnOwnerMap[$alias] == $item->expression->identificationVariable) {
$sqlOrderColumns[] = $alias;
$orderBy[] = $alias . ' ' . $item->type;
break;
}
}
}
//remove identifier aliases
$sqlOrderColumns = array_diff($sqlOrderColumns, $sqlIdentifier);
}
//we don't need orderBy in inner query
//However at least on 5.4.6 I'm getting a segmentation fault and thus we don't clear it for now
/*$AST->orderByClause = null;
$innerSql = parent::walkSelectStatement($AST);*/
if (count($orderBy)) {
$sql = sprintf(
'SELECT DISTINCT %s FROM (%s) dctrn_result ORDER BY %s',
implode(', ', array_merge($sqlIdentifier, $sqlOrderColumns)),
$innerSql,
implode(', ', $orderBy)
);
}
}
}

View File

@@ -174,18 +174,15 @@ class Paginator implements \Countable, \IteratorAggregate
$whereInQuery = $this->cloneQuery($this->query);
// don't do this for an empty id array
if (count($ids) > 0) {
$namespace = WhereInWalker::PAGINATOR_ID_ALIAS;
$whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\WhereInWalker'));
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids));
$whereInQuery->setFirstResult(null)->setMaxResults(null);
foreach ($ids as $i => $id) {
$i++;
$whereInQuery->setParameter("{$namespace}_{$i}", $id);
}
if (count($ids) == 0) {
return new \ArrayIterator(array());
}
$whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\WhereInWalker'));
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids));
$whereInQuery->setFirstResult(null)->setMaxResults(null);
$whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids);
$result = $whereInQuery->getResult($this->query->getHydrationMode());
} else {
$result = $this->cloneQuery($this->query)

View File

@@ -102,11 +102,8 @@ class WhereInWalker extends TreeWalkerAdapter
array($pathExpression)
);
$expression = new InExpression($arithmeticExpression);
$ns = self::PAGINATOR_ID_ALIAS;
$expression->literals[] = new InputParameter(":" . self::PAGINATOR_ID_ALIAS);
for ($i = 1; $i <= $count; $i++) {
$expression->literals[] = new InputParameter(":{$ns}_$i");
}
} else {
$expression = new NullComparisonExpression($pathExpression);
$expression->not = false;

View File

@@ -73,6 +73,7 @@ class ResolveTargetEntityListener
$newMapping = $this->resolveTargetEntities[$mapping['targetEntity']];
$newMapping = array_replace_recursive($mapping, $newMapping);
$newMapping['fieldName'] = $mapping['fieldName'];
unset($classMetadata->associationMappings[$mapping['fieldName']]);
switch ($mapping['type']) {

View File

@@ -385,6 +385,16 @@ class SchemaTool
}
if (isset($mapping['options'])) {
$knownOptions = array('comment', 'unsigned', 'fixed', 'default');
foreach ($knownOptions as $knownOption) {
if ( isset($mapping['options'][$knownOption])) {
$options[$knownOption] = $mapping['options'][$knownOption];
unset($mapping['options'][$knownOption]);
}
}
$options['customSchemaOptions'] = $mapping['options'];
}
@@ -546,6 +556,11 @@ class SchemaTool
if (isset($joinColumn['nullable'])) {
$columnOptions['notnull'] = !$joinColumn['nullable'];
}
if (isset($fieldMapping['options'])) {
$columnOptions['options'] = $fieldMapping['options'];
}
if ($fieldMapping['type'] == "string" && isset($fieldMapping['length'])) {
$columnOptions['length'] = $fieldMapping['length'];
} else if ($fieldMapping['type'] == "decimal") {

View File

@@ -63,6 +63,9 @@ class Setup
* Use this method to register all autoloaders for a setup where Doctrine is installed
* though {@link http://pear.doctrine-project.org}.
*
* This method registers autoloaders for both Doctrine and Symfony top
* level namespaces.
*
* @return void
*/
static public function registerAutoloadPEAR()
@@ -74,15 +77,8 @@ class Setup
$loader = new ClassLoader("Doctrine");
$loader->register();
$parts = explode(PATH_SEPARATOR, get_include_path());
foreach ($parts as $includePath) {
if ($includePath != "." && file_exists($includePath . "/Doctrine")) {
$loader = new ClassLoader("Symfony\Component", $includePath . "/Doctrine");
$loader->register();
return;
}
}
$loader = new ClassLoader("Symfony");
$loader->register();
}
/**

View File

@@ -67,6 +67,13 @@ class UnitOfWork implements PropertyChangedListener
*/
const STATE_REMOVED = 4;
/**
* Hint used to collect all primary keys of associated entities during hydration
* and execute it in a dedicated query afterwards
* @see https://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html?highlight=eager#temporarily-change-fetch-mode-in-dql
*/
const HINT_DEFEREAGERLOAD = 'deferEagerLoad';
/**
* The identity map that holds references to all managed entities that have
* an identity. The entities are grouped by their class name.
@@ -206,7 +213,7 @@ class UnitOfWork implements PropertyChangedListener
/**
* The EventManager used for dispatching events.
*
* @var EventManager
* @var \Doctrine\Common\EventManager
*/
private $evm;
@@ -256,6 +263,9 @@ class UnitOfWork implements PropertyChangedListener
* 5) All entity deletions
*
* @param null|object|array $entity
*
* @throws \Exception
*
* @return void
*/
public function commit($entity = null)
@@ -390,17 +400,22 @@ class UnitOfWork implements PropertyChangedListener
* 4. Only if entity is properly managed.
*
* @param object $entity
*
* @throws \InvalidArgumentException
*
* @return void
*/
private function computeSingleEntityChangeSet($entity)
{
if ( $this->getEntityState($entity) !== self::STATE_MANAGED) {
throw new \InvalidArgumentException("Entity has to be managed for single computation " . self::objToStr($entity));
$state = $this->getEntityState($entity);
if ($state !== self::STATE_MANAGED && $state !== self::STATE_REMOVED) {
throw new \InvalidArgumentException("Entity has to be managed or scheduled for removal for single computation " . self::objToStr($entity));
}
$class = $this->em->getClassMetadata(get_class($entity));
if ($class->isChangeTrackingDeferredImplicit()) {
if ($state === self::STATE_MANAGED && $class->isChangeTrackingDeferredImplicit()) {
$this->persist($entity);
}
@@ -440,6 +455,8 @@ class UnitOfWork implements PropertyChangedListener
/**
* Gets the changeset for an entity.
*
* @param object $entity
*
* @return array
*/
public function getEntityChangeSet($entity)
@@ -708,8 +725,13 @@ class UnitOfWork implements PropertyChangedListener
/**
* Computes the changes of an association.
*
* @param AssociationMapping $assoc
* @param array $assoc
* @param mixed $value The value of the association.
*
* @throws ORMInvalidArgumentException
* @throws ORMException
*
* @return void
*/
private function computeAssociationChanges($assoc, $value)
{
@@ -779,6 +801,10 @@ class UnitOfWork implements PropertyChangedListener
}
}
/**
* @param ClassMetadata $class
* @param object $entity
*/
private function persistNew($class, $entity)
{
$oid = spl_object_hash($entity);
@@ -822,7 +848,8 @@ class UnitOfWork implements PropertyChangedListener
* @ignore
* @param ClassMetadata $class The class descriptor of the entity.
* @param object $entity The entity for which to (re)calculate the change set.
* @throws InvalidArgumentException If the passed entity is not MANAGED.
*
* @throws ORMInvalidArgumentException If the passed entity is not MANAGED.
*/
public function recomputeSingleEntityChangeSet(ClassMetadata $class, $entity)
{
@@ -962,7 +989,7 @@ class UnitOfWork implements PropertyChangedListener
);
}
if ($this->entityChangeSets[$oid]) {
if (!empty($this->entityChangeSets[$oid])) {
$persister->update($entity);
}
@@ -1025,6 +1052,8 @@ class UnitOfWork implements PropertyChangedListener
/**
* Gets the commit order.
*
* @param array $entityChangeSet
*
* @return array
*/
private function getCommitOrder(array $entityChangeSet = null)
@@ -1099,6 +1128,9 @@ class UnitOfWork implements PropertyChangedListener
* If the entity already has an identifier, it will be added to the identity map.
*
* @param object $entity The entity to schedule for insertion.
*
* @throws ORMInvalidArgumentException
* @throws \InvalidArgumentException
*/
public function scheduleForInsert($entity)
{
@@ -1134,6 +1166,7 @@ class UnitOfWork implements PropertyChangedListener
* Checks whether an entity is scheduled for insertion.
*
* @param object $entity
*
* @return boolean
*/
public function isScheduledForInsert($entity)
@@ -1145,6 +1178,8 @@ class UnitOfWork implements PropertyChangedListener
* Schedules an entity for being updated.
*
* @param object $entity The entity to schedule for being updated.
*
* @throws ORMInvalidArgumentException
*/
public function scheduleForUpdate($entity)
{
@@ -1194,6 +1229,7 @@ class UnitOfWork implements PropertyChangedListener
* at commit time.
*
* @param object $entity
*
* @return boolean
*/
public function isScheduledForUpdate($entity)
@@ -1206,6 +1242,7 @@ class UnitOfWork implements PropertyChangedListener
* Checks whether an entity is registered to be checked in the unit of work.
*
* @param object $entity
*
* @return boolean
*/
public function isScheduledForDirtyCheck($entity)
@@ -1256,6 +1293,7 @@ class UnitOfWork implements PropertyChangedListener
* of work.
*
* @param object $entity
*
* @return boolean
*/
public function isScheduledForDelete($entity)
@@ -1267,6 +1305,7 @@ class UnitOfWork implements PropertyChangedListener
* Checks whether an entity is scheduled for insertion, update or deletion.
*
* @param $entity
*
* @return boolean
*/
public function isEntityScheduled($entity)
@@ -1286,6 +1325,9 @@ class UnitOfWork implements PropertyChangedListener
*
* @ignore
* @param object $entity The entity to register.
*
* @throws ORMInvalidArgumentException
*
* @return boolean TRUE if the registration was successful, FALSE if the identity of
* the entity in question is already managed.
*/
@@ -1317,6 +1359,7 @@ class UnitOfWork implements PropertyChangedListener
* This parameter can be set to improve performance of entity state detection
* by potentially avoiding a database lookup if the distinction between NEW and DETACHED
* is either known or does not matter for the caller of the method.
*
* @return int The entity state.
*/
public function getEntityState($entity, $assume = null)
@@ -1342,6 +1385,10 @@ class UnitOfWork implements PropertyChangedListener
return self::STATE_NEW;
}
if ($class->containsForeignIdentifier) {
$id = $this->flattenIdentifier($class, $id);
}
switch (true) {
case ($class->isIdentifierNatural());
// Check for a version field, if available, to avoid a db lookup.
@@ -1392,6 +1439,9 @@ class UnitOfWork implements PropertyChangedListener
*
* @ignore
* @param object $entity
*
* @throws ORMInvalidArgumentException
*
* @return boolean
*/
public function removeFromIdentityMap($entity)
@@ -1425,6 +1475,7 @@ class UnitOfWork implements PropertyChangedListener
* @ignore
* @param string $idHash
* @param string $rootClassName
*
* @return object
*/
public function getByIdHash($idHash, $rootClassName)
@@ -1440,6 +1491,7 @@ class UnitOfWork implements PropertyChangedListener
* @ignore
* @param string $idHash
* @param string $rootClassName
*
* @return mixed The found entity or FALSE.
*/
public function tryGetByIdHash($idHash, $rootClassName)
@@ -1455,6 +1507,7 @@ class UnitOfWork implements PropertyChangedListener
* Checks whether an entity is registered in the identity map of this UnitOfWork.
*
* @param object $entity
*
* @return boolean
*/
public function isInIdentityMap($entity)
@@ -1482,6 +1535,7 @@ class UnitOfWork implements PropertyChangedListener
* @ignore
* @param string $idHash
* @param string $rootClassName
*
* @return boolean
*/
public function containsIdHash($idHash, $rootClassName)
@@ -1509,6 +1563,9 @@ class UnitOfWork implements PropertyChangedListener
*
* @param object $entity The entity to persist.
* @param array $visited The already visited entities.
*
* @throws ORMInvalidArgumentException
* @throws UnexpectedValueException
*/
private function doPersist($entity, array &$visited)
{
@@ -1578,7 +1635,9 @@ class UnitOfWork implements PropertyChangedListener
*
* @param object $entity The entity to delete.
* @param array $visited The map of the already visited entities.
* @throws InvalidArgumentException If the instance is a detached entity.
*
* @throws ORMInvalidArgumentException If the instance is a detached entity.
* @throws UnexpectedValueException
*/
private function doRemove($entity, array &$visited)
{
@@ -1627,10 +1686,12 @@ class UnitOfWork implements PropertyChangedListener
* Merges the state of the given detached entity into this UnitOfWork.
*
* @param object $entity
* @return object The managed copy of the entity.
*
* @throws OptimisticLockException If the entity uses optimistic locking through a version
* attribute and the version check against the managed copy fails.
*
* @return object The managed copy of the entity.
*
* @todo Require active transaction!? OptimisticLockException may result in undefined state!?
*/
public function merge($entity)
@@ -1640,15 +1701,43 @@ class UnitOfWork implements PropertyChangedListener
return $this->doMerge($entity, $visited);
}
/**
* convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures.
*
* @param ClassMetadata $class
* @param array $id
* @return array
*/
private function flattenIdentifier($class, $id)
{
$flatId = array();
foreach ($id as $idField => $idValue) {
if (isset($class->associationMappings[$idField])) {
$targetClassMetadata = $this->em->getClassMetadata($class->associationMappings[$idField]['targetEntity']);
$associatedId = $this->getEntityIdentifier($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
}
}
return $flatId;
}
/**
* Executes a merge operation on an entity.
*
* @param object $entity
* @param array $visited
* @return object The managed copy of the entity.
* @param object $prevManagedCopy
* @param array $assoc
*
* @throws OptimisticLockException If the entity uses optimistic locking through a version
* attribute and the version check against the managed copy fails.
* @throws InvalidArgumentException If the entity instance is NEW.
* @throws ORMInvalidArgumentException If the entity instance is NEW.
* @throws EntityNotFoundException
*
* @return object The managed copy of the entity.
*/
private function doMerge($entity, array &$visited, $prevManagedCopy = null, $assoc = null)
{
@@ -1682,19 +1771,9 @@ class UnitOfWork implements PropertyChangedListener
$this->persistNew($class, $managedCopy);
} else {
$flatId = $id;
if ($class->containsForeignIdentifier) {
// convert foreign identifiers into scalar foreign key
// values to avoid object to string conversion failures.
foreach ($id as $idField => $idValue) {
if (isset($class->associationMappings[$idField])) {
$targetClassMetadata = $this->em->getClassMetadata($class->associationMappings[$idField]['targetEntity']);
$associatedId = $this->getEntityIdentifier($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
}
}
}
$flatId = ($class->containsForeignIdentifier)
? $this->flattenIdentifier($class, $id)
: $id;
$managedCopy = $this->tryGetById($flatId, $class->rootEntityName);
@@ -1754,7 +1833,7 @@ class UnitOfWork implements PropertyChangedListener
// do not merge fields marked lazy that have not been fetched.
continue;
} else if ( ! $assoc2['isCascadeMerge']) {
if ($this->getEntityState($other, self::STATE_DETACHED) !== self::STATE_MANAGED) {
if ($this->getEntityState($other) === self::STATE_DETACHED) {
$targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
$relatedId = $targetClass->getIdentifierValues($other);
@@ -1765,6 +1844,7 @@ class UnitOfWork implements PropertyChangedListener
$this->registerManaged($other, $relatedId, array());
}
}
$prop->setValue($managedCopy, $other);
}
} else {
@@ -1895,6 +1975,7 @@ class UnitOfWork implements PropertyChangedListener
* any local, unpersisted changes.
*
* @param object $entity The entity to refresh.
*
* @throws InvalidArgumentException If the entity is not MANAGED.
*/
public function refresh($entity)
@@ -1909,7 +1990,8 @@ class UnitOfWork implements PropertyChangedListener
*
* @param object $entity The entity to refresh.
* @param array $visited The already visited entities during cascades.
* @throws InvalidArgumentException If the entity is not MANAGED.
*
* @throws ORMInvalidArgumentException If the entity is not MANAGED.
*/
private function doRefresh($entity, array &$visited)
{
@@ -2060,7 +2142,8 @@ class UnitOfWork implements PropertyChangedListener
*
* @param object $entity
* @param array $visited
* @param array $insertNow
*
* @return void
*/
private function cascadePersist($entity, array &$visited)
{
@@ -2144,9 +2227,19 @@ class UnitOfWork implements PropertyChangedListener
* @param object $entity
* @param int $lockMode
* @param int $lockVersion
*
* @throws ORMInvalidArgumentException
* @throws TransactionRequiredException
* @throws OptimisticLockException
*
* @return void
*/
public function lock($entity, $lockMode, $lockVersion = null)
{
if ($entity === null) {
throw new \InvalidArgumentException("No entity passed to UnitOfWork#lock().");
}
if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) {
throw ORMInvalidArgumentException::entityNotManaged($entity);
}
@@ -2279,13 +2372,20 @@ class UnitOfWork implements PropertyChangedListener
$this->collectionDeletions[$coid] = $coll;
}
/**
* @param PersistentCollection $coll
*
* @return bool
*/
public function isCollectionScheduledForDeletion(PersistentCollection $coll)
{
return isset($this->collectionsDeletions[spl_object_hash($coll)]);
return isset($this->collectionDeletions[spl_object_hash($coll)]);
}
/**
* @param ClassMetadata $class
*
* @return \Doctrine\Common\Persistence\ObjectManagerAware|object
*/
private function newInstance($class)
{
@@ -2306,6 +2406,7 @@ class UnitOfWork implements PropertyChangedListener
* @param string $className The name of the entity class.
* @param array $data The data for the entity.
* @param array $hints Any hints to account for during reconstitution/lookup of the entity.
*
* @return object The managed entity instance.
* @internal Highly performance-sensitive method.
*
@@ -2345,17 +2446,23 @@ class UnitOfWork implements PropertyChangedListener
if ($entity instanceof NotifyPropertyChanged) {
$entity->addPropertyChangedListener($this);
}
// inject ObjectManager into just loaded proxies.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
} else {
$overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
// If only a specific entity is set to refresh, check that it's the one
if(isset($hints[Query::HINT_REFRESH_ENTITY])) {
$overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity;
}
// inject ObjectManager into just loaded proxies.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
// inject ObjectManager upon refresh.
if ($overrideLocalValues && $entity instanceof ObjectManagerAware) {
$entity->injectObjectManager($this->em, $class);
}
}
@@ -2459,7 +2566,7 @@ class UnitOfWork implements PropertyChangedListener
// this association is marked as eager fetch, and its an uninitialized proxy (wtf!)
// then we can append this entity for eager loading!
if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER &&
isset($hints['deferEagerLoad']) &&
isset($hints[self::HINT_DEFEREAGERLOAD]) &&
!$targetClass->isIdentifierComposite &&
$newValue instanceof Proxy &&
$newValue->__isInitialized__ === false) {
@@ -2484,7 +2591,7 @@ class UnitOfWork implements PropertyChangedListener
break;
// Deferred eager load only works for single identifier classes
case (isset($hints['deferEagerLoad']) && ! $targetClass->isIdentifierComposite):
case (isset($hints[self::HINT_DEFEREAGERLOAD]) && ! $targetClass->isIdentifierComposite):
// TODO: Is there a faster approach?
$this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);
@@ -2501,6 +2608,10 @@ class UnitOfWork implements PropertyChangedListener
$newValueOid = spl_object_hash($newValue);
$this->entityIdentifiers[$newValueOid] = $associatedId;
$this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue;
if ($newValue instanceof NotifyPropertyChanged) {
$newValue->addPropertyChangedListener($this);
}
$this->entityStates[$newValueOid] = self::STATE_MANAGED;
// make sure that when an proxy is then finally loaded, $this->originalEntityData is set also!
break;
@@ -2578,7 +2689,9 @@ class UnitOfWork implements PropertyChangedListener
/**
* Initializes (loads) an uninitialized persistent collection of an entity.
*
* @param PeristentCollection $collection The collection to initialize.
* @param \Doctrine\ORM\PersistentCollection $collection The collection to initialize.
*
* @return void
* @todo Maybe later move to EntityManager#initialize($proxyOrCollection). See DDC-733.
*/
public function loadCollection(PersistentCollection $collection)
@@ -2612,6 +2725,7 @@ class UnitOfWork implements PropertyChangedListener
* present at the time the entity was reconstituted from the database.
*
* @param object $entity
*
* @return array
*/
public function getOriginalEntityData($entity)
@@ -2654,6 +2768,7 @@ class UnitOfWork implements PropertyChangedListener
* order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames().
*
* @param object $entity
*
* @return array The identifier values.
*/
public function getEntityIdentifier($entity)
@@ -2667,6 +2782,7 @@ class UnitOfWork implements PropertyChangedListener
*
* @param mixed $id The entity identifier to look for.
* @param string $rootClassName The name of the root class of the mapped entity hierarchy.
*
* @return mixed Returns the entity with the specified identifier if it exists in
* this UnitOfWork, FALSE otherwise.
*/
@@ -2757,9 +2873,9 @@ class UnitOfWork implements PropertyChangedListener
/**
* Gets a collection persister for a collection-valued association.
*
* @param AssociationMapping $association
* @param array $association
*
* @return AbstractCollectionPersister
* @return \Doctrine\ORM\Persisters\AbstractCollectionPersister
*/
public function getCollectionPersister(array $association)
{
@@ -2901,6 +3017,7 @@ class UnitOfWork implements PropertyChangedListener
* Helper method to initialize a lazy loading proxy or persistent collection.
*
* @param object
*
* @return void
*/
public function initializeObject($obj)
@@ -2920,6 +3037,7 @@ class UnitOfWork implements PropertyChangedListener
* Helper method to show an object as string.
*
* @param object $obj
*
* @return string
*/
private static function objToStr($obj)
@@ -2931,10 +3049,13 @@ class UnitOfWork implements PropertyChangedListener
* Marks an entity as read-only so that it will not be considered for updates during UnitOfWork#commit().
*
* This operation cannot be undone as some parts of the UnitOfWork now keep gathering information
* on this object that might be necessary to perform a correct udpate.
* on this object that might be necessary to perform a correct update.
*
*
* @param object $object
*
* @throws ORMInvalidArgumentException
*
* @throws \InvalidArgumentException
* @param $object
* @return void
*/
public function markReadOnly($object)
@@ -2949,9 +3070,11 @@ class UnitOfWork implements PropertyChangedListener
/**
* Is this entity read only?
*
* @throws \InvalidArgumentException
* @param $object
* @return void
* @param object $object
*
* @throws ORMInvalidArgumentException
*
* @return bool
*/
public function isReadOnly($object)
{

View File

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

View File

@@ -10,7 +10,7 @@ namespace Doctrine\Tests\Mocks;
class StatementMock implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement
{
public function bindValue($param, $value, $type = null){}
public function bindParam($column, &$variable, $type = null){}
public function bindParam($column, &$variable, $type = null, $length = null){}
public function errorCode(){}
public function errorInfo(){}
public function execute($params = null){}

View File

@@ -1118,7 +1118,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user->username = 'domnikl';
$user->status = 'developer';
$this->setExpectedException('InvalidArgumentException', 'Entity has to be managed for single computation');
$this->setExpectedException('InvalidArgumentException', 'Entity has to be managed or scheduled for removal for single computation');
$this->_em->flush($user);
}
@@ -1202,8 +1202,9 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
/**
* @group DDC-720
* @group DDC-1612
* @group DDC-2267
*/
public function testFlushSingleNewEntity()
public function testFlushSingleNewEntityThenRemove()
{
$user = new CmsUser;
$user->name = 'Dominik';
@@ -1212,6 +1213,14 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($user);
$this->_em->flush($user);
$userId = $user->id;
$this->_em->remove($user);
$this->_em->flush($user);
$this->_em->clear();
$this->assertNull($this->_em->find(get_class($user), $userId));
}
/**

View File

@@ -2,12 +2,9 @@
namespace Doctrine\Tests\ORM\Functional;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\Common\Util\Inflector;
class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
class DatabaseDriverTest extends DatabaseDriverTestCase
{
/**
* @var \Doctrine\DBAL\Schema\AbstractSchemaManager
@@ -22,6 +19,31 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_sm = $this->_em->getConnection()->getSchemaManager();
}
/**
* @group DDC-2059
*/
public function testIssue2059()
{
if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$this->markTestSkipped('Platform does not support foreign keys.');
}
$user = new \Doctrine\DBAL\Schema\Table("ddc2059_user");
$user->addColumn('id', 'integer');
$user->setPrimaryKey(array('id'));
$project = new \Doctrine\DBAL\Schema\Table("ddc2059_project");
$project->addColumn('id', 'integer');
$project->addColumn('user_id', 'integer');
$project->addColumn('user', 'string');
$project->setPrimaryKey(array('id'));
$project->addForeignKeyConstraint('ddc2059_user', array('user_id'), array('id'));
$metadata = $this->convertToClassMetadata(array($project, $user), array());
$this->assertTrue(isset($metadata['Ddc2059Project']->fieldMappings['user']));
$this->assertTrue(isset($metadata['Ddc2059Project']->associationMappings['user2']));
}
public function testLoadMetadataFromDatabase()
{
if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
@@ -123,44 +145,4 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
$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
*/
protected function extractClassMetadata(array $classNames)
{
$classNames = array_map('strtolower', $classNames);
$metadatas = array();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_sm);
foreach ($driver->getAllClassNames() as $className) {
if (!in_array(strtolower($className), $classNames)) {
continue;
}
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
if (count($metadatas) != count($classNames)) {
$this->fail("Have not found all classes matching the names '" . implode(", ", $classNames) . "' only tables " . implode(", ", array_keys($metadatas)));
}
return $metadatas;
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Common BaseClass for DatabaseDriver Tests
*/
abstract class DatabaseDriverTestCase extends OrmFunctionalTestCase
{
protected function convertToClassMetadata(array $entityTables, array $manyTables = array())
{
$sm = $this->_em->getConnection()->getSchemaManager();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($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
*/
protected function extractClassMetadata(array $classNames)
{
$classNames = array_map('strtolower', $classNames);
$metadatas = array();
$sm = $this->_em->getConnection()->getSchemaManager();
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($sm);
foreach ($driver->getAllClassNames() as $className) {
if (!in_array(strtolower($className), $classNames)) {
continue;
}
$class = new ClassMetadataInfo($className);
$driver->loadMetadataForClass($className, $class);
$metadatas[$className] = $class;
}
if (count($metadatas) != count($classNames)) {
$this->fail("Have not found all classes matching the names '" . implode(", ", $classNames) . "' only tables " . implode(", ", array_keys($metadatas)));
}
return $metadatas;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\Generic\DateTimeModel;
use Doctrine\Common\Collections\Criteria;
/**
* @author Josiah <josiah@jjs.id.au>
*/
class EntityRepositoryCriteriaTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('generic');
parent::setUp();
}
public function tearDown()
{
if ($this->_em) {
$this->_em->getConfiguration()->setEntityNamespaces(array());
}
parent::tearDown();
}
public function loadFixture()
{
$today = new DateTimeModel();
$today->datetime =
$today->date =
$today->time =
new \DateTime('today');
$this->_em->persist($today);
$tomorrow = new DateTimeModel();
$tomorrow->datetime =
$tomorrow->date =
$tomorrow->time =
new \DateTime('tomorrow');
$this->_em->persist($tomorrow);
$yesterday = new DateTimeModel();
$yesterday->datetime =
$yesterday->date =
$yesterday->time =
new \DateTime('yesterday');
$this->_em->persist($yesterday);
$this->_em->flush();
unset($today);
unset($tomorrow);
unset($yesterday);
$this->_em->clear();
}
public function testLteDateComparison()
{
$this->loadFixture();
$repository = $this->_em->getRepository('Doctrine\Tests\Models\Generic\DateTimeModel');
$dates = $repository->matching(new Criteria(
Criteria::expr()->lte('datetime', new \DateTime('today'))
));
$this->assertEquals(2, count($dates));
}
}

View File

@@ -344,6 +344,20 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($addressId, $address->id);
}
/**
* @group DDC-1241
*/
public function testFindOneByOrderBy()
{
$this->loadFixture();
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
$userAsc = $repos->findOneBy(array(), array("username" => "ASC"));
$userDesc = $repos->findOneBy(array(), array("username" => "DESC"));
$this->assertNotSame($userAsc, $userDesc);
}
/**
* @group DDC-817
*/

View File

@@ -174,6 +174,52 @@ class OneToManyBidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctiona
$this->assertEquals(2, count($results));
}
/**
* @group DDC-2340
*/
public function testMatchingOnDirtyCollection()
{
$this->_createFixture();
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->product->getId());
$thirdFeature = new ECommerceFeature();
$thirdFeature->setDescription('Model writing tutorial');
$features = $product->getFeatures();
$features->add($thirdFeature);
$results = $features->matching(new Criteria(
Criteria::expr()->eq('description', 'Model writing tutorial')
));
$this->assertEquals(2, count($results));
}
public function testMatchingBis()
{
$this->_createFixture();
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->product->getId());
$features = $product->getFeatures();
$thirdFeature = new ECommerceFeature();
$thirdFeature->setDescription('Third feature');
$product->addFeature($thirdFeature);
$results = $features->matching(new Criteria(
Criteria::expr()->eq('description', 'Third feature')
));
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $results);
$this->assertCount(1, $results);
$results = $features->matching(new Criteria());
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $results);
$this->assertCount(3, $results);
}
private function _createFixture()
{
$this->product->addFeature($this->firstFeature);

View File

@@ -453,6 +453,22 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(1, count($query->getResult()));
}
public function testWhereOrFilter()
{
$this->loadFixtureData();
$query = $this->_em->createQuery('select ug from Doctrine\Tests\Models\CMS\CmsGroup ug WHERE 1=1 OR 1=1');
// We get two users before enabling the filter
$this->assertEquals(2, count($query->getResult()));
$conf = $this->_em->getConfiguration();
$conf->addFilter("group_prefix", "\Doctrine\Tests\ORM\Functional\CMSGroupPrefixFilter");
$this->_em->getFilters()->enable("group_prefix")->setParameter("prefix", "bar_%", DBALType::STRING);
// We get one user after enabling the filter
$this->assertEquals(1, count($query->getResult()));
}
private function loadLazyFixtureData()
{

View File

@@ -0,0 +1,60 @@
<?php
namespace Doctrine\Tests\ORM\Functional\SchemaTool;
use Doctrine\ORM\Tools;
class DBAL483Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
$conn = $this->_em->getConnection();
if ($conn->getDatabasePlatform()->getName() === 'sqlite') {
$this->markTestSkipped('Sqlite does not support ALTER TABLE');
}
$this->schemaTool = new Tools\SchemaTool($this->_em);
}
/**
* @group DBAL-483
*/
public function testDefaultValueIsComparedCorrectly()
{
$class = $this->_em->getClassMetadata(__NAMESPACE__ . '\\DBAL483Default');
$this->schemaTool->createSchema(array($class));
$updateSql = $this->schemaTool->getUpdateSchemaSql(array($class));
$updateSql = array_filter($updateSql, function ($sql) {
return strpos($sql, 'DBAL483') !== false;
});
$this->assertEquals(0, count($updateSql));
}
}
/**
* @Entity
*/
class DBAL483Default
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
public $id;
/**
* @Column(type="integer", options={"default": 0})
*/
public $num;
/**
* @Column(type="string", options={"default": "foo"})
*/
public $str = "foo";
}

View File

@@ -4,9 +4,6 @@ namespace Doctrine\Tests\ORM\Functional\SchemaTool;
use Doctrine\ORM\Tools;
require_once __DIR__ . '/../../../TestInit.php';
/**
* WARNING: This test should be run as last test! It can affect others very easily!
*/
@@ -15,7 +12,8 @@ class DDC214Test extends \Doctrine\Tests\OrmFunctionalTestCase
private $classes = array();
private $schemaTool = null;
public function setUp() {
public function setUp()
{
parent::setUp();
$conn = $this->_em->getConnection();
@@ -88,4 +86,4 @@ class DDC214Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0, count($sql), "SQL: " . implode(PHP_EOL, $sql));
}
}
}

View File

@@ -29,12 +29,12 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$tool = new SchemaTool($this->_em);
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals("CREATE TABLE cms_groups (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, email_id INT DEFAULT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_3AF03EC5F85E0677 (username), UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 (email_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[1]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, INDEX IDX_7EA9409AA76ED395 (user_id), INDEX IDX_7EA9409AFE54D947 (group_id), PRIMARY KEY(user_id, group_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[2]);
$this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, UNIQUE INDEX UNIQ_ACAC157BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[3]);
$this->assertEquals("CREATE TABLE cms_emails (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(250) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[4]);
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, INDEX IDX_F21F790FA76ED395 (user_id), PRIMARY KEY(phonenumber)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[5]);
$this->assertEquals("CREATE TABLE cms_groups (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, email_id INT DEFAULT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_3AF03EC5F85E0677 (username), UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 (email_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[1]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, INDEX IDX_7EA9409AA76ED395 (user_id), INDEX IDX_7EA9409AFE54D947 (group_id), PRIMARY KEY(user_id, group_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[2]);
$this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, UNIQUE INDEX UNIQ_ACAC157BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[3]);
$this->assertEquals("CREATE TABLE cms_emails (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(250) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[4]);
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, INDEX IDX_F21F790FA76ED395 (user_id), PRIMARY KEY(phonenumber)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[5]);
$this->assertEquals("ALTER TABLE cms_users ADD CONSTRAINT FK_3AF03EC5A832C1C9 FOREIGN KEY (email_id) REFERENCES cms_emails (id)", $sql[6]);
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users (id)", $sql[7]);
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AFE54D947 FOREIGN KEY (group_id) REFERENCES cms_groups (id)", $sql[8]);
@@ -54,7 +54,7 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals(1, count($sql));
$this->assertEquals("CREATE TABLE decimal_model (id INT AUTO_INCREMENT NOT NULL, `decimal` NUMERIC(5, 2) NOT NULL, `high_scale` NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE decimal_model (id INT AUTO_INCREMENT NOT NULL, `decimal` NUMERIC(5, 2) NOT NULL, `high_scale` NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[0]);
}
public function testGetCreateSchemaSql3()
@@ -67,7 +67,7 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals(1, count($sql));
$this->assertEquals("CREATE TABLE boolean_model (id INT AUTO_INCREMENT NOT NULL, booleanField TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE boolean_model (id INT AUTO_INCREMENT NOT NULL, booleanField TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[0]);
}
/**

View File

@@ -461,4 +461,22 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($before + 3, count($data));
}
/**
* @group DDC-2246
*/
public function testGetEntityState()
{
$this->article1 = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Article", $this->article1->id());
$this->article2 = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Article", $this->article2->id());
$this->reference = new DDC117Reference($this->article2, $this->article1, "Test-Description");
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($this->reference));
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
$reference = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($reference));
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsEmail;
/**
* @group DDC-1666
*/
class DDC1666Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testGivenOrphanRemovalOneToOne_WhenReplacing_ThenNoUniqueConstraintError()
{
$user = new CmsUser();
$user->name = "Benjamin";
$user->username = "beberlei";
$user->status = "something";
$user->setEmail($email = new CmsEmail());
$email->setEmail("kontakt@beberlei.de");
$this->_em->persist($user);
$this->_em->flush();
$this->assertTrue($this->_em->contains($email));
$user->setEmail($newEmail = new CmsEmail());
$newEmail->setEmail("benjamin.eberlei@googlemail.com");
$this->_em->flush();
$this->assertFalse($this->_em->contains($email));
}
}

View File

@@ -0,0 +1,153 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\NotifyPropertyChanged,
Doctrine\Common\PropertyChangedListener;
require_once __DIR__ . '/../../../TestInit.php';
class DDC1690Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp() {
parent::setUp();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1690Parent'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1690Child')
));
} catch (\Exception $e) {
// Swallow all exceptions. We do not test the schema tool here.
}
}
public function testChangeTracking()
{
$parent = new DDC1690Parent();
$child = new DDC1690Child();
$parent->setName('parent');
$child->setName('child');
$parent->setChild($child);
$child->setParent($parent);
$this->_em->persist($parent);
$this->_em->persist($child);
$this->assertEquals(1, count($parent->listeners));
$this->assertEquals(1, count($child->listeners));
$this->_em->flush();
$this->_em->clear();
$this->assertEquals(1, count($parent->listeners));
$this->assertEquals(1, count($child->listeners));
$parentId = $parent->getId();
$childId = $child->getId();
unset($parent, $child);
$parent = $this->_em->find(__NAMESPACE__.'\DDC1690Parent', $parentId);
$child = $this->_em->find(__NAMESPACE__.'\DDC1690Child', $childId);
$this->assertEquals(1, count($parent->listeners));
$this->assertEquals(1, count($child->listeners));
unset($parent, $child);
$parent = $this->_em->find(__NAMESPACE__.'\DDC1690Parent', $parentId);
$child = $parent->getChild();
$this->assertEquals(1, count($parent->listeners));
$this->assertEquals(1, count($child->listeners));
unset($parent, $child);
$child = $this->_em->find(__NAMESPACE__.'\DDC1690Child', $childId);
$parent = $child->getParent();
$this->assertEquals(1, count($parent->listeners));
$this->assertEquals(1, count($child->listeners));
}
}
class NotifyBaseEntity implements NotifyPropertyChanged {
public $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener) {
if (!in_array($listener, $this->listeners)) {
$this->listeners[] = $listener;
}
}
protected function onPropertyChanged($propName, $oldValue, $newValue) {
if ($this->listeners) {
foreach ($this->listeners as $listener) {
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
}
}
}
}
/** @Entity @ChangeTrackingPolicy("NOTIFY") */
class DDC1690Parent extends NotifyBaseEntity {
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Column */
private $name;
/** @OneToOne(targetEntity="DDC1690Child") */
private $child;
function getId() {
return $this->id;
}
function getName() {
return $this->name;
}
function setName($name) {
$this->onPropertyChanged('name', $this->name, $name);
$this->name = $name;
}
function setChild($child) {
$this->child = $child;
}
function getChild() {
return $this->child;
}
}
/** @Entity */
class DDC1690Child extends NotifyBaseEntity {
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Column */
private $name;
/** @OneToOne(targetEntity="DDC1690Parent", mappedBy="child") */
private $parent;
function getId() {
return $this->id;
}
function getName() {
return $this->name;
}
function setName($name) {
$this->onPropertyChanged('name', $this->name, $name);
$this->name = $name;
}
function setParent($parent) {
$this->parent = $parent;
}
function getParent() {
return $this->parent;
}
}

View File

@@ -5,8 +5,6 @@ namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Quote\Group;
use Doctrine\Tests\Models\Quote\User;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1845
* @group DDC-1885
@@ -170,4 +168,4 @@ class DDC1885Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertInstanceOf('Doctrine\Tests\Models\Quote\Group', $user->getGroups()->get(0));
$this->assertInstanceOf('Doctrine\Tests\Models\Quote\Group', $user->getGroups()->get(1));
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
* @group DDC-1918
*/
class DDC1918Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testLastPageCorrect()
{
$groups = array();
for ($i = 0; $i < 3; $i++) {
$group = new CmsGroup();
$group->name = "test";
$this->_em->persist($group);
$groups[] = $group;
}
for ($i = 0; $i < 10; $i++) {
$user = new CmsUser();
$user->username = "user$i";
$user->name = "user$i";
$user->status = "active";
$user->groups = $groups;
$this->_em->persist($user);
}
$this->_em->flush();
$query = $this->_em->createQuery('SELECT u, g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
$query->setFirstResult(6);
$query->setMaxResults(3);
$paginator = new Paginator($query, true);
$this->assertEquals(3, count(iterator_to_array($paginator)));
$query->setFirstResult(8);
$query->setMaxResults(3);
$paginator = new Paginator($query, true);
$this->assertEquals(2, count(iterator_to_array($paginator)));
$query->setFirstResult(10);
$query->setMaxResults(3);
$paginator = new Paginator($query, true);
$this->assertEquals(0, count(iterator_to_array($paginator)));
}
}

View File

@@ -1,182 +0,0 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1925
* @group DDC-1210
*/
class DDC1925Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function testIssue()
{
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1925User'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1925Product'),
));
$user = new DDC1925User();
$user->setTitle("Test User");
$this->_em->persist($user);
$product = new DDC1925Product();
$product->setTitle("Test product");
$this->_em->persist($product);
$this->_em->flush();
$product->addBuyer($user);
$this->_em->getUnitOfWork()->computeChangeSets();
$this->_em->persist($product);
$this->_em->flush();
}
}
/**
* @Table
* @Entity
*/
class DDC1925Product
{
/**
* @var integer $id
*
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string $title
*
* @Column(name="title", type="string", length=255)
*/
private $title;
/**
* @ManyToMany(targetEntity="DDC1925User")
* @JoinTable(
* name="user_purchases",
* joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
private $buyers;
/**
* Default constructor
*/
public function __construct()
{
$this->buyers = new ArrayCollection();
}
/**
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $buyers
*/
public function setBuyers($buyers)
{
$this->buyers = $buyers;
}
/**
* @return string
*/
public function getBuyers()
{
return $this->buyers;
}
/**
* @param DDC1925User $buyer
*/
public function addBuyer(DDC1925User $buyer)
{
$this->buyers[] = $buyer;
}
}
/**
* @Table
* @Entity
*/
class DDC1925User
{
/**
* @var integer
*
* @Column(name="id", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @Column(name="title", type="string", length=255)
*/
private $title;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
}

View File

@@ -0,0 +1,177 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* @group DDC-2012
*/
class DDC2012Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
Type::addType(DDC2012TsVectorType::MYTYPE, __NAMESPACE__ . '\DDC2012TsVectorType');
DDC2012TsVectorType::$calls = array();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2012Item'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2012ItemPerson'),
));
}
public function testIssue()
{
$item = new DDC2012ItemPerson();
$item->tsv = array('word1', 'word2', 'word3');
$this->_em->persist($item);
$this->_em->flush();
$this->_em->clear();
$item = $this->_em->find(get_class($item), $item->id);
$this->assertArrayHasKey('convertToDatabaseValueSQL', DDC2012TsVectorType::$calls);
$this->assertArrayHasKey('convertToDatabaseValue', DDC2012TsVectorType::$calls);
$this->assertArrayHasKey('convertToPHPValue', DDC2012TsVectorType::$calls);
$this->assertCount(1, DDC2012TsVectorType::$calls['convertToDatabaseValueSQL']);
$this->assertCount(1, DDC2012TsVectorType::$calls['convertToDatabaseValue']);
$this->assertCount(1, DDC2012TsVectorType::$calls['convertToPHPValue']);
$this->assertInstanceOf(__NAMESPACE__ . '\DDC2012Item', $item);
$this->assertEquals(array('word1', 'word2', 'word3'), $item->tsv);
$item->tsv = array('word1', 'word2');
$this->_em->persist($item);
$this->_em->flush();
$this->_em->clear();
$item = $this->_em->find(get_class($item), $item->id);
$this->assertCount(2, DDC2012TsVectorType::$calls['convertToDatabaseValueSQL']);
$this->assertCount(2, DDC2012TsVectorType::$calls['convertToDatabaseValue']);
$this->assertCount(2, DDC2012TsVectorType::$calls['convertToPHPValue']);
$this->assertInstanceOf(__NAMESPACE__ . '\DDC2012Item', $item);
$this->assertEquals(array('word1', 'word2'), $item->tsv);
}
}
/**
* @Table(name="ddc2010_item")
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="type_id", type="smallint")
* @DiscriminatorMap({
* 1 = "DDC2012ItemPerson"
* })
*/
class DDC2012Item
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
public $id;
/**
* @Column(name="tsv", type="tsvector", nullable=true)
*/
public $tsv;
}
/**
* @Table(name="ddc2010_item_person")
* @Entity
*/
class DDC2012ItemPerson extends DDC2012Item
{
}
class DDC2012TsVectorType extends Type
{
const MYTYPE = 'tsvector';
public static $calls = array();
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if (is_array($value)) {
$value = implode(" ", $value);
}
self::$calls[__FUNCTION__][] = array(
'value' => $value,
'platform' => $platform,
);
return $value;
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
self::$calls[__FUNCTION__][] = array(
'value' => $value,
'platform' => $platform,
);
return explode(" ", strtolower($value));
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
{
self::$calls[__FUNCTION__][] = array(
'sqlExpr' => $sqlExpr,
'platform' => $platform,
);
// changed to upper expression to keep the test compatible with other Databases
//sprintf('to_tsvector(%s)', $sqlExpr);
return $platform->getUpperExpression($sqlExpr);
}
/**
* {@inheritdoc}
*/
public function canRequireSQLConversion()
{
return true;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return self::MYTYPE;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\PersistentCollection;
use Doctrine\Tests\Models\ECommerce\ECommerceCategory;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
/**
* @group DDC-2074
*/
class DDC2074Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function testShouldNotScheduleDeletionOnClonedInstances()
{
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
$product = new ECommerceProduct();
$category = new ECommerceCategory();
$collection = new PersistentCollection($this->_em, $class, new ArrayCollection(array($category)));
$collection->setOwner($product, $class->associationMappings['categories']);
$uow = $this->_em->getUnitOfWork();
$clonedCollection = clone $collection;
$clonedCollection->clear();
$this->assertEquals(0, count($uow->getScheduledCollectionDeletions()));
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Company\CompanyEmployee;
/**
* @group DDC-2090
*/
class DDC2090Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('company');
parent::setUp();
}
public function testIssue()
{
$className = 'Doctrine\Tests\Models\Company\CompanyEmployee';
$date1 = new \DateTime('2011-11-11 11:11:11');
$date2 = new \DateTime('2012-12-12 12:12:12');
$employee1 = new CompanyEmployee;
$employee2 = new CompanyEmployee;
$employee1->setName("Fabio B. Silva");
$employee1->setStartDate(new \DateTime('yesterday'));
$employee1->setDepartment("R&D");
$employee1->setSalary(100);
$employee2->setName("Doctrine Bot");
$employee1->setStartDate(new \DateTime('yesterday'));
$employee2->setDepartment("QA");
$employee2->setSalary(100);
$this->_em->persist($employee1);
$this->_em->persist($employee2);
$this->_em->flush();
$this->_em->clear();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', ':date')
->set('e.salary', ':salary')
->where('e = :e')
->setParameters(array(
'e' => $employee1,
'date' => $date1,
'salary' => 101,
))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', ':date')
->set('e.salary', ':salary')
->where('e = :e')
->setParameters(array(
'e' => $employee2,
'date' => $date2,
'salary' => 102,
))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->clear();
$e1 = $this->_em->find($className, $employee1->getId());
$e2 = $this->_em->find($className, $employee2->getId());
$this->assertEquals(101, $e1->getSalary());
$this->assertEquals(102, $e2->getSalary());
$this->assertEquals($date1, $e1->getStartDate());
$this->assertEquals($date2, $e2->getStartDate());
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', '?1')
->set('e.salary', '?2')
->where('e = ?0')
->setParameters(array($employee1, $date1, 101))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->createQueryBuilder()
->update($className, 'e')
->set('e.startDate', '?1')
->set('e.salary', '?2')
->where('e = ?0')
->setParameters(array($employee2, $date2, 102))
->getQuery()
->useQueryCache(true)
->execute();
$this->_em->clear();
$e1 = $this->_em->find($className, $employee1->getId());
$e2 = $this->_em->find($className, $employee2->getId());
$this->assertEquals(101, $e1->getSalary());
$this->assertEquals(102, $e2->getSalary());
$this->assertEquals($date1, $e1->getStartDate());
$this->assertEquals($date2, $e2->getStartDate());
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
/**
* @group DDC-2175
*/
class DDC2175Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2175Entity'),
));
}
public function testIssue()
{
$entity = new DDC2175Entity();
$entity->field = "foo";
$this->_em->persist($entity);
$this->_em->flush();
$this->assertEquals(1, $entity->version);
$entity->field = "bar";
$this->_em->flush();
$this->assertEquals(2, $entity->version);
$entity->field = "baz";
$this->_em->flush();
$this->assertEquals(3, $entity->version);
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorMap({"entity": "DDC2175Entity"})
*/
class DDC2175Entity
{
/**
* @Id @GeneratedValue @Column(type="integer")
*/
public $id;
/**
* @Column(type="string")
*/
public $field;
/**
* @Version
* @Column(type="integer")
*/
public $version;
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\UnitOfWork;
require_once __DIR__ . '/../../../TestInit.php';
class DDC2182Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function testPassColumnOptionsToJoinColumns()
{
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != 'mysql') {
$this->markTestSkipped("This test is useful for all databases, but designed only for mysql.");
}
$sql = $this->_schemaTool->getCreateSchemaSql(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2182OptionParent'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2182OptionChild'),
));
$this->assertEquals("CREATE TABLE DDC2182OptionParent (id INT UNSIGNED NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE DDC2182OptionChild (id VARCHAR(255) NOT NULL, parent_id INT UNSIGNED DEFAULT NULL, INDEX IDX_B314D4AD727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB", $sql[1]);
$this->assertEquals("ALTER TABLE DDC2182OptionChild ADD CONSTRAINT FK_B314D4AD727ACA70 FOREIGN KEY (parent_id) REFERENCES DDC2182OptionParent (id)", $sql[2]);
}
}
/**
* @Entity
* @Table
*/
class DDC2182OptionParent
{
/** @Id @Column(type="integer", options={"unsigned": true}) */
private $id;
}
/**
* @Entity
* @Table
*/
class DDC2182OptionChild
{
/** @Id @Column */
private $id;
/**
* @ManyToOne(targetEntity="DDC2182OptionParent")
* @JoinColumn(referencedColumnName="id")
*/
private $parent;
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ObjectManagerAware;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-2231
*/
class DDC2231Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityY'),
));
}
public function testInjectObjectManagerInProxyIfInitializedInUow()
{
$y1 = new DDC2231EntityY;
$this->_em->persist($y1);
$this->_em->flush();
$this->_em->clear();
$y1ref = $this->_em->getReference(get_class($y1), $y1->id);
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $y1ref);
$this->assertFalse($y1ref->__isInitialized__);
$id = $y1ref->doSomething();
$this->assertTrue($y1ref->__isInitialized__);
$this->assertEquals($this->_em, $y1ref->om);
}
}
/** @Entity @Table(name="ddc2231_y") */
class DDC2231EntityY implements ObjectManagerAware
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
public $id;
public $om;
public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata)
{
$this->om = $objectManager;
}
public function getId()
{
return $this->id;
}
public function doSomething()
{
}
}

View File

@@ -0,0 +1,229 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @group DDC-2252
*/
class DDC2252Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $user;
private $merchant;
private $membership;
private $privileges = array();
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252User'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252Privilege'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252Membership'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Ticket\DDC2252MerchantAccount'),
));
$this->loadFixtures();
}
public function loadFixtures()
{
$this->user = new DDC2252User;
$this->merchant = new DDC2252MerchantAccount;
$this->membership = new DDC2252Membership($this->user, $this->merchant);
$this->privileges[] = new DDC2252Privilege;
$this->privileges[] = new DDC2252Privilege;
$this->privileges[] = new DDC2252Privilege;
$this->membership->addPrivilege($this->privileges[0]);
$this->membership->addPrivilege($this->privileges[1]);
$this->membership->addPrivilege($this->privileges[2]);
$this->_em->persist($this->user);
$this->_em->persist($this->merchant);
$this->_em->persist($this->privileges[0]);
$this->_em->persist($this->privileges[1]);
$this->_em->persist($this->privileges[2]);
$this->_em->flush();
$this->_em->persist($this->membership);
$this->_em->flush();
$this->_em->clear();
}
public function testIssue()
{
$identifier = array(
'merchantAccount' => $this->merchant->getAccountid(),
'userAccount' => $this->user->getUid(),
);
$class = 'Doctrine\Tests\ORM\Functional\Ticket\DDC2252Membership';
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(3, $membership->getPrivileges());
$membership->getPrivileges()->remove(2);
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(2, $membership->getPrivileges());
$membership->getPrivileges()->clear();
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(0, $membership->getPrivileges());
$membership->addPrivilege($privilege3 = new DDC2252Privilege);
$this->_em->persist($privilege3);
$this->_em->persist($membership);
$this->_em->flush();
$this->_em->clear();
$membership = $this->_em->find($class, $identifier);
$this->assertInstanceOf($class, $membership);
$this->assertCount(1, $membership->getPrivileges());
}
}
/**
* @Entity()
* @Table(name="ddc2252_acl_privilege")
*/
class DDC2252Privilege
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected $privilegeid;
public function getPrivilegeid()
{
return $this->privilegeid;
}
}
/**
* @Entity
* @Table(name="ddc2252_mch_account")
*/
class DDC2252MerchantAccount
{
/**
* @Id
* @Column(type="integer")
*/
protected $accountid = 111;
public function getAccountid()
{
return $this->accountid;
}
}
/**
* @Entity
* @Table(name="ddc2252_user_account")
*/
class DDC2252User {
/**
* @Id
* @Column(type="integer")
*/
protected $uid = 222;
/**
* @OneToMany(targetEntity="DDC2252Membership", mappedBy="userAccount", cascade={"persist"})
* @JoinColumn(name="uid", referencedColumnName="uid")
*/
protected $memberships;
public function __construct()
{
$this->memberships = new ArrayCollection;
}
public function getUid()
{
return $this->uid;
}
public function getMemberships()
{
return $this->memberships;
}
public function addMembership(DDC2252Membership $membership)
{
$this->memberships[] = $membership;
}
}
/**
* @Entity
* @Table(name="ddc2252_mch_account_member")
* @HasLifecycleCallbacks
*/
class DDC2252Membership
{
/**
* @Id
* @ManyToOne(targetEntity="DDC2252User", inversedBy="memberships")
* @JoinColumn(name="uid", referencedColumnName="uid")
*/
protected $userAccount;
/**
* @Id
* @ManyToOne(targetEntity="DDC2252MerchantAccount")
* @JoinColumn(name="mch_accountid", referencedColumnName="accountid")
*/
protected $merchantAccount;
/**
* @ManyToMany(targetEntity="DDC2252Privilege", indexBy="privilegeid")
* @JoinTable(name="ddc2252_user_mch_account_privilege",
* joinColumns={
* @JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
* @JoinColumn(name="uid", referencedColumnName="uid")
* },
* inverseJoinColumns={
* @JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
* }
* )
*/
protected $privileges;
public function __construct(DDC2252User $user, DDC2252MerchantAccount $merchantAccount)
{
$this->userAccount = $user;
$this->merchantAccount = $merchantAccount;
$this->privileges = new ArrayCollection();
}
public function addPrivilege($privilege)
{
$this->privileges[] = $privilege;
}
public function getPrivileges()
{
return $this->privileges;
}
}

View File

@@ -0,0 +1,109 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\DBAL\Logging\DebugStack;
/**
* @group DDC-2346
*/
class DDC2346Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* @var \Doctrine\DBAL\Logging\DebugStack
*/
protected $logger;
/**
* {@inheritDoc}
*/
protected function setup()
{
parent::setup();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Foo'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Bar'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2346Baz'),
));
$this->logger = new DebugStack();
}
/**
* Verifies that fetching a OneToMany association with fetch="EAGER" does not cause N+1 queries
*/
public function testIssue()
{
$foo1 = new DDC2346Foo();
$foo2 = new DDC2346Foo();
$baz1 = new DDC2346Baz();
$baz2 = new DDC2346Baz();
$baz1->foo = $foo1;
$baz2->foo = $foo2;
$foo1->bars[] = $baz1;
$foo1->bars[] = $baz2;
$this->_em->persist($foo1);
$this->_em->persist($foo2);
$this->_em->persist($baz1);
$this->_em->persist($baz2);
$this->_em->flush();
$this->_em->clear();
$this->_em->getConnection()->getConfiguration()->setSQLLogger($this->logger);
$fetchedBazs = $this->_em->getRepository(__NAMESPACE__ . '\\DDC2346Baz')->findAll();
$this->assertCount(2, $fetchedBazs);
$this->assertCount(2, $this->logger->queries, 'The total number of executed queries is 2, and not n+1');
}
}
/** @Entity */
class DDC2346Foo
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/**
* @var DDC2346Bar[]|\Doctrine\Common\Collections\Collection
*
* @OneToMany(targetEntity="DDC2346Bar", mappedBy="foo")
*/
public $bars;
/** Constructor */
public function __construct() {
$this->bars = new ArrayCollection();
}
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"baz" = "DDC2346Baz"})
*/
class DDC2346Bar
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @ManyToOne(targetEntity="DDC2346Foo", inversedBy="bars", fetch="EAGER") */
public $foo;
}
/**
* @Entity
*/
class DDC2346Baz extends DDC2346Bar
{
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\ORM\Functional\DatabaseDriverTestCase;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
class DDC2387Test extends DatabaseDriverTestCase
{
/**
* @group DDC-2387
*/
public function testCompositeAssociationKeyDetection()
{
$product = new \Doctrine\DBAL\Schema\Table('ddc2387_product');
$product->addColumn('id', 'integer');
$product->setPrimaryKey(array('id'));
$attributes = new \Doctrine\DBAL\Schema\Table('ddc2387_attributes');
$attributes->addColumn('product_id', 'integer');
$attributes->addColumn('attribute_name', 'string');
$attributes->setPrimaryKey(array('product_id', 'attribute_name'));
$attributes->addForeignKeyConstraint('ddc2387_product', array('product_id'), array('product_id'));
$metadata = $this->convertToClassMetadata(array($product, $attributes), array());
$this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_NONE, $metadata['Ddc2387Attributes']->generatorType);
$this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_AUTO, $metadata['Ddc2387Product']->generatorType);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsArticle;
/**
* @group DDC-2409
*/
class DDC2409Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testIssue()
{
$em = $this->_em;
$uow = $em->getUnitOfWork();
$originalArticle = new CmsArticle();
$originalUser = new CmsUser();
$originalArticle->topic = 'Unit Test';
$originalArticle->text = 'How to write a test';
$originalUser->name = 'Doctrine Bot';
$originalUser->username = 'DoctrineBot';
$originalUser->status = 'active';
$originalUser->addArticle($originalArticle);
$em->persist($originalUser);
$em->persist($originalArticle);
$em->flush();
$em->clear();
$article = $em->find('Doctrine\Tests\Models\CMS\CmsArticle', $originalArticle->id);
$user = new CmsUser();
$user->name = 'Doctrine Bot 2.0';
$user->username = 'BotDoctrine2';
$user->status = 'new';
$article->setAuthor($user);
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($originalArticle));
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($originalUser));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($article));
$this->assertEquals(UnitOfWork::STATE_NEW, $uow->getEntityState($user));
$em->detach($user);
$em->detach($article);
$userMerged = $em->merge($user);
$articleMerged = $em->merge($article);
$this->assertEquals(UnitOfWork::STATE_NEW, $uow->getEntityState($user));
$this->assertEquals(UnitOfWork::STATE_DETACHED, $uow->getEntityState($article));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($userMerged));
$this->assertEquals(UnitOfWork::STATE_MANAGED, $uow->getEntityState($articleMerged));
$this->assertNotSame($user, $userMerged);
$this->assertNotSame($article, $articleMerged);
$this->assertNotSame($userMerged, $articleMerged->user);
$this->assertSame($user, $articleMerged->user);
}
}

View File

@@ -34,4 +34,28 @@ class SimpleObjectHydratorTest extends HydrationTestCase
$hydrator = new \Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator($this->_em);
$hydrator->hydrateAll($stmt, $rsm);
}
public function testExtraFieldInResultSetShouldBeIgnore()
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsAddress', 'a');
$rsm->addFieldResult('a', 'a__id', 'id');
$rsm->addFieldResult('a', 'a__city', 'city');
$resultSet = array(
array(
'a__id' => '1',
'a__city' => 'Cracow',
'doctrine_rownum' => '1'
),
);
$expectedEntity = new \Doctrine\Tests\Models\CMS\CmsAddress();
$expectedEntity->id = 1;
$expectedEntity->city = 'Cracow';
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator($this->_em);
$result = $hydrator->hydrateAll($stmt, $rsm);
$this->assertEquals($result[0], $expectedEntity);
}
}

View File

@@ -139,14 +139,27 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testFieldMappings($class)
{
$this->assertEquals(3, count($class->fieldMappings));
$this->assertEquals(4, count($class->fieldMappings));
$this->assertTrue(isset($class->fieldMappings['id']));
$this->assertTrue(isset($class->fieldMappings['name']));
$this->assertTrue(isset($class->fieldMappings['email']));
$this->assertTrue(isset($class->fieldMappings['version']));
return $class;
}
/**
* @depends testFieldMappings
* @param ClassMetadata $class
*/
public function testVersionedField($class)
{
$this->assertTrue($class->isVersioned);
$this->assertEquals("version", $class->versionField);
$this->assertFalse(isset($class->fieldMappings['version']['version']));
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
@@ -464,24 +477,22 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
/**
* @group DDC-889
* @expectedException Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.
*/
public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses()
{
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.');
$this->createClassMetadata('Doctrine\Tests\Models\DDC889\DDC889Class');
}
/**
* @group DDC-889
* @expectedException Doctrine\ORM\Mapping\MappingException
* @expectedExceptionMessage No identifier/primary key specified for Entity "Doctrine\Tests\Models\DDC889\DDC889Entity" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass". Every Entity must have an identifier/primary key.
*/
public function testIdentifierRequiredShouldMentionParentClasses()
{
$factory = $this->createClassMetadataFactory();
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'No identifier/primary key specified for Entity "Doctrine\Tests\Models\DDC889\DDC889Entity" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass". Every Entity must have an identifier/primary key.');
$factory->getMetadataFor('Doctrine\Tests\Models\DDC889\DDC889Entity');
}
@@ -498,7 +509,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testNamedNativeQuery()
{
$class = $this->createClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
//named native query
@@ -527,7 +538,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertArrayHasKey('mapping-count', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-find-all', $class->sqlResultSetMappings);
$this->assertArrayHasKey('mapping-without-fields', $class->sqlResultSetMappings);
$findAllMapping = $class->getSqlResultSetMapping('mapping-find-all');
$this->assertEquals('mapping-find-all', $findAllMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $findAllMapping['entities'][0]['entityClass']);
@@ -539,7 +550,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('mapping-without-fields', $withoutFieldsMapping['name']);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsAddress', $withoutFieldsMapping['entities'][0]['entityClass']);
$this->assertEquals(array(), $withoutFieldsMapping['entities'][0]['fields']);
$countMapping = $class->getSqlResultSetMapping('mapping-count');
$this->assertEquals('mapping-count', $countMapping['name']);
$this->assertEquals(array('name'=>'count'), $countMapping['columns'][0]);
@@ -627,7 +638,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$adminMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Admin');
$guestMetadata = $factory->getMetadataFor('Doctrine\Tests\Models\DDC964\DDC964Guest');
// assert groups association mappings
$this->assertArrayHasKey('groups', $guestMetadata->associationMappings);
$this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
@@ -686,7 +697,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']);
$this->assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']);
$this->assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']);
// assert override
$this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']);
$this->assertEquals(array('address_id'=>'id'), $guestAddress['sourceToTargetKeyColumns']);
@@ -793,6 +804,12 @@ class User
*/
public $groups;
/**
* @Column(type="integer")
* @Version
*/
public $version;
/**
* @PrePersist
@@ -847,6 +864,9 @@ class User
'columnName' => 'user_email',
'columnDefinition' => 'CHAR(32) NOT NULL',
));
$mapping = array('fieldName' => 'version', 'type' => 'integer');
$metadata->setVersionMapping($mapping);
$metadata->mapField($mapping);
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
$metadata->mapOneToOne(array(
'fieldName' => 'address',
@@ -1051,7 +1071,7 @@ class DDC807Entity
* @GeneratedValue(strategy="NONE")
**/
public $id;
public static function loadMetadata(ClassMetadataInfo $metadata)
{
$metadata->mapField(array(

View File

@@ -922,26 +922,6 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('doctrineglobal_article_cms_cmsuser', $articleMetadata->associationMappings['author']['joinTable']['name']);
}
/**
* @group DDC-984
* @group DDC-559
*/
public function testFullyQualifiedClassNameShouldBeGivenToNamingStrategyPropertyToColumnName()
{
$namingStrategy = new MyPrefixNamingStrategy();
$metadata = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', $namingStrategy);
$metadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$metadata->mapField(array('fieldName'=>'country'));
$metadata->mapField(array('fieldName'=>'city'));
$this->assertEquals($metadata->fieldNames, array(
'cmsaddress_country' => 'country',
'cmsaddress_city' => 'city'
));
}
/**
* @group DDC-1746
*/
@@ -1013,14 +993,3 @@ class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStra
return strtolower($className);
}
}
class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
{
/**
* {@inheritdoc}
*/
public function propertyToColumnName($propertyName, $className = null)
{
return strtolower($this->classToTableName($className)) . '_' . $propertyName;
}
}

View File

@@ -54,4 +54,35 @@ class YamlMappingDriverTest extends AbstractMappingDriverTest
$this->createClassMetadata('Doctrine\Tests\Models\Generic\SerializationModel');
}
/**
* @group DDC-2069
*/
public function testSpacesShouldBeIgnoredWhenUseExplode()
{
$metadata = $this->createClassMetadata(__NAMESPACE__.'\DDC2069Entity');
$unique = $metadata->table['uniqueConstraints'][0]['columns'];
$indexes = $metadata->table['indexes'][0]['columns'];
$nameField = $metadata->fieldMappings['name'];
$valueField = $metadata->fieldMappings['value'];
$this->assertEquals('name', $unique[0]);
$this->assertEquals('value', $unique[1]);
$this->assertEquals('value', $indexes[0]);
$this->assertEquals('name', $indexes[1]);
$this->assertEquals(255, $nameField['length']);
$this->assertEquals(255, $valueField['length']);
}
}
class DDC2069Entity
{
public $id;
public $name;
public $value;
}

View File

@@ -35,6 +35,9 @@ $metadata->mapField(array(
'columnName' => 'user_email',
'columnDefinition' => 'CHAR(32) NOT NULL',
));
$mapping = array('fieldName' => 'version', 'type' => 'integer');
$metadata->setVersionMapping($mapping);
$metadata->mapField($mapping);
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
$metadata->mapOneToOne(array(
'fieldName' => 'address',
@@ -121,4 +124,4 @@ $metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => 'tablename_seq',
'allocationSize' => 100,
'initialValue' => 1,
));
));

View File

@@ -4,7 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
<options>
<option name="foo">bar</option>
@@ -36,7 +36,7 @@
<generator strategy="AUTO"/>
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
</id>
<field name="name" column="name" type="string" length="50" nullable="true" unique="true">
<options>
<option name="foo">bar</option>
@@ -46,12 +46,14 @@
</options>
</field>
<field name="email" column="user_email" type="string" column-definition="CHAR(32) NOT NULL" />
<field name="version" type="integer" version="true" />
<one-to-one field="address" target-entity="Address" inversed-by="user">
<cascade><cascade-remove /></cascade>
<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" index-by="number" orphan-removal="true">
<cascade>
<cascade-persist/>
@@ -60,7 +62,7 @@
<order-by-field name="number" direction="ASC" />
</order-by>
</one-to-many>
<many-to-many field="groups" target-entity="Group">
<cascade>
<cascade-all/>
@@ -74,7 +76,7 @@
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
</doctrine-mapping>

View File

@@ -5,4 +5,4 @@ Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType:
generator:
strategy: NONE
fields:
name:
name: ~

View File

@@ -0,0 +1,15 @@
Doctrine\Tests\ORM\Mapping\DDC2069Entity:
type: entity
id:
id: ~
fields:
name:
type: string ( 255 )
value:
type: string ( 255 )
uniqueConstraints:
0:
columns: name, value
indexes:
0:
columns: value, name

View File

@@ -30,6 +30,9 @@ Doctrine\Tests\ORM\Mapping\User:
type: string
column: user_email
columnDefinition: CHAR(32) NOT NULL
version:
type: integer
version: true
oneToOne:
address:
targetEntity: Address
@@ -73,4 +76,4 @@ Doctrine\Tests\ORM\Mapping\User:
name_idx:
columns: name
0:
columns: user_email
columns: user_email

View File

@@ -7,6 +7,7 @@ use Doctrine\ORM\Persisters\BasicEntityPersister;
use Doctrine\Tests\Models\CustomType\CustomTypeParent;
use Doctrine\Tests\Models\CustomType\CustomTypeChild;
use Doctrine\Tests\Models\CustomType\CustomTypeFriend;
use Doctrine\Common\Collections\Expr\Comparison;
require_once __DIR__ . '/../../TestInit.php';
@@ -88,4 +89,13 @@ class BasicEntityPersisterTypeValueSqlTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('t0."simple-entity-id" AS simpleentityid1, t0."simple-entity-value" AS simpleentityvalue2', $method->invoke($persister));
}
/**
* @group DDC-2073
*/
public function testSelectConditionStatementIsNull()
{
$statement = $this->_persister->getSelectConditionStatementSQL('test', null, array(), Comparison::IS);
$this->assertEquals('test IS ?', $statement);
}
}

View File

@@ -409,4 +409,18 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
$select = new Expr\Select(array('foo', 'bar'));
$this->assertEquals(array('foo', 'bar'), $select->getParts());
}
public function testAddEmpty() {
$andExpr = $this->_expr->andx();
$andExpr->add($this->_expr->andx());
$this->assertEquals(0, $andExpr->count());
}
public function testAddNull() {
$andExpr = $this->_expr->andx();
$andExpr->add(null);
$this->assertEquals(0, $andExpr->count());
}
}

View File

@@ -163,4 +163,16 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('cities', $parameter->getName());
$this->assertEquals($cities, $parameter->getValue());
}
/**
* @group DDC-2224
*/
public function testProcessParameterValueClassMetadata()
{
$query = $this->_em->createQuery("SELECT a FROM Doctrine\Tests\Models\CMS\CmsAddress a WHERE a.city IN (:cities)");
$this->assertEquals(
'Doctrine\Tests\Models\CMS\CmsAddress',
$query->processParameterValue($this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'))
);
}
}

View File

@@ -143,6 +143,19 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}
public function testSupportsJoinOnMultipleComponentsWithJoinedInheritanceType()
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_managers c2_ INNER JOIN company_employees c3_ ON c2_.id = c3_.id INNER JOIN company_persons c4_ ON c2_.id = c4_.id AND (c0_.id = c4_.id)'
);
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ INNER JOIN company_employees c3_ ON c2_.id = c3_.id INNER JOIN company_persons c4_ ON c2_.id = c4_.id ON (c0_.id = c4_.id)'
);
}
public function testSupportsSelectWithCollectionAssociationJoin()
{
$this->assertSqlGeneration(
@@ -461,7 +474,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN ('employee')",
"SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_ WHERE c0_.discr IN (?)",
array(), array(1 => $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee'))
);
}

View File

@@ -137,6 +137,19 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a ON u.id = a.author_id'
);
}
public function testComplexInnerJoinWithIndexBy()
{
$qb = $this->_em->createQueryBuilder()
->select('u', 'a')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->innerJoin('u.articles', 'a', 'ON', 'u.id = a.author_id', 'a.name');
$this->assertValidQueryBuilder(
$qb,
'SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a INDEX BY a.name ON u.id = a.author_id'
);
}
public function testLeftJoin()
{

View File

@@ -64,6 +64,7 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$metadata->mapManyToMany(array(
'fieldName' => 'comments',
'targetEntity' => 'Doctrine\Tests\ORM\Tools\EntityGeneratorComment',
'fetch' => ClassMetadataInfo::FETCH_EXTRA_LAZY,
'joinTable' => array(
'name' => 'book_comment',
'joinColumns' => array(array('name' => 'book_id', 'referencedColumnName' => 'id')),
@@ -167,6 +168,24 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($reflClass->getMethod('getTest')->isPublic(), "Check for public visibility of method 'getTest' failed.");
}
/**
* @group DDC-2121
*/
public function testMethodDocBlockShouldStartWithBackSlash()
{
$metadata = $this->generateBookEntityFixture();
$book = $this->newInstance($metadata);
$this->assertPhpDocVarType('\Doctrine\Common\Collections\Collection', new \ReflectionProperty($book, 'comments'));
$this->assertPhpDocReturnType('\Doctrine\Common\Collections\Collection', new \ReflectionMethod($book, 'getComments'));
$this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'addComment'));
$this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'removeComment'));
$this->assertPhpDocVarType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', new \ReflectionProperty($book, 'author'));
$this->assertPhpDocReturnType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', new \ReflectionMethod($book, 'getAuthor'));
$this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', new \ReflectionMethod($book, 'setAuthor'));
}
public function testEntityExtendsStdClass()
{
$this->_generator->setClassToExtend('stdClass');
@@ -205,6 +224,8 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($cm->identifier, $metadata->identifier);
$this->assertEquals($cm->idGenerator, $metadata->idGenerator);
$this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
$this->assertEquals(ClassMetadataInfo::FETCH_EXTRA_LAZY, $cm->associationMappings['comments']['fetch']);
}
public function testLoadPrefixedMetadata()
@@ -278,6 +299,131 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
$this->assertContains('@SequenceGenerator(sequenceName="DDC1784_ID_SEQ", allocationSize=1, initialValue=2)', $docComment);
}
/**
* @group DDC-2079
*/
public function testGenerateEntityWithMultipleInverseJoinColumns()
{
$metadata = new ClassMetadataInfo($this->_namespace . '\DDC2079Entity');
$metadata->namespace = $this->_namespace;
$metadata->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
$metadata->mapManyToMany(array(
'fieldName' => 'centroCustos',
'targetEntity' => 'DDC2079CentroCusto',
'joinTable' => array(
'name' => 'unidade_centro_custo',
'joinColumns' => array(
array('name' => 'idorcamento', 'referencedColumnName' => 'idorcamento'),
array('name' => 'idunidade', 'referencedColumnName' => 'idunidade')
),
'inverseJoinColumns' => array(
array('name' => 'idcentrocusto', 'referencedColumnName' => 'idcentrocusto'),
array('name' => 'idpais', 'referencedColumnName' => 'idpais'),
),
),
));
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
$filename = $this->_tmpDir . DIRECTORY_SEPARATOR
. $this->_namespace . DIRECTORY_SEPARATOR . 'DDC2079Entity.php';
$this->assertFileExists($filename);
require_once $filename;
$property = new \ReflectionProperty($metadata->name, 'centroCustos');
$docComment = $property->getDocComment();
//joinColumns
$this->assertContains('@JoinColumn(name="idorcamento", referencedColumnName="idorcamento"),', $docComment);
$this->assertContains('@JoinColumn(name="idunidade", referencedColumnName="idunidade")', $docComment);
//inverseJoinColumns
$this->assertContains('@JoinColumn(name="idcentrocusto", referencedColumnName="idcentrocusto"),', $docComment);
$this->assertContains('@JoinColumn(name="idpais", referencedColumnName="idpais")', $docComment);
}
/**
* @group DDC-2172
*/
public function testGetInheritanceTypeString()
{
$reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadata');
$method = new \ReflectionMethod($this->_generator, 'getInheritanceTypeString');
$constants = $reflection->getConstants();
$pattern = '/^INHERITANCE_TYPE_/';
$method->setAccessible(true);
foreach ($constants as $name => $value) {
if( ! preg_match($pattern, $name)) {
continue;
}
$expected = preg_replace($pattern, '', $name);
$actual = $method->invoke($this->_generator, $value);
$this->assertEquals($expected, $actual);
}
$this->setExpectedException('\InvalidArgumentException', 'Invalid provided InheritanceType: INVALID');
$method->invoke($this->_generator, 'INVALID');
}
/**
* @group DDC-2172
*/
public function testGetChangeTrackingPolicyString()
{
$reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadata');
$method = new \ReflectionMethod($this->_generator, 'getChangeTrackingPolicyString');
$constants = $reflection->getConstants();
$pattern = '/^CHANGETRACKING_/';
$method->setAccessible(true);
foreach ($constants as $name => $value) {
if( ! preg_match($pattern, $name)) {
continue;
}
$expected = preg_replace($pattern, '', $name);
$actual = $method->invoke($this->_generator, $value);
$this->assertEquals($expected, $actual);
}
$this->setExpectedException('\InvalidArgumentException', 'Invalid provided ChangeTrackingPolicy: INVALID');
$method->invoke($this->_generator, 'INVALID');
}
/**
* @group DDC-2172
*/
public function testGetIdGeneratorTypeString()
{
$reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadata');
$method = new \ReflectionMethod($this->_generator, 'getIdGeneratorTypeString');
$constants = $reflection->getConstants();
$pattern = '/^GENERATOR_TYPE_/';
$method->setAccessible(true);
foreach ($constants as $name => $value) {
if( ! preg_match($pattern, $name)) {
continue;
}
$expected = preg_replace($pattern, '', $name);
$actual = $method->invoke($this->_generator, $value);
$this->assertEquals($expected, $actual);
}
$this->setExpectedException('\InvalidArgumentException', 'Invalid provided IdGeneratorType: INVALID');
$method->invoke($this->_generator, 'INVALID');
}
/**
* @dataProvider getEntityTypeAliasDataProvider
*

View File

@@ -41,5 +41,22 @@ class CountOutputWalkerTest extends PaginationTestCase
"SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id1 FROM (SELECT count(u0_.id) AS sclr0, g1_.id AS id1, u0_.id AS id2 FROM groups g1_ LEFT JOIN user_group u2_ ON g1_.id = u2_.group_id LEFT JOIN User u0_ ON u0_.id = u2_.user_id GROUP BY g1_.id HAVING sclr0 > 0) dctrn_result) dctrn_table", $query->getSql()
);
}
public function testCountQueryOrderBySqlServer()
{
if ($this->entityManager->getConnection()->getDatabasePlatform()->getName() !== "mssql") {
$this->markTestSkipped('SQLServer only test.');
}
$query = $this->entityManager->createQuery(
'SELECT p FROM Doctrine\Tests\ORM\Tools\Pagination\BlogPost p ORDER BY p.id');
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$query->setFirstResult(null)->setMaxResults(null);
$this->assertEquals(
"SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id0 FROM (SELECT b0_.id AS id0, b0_.author_id AS author_id1, b0_.category_id AS category_id2 FROM BlogPost b0_) dctrn_result) dctrn_table",
$query->getSql()
);
}
}

View File

@@ -10,14 +10,42 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
{
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a');
$query->expireQueryCache(true);
$limitQuery = clone $query;
$limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
"SELECT DISTINCT id0 FROM (SELECT m0_.id AS id0, c1_.id AS id1, a2_.id AS id2, a2_.name AS name3, m0_.author_id AS author_id4, m0_.category_id AS category_id5 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result", $limitQuery->getSql()
"SELECT DISTINCT id0 FROM (SELECT m0_.id AS id0, m0_.title AS title1, c1_.id AS id2, a2_.id AS id3, a2_.name AS name4, m0_.author_id AS author_id5, m0_.category_id AS category_id6 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id) dctrn_result", $limitQuery->getSql()
);
}
public function testLimitSubqueryWithSortPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
$limitQuery = clone $query;
$limitQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
$this->assertEquals(
"SELECT DISTINCT id0, title1 FROM (SELECT m0_.id AS id0, m0_.title AS title1, c1_.id AS id2, a2_.id AS id3, a2_.name AS name4, m0_.author_id AS author_id5, m0_.category_id AS category_id6 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id ORDER BY m0_.title ASC) dctrn_result ORDER BY title1 ASC", $limitQuery->getSql()
);
$this->entityManager->getConnection()->setDatabasePlatform($odp);
}
public function testLimitSubqueryPg()
{
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
$this->testLimitSubquery();
$this->entityManager->getConnection()->setDatabasePlatform($odp);
}
public function testCountQuery_MixedResultsWithName()
{
$query = $this->entityManager->createQuery(

View File

@@ -21,6 +21,18 @@ class LimitSubqueryWalkerTest extends PaginationTestCase
);
}
public function testLimitSubqueryWithSort()
{
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
$limitQuery = clone $query;
$limitQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker'));
$this->assertEquals(
"SELECT DISTINCT m0_.id AS id0, m0_.title AS title1 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id ORDER BY m0_.title ASC", $limitQuery->getSql()
);
}
public function testCountQuery_MixedResultsWithName()
{
$query = $this->entityManager->createQuery(

View File

@@ -31,6 +31,8 @@ class MyBlogPost
* @ManyToOne(targetEntity="Category")
*/
public $category;
/** @column(type="string") */
public $title;
}
/**

View File

@@ -20,7 +20,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -34,7 +34,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT a0_.id AS id0, a0_.name AS name1, sum(a0_.name) AS sclr2 FROM Author a0_ WHERE a0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT a0_.id AS id0, a0_.name AS name1, sum(a0_.name) AS sclr2 FROM Author a0_ WHERE a0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -48,7 +48,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE 1 = 1 AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE 1 = 1 AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -62,7 +62,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE 1 = 1 AND 2 = 2 AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE 1 = 1 AND 2 = 2 AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -76,7 +76,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 OR 2 = 2) AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 OR 2 = 2) AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -90,7 +90,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 OR 2 = 2) AND 3 = 3 AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 OR 2 = 2) AND 3 = 3 AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -104,7 +104,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 AND 2 = 2 OR 3 = 3) AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (1 = 1 AND 2 = 2 OR 3 = 3) AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
@@ -118,7 +118,7 @@ class WhereInWalkerTest extends PaginationTestCase
$whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, 10);
$this->assertEquals(
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (NOT 1 = 2) AND u0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $whereInQuery->getSql()
"SELECT u0_.id AS id0, g1_.id AS id1 FROM User u0_ INNER JOIN user_group u2_ ON u0_.id = u2_.user_id INNER JOIN groups g1_ ON g1_.id = u2_.group_id WHERE (NOT 1 = 2) AND u0_.id IN (?)", $whereInQuery->getSql()
);
}
}

View File

@@ -60,6 +60,31 @@ class ResolveTargetEntityListenerTest extends \Doctrine\Tests\OrmTestCase
$this->assertSame('Doctrine\Tests\ORM\Tools\ResolveTargetEntity', $meta['oneToMany']['targetEntity']);
$this->assertSame('Doctrine\Tests\ORM\Tools\TargetEntity', $meta['oneToOne']['targetEntity']);
}
/**
* @group DDC-2109
*/
public function testAssertTableColumnsAreNotAddedInManyToMany()
{
$evm = $this->em->getEventManager();
$this->listener->addResolveTargetEntity(
'Doctrine\Tests\ORM\Tools\ResolveTargetInterface',
'Doctrine\Tests\ORM\Tools\ResolveTargetEntity',
array()
);
$this->listener->addResolveTargetEntity(
'Doctrine\Tests\ORM\Tools\TargetInterface',
'Doctrine\Tests\ORM\Tools\TargetEntity',
array()
);
$evm->addEventListener(Events::loadClassMetadata, $this->listener);
$cm = $this->factory->getMetadataFor('Doctrine\Tests\ORM\Tools\ResolveTargetEntity');
$meta = $cm->associationMappings['manyToMany'];
$this->assertSame('Doctrine\Tests\ORM\Tools\TargetEntity', $meta['targetEntity']);
$this->assertEquals(array('resolvetargetentity_id', 'targetinterface_id'), $meta['joinTableColumns']);
}
}
interface ResolveTargetInterface

View File

@@ -44,8 +44,8 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
$schema = $schemaTool->getSchemaFromMetadata($classes);
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getOptions(), "options annotation are passed to the tables optionss");
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getOptions(), "options annotation are passed to the tables options");
$this->assertEquals($expected, $schema->getTable('TestEntityWithAnnotationOptionsAttribute')->getColumn('test')->getCustomSchemaOptions(), "options annotation are passed to the columns customSchemaOptions");
}

View File

@@ -204,6 +204,38 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(UnitOfWork::STATE_DETACHED, $this->_unitOfWork->getEntityState($ph2));
$this->assertFalse($persister->isExistsCalled());
}
/**
* DDC-2086 [GH-484] Prevented "Undefined index" notice when updating.
*/
public function testNoUndefinedIndexNoticeOnScheduleForUpdateWithoutChanges()
{
// Setup fake persister and id generator
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
$userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
// Create a test user
$user = new ForumUser();
$user->name = 'Jasper';
$this->_unitOfWork->persist($user);
$this->_unitOfWork->commit();
// Schedule user for update without changes
$this->_unitOfWork->scheduleForUpdate($user);
// This commit should not raise an E_NOTICE
$this->_unitOfWork->commit();
}
/**
* @group DDC-1984
*/
public function testLockWithoutEntityThrowsException()
{
$this->setExpectedException('InvalidArgumentException');
$this->_unitOfWork->lock(null, null, null);
}
}
/**
@@ -309,4 +341,4 @@ class VersionedAssignedIdentifierEntity
* @Version @Column(type="integer")
*/
public $version;
}
}