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

QueryDSL-SQL Generates Bad Query With Oracle, CTE's and limit() #1487

Closed
bheisler opened this Issue Aug 18, 2015 · 0 comments

Comments

Projects
None yet
2 participants
@bheisler

Using QueryDSL 4.0.3. I have several queries which use recursive CTE's to search a version table. This works fine with H2 and PostgreSQL. However, I'm trying to get it to work with Oracle and it's producing invalid SQL.

Here's my code:

new SQLQuery<>( conn, templates )
.withRecursive( versionCTE, versionCTE.versionId, versionCTE.versionDepId, versionCTE.versionCreated )
    .as( SQLExpressions.unionAll(
            SQLExpressions.select( version.versionId, version.versionDependsOnId, version.versionCreated )
                .from( version )
                .join( workspace ).on( workspace.workspaceCurrentVersionId.eq( version.versionId ) )
                .where( workspace.workspaceName.eq( params.getWorkspace().val() ),
                    workspace.satellite.eq( params.getSatellite().val() ) ),
             SQLExpressions.select( version.versionId, version.versionDependsOnId, version.versionCreated )
                 .from( version, versionCTE )
                 .where( version.versionId.eq( versionCTE.versionDepId ) ) ) )
.select( baseTable, versionedTable, versionCTE.versionId )
.from( versionCTE, baseTable, versionedTable )
.where(
    versionedPred.apply( id )
        .and( tableVersionId.eq( versionCTE.versionId ) )
        .and( satelliteMatches( versionedSatellite, params.getSatellite() ) ),
    basePred.apply( id )
        .and( satelliteMatches( baseSatellite, params.getSatellite() ) ) )
.orderBy( new OrderSpecifier<>( Order.DESC, versionCTE.versionCreatedAsDateTime ) )
.limit( 1 )
.fetchOne();

This is the malformed SQL generated by QueryDSL (I modified it slightly to cut out a huge list of columns):

with select * from (
 versionCTE (version_id, version_depends_on_id, version_created) as ((select version.version_id, version.version_depends_on_id, version.version_created
from version version
join workspace workspace
on workspace.workspace_current_version_id = version.version_id
where workspace.workspace_name = ? and workspace.satellite = ?)
union all
(select version.version_id, version.version_depends_on_id, version.version_created
from version version, versionCTE versionCTE
where version.version_id = versionCTE.version_depends_on_id))
select access_structure.*, access_structure_pdata.*, versionCTE.*
from versionCTE versionCTE, access_structure access_structure, access_structure_pdata access_structure_pdata
where access_structure_pdata.struct_id = ? and access_structure_pdata.version_id = versionCTE.version_id and access_structure_pdata.satellite = ? and (access_structure.struct_id = ? and access_structure.satellite = ?)
order by cast(versionCTE.version_created as timestamp) desc
) where rownum <= ?`

Notice how the CTE's with is interfering with the select * from (...) where rownum <= ? wrapper produced by the limit() call. Moving the with inside the select * from ( clause executes correctly, as does moving the entire CTE outside of the select * from ( clause leaving only the select access_structure.*, ... query inside it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment