Polishing.
Ensure ordering of the last query only, applying ordering after the set operation. Original pull request: #3429 See #3427
This commit is contained in:
@@ -47,10 +47,10 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
this.primaryFromAlias = primaryFromAlias;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitQueryExpression(HqlParser.QueryExpressionContext ctx) {
|
||||
|
||||
if(ObjectUtils.isEmpty(ctx.setOperator())) {
|
||||
if (ObjectUtils.isEmpty(ctx.setOperator())) {
|
||||
return super.visitQueryExpression(ctx);
|
||||
}
|
||||
|
||||
@@ -59,15 +59,20 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
builder.appendExpression(visit(ctx.withClause()));
|
||||
}
|
||||
|
||||
builder.append(visitOrderedQuery(ctx.orderedQuery(0), Sort.unsorted()));
|
||||
List<HqlParser.OrderedQueryContext> orderedQueries = ctx.orderedQuery();
|
||||
for (int i = 0; i < orderedQueries.size(); i++) {
|
||||
|
||||
for (int i = 1; i < ctx.orderedQuery().size(); i++) {
|
||||
if (i != 0) {
|
||||
builder.append(visit(ctx.setOperator(i - 1)));
|
||||
}
|
||||
|
||||
builder.append(visit(ctx.setOperator(i - 1)));
|
||||
builder.append(visit(ctx.orderedQuery(i)));
|
||||
if (i == orderedQueries.size() - 1) {
|
||||
builder.append(visitOrderedQuery(ctx.orderedQuery(i), this.sort));
|
||||
} else {
|
||||
builder.append(visitOrderedQuery(ctx.orderedQuery(i), Sort.unsorted()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -81,7 +86,7 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
QueryTokenStream tokens = super.visitJoinPath(ctx);
|
||||
|
||||
if (ctx.variable() != null && !isSubquery(ctx)) {
|
||||
if (ctx.variable() != null && !isSubquery(ctx)) {
|
||||
transformerSupport.registerAlias(tokens.getLast());
|
||||
}
|
||||
|
||||
@@ -93,7 +98,7 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
QueryTokenStream tokens = super.visitJoinSubquery(ctx);
|
||||
|
||||
if (ctx.variable() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
|
||||
if (ctx.variable() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
|
||||
transformerSupport.registerAlias(tokens.getLast());
|
||||
}
|
||||
|
||||
@@ -105,7 +110,7 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
QueryTokenStream tokens = super.visitVariable(ctx);
|
||||
|
||||
if (ctx.identifier() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
|
||||
if (ctx.identifier() != null && !tokens.isEmpty() && !isSubquery(ctx)) {
|
||||
transformerSupport.registerAlias(tokens.getLast());
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ class EqlQueryTransformerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyCountToAlreadySorteQuery() {
|
||||
void applyCountToAlreadySortedQuery() {
|
||||
|
||||
// given
|
||||
var original = "SELECT e FROM Employee e where e.name = :name ORDER BY e.modified_date";
|
||||
@@ -762,10 +762,12 @@ class EqlQueryTransformerTests {
|
||||
@Test // GH-3427
|
||||
void sortShouldBeAppendedToFullSelectOnlyInCaseOfSetOperator() {
|
||||
|
||||
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B')";
|
||||
String source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B') UNION SELECT tb FROM Test tb WHERE (tb.type='C')";
|
||||
String target = createQueryFor(source, Sort.by("Type").ascending());
|
||||
|
||||
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') order by tb.Type asc");
|
||||
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') " //
|
||||
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') " //
|
||||
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'C') order by tb.Type asc");
|
||||
}
|
||||
|
||||
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
|
||||
|
||||
@@ -705,11 +705,9 @@ class HqlQueryTransformerTests {
|
||||
.isEqualTo("select dense_rank() over (order by lastname) from user u order by u.lastname, u.age desc");
|
||||
|
||||
// partition by + order by in over clause
|
||||
assertThat(
|
||||
createQueryFor(
|
||||
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u",
|
||||
sort))
|
||||
.isEqualTo(
|
||||
assertThat(createQueryFor(
|
||||
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u",
|
||||
sort)).isEqualTo(
|
||||
"select dense_rank() over (partition by active, age order by lastname range between 1.0 preceding and 1.0 following) from user u order by u.age desc");
|
||||
|
||||
// partition by + order by in over clause + order by at the end
|
||||
@@ -1068,19 +1066,23 @@ class HqlQueryTransformerTests {
|
||||
@Test // GH-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 source = "SELECT tb FROM Test tb WHERE (tb.type='A') UNION SELECT tb FROM Test tb WHERE (tb.type='B') UNION SELECT tb FROM Test tb WHERE (tb.type='C')";
|
||||
String target = createQueryFor(source, Sort.by("Type").ascending());
|
||||
|
||||
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') order by tb.Type asc");
|
||||
|
||||
assertThat(target).isEqualTo("SELECT tb FROM Test tb WHERE (tb.type = 'A') " //
|
||||
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'B') " //
|
||||
+ "UNION SELECT tb FROM Test tb WHERE (tb.type = 'C') order by tb.Type asc");
|
||||
}
|
||||
|
||||
@ParameterizedTest // GH-3427
|
||||
@ValueSource(strings = {"", "res"})
|
||||
@ValueSource(strings = { "", "res" })
|
||||
void sortShouldBeAppendedToSubSelectWithSetOperatorInSubselect(String alias) {
|
||||
|
||||
String prefix = StringUtils.hasText(alias) ? (alias + ".") : "";
|
||||
String source = "SELECT %sname FROM (SELECT c.name as name FROM Category c UNION SELECT t.name as name FROM Tag t)".formatted(prefix);
|
||||
if(StringUtils.hasText(alias)) {
|
||||
String source = "SELECT %sname FROM (SELECT c.name as name FROM Category c UNION SELECT t.name as name FROM Tag t)"
|
||||
.formatted(prefix);
|
||||
|
||||
if (StringUtils.hasText(alias)) {
|
||||
source = source + " %s".formatted(alias);
|
||||
}
|
||||
|
||||
@@ -1088,10 +1090,10 @@ class HqlQueryTransformerTests {
|
||||
|
||||
assertThat(target).contains(" UNION SELECT ").doesNotContainPattern(Pattern.compile(".*\\SUNION"));
|
||||
assertThat(target).endsWith("order by %sname asc".formatted(prefix)).satisfies(it -> {
|
||||
Pattern pattern = Pattern.compile("order by %sname".formatted(prefix));
|
||||
Pattern pattern = Pattern.compile("order by");
|
||||
Matcher matcher = pattern.matcher(target);
|
||||
int count = 0;
|
||||
while(matcher.find()) {
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
assertThat(count).describedAs("Found order by clause more than once in: \n%s", it).isOne();
|
||||
|
||||
@@ -198,16 +198,6 @@ class JpqlQueryTransformerTests {
|
||||
|
||||
Sort sort = Sort.by(Sort.Order.desc("age"));
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
assertThat(newParser("""
|
||||
select u
|
||||
from user u
|
||||
|
||||
Reference in New Issue
Block a user