CaseForEqBuilder generates SimpleOperation instead of concrete type #1253

Closed
rt15 opened this Issue Mar 12, 2015 · 5 comments

Projects

None yet

3 participants

@rt15
rt15 commented Mar 12, 2015

Hello,

It seems somehow the same issue as:
#702
but applied to CaseForEqBuilder instead of CaseBuilder.

The expression returned by CaseForEqBuilder.Cases.otherwise() comes from a call to abstract method createResult.
There are three implementations of createResult, one that creates a SimpleOperation, another that creates a NumberOperation and the last one that create a StringOperation.
The implementation used depends on which CaseForEqBuilder.then method is used.

But for example, there is no way to obtain a DateExpression, a DateTimeExpression...

Perhaps a solution would be to do somehow like in CaseBuilder.then(Expression expr).
Something like:

    public <T> CaseForEqBuilder<D>.Cases<T, Expression<T>> then(final Expression<T> then)
    {
        type = then.getType();
        return this.inner.new Cases<T, Expression<T>>()
        {
            @SuppressWarnings("unchecked")
            @Override
            protected Expression<T> createResult(Class<T> type, Expression<T> last)
            {
                if (then instanceof StringExpression)
                {
                    return (Expression<T>) StringOperation.create(Ops.CASE_EQ, base, last);
                }
                else if (then instanceof NumberExpression)
                {
                    return (Expression<T>) NumberOperation.create(type, base, last);
                }
                else if (then instanceof DateExpression)
                {
                    return (Expression<T>) DateOperation.create(type, Ops.CASE_EQ, base, last);
                }
                else if (then instanceof DateTimeExpression)
                {
                    return (Expression<T>) DateTimeOperation.create(type, Ops.CASE_EQ, base, last);
                }
                else
                {
                    return SimpleOperation.create(type, Ops.CASE_EQ, base, last);
                }
            }
        }.when(this.other).then(then);
    }

What do you think about that?

@johnjaylward

I just recently tried upgrading my QueryDSL version from 3.4.1 to 3.6.3 and I am seeing this issue as part of the update. When I try to use the following code, I get an exception about an unknown String Constant:

QVendorSubAccount qva = new QVendorSubAccount("qva");
OrderSpecifier<Long> ord = qva.when(current.getMySubAccount())
    .then(Long.valueOf(0))
    .otherwise(Long.valueOf(1)).asc();
// execute query ordered by ord

This produces an exception:

Stack Trace: 
java.lang.IllegalArgumentException: Unsupported constant VendorSubAccount(id:name)
    at com.mysema.query.jpa.JPQLSerializer.visitLiteral(JPQLSerializer.java:334)
    at com.mysema.query.jpa.JPQLSerializer.visitConstant(JPQLSerializer.java:298)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:201)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:32)
    at com.mysema.query.types.ConstantImpl.accept(ConstantImpl.java:127)
    at com.mysema.query.support.SerializerBase.handle(SerializerBase.java:98)
    at com.mysema.query.support.SerializerBase.visitOperation(SerializerBase.java:281)
    at com.mysema.query.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:443)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:242)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:32)
    at com.mysema.query.types.OperationImpl.accept(OperationImpl.java:88)
    at com.mysema.query.support.SerializerBase.handle(SerializerBase.java:98)
    at com.mysema.query.support.SerializerBase.visitOperation(SerializerBase.java:278)
    at com.mysema.query.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:443)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:242)
    at com.mysema.query.support.SerializerBase.visit(SerializerBase.java:32)
    at com.mysema.query.types.OperationImpl.accept(OperationImpl.java:88)
    at com.mysema.query.support.SerializerBase.handle(SerializerBase.java:98)
    at com.mysema.query.jpa.JPQLSerializer.serialize(JPQLSerializer.java:231)
    at com.mysema.query.jpa.JPAQueryBase.serialize(JPAQueryBase.java:57)
    at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:127)
    at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:97)
    at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.list(AbstractHibernateQuery.java:223)
... exception trace into my code

"VendorSubAccount(id:name)" is the toString() of my VendorSubAccount class. It appears to be casting my Entity to a String.

After changing to use the simple Id (of type Long) this code works with no errors:

QVendorSubAccount qva = new QVendorSubAccount("qva");
OrderSpecifier<Long> ord = qva.id.when(current.getMySubAccount().getId())
    .then(Long.valueOf(0))
    .otherwise(Long.valueOf(1)).asc();
// execute query ordered by ord
@johnjaylward

I've confirmed that this only affects the 3.6.x branch. 3.4.1 through 3.5.1 work fine.

@timowest
Member
timowest commented Aug 5, 2015

@johnjaylward Could you try again with 3.6.6?

@timowest timowest added the progress label Aug 5, 2015
@johnjaylward

it appears to be working with 3.6.6

@johnjaylward

To clarify, I know this fixed my issue with the case statement in the orderby clause. I'm unsure if it solved the original issue @rt15 posted. They look similar enough that I'd assume that one would be fixed as well.

@johnktims johnktims closed this in #1469 Aug 31, 2015
@timowest timowest removed the progress label Aug 31, 2015
@timowest timowest added this to the 4.0.4 milestone Aug 31, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment