Issue Details (XML | Word | Printable)

Key: NUCRDBMS-28
Type: Bug Bug
Status: Open Open
Priority: Testcase Required Testcase Required
Assignee: Unassigned
Reporter: Marco Schulze
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
DataNucleus Store RDBMS

Usage of an interface as mapped-by field in a Set leads to missing/wrong elements in the Set

Created: 05/Jun/08 12:53 AM   Updated: 29/Oct/13 11:12 AM
Component/s: None
Affects Version/s: None
Fix Version/s: None

Forum Thread URL: http://www.jpox.org/servlet/forum/viewthread?thread=5118


 Description  « Hide
When using an interface field in the mapped element as mapped-by field, the Set of the element-holder (i.e. the object having the Set field) behaves incorrectly:

* Set.isEmpty() returns true (even though there is an element).
* Set.size() returns 0 (even though there is an element).
* After calling Set.iterator(), isEmpty() returns false (correct), but the Set contains more elements than there should be (Set.size() returned 2 in my test even though there is only 1 element).

Test case: http://www.nightlabs.de/~marco/datanucleus/2008-06-03.00/TestDataNucleusOneDatastore.tar.gz
Log file: http://www.nightlabs.de/~marco/datanucleus/2008-06-03.00/datanucleus.log.gz

Sort Order: Ascending order - Click to sort in descending order
Marco Schulze added a comment - 05/Jun/08 01:36 AM
I just digged deeper into the query that returns too many results (i.e. 2 instead of 1):

SELECT
   'org.datanucleus.test.E' AS JPOXMETADATA,
   `THIS`.`EEE_ID`,
   `THIS`.`ORGANISATION_ID`
FROM `E` `THIS`
LEFT OUTER JOIN `F` `SUBELEMENT0`
   ON
   `SUBELEMENT0`.`EEE_ID` = `THIS`.`EEE_ID` AND
   `SUBELEMENT0`.`ORGANISATION_ID` = `THIS`.`ORGANISATION_ID`
WHERE
   `SUBELEMENT0`.`EEE_ID` IS NULL AND
   `SUBELEMENT0`.`ORGANISATION_ID` IS NULL AND
   (
     (
       (
         0 = `THIS`.`ELEMENT_HOLDER_B_BBB_ID_EID` AND
         'nightlabs.org' = `THIS`.`ELEMENT_HOLDER_B_ORGANISATION_ID_EID`
       ) OR
       (
         0 = `THIS`.`ELEMENT_HOLDER_A_AAA_ID_EID` AND
         'nightlabs.org' = `THIS`.`ELEMENT_HOLDER_A_ORGANISATION_ID_EID`
       )
     )
   )
UNION
SELECT
   'org.datanucleus.test.F' AS JPOXMETADATA,
   `THIS`.`EEE_ID`,`THIS`.`ORGANISATION_ID`
FROM `E` `THIS`
INNER JOIN `F` `ELEMENT`
   ON
   `ELEMENT`.`EEE_ID` = `THIS`.`EEE_ID` AND
   `ELEMENT`.`ORGANISATION_ID` = `THIS`.`ORGANISATION_ID`
WHERE
   (
     (
       0 = `THIS`.`ELEMENT_HOLDER_B_BBB_ID_EID` AND
       'nightlabs.org' = `THIS`.`ELEMENT_HOLDER_B_ORGANISATION_ID_EID`
     ) OR
     (
       0 = `THIS`.`ELEMENT_HOLDER_A_AAA_ID_EID` AND
       'nightlabs.org' = `THIS`.`ELEMENT_HOLDER_A_ORGANISATION_ID_EID`
     )
   )

The part before the UNION returns already 2 records. The part after the UNION returns none. Playing a bit around with it, I found out that it seems to be an issue with MySQL's query engine that evaluates this part always to true (even though the field ELEMENT_HOLDER_B_BBB_ID_EID is NULL:

  (
    0 = `THIS`.`ELEMENT_HOLDER_B_BBB_ID_EID` AND
    'nightlabs.org' = `THIS`.`ELEMENT_HOLDER_B_ORGANISATION_ID_EID`
  )

The problem seems to be that 0 is an integer while the field ELEMENT_HOLDER_B_BBB_ID_EID is a VARCHAR. Maybe that's because internally a NULL String is stored as 0. I don't know how other SQL servers behave in this situation.

Even though it's IMHO a bug in MySQL, I think it is not clean to do add this part above the "OR" in the first place: It compares primary key fields of class A with columns of class B. Since the type of the object having the pk values "nightlabs.org" and "0" is known, DataNucleus should only query the corresponding fields - i.e. the A fields (the part under the "OR").

Btw. I'm wondering what will happen, if the number of primary key fields between class A and B differs. Probably an exception ;-)

Andy Jefferson added a comment - 29/Oct/13 11:12 AM
testcase no longer exists on that server. left as guesswork as to whether the set has an interface type or the other end, whether using join table or not, etc.