Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 326104 - in-memory query BigDecimal equality comparation fails
Summary: in-memory query BigDecimal equality comparation fails
Status: CLOSED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P2 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Tom Ware CLA
QA Contact:
URL:
Whiteboard: submitted_patch
Keywords:
Depends on:
Blocks:
 
Reported: 2010-09-23 17:20 EDT by Vladimir CLA
Modified: 2022-06-09 10:10 EDT (History)
5 users (show)

See Also:
tom.ware: iplog+


Attachments
patch with test (5.91 KB, application/octet-stream)
2010-12-22 15:21 EST, Tom Ware CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir CLA 2010-09-23 17:20:27 EDT
Build Identifier: 2.1.0

In memory query (ReadAllQuery.conformResultsInUnitOfWork) with selection criteria consisting of BigDecimal attribute equality comparation fails if compared values has different BigDecimal.scale. 
Bad result of Expression.equal expression evaluation comes from BigDecimal.equal method usage. This method is not suited for numerical value comparation as javadoc imply. It is true for Double.equals as well.

Solution:
Replace "if (this.selector == Equal) {...} else if (this.selector == NotEqual) {...}" code block in method ExpressionOperator.doesRelationConform with this:
<code>
        if (this.selector == Equal
        || this.selector == NotEqual) {
            if ((left == null) && (right == null)) {
                return  this.selector == Equal;
            } else if ((left == null) || (right == null)) {
                return this.selector == NotEqual;
            }
            if (left instanceof Number
            && left instanceof Comparable && right instanceof Comparable
            && left.getClass().equals (right.getClass())) {
                return (((Comparable) left).compareTo( (Comparable) right) == 0) 
                    == (this.selector == Equal);
            }
            if (((left instanceof Number) && (right instanceof Number)) && (left.getClass() != right.getClass())) {
                return (((Number)left).doubleValue() == ((Number)right).doubleValue())
                    == (this.selector == Equal);
            }
            return left.equals( right)
                    == (this.selector == Equal);
        }
</code>

Reproducible: Always
Comment 1 Martin JANDA CLA 2010-09-27 01:37:16 EDT
I think that there is problem in proposed fix.
  You get EQUAL when you compare two NaN values of same type Double or Float. Because 'Double.NaN compareTo(Double.NaN)' return 0.

Problem is when types of left and right values differ.
(((Number)left).doubleValue() == ((Number)right).doubleValue())
  return FALSE for both NaN values not true as compareTo(...) == 0


>             if (((left instanceof Number) && (right instanceof Number)) &&
> (left.getClass() != right.getClass())) {
>                 return (((Number)left).doubleValue() ==
> ((Number)right).doubleValue())
>                     == (this.selector == Equal);
>             }
Comment 2 Vladimir CLA 2010-09-29 04:11:59 EDT
I hope NaN is not real problem in real database world.

(In reply to comment #1)
> I think that there is problem in proposed fix.
>   You get EQUAL when you compare two NaN values of same type Double or Float.
> Because 'Double.NaN compareTo(Double.NaN)' return 0.
> 
> Problem is when types of left and right values differ.
> (((Number)left).doubleValue() == ((Number)right).doubleValue())
>   return FALSE for both NaN values not true as compareTo(...) == 0
> 
> 
> >             if (((left instanceof Number) && (right instanceof Number)) &&
> > (left.getClass() != right.getClass())) {
> >                 return (((Number)left).doubleValue() ==
> > ((Number)right).doubleValue())
> >                     == (this.selector == Equal);
> >             }
Comment 3 Tom Ware CLA 2010-10-07 10:53:02 EDT
Setting target and priority.  See the following page for details of the
meanings of these:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 4 Tom Ware CLA 2010-12-21 16:00:32 EST
It's not clear to me what is meant by the comment:

" think that there is problem in proposed fix.
  You get EQUAL when you compare two NaN values of same type Double or Float.
Because 'Double.NaN compareTo(Double.NaN)' return 0."

The line of code referred to in that comment should not be reached for Double or Float since both are Comparable and the comment metions "same type".

Can you provide an example?
Comment 5 Tom Ware CLA 2010-12-22 11:15:15 EST
I understand the issue with NaN now.  I'm undecided about whether this requires a change in EclipseLink.
Comment 6 Tom Ware CLA 2010-12-22 15:21:40 EST
Created attachment 185735 [details]
patch with test
Comment 7 Tom Ware CLA 2010-12-22 15:45:10 EST
Checked in fix provided in bug with an ammendment to deal with NaN

Reviewed By: Tom Ware - reviewed community-submitted fix

Added DoesRelationConformTestSuite

Tested with JPA and Core LRG
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:10:55 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink