New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CaseForEqBuilder generates SimpleOperation instead of concrete type #1253

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

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

This comment has been minimized.

Show comment
Hide comment
@johnjaylward

johnjaylward May 27, 2015

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

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

This comment has been minimized.

Show comment
Hide comment
@johnjaylward

johnjaylward May 28, 2015

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

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

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Aug 5, 2015

Member

@johnjaylward Could you try again with 3.6.6?

Member

timowest commented Aug 5, 2015

@johnjaylward Could you try again with 3.6.6?

@johnjaylward

This comment has been minimized.

Show comment
Hide comment
@johnjaylward

johnjaylward Aug 12, 2015

it appears to be working with 3.6.6

it appears to be working with 3.6.6

@johnjaylward

This comment has been minimized.

Show comment
Hide comment
@johnjaylward

johnjaylward Aug 12, 2015

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.

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