19
19
20
20
import java .util .ArrayList ;
21
21
import java .util .Collections ;
22
+ import java .util .HashSet ;
22
23
import java .util .List ;
24
+ import java .util .Set ;
23
25
24
26
import org .antlr .v4 .runtime .ParserRuleContext ;
25
27
import org .springframework .data .domain .Sort ;
@@ -41,13 +43,15 @@ class HqlQueryTransformer extends HqlQueryRenderer {
41
43
42
44
private final @ Nullable String countProjection ;
43
45
44
- private @ Nullable String alias = null ;
46
+ private @ Nullable String primaryFromClauseAlias = null ;
45
47
46
48
private List <JpaQueryParsingToken > projection = Collections .emptyList ();
47
49
private boolean projectionProcessed ;
48
50
49
51
private boolean hasConstructorExpression = false ;
50
52
53
+ private Set <String > projectionAliases ;
54
+
51
55
HqlQueryTransformer () {
52
56
this (Sort .unsorted (), false , null );
53
57
}
@@ -67,11 +71,12 @@ private HqlQueryTransformer(Sort sort, boolean countQuery, @Nullable String coun
67
71
this .sort = sort ;
68
72
this .countQuery = countQuery ;
69
73
this .countProjection = countProjection ;
74
+ this .projectionAliases = new HashSet <>();
70
75
}
71
76
72
77
@ Nullable
73
78
public String getAlias () {
74
- return this .alias ;
79
+ return this .primaryFromClauseAlias ;
75
80
}
76
81
77
82
public List <JpaQueryParsingToken > getProjection () {
@@ -137,13 +142,14 @@ public List<JpaQueryParsingToken> visitOrderedQuery(HqlParser.OrderedQueryContex
137
142
if (order .isIgnoreCase ()) {
138
143
tokens .add (TOKEN_LOWER_FUNC );
139
144
}
145
+
140
146
tokens .add (new JpaQueryParsingToken (() -> {
141
147
142
- if (order .getProperty ().contains ("(" )) {
148
+ if (shouldAlias (order )) {
149
+ return primaryFromClauseAlias + "." + order .getProperty ();
150
+ } else {
143
151
return order .getProperty ();
144
152
}
145
-
146
- return this .alias + "." + order .getProperty ();
147
153
}, true ));
148
154
if (order .isIgnoreCase ()) {
149
155
NOSPACE (tokens );
@@ -164,6 +170,33 @@ public List<JpaQueryParsingToken> visitOrderedQuery(HqlParser.OrderedQueryContex
164
170
return tokens ;
165
171
}
166
172
173
+ /**
174
+ * Determine when an {@link org.springframework.data.domain.Sort.Order} parameter should alias (or not).
175
+ *
176
+ * @param order
177
+ * @return boolean whether or not to apply the primary FROM clause's alias
178
+ */
179
+ private boolean shouldAlias (Sort .Order order ) {
180
+
181
+ if (orderParameterIsAFunction (order )) {
182
+ return false ;
183
+ }
184
+
185
+ if (orderParameterReferencesAProjectionAlias (order )) {
186
+ return false ;
187
+ }
188
+
189
+ return true ;
190
+ }
191
+
192
+ private boolean orderParameterIsAFunction (Sort .Order order ) {
193
+ return order .getProperty ().contains ("(" );
194
+ }
195
+
196
+ private boolean orderParameterReferencesAProjectionAlias (Sort .Order order ) {
197
+ return projectionAliases .contains (order .getProperty ());
198
+ }
199
+
167
200
@ Override
168
201
public List <JpaQueryParsingToken > visitFromQuery (HqlParser .FromQueryContext ctx ) {
169
202
@@ -176,7 +209,7 @@ public List<JpaQueryParsingToken> visitFromQuery(HqlParser.FromQueryContext ctx)
176
209
if (countProjection != null ) {
177
210
tokens .add (new JpaQueryParsingToken (countProjection ));
178
211
} else {
179
- tokens .add (new JpaQueryParsingToken (() -> this .alias , false ));
212
+ tokens .add (new JpaQueryParsingToken (() -> this .primaryFromClauseAlias , false ));
180
213
}
181
214
182
215
tokens .add (TOKEN_CLOSE_PAREN );
@@ -240,8 +273,8 @@ public List<JpaQueryParsingToken> visitFromRoot(HqlParser.FromRootContext ctx) {
240
273
if (ctx .variable () != null ) {
241
274
tokens .addAll (visit (ctx .variable ()));
242
275
243
- if (this .alias == null && !isSubquery (ctx )) {
244
- this .alias = tokens .get (tokens .size () - 1 ).getToken ();
276
+ if (this .primaryFromClauseAlias == null && !isSubquery (ctx )) {
277
+ this .primaryFromClauseAlias = tokens .get (tokens .size () - 1 ).getToken ();
245
278
}
246
279
}
247
280
} else if (ctx .subquery () != null ) {
@@ -256,8 +289,8 @@ public List<JpaQueryParsingToken> visitFromRoot(HqlParser.FromRootContext ctx) {
256
289
if (ctx .variable () != null ) {
257
290
tokens .addAll (visit (ctx .variable ()));
258
291
259
- if (this .alias == null && !isSubquery (ctx )) {
260
- this .alias = tokens .get (tokens .size () - 1 ).getToken ();
292
+ if (this .primaryFromClauseAlias == null && !isSubquery (ctx )) {
293
+ this .primaryFromClauseAlias = tokens .get (tokens .size () - 1 ).getToken ();
261
294
}
262
295
}
263
296
}
@@ -268,16 +301,22 @@ public List<JpaQueryParsingToken> visitFromRoot(HqlParser.FromRootContext ctx) {
268
301
@ Override
269
302
public List <JpaQueryParsingToken > visitAlias (HqlParser .AliasContext ctx ) {
270
303
271
- List <JpaQueryParsingToken > tokens = newArrayList ( );
304
+ List <JpaQueryParsingToken > tokens = super . visitAlias ( ctx );
272
305
273
- if (ctx . AS () != null ) {
274
- tokens .add ( new JpaQueryParsingToken ( ctx . AS ()) );
306
+ if (primaryFromClauseAlias == null && ! isSubquery ( ctx ) ) {
307
+ primaryFromClauseAlias = tokens .get ( tokens . size () - 1 ). getToken ( );
275
308
}
276
309
277
- tokens .addAll (visit (ctx .identifier ()));
310
+ return tokens ;
311
+ }
312
+
313
+ @ Override
314
+ public List <JpaQueryParsingToken > visitVariable (HqlParser .VariableContext ctx ) {
315
+
316
+ List <JpaQueryParsingToken > tokens = super .visitVariable (ctx );
278
317
279
- if (this . alias == null && ! isSubquery ( ctx ) ) {
280
- this . alias = tokens .get (tokens .size () - 1 ).getToken ();
318
+ if (ctx . identifier () != null ) {
319
+ projectionAliases . add ( tokens .get (tokens .size () - 1 ).getToken () );
281
320
}
282
321
283
322
return tokens ;
@@ -312,13 +351,13 @@ public List<JpaQueryParsingToken> visitSelectClause(HqlParser.SelectClauseContex
312
351
313
352
if (selectionListTokens .stream ().anyMatch (hqlToken -> hqlToken .getToken ().contains ("new" ))) {
314
353
// constructor
315
- tokens .add (new JpaQueryParsingToken (() -> this .alias ));
354
+ tokens .add (new JpaQueryParsingToken (() -> this .primaryFromClauseAlias ));
316
355
} else {
317
356
// keep all the select items to distinct against
318
357
tokens .addAll (selectionListTokens );
319
358
}
320
359
} else {
321
- tokens .add (new JpaQueryParsingToken (() -> this .alias ));
360
+ tokens .add (new JpaQueryParsingToken (() -> this .primaryFromClauseAlias ));
322
361
}
323
362
}
324
363
0 commit comments