Hi,

I think I might have stumbled upon a bug, but I thought it best to ask
here first.

I just upgraded to version 1.6.8 from 1.5.5.2., and now one of my
queries which contains a nested select that uses the 'extract'
function no longer works. I'm getting the following exception:

org.jooq.SQLDialectNotSupportedException: extract not supported
        at org.jooq.impl.Extract.getFunction0(Extract.java:153)
        at org.jooq.impl.AbstractFunction.getFunction(AbstractFunction.java:
89)
        at org.jooq.impl.AbstractFunction.toSQL(AbstractFunction.java:75)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
160)
        at org.jooq.impl.AliasProviderImpl.toSQL(AliasProviderImpl.java:85)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
173)
        at org.jooq.impl.FieldAlias.toSQL(FieldAlias.java:69)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
173)
        at org.jooq.impl.QueryPartList.toSQL(QueryPartList.java:89)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
173)
        at
org.jooq.impl.AbstractSubSelect.toSQLReference0(AbstractSubSelect.java:
456)
        at org.jooq.impl.AbstractSubSelect.toSQL(AbstractSubSelect.java:229)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
173)
        at org.jooq.impl.SelectQueryAsTable.toSQL(SelectQueryAsTable.java:
106)
        at org.jooq.impl.DefaultRenderContext.sql(DefaultRenderContext.java:
173)
        at
org.jooq.impl.DefaultRenderContext.render(DefaultRenderContext.java:
92)
        at org.jooq.impl.Factory.renderInlined(Factory.java:257)
        at org.jooq.impl.AbstractQueryPart.hashCode(AbstractQueryPart.java:
239)
        at org.jooq.impl.AbstractSelect.asTable(AbstractSelect.java:129)
        at org.jooq.impl.AbstractSelect.asTable(AbstractSelect.java:134)
        at
org.jooq.impl.AbstractDelegatingSelect.asTable(AbstractDelegatingSelect.java:
245)
        at be.pensionarchitects.dashboard.JooqTest$1.execute(JooqTest.java:
44)
        at org.hibernate.impl.SessionImpl.doWork(SessionImpl.java:1997)
        at $Session_13340728974.doWork($Session_13340728974.java)
        at $Session_13340728970.doWork($Session_13340728970.java)
        at be.pensionarchitects.dashboard.JooqTest.test(JooqTest.java:53)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.junit.runners.model.FrameworkMethod
$1.runReflectiveCall(FrameworkMethod.java:44)
        at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:
15)
        at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:
41)
        at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:
20)
        at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
        at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
        at org.junit.rules.TestWatchman$1.evaluate(TestWatchman.java:48)
        at
org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:
79)
        at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
71)
        at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
49)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
        at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
        at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:
49)
        at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:
38)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
467)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
683)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
390)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:
197)


Now, I found the cause of this exception. The
AbstractSelect.asTable(String alias) method delegates to the no-
arg .asTable() method in the same class, which calls the hashCode
method on a newly created SelectQueryAsTable instance to generate an
alias. The hashCode method calls the renderInlined method on a new
factory to render the subselect's SQL. However, all this happens in a
disconnected fashion with a default configuration and the default
dialect which does not support the extract function. Hence the
exception.

As a workaround, I am using a patched version of the AbstractSelect
class where the asTable(String alias) method does not delegate to the
no-arg variant but creates the SelectQueryAsTable directly. This
avoids the call to hashCode() and the exception. I think it also makes
more sense this way because the current code generates an alias
unnecessarily.

But I was wondering: is there a newly imposed restriction on nested
selects? Am I doing it wrong? Here is a code sample that illustrates
the problem:

        SchemaMapping mapping = new SchemaMapping();
        mapping.add(Pfadmin.PFADMIN, "pfadmin_fuel");

        Factory create = new Factory(connection, SQLDialect.MYSQL, mapping);

        Table<Record> subselect = getSubselect(create,
19).asTable("subselect");

        @SuppressWarnings("unchecked")
        Field<Integer> txYear = (Field<Integer>)subselect.getField("txYear");

        create.select(txYear).from(subselect).fetch();

And the subselect method:

        private Select<Record> getSubselect(Factory create, Integer policyId)
{

                Field<Integer> txYear =
TransactionTable.T_DATE_VALUTA.extract(DatePart.YEAR).as("txYear");

                return create
                        .select(txYear)
                        .from(TBL_TRANSACTION)
                        
.join(TBL_ACCOUNT).on(AccountTable.A_ACCOUNT_ID.equal(TransactionTable.T_ACCOUNT_ID))
                        
.join(TBL_POLICY_SUB_POLICY).on(PolicySubPolicyTable.POLICY_SUB_POLICY_ID.equal(AccountTable.A_SPOL_ID))
                        
.join(TBL_POLICY).on(PolicyTable.POL_POLICY_ID.equal(PolicySubPolicyTable.SPOL_POLICY_ID))
                        .where(PolicyTable.POL_POLICY_ID.equal(policyId));
        }

Thanks in advance.

Regards,

Gunther

Reply via email to