Skip to content
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

Fix order by rendering for queries containing UNION #3429

Closed
wants to merge 5 commits into from

Conversation

christophstrobl
Copy link
Member

Make sure to append space after order by clause and fix alias detection for wrapped sub select.
Also make sure to ignore alias used in subselect so they do not conflict with root ones.

Closes: #3427

void sortShouldBeAppendedWithSpacingInCaseOfSetOperator() {

String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B')";
String target = createQueryFor(source, Sort.by("Type").ascending());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this line target has the value

SELECT tb 
    FROM Test tb 
    WHERE (tb.type = 'A') 
    order by tb.Type asc 
UNION 
SELECT tb 
    FROM Test tb 
    WHERE (tb.type = 'B') 
    order by tb.Type asc`

i.e. the order by is applied twice which is illegal, since according to answers here https://stackoverflow.com/questions/4715820/how-to-order-by-with-union-in-sql the later order by applies to the full union and an order by on the individual selects might be even illegal (probably depends on the database)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we do not know the target db nor how it handles order by we cannot imply ordering the last is the correct behaviour, nor do we have the means to define which of the selects to decorate. an alternative would be to raise an error and demand wrapping the entire thing as it's done in one of the follow up tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, let's wait and see what kind of reports we get. We can then still react to the feedback we receive.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reading through IBM an Oracle SQL reference docs @schauder has a good point in the above mentioned query not being compliant (at least not in the form it is currently rendered)

For example, the following is not valid (SQLSTATE 428FJ):
SELECT * FROM T1
ORDER BY C1
UNION
SELECT * FROM T2
ORDER BY C1

The following example is valid:
(SELECT * FROM T1
ORDER BY C1)
UNION
(SELECT * FROM T2
ORDER BY C1)

String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B')";
String target = createQueryFor(source, Sort.by("Type").ascending());

assertThat(target).contains(" UNION SELECT ").doesNotContainPattern(Pattern.compile(".*\\SUNION"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we put in an exact SQL statement we should be able to assert on a precise output and not rely on pattern matching and simiar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems legit

}

@ParameterizedTest // GH-3427
@ValueSource(strings = {"", "res"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment would be nice explaining why we need to run this with different prefixes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deemed to be obvious - apparently isn't

@ValueSource(strings = {"", "res"})
void sortShouldBeAppendedToSubSelectWithSetOperatorInSubselect(String alias) {

String prefix = StringUtils.hasText(alias) ? (alias + ".") : "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I think we should be able to and prefer a simple equals-assertion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of duplication.

@christophstrobl
Copy link
Member Author

we should additionally check the count query creation for UNION.

Make sure to append space after order by clause and fix alias detection for wrapped sub select.
Also make sure to ignore alias used in subselect so they do not conflict with root ones.
@christophstrobl
Copy link
Member Author

@schauder @mp911de - care to have another look at this one.
Changed the sort transformation so that the provided Sort is now appended after the last query expression.

mp911de pushed a commit that referenced this pull request Aug 2, 2024
Make sure to append space after order by clause and fix alias detection for wrapped sub select.
Also make sure to ignore alias used in subselect so they do not conflict with root ones.

Render order by only on full select if set operator is present in EQL.

Original pull request: #3429
Closes #3427
mp911de added a commit that referenced this pull request Aug 2, 2024
Ensure ordering of the last query only, applying ordering after the set operation.

Original pull request: #3429
See #3427
@mp911de mp911de added this to the 3.4 M1 (2024.1.0) milestone Aug 2, 2024
@mp911de mp911de added the type: bug A general bug label Aug 2, 2024
@mp911de
Copy link
Member

mp911de commented Aug 2, 2024

Updated the HQL code to apply ordering after the last set operation, EQL did that already.

@mp911de mp911de closed this Aug 2, 2024
@mp911de mp911de deleted the issue/3427 branch August 2, 2024 08:23
mp911de pushed a commit that referenced this pull request Oct 1, 2024
Make sure to append space after order by clause and fix alias detection for wrapped sub select.
Also make sure to ignore alias used in subselect so they do not conflict with root ones.

Render order by only on full select if set operator is present in EQL.

Closes #3630
Original pull request: #3429
See #3427
mp911de pushed a commit that referenced this pull request Oct 1, 2024
Make sure to append space after order by clause and fix alias detection for wrapped sub select.
Also make sure to ignore alias used in subselect so they do not conflict with root ones.

Render order by only on full select if set operator is present in EQL.

Closes #3630
Original pull request: #3429
See #3427
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Spring Data JPA generates incorrect JPQL query for sorted pagination request with UNION clause
3 participants