Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Critical
-
Resolution: Fixed
-
Affects Version/s: 2.0.1
-
Fix Version/s: 2.0.4
-
Component/s: Persistence
-
Environment:OS X 10.7.2, java x64 build 1.6.0_29-b11-402-11M3527
-
Testcase included:yes
Description
The withCriteria method on Domain classes returns different result structures when running in Unit and Integration Tests when using projections. In Integration Tests (verified in 2.0.1 and 1.3.6), if multiple projections are stated for a withCriteria call, then the results are returned as though they are in 1 row:
Foo.withCriteria {
projections {
rowCount()
sum 'amount'
}
Returns an object that looks like
[[<rowCount>, <sum>]]
However, in 2.0.1 Unit Tests, the same project is decomposed from the wrapper list and returns --> [<rowCount>, <sum>]
This makes code that uses withCriteria and projections untestable using UnitTests because the results return differently than they do in integration tests and in run-time
I've attached a test project that has the same test methods in both a unit & integration test. The Integration tests pass and the unit tests fail.
I've traced this all the way down to the difference between org.hibernate.loader.Loader.doQuery:829 and org.grails.datastore.mapping.simple.query.SimpleMapQuery (starting at line 77)
The SimpleMapQuery iterates through each projection and adds it to the result list, where as Hibernate performs the query which returns a row with all the projections and adds the row to the result list (thus the double list wrapping).
The funny thing is the the UnitTest implementation behavior matches the Grails documentation: http://grails.org/doc/latest/ref/Domain%20Classes/withCriteria.html
-
- 0001-Fix-and-clean-up-projection-tests-a-bit.patch
- 08/May/12 2:40 PM
- 4 kB
- R
-
Hide
- criteriaTest2.zip
- 02/Apr/12 7:48 PM
- 123 kB
- R
-
- criteriaTest/.project 0.5 kB
- criteriaTest/web-app/js/application.js 0.2 kB
- criteriaTest/web-app/css/errors.css 2 kB
- criteriaTest/web-app/css/mobile.css 1 kB
- criteriaTest/web-app/css/main.css 11 kB
- criteriaTest/web-app/.../grails_logo.jpg 8 kB
- criteriaTest/.../apple-touch-icon.png 5 kB
- criteriaTest/web-app/.../leftnav_btm.png 4 kB
- criteriaTest/.../apple-touch-icon-retina.png 15 kB
- criteriaTest/web-app/images/spinner.gif 2 kB
- criteriaTest/web-app/images/favicon.ico 10 kB
- criteriaTest/.../leftnav_midstretch.png 3 kB
- criteriaTest/web-app/.../grails_logo.png 10 kB
- criteriaTest/web-app/.../information.png 0.8 kB
- criteriaTest/web-app/.../database_delete.png 0.6 kB
- criteriaTest/web-app/.../skin/house.png 0.8 kB
- criteriaTest/web-app/.../skin/shadow.jpg 0.3 kB
- criteriaTest/web-app/.../skin/sorted_asc.gif 0.8 kB
- criteriaTest/web-app/.../exclamation.png 0.7 kB
- criteriaTest/web-app/.../database_table.png 0.7 kB
- criteriaTest/web-app/.../sorted_desc.gif 0.8 kB
- criteriaTest/web-app/.../database_save.png 0.7 kB
- criteriaTest/web-app/.../database_edit.png 0.7 kB
- criteriaTest/web-app/.../database_add.png 0.6 kB
- criteriaTest/web-app/.../springsource.png 9 kB
- criteriaTest/web-app/.../leftnav_top.png 3 kB
- criteriaTest/.../applicationContext.xml 1 kB
- criteriaTest/web-app/.../tld/grails.tld 18 kB
- criteriaTest/web-app/WEB-INF/tld/c.tld 16 kB
- criteriaTest/web-app/WEB-INF/tld/fmt.tld 19 kB
-
Hide
- criteriaTest2.zip
- 02/Apr/12 5:01 AM
- 120 kB
- R
-
- criteriaTest/.project 0.5 kB
- criteriaTest/web-app/js/application.js 0.2 kB
- criteriaTest/web-app/css/errors.css 2 kB
- criteriaTest/web-app/css/mobile.css 1 kB
- criteriaTest/web-app/css/main.css 11 kB
- criteriaTest/web-app/.../grails_logo.jpg 8 kB
- criteriaTest/.../apple-touch-icon.png 5 kB
- criteriaTest/web-app/.../leftnav_btm.png 4 kB
- criteriaTest/.../apple-touch-icon-retina.png 15 kB
- criteriaTest/web-app/images/spinner.gif 2 kB
- criteriaTest/web-app/images/favicon.ico 10 kB
- criteriaTest/.../leftnav_midstretch.png 3 kB
- criteriaTest/web-app/.../grails_logo.png 10 kB
- criteriaTest/web-app/.../information.png 0.8 kB
- criteriaTest/web-app/.../database_delete.png 0.6 kB
- criteriaTest/web-app/.../skin/house.png 0.8 kB
- criteriaTest/web-app/.../skin/shadow.jpg 0.3 kB
- criteriaTest/web-app/.../skin/sorted_asc.gif 0.8 kB
- criteriaTest/web-app/.../exclamation.png 0.7 kB
- criteriaTest/web-app/.../database_table.png 0.7 kB
- criteriaTest/web-app/.../sorted_desc.gif 0.8 kB
- criteriaTest/web-app/.../database_save.png 0.7 kB
- criteriaTest/web-app/.../database_edit.png 0.7 kB
- criteriaTest/web-app/.../database_add.png 0.6 kB
- criteriaTest/web-app/.../springsource.png 9 kB
- criteriaTest/web-app/.../leftnav_top.png 3 kB
- criteriaTest/.../applicationContext.xml 1 kB
- criteriaTest/web-app/.../tld/grails.tld 18 kB
- criteriaTest/web-app/WEB-INF/tld/c.tld 16 kB
- criteriaTest/web-app/WEB-INF/tld/fmt.tld 19 kB
-
Hide
- criteriaTest2.zip
- 02/Apr/12 4:43 AM
- 120 kB
- R
-
- criteriaTest/.project 0.5 kB
- criteriaTest/web-app/js/application.js 0.2 kB
- criteriaTest/web-app/css/errors.css 2 kB
- criteriaTest/web-app/css/mobile.css 1 kB
- criteriaTest/web-app/css/main.css 11 kB
- criteriaTest/web-app/.../grails_logo.jpg 8 kB
- criteriaTest/.../apple-touch-icon.png 5 kB
- criteriaTest/web-app/.../leftnav_btm.png 4 kB
- criteriaTest/.../apple-touch-icon-retina.png 15 kB
- criteriaTest/web-app/images/spinner.gif 2 kB
- criteriaTest/web-app/images/favicon.ico 10 kB
- criteriaTest/.../leftnav_midstretch.png 3 kB
- criteriaTest/web-app/.../grails_logo.png 10 kB
- criteriaTest/web-app/.../information.png 0.8 kB
- criteriaTest/web-app/.../database_delete.png 0.6 kB
- criteriaTest/web-app/.../skin/house.png 0.8 kB
- criteriaTest/web-app/.../skin/shadow.jpg 0.3 kB
- criteriaTest/web-app/.../skin/sorted_asc.gif 0.8 kB
- criteriaTest/web-app/.../exclamation.png 0.7 kB
- criteriaTest/web-app/.../database_table.png 0.7 kB
- criteriaTest/web-app/.../sorted_desc.gif 0.8 kB
- criteriaTest/web-app/.../database_save.png 0.7 kB
- criteriaTest/web-app/.../database_edit.png 0.7 kB
- criteriaTest/web-app/.../database_add.png 0.6 kB
- criteriaTest/web-app/.../springsource.png 9 kB
- criteriaTest/web-app/.../leftnav_top.png 3 kB
- criteriaTest/.../applicationContext.xml 1 kB
- criteriaTest/web-app/.../tld/grails.tld 18 kB
- criteriaTest/web-app/WEB-INF/tld/c.tld 16 kB
- criteriaTest/web-app/WEB-INF/tld/fmt.tld 19 kB
-
Hide
- criteriaTest-bug-report-28022012.zip
- 28/Feb/12 1:28 PM
- 23 kB
- John Engelman
-
- grails-app/.../ApplicationResources.groovy 0.1 kB
- grails-app/conf/BootStrap.groovy 0.1 kB
- grails-app/conf/BuildConfig.groovy 2 kB
- grails-app/conf/Config.groovy 4 kB
- grails-app/conf/DataSource.groovy 1 kB
- grails-app/conf/UrlMappings.groovy 0.2 kB
- grails-app/conf/spring/resources.groovy 0.0 kB
- grails-app/domain/.../Check.groovy 0.1 kB
- grails-app/i18n/messages.properties 3 kB
- grails-app/.../messages_cs_CZ.properties 3 kB
- grails-app/i18n/messages_da.properties 3 kB
- grails-app/i18n/messages_de.properties 4 kB
- grails-app/i18n/messages_es.properties 3 kB
- grails-app/i18n/messages_fr.properties 2 kB
- grails-app/i18n/messages_it.properties 2 kB
- grails-app/i18n/messages_ja.properties 4 kB
- grails-app/i18n/messages_nl.properties 3 kB
- grails-app/.../messages_pt_BR.properties 3 kB
- grails-app/.../messages_pt_PT.properties 3 kB
- grails-app/i18n/messages_ru.properties 4 kB
- grails-app/i18n/messages_sv.properties 3 kB
- grails-app/i18n/messages_th.properties 6 kB
- grails-app/.../messages_zh_CN.properties 2 kB
- grails-app/services/.../CheckService.groovy 0.1 kB
- grails-app/views/error.gsp 0.3 kB
- grails-app/views/index.gsp 3 kB
- grails-app/views/layouts/main.gsp 2 kB
- test/.../CheckServiceTests.groovy 0.9 kB
- test/unit/.../CheckServiceUnitTests.groovy 1.0 kB
- test/unit/criteriatest/CheckTests.groovy 0.9 kB
-
- order.patch
- 02/Apr/12 7:46 PM
- 1 kB
- R
-
- results.patch
- 02/Apr/12 7:28 PM
- 0.8 kB
- R
Activity
- All
- Comments
- Work Log
- History
- Activity
- Git Commits
Don't mean to hijack this bug, but just ran into a very similar bug related to the same grails code (if you feel it warrants a separate bug, then I'll create one). For simple column projections where you end up with multiple rows the problem as follows: where Hibernate returns something like
[ [row1_proj1, row1_proj2, row1_proj3], [row2_proj1, row2_proj2, row3_proj3] ]
the in-memory GORM implemenation returns
[[row1_proj1, row2_proj1], [row1_proj2, row2_proj2], [row1_proj3, row2_proj3]]
It looks like a simple
results.transpose
would fix this, except it won't handle the case where you both column- as well as aggregation-projections, i.e. where you end up with a different number of results for each projection.
As to which one is "right": besides the fact that the Hibernate behaviour is really more consistent, the fact is the app is going to run against Hibernate in production, and since Hibernate is very unlikely to change their current behaviour and break everything out there, it's therefore really a no-brainer: the Hibernate is the right one.
The Hibernate behavior is right yes, the bug is in the unit test impl
@R btw if you can attach your example as well it would be good to get more test cases
I took the original criteriaTest app attached here, cleaned up a couple things (removed unneeded service and duplicate unit test), and added a third test to both the unit- and integration-tests for testing the multiple-rows results.
I also discovered another bug here having to do with the order() in the criteria where it is throwing an exception (this appears to be related to this rows/columns confusion too). The order() is commented out right now so that results are returned and the original error is made clear, but should of course be uncommented when that is fixed.
Oh heck, added a fourth test for completeness: so now there is the full matrix of single/multiple columns x single/multiple rows.
Again, the order() is not working - a quick perusal of the code indicates the order() criteria is fully borked as it appears to expect the result to be a map instead of a list.
Patch to fix order problems.
There were several issues with the order implementation, all of which this patch fixes:
- ordering was being applied after ranges instead of before
- multiple orders were being applied in reverse
- if there were projections order would throw an exception
@R - I have pushed the changes https://github.com/SpringSource/grails-data-mapping/commit/146c276fc061b84171e346a0dcc0985f40864476
However this test fails https://github.com/SpringSource/grails-data-mapping/blob/146c276fc061b84171e346a0dcc0985f40864476/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CriteriaProjectedResultsSpec.groovy#L46
Is the expectation correct? Or have I not applied the patch correctly? Thanks for your help
Apologies, I appear to have screwed up the tests a bit in the last set - the patches are correct, however. I was missing a bunch of 'assert' keywords, so a number of what should've been assertions were not.
I checked out the above code from github and fixed the test, as well as spock'ified the last test, and verified it all passes. Attached is the patch.
I think I'm going to try and tackle this bug this weekend, but I'm curious as to what the "right" behavior should be. I'm guessing that since Hibernate is "truth" for runtime, that the unit-tests should match that, which would also require an update to the documentation for withCriteria...thoughts?